mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
fix(agent): filter out empty params to ensure LLM can set tool params at runtime (#2288)
This commit is contained in:
@@ -1011,10 +1011,21 @@ export function prepareToolExecution(
|
||||
toolParams: Record<string, any>
|
||||
executionParams: Record<string, any>
|
||||
} {
|
||||
// Filter out empty/null/undefined values from user params
|
||||
// so that cleared fields don't override LLM-generated values
|
||||
const filteredUserParams: Record<string, any> = {}
|
||||
if (tool.params) {
|
||||
for (const [key, value] of Object.entries(tool.params)) {
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
filteredUserParams[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User-provided params take precedence over LLM-generated params
|
||||
const toolParams = {
|
||||
...llmArgs,
|
||||
...tool.params,
|
||||
...filteredUserParams,
|
||||
}
|
||||
|
||||
// Add system parameters for execution
|
||||
|
||||
@@ -177,6 +177,44 @@ describe('Tool Parameters Utils', () => {
|
||||
expect(merged.message).toBe('Hello world')
|
||||
expect(merged.timeout).toBe(10000)
|
||||
})
|
||||
|
||||
it.concurrent('should skip empty strings so LLM values are used', () => {
|
||||
const userProvided = {
|
||||
apiKey: 'user-key',
|
||||
channel: '', // User cleared this field
|
||||
message: '', // User cleared this field too
|
||||
}
|
||||
const llmGenerated = {
|
||||
message: 'Hello world',
|
||||
channel: '#random',
|
||||
timeout: 10000,
|
||||
}
|
||||
|
||||
const merged = mergeToolParameters(userProvided, llmGenerated)
|
||||
|
||||
expect(merged.apiKey).toBe('user-key') // Non-empty user value preserved
|
||||
expect(merged.channel).toBe('#random') // LLM value used because user value was empty
|
||||
expect(merged.message).toBe('Hello world') // LLM value used because user value was empty
|
||||
expect(merged.timeout).toBe(10000)
|
||||
})
|
||||
|
||||
it.concurrent('should skip null and undefined values', () => {
|
||||
const userProvided = {
|
||||
apiKey: 'user-key',
|
||||
channel: null,
|
||||
message: undefined,
|
||||
}
|
||||
const llmGenerated = {
|
||||
message: 'Hello world',
|
||||
channel: '#random',
|
||||
}
|
||||
|
||||
const merged = mergeToolParameters(userProvided, llmGenerated)
|
||||
|
||||
expect(merged.apiKey).toBe('user-key')
|
||||
expect(merged.channel).toBe('#random') // LLM value used
|
||||
expect(merged.message).toBe('Hello world') // LLM value used
|
||||
})
|
||||
})
|
||||
|
||||
describe('validateToolParameters', () => {
|
||||
|
||||
@@ -572,16 +572,27 @@ export function createExecutionToolSchema(toolConfig: ToolConfig): ToolSchema {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges user-provided parameters with LLM-generated parameters
|
||||
* Merges user-provided parameters with LLM-generated parameters.
|
||||
* User-provided parameters take precedence, but empty strings are skipped
|
||||
* so that LLM-generated values are used when user clears a field.
|
||||
*/
|
||||
export function mergeToolParameters(
|
||||
userProvidedParams: Record<string, unknown>,
|
||||
llmGeneratedParams: Record<string, unknown>
|
||||
): Record<string, unknown> {
|
||||
// User-provided parameters take precedence
|
||||
// Filter out empty strings from user-provided params
|
||||
// so that cleared fields don't override LLM values
|
||||
const filteredUserParams: Record<string, unknown> = {}
|
||||
for (const [key, value] of Object.entries(userProvidedParams)) {
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
filteredUserParams[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// User-provided parameters take precedence (after filtering empty values)
|
||||
return {
|
||||
...llmGeneratedParams,
|
||||
...userProvidedParams,
|
||||
...filteredUserParams,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user