feat(agent,coding-agent): add prepareArguments hook for pre-validation argument preparation
Add AgentTool.prepareArguments and ToolDefinition.prepareArguments hook that runs before schema validation in the agent loop. This lets tools silently accept legacy argument shapes from resumed old sessions without polluting the public schema. The built-in edit tool uses this to fold legacy top-level oldText/newText into edits[] when resuming sessions that predate the edits-only schema. - AgentTool/ToolDefinition: typed prepareArguments returning Static<TParameters> - agent-loop: prepareToolCallArguments() runs before validateToolArguments() - edit tool: prepareEditArguments folds legacy fields, validateEditInput is strict - Documented in extensions.md with edit-tool example
This commit is contained in:
@@ -455,6 +455,20 @@ type ExecutedToolCallOutcome = {
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
function prepareToolCallArguments(tool: AgentTool<any>, toolCall: AgentToolCall): AgentToolCall {
|
||||
if (!tool.prepareArguments) {
|
||||
return toolCall;
|
||||
}
|
||||
const preparedArguments = tool.prepareArguments(toolCall.arguments);
|
||||
if (preparedArguments === toolCall.arguments) {
|
||||
return toolCall;
|
||||
}
|
||||
return {
|
||||
...toolCall,
|
||||
arguments: preparedArguments as Record<string, any>,
|
||||
};
|
||||
}
|
||||
|
||||
async function prepareToolCall(
|
||||
currentContext: AgentContext,
|
||||
assistantMessage: AssistantMessage,
|
||||
@@ -472,7 +486,8 @@ async function prepareToolCall(
|
||||
}
|
||||
|
||||
try {
|
||||
const validatedArgs = validateToolArguments(tool, toolCall);
|
||||
const preparedToolCall = prepareToolCallArguments(tool, toolCall);
|
||||
const validatedArgs = validateToolArguments(tool, preparedToolCall);
|
||||
if (config.beforeToolCall) {
|
||||
const beforeResult = await config.beforeToolCall(
|
||||
{
|
||||
|
||||
@@ -269,10 +269,13 @@ export interface AgentToolResult<T> {
|
||||
// Callback for streaming tool execution updates
|
||||
export type AgentToolUpdateCallback<T = any> = (partialResult: AgentToolResult<T>) => void;
|
||||
|
||||
// AgentTool extends Tool but adds the execute function
|
||||
// AgentTool extends Tool but adds argument preparation and execution hooks
|
||||
export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any> extends Tool<TParameters> {
|
||||
// A human-readable label for the tool to be displayed in UI
|
||||
label: string;
|
||||
// Optional compatibility shim to prepare raw tool call arguments before schema validation.
|
||||
// Must return an object conforming to TParameters.
|
||||
prepareArguments?: (args: unknown) => Static<TParameters>;
|
||||
execute: (
|
||||
toolCallId: string,
|
||||
params: Static<TParameters>,
|
||||
|
||||
Reference in New Issue
Block a user