refactor(tools): compose PTC instructions without prose replacement

Pass execution-specific phrases directly to the run_code flavor factory and render SDK instructions from explicit program-format branches. Keep all emitted text byte-identical while removing coupling to exact shared prose. Validate the owning tests with full scoped coverage, focused session/SDK replays, and a complete build.
This commit is contained in:
fz committed 2026-10-16 15:30:12 +08:00
1 parent c34a107428
commit 839bd5131d
2 files changed
+30 -20

No files matched your search

+12 -9
View File
@@ -47,23 +47,26 @@ interface RunCodeFlavor {
}
/** Keep tool-call rules here; the runtime owns evaluation syntax and state retention. */
function runCodeFlavor(language: string): RunCodeFlavor {
function runCodeFlavor(language: string, execution = {
programDescription: 'the program to execute',
outputInstruction: 'Curate the program output.',
codeDescription: `The ${language} program to execute, following this tool's execution instructions.`,
}): RunCodeFlavor {
return {
description: `Execute a ${language} program against the available tools. Takes two required arguments: `
+ '`code`, the program to execute, and `description`, a short summary of what the program does. '
+ `\`code\`, ${execution.programDescription}, and \`description\`, a short summary of what the program does. `
+ 'Call tools as `await tools.name(args)` per the declarations in the system prompt. '
+ 'Curate the program output. Image-bearing subtool results are attached after the run.',
codeDescription: `The ${language} program to execute, following this tool's execution instructions.`,
+ `${execution.outputInstruction} Image-bearing subtool results are attached after the run.`,
codeDescription: execution.codeDescription,
}
}
const TYPESCRIPT_FLAVOR = runCodeFlavor('TypeScript')
const TYPESCRIPT_FUNCTION_FLAVOR: RunCodeFlavor = {
description: TYPESCRIPT_FLAVOR.description
.replace('`code`, the program to execute', '`code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work)')
.replace('Curate the program output.', 'Only what you print or return is program output — curate it.'),
const TYPESCRIPT_FUNCTION_FLAVOR = runCodeFlavor('TypeScript', {
programDescription: 'the BODY of an async function (erasable syntax only; top-level `await` and `return` work)',
outputInstruction: 'Only what you print or return is program output — curate it.',
codeDescription: 'The program: the body of an async TypeScript function.',
}
})
const PYTHON_FLAVOR = runCodeFlavor('Python')
/**
+18 -11
View File
@@ -246,19 +246,30 @@ export function jsonSchemaToTs(schema: unknown, indent = 0): string {
}
}
/** The fixed model-facing usage contract rendered above the declarations (see the PTC mode Agent Note's "What the model sees"). */
const SDK_INSTRUCTIONS = `## Writing code for run_code
/** Render the argument and call instructions for the selected execution syntax. */
function renderSdkInstructions(programFormat: 'function-body' | 'repl'): string {
const programDescription = programFormat === 'function-body'
? 'the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped)'
: 'the program to execute'
return `## Writing code for run_code
\`run_code\` takes two required arguments: \`code\`, the program to execute, and \`description\`, a short summary of what the program does. The declarations below are SDK bindings for this program. A declaration does not make its name a directly callable tool; only names supplied as separate tool schemas may be called directly.`
\`run_code\` takes two required arguments: \`code\`, ${programDescription}, and \`description\`, a short summary of what the program does. The declarations below are SDK bindings for this program. A declaration does not make its name a directly callable tool; only names supplied as separate tool schemas may be called directly.`
}
const SDK_PROGRAM_INSTRUCTIONS = `Inside the program:
/** Render tool execution and output instructions for the selected execution syntax. */
function renderSdkProgramInstructions(programFormat: 'function-body' | 'repl'): string {
const outputInstruction = programFormat === 'function-body'
? 'Emit results with `return` and/or `console.log(...)`. Only what you print or return is program output.'
: 'Only values emitted as program output enter the conversation.'
return `Inside the program:
- Call tools as \`await tools.name(args)\` — quoted access for exotic names: \`tools["my-tool"](args)\`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.
- A FAILED tool call rejects with \`ToolCallError\`, whose \`toolName\` identifies the failed tool and whose \`message\` is human-readable — \`try/catch\` it to handle and continue.
- Independent read-only calls MAY overlap under \`Promise.all\` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with \`await\`.
- Only values emitted as program output enter the conversation. A successful tool result containing an image is attached after the run so you can inspect it on the next step; every other intermediate result stays out of the conversation, so extract just what you need.
- ${outputInstruction} A successful tool result containing an image is attached after the run so you can inspect it on the next step; every other intermediate result stays out of the conversation, so extract just what you need.
Program-only SDK bindings:`
}
/** Whether one string schema accepts the literal used by the bash example. */
function acceptsExampleString(schema: JsonSchemaNode | undefined, value: string): boolean {
@@ -317,11 +328,7 @@ export function renderToolsSdk(schemas: ToolSdkSchema[], programFormat: 'functio
['declare const tools: {', ' [K in ToolName]: (args: ToolArgsMap[K]) => Promise<ToolOutputMap[K]>;', '}'].join('\n'),
].join('\n\n')
const jsonValue = 'type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }'
const instructions = programFormat === 'function-body'
? SDK_INSTRUCTIONS.replace('the program to execute', 'the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped)')
: SDK_INSTRUCTIONS
const programInstructions = programFormat === 'function-body'
? SDK_PROGRAM_INSTRUCTIONS.replace('Only values emitted as program output enter the conversation.', 'Emit results with `return` and/or `console.log(...)`. Only what you print or return is program output.')
: SDK_PROGRAM_INSTRUCTIONS
const instructions = renderSdkInstructions(programFormat)
const programInstructions = renderSdkProgramInstructions(programFormat)
return `${instructions}${renderBashExample(sorted, programFormat)}\n\n${programInstructions}\n\n\`\`\`ts\n${jsonValue}\n\n${declaration}\n\`\`\``
}