diff --git a/src/modules/aifn/agiattachmentprompts/agiAttachmentPrompts.ts b/src/modules/aifn/agiattachmentprompts/agiAttachmentPrompts.ts index 995ba5538..48dc9661d 100644 --- a/src/modules/aifn/agiattachmentprompts/agiAttachmentPrompts.ts +++ b/src/modules/aifn/agiattachmentprompts/agiAttachmentPrompts.ts @@ -50,7 +50,7 @@ Analyze the provided content to determine its nature, identify any relationships fragments: attachmentFragments, }, { role: 'user', - fragments: [createTextContentFragment(`Call the function once, filling in order the attachments, the relationships between them, the top ${num_suggestions} orthogonal actions you inferred and the single modst valuable action.`)], + fragments: [createTextContentFragment(`Call the function once, filling in order the attachments, the relationships between them, the top ${num_suggestions} orthogonal actions you inferred and the single most valuable action.`)], }])).chatSequence, tools: [ aixFunctionCallTool({ @@ -71,7 +71,7 @@ Analyze the provided content to determine its nature, identify any relationships ); // extract the function call - const { argsObject } = aixRequireSingleFunctionCallInvocation(fragments, 'propose_user_actions_for_attachments', 'agiAttachmentPrompts'); + const { argsObject } = aixRequireSingleFunctionCallInvocation(fragments, 'propose_user_actions_for_attachments', false, 'agiAttachmentPrompts'); const args = inputSchema.parse(argsObject); if (!args.top_orthogonal_user_actions?.length) diff --git a/src/modules/aifn/agicodefixup/agiFixupCode.ts b/src/modules/aifn/agicodefixup/agiFixupCode.ts index 363bb4362..e959abdf5 100644 --- a/src/modules/aifn/agicodefixup/agiFixupCode.ts +++ b/src/modules/aifn/agicodefixup/agiFixupCode.ts @@ -16,6 +16,7 @@ interface CodeFix { systemMessage: string; userInstructionTemplate: string; // Template with placeholders for `codeToFix` and `errorString` functionName: string; + functionPolicy: 'invoke' | 'think-then-invoke'; outputSchema: ZodObject; } @@ -23,21 +24,21 @@ const CodeFixes: Record = { // See `RenderCodeChartJS` 'chartjs-issue': { - description: 'Provides the corrected ChartJS configuration code.', - systemMessage: `You are an AI assistant that helps fix invalid ChartJS configuration JSON code. -When provided with invalid ChartJS code, you analyze it, identify errors, and output a corrected version in valid JSON format. -Respond only by calling the \`{{functionName}}\` function.`, - userInstructionTemplate: `The following ChartJS configuration code is invalid and cannot be parsed: + description: 'Provides the corrected Chart.js configuration code.', + systemMessage: `You are an AI assistant that fixes invalid Chart.js configuration JSON. +When provided with invalid Chart.js code, you analyze it, identify errors, especially remove all functions if any, and output a corrected version in valid JSON format. +Respond first with a very brief analysis of where the error is and exactly what to change, and then call the \`{{functionName}}\` function.`, + userInstructionTemplate: `The following Chart.js ChartOptions JSON is invalid and cannot be parsed: \`\`\`json {{codeToFix}} \`\`\` {{errorMessageSection}} -Please analyze the JSON, correct any errors (of course remove functions if any), and provide a valid JSON configuration that can be parsed by ChartJS. -Call the function \`{{functionName}}\` once, providing the corrected code.`, +Please analyze the JSON, correct any errors (REMOVE FUNCTIONS!!!), and provide a valid JSON-only ChartOptions that can be parsed by Chart.js.`, functionName: 'provide_corrected_chartjs_code', + functionPolicy: 'think-then-invoke', outputSchema: z.object({ - corrected_code: z.string().describe('The corrected ChartJS configuration code in valid JSON format.'), + corrected_code: z.string().describe('The corrected Chart.js ChartOptions in valid JSON format.'), }), }, @@ -77,7 +78,9 @@ export async function agiFixupCode(issueType: CodeFixType, codeToFix: string, er inputSchema: config.outputSchema, }), ], - toolsPolicy: { type: 'function_call', function_call: { name: config.functionName } }, + toolsPolicy: + config.functionPolicy === 'invoke' ? { type: 'function_call', function_call: { name: config.functionName } } + : config.functionPolicy === 'think-then-invoke' ? { type: 'auto' } : undefined, }; // Invoke the AI model @@ -90,7 +93,7 @@ export async function agiFixupCode(issueType: CodeFixType, codeToFix: string, er ); // Validate and parse the AI's response - const { argsObject } = aixRequireSingleFunctionCallInvocation(fragments, config.functionName, issueType); + const { argsObject } = aixRequireSingleFunctionCallInvocation(fragments, config.functionName, config.functionPolicy === 'think-then-invoke', issueType); const argsZod = config.outputSchema.parse(argsObject); // Return the corrected code diff --git a/src/modules/aix/client/aix.client.fromSimpleFunction.ts b/src/modules/aix/client/aix.client.fromSimpleFunction.ts index f48a7aefd..bf6c2ec9c 100644 --- a/src/modules/aix/client/aix.client.fromSimpleFunction.ts +++ b/src/modules/aix/client/aix.client.fromSimpleFunction.ts @@ -62,24 +62,25 @@ function _recursiveObjectSchemaCleanup(obj: Record, thisKey?: strin /** Extract the function name from the Aix FunctionCall Tool Definition */ -export function aixRequireSingleFunctionCallInvocation(fragments: DMessageContentFragment[], expectedFunctionName: string, debugLabel: string): { +export function aixRequireSingleFunctionCallInvocation(fragments: DMessageContentFragment[], expectedFunctionName: string, allowThinkPart: boolean, debugLabel: string): { invocation: Extract; argsObject: object; } { - if (!Array.isArray(fragments) || fragments.length !== 1) { + if (!Array.isArray(fragments) || !(fragments.length >= 1)) { if (AIX_DEBUG_CLIENT_TOOLS) console.error('[DEV] single-function-call: invalid fragments:', fragments, 'for', debugLabel); throw new Error('AIX: Unexpected response.'); } - if (!isContentFragment(fragments[0]) || fragments[0].part.pt !== 'tool_invocation') { + const toolIdx = allowThinkPart ? fragments.length - 1 : 0; + if (!isContentFragment(fragments[toolIdx]) || fragments[toolIdx].part.pt !== 'tool_invocation') { if (AIX_DEBUG_CLIENT_TOOLS) - console.error('[DEV] single-function-call: invalid fragment part:', fragments[0].part, 'for', debugLabel); + console.error('[DEV] single-function-call: invalid fragment part:', fragments[toolIdx].part, 'for', debugLabel); throw new Error('AIX: Missing tool invocation.'); } - const { invocation } = fragments[0].part; + const { invocation } = fragments[toolIdx].part; if (invocation.type !== 'function_call' || invocation.name !== expectedFunctionName) { if (AIX_DEBUG_CLIENT_TOOLS)