fix(ptc): describe fresh Script failures without retained state

This commit is contained in:
_Kerman committed 2026-10-21 19:51:52 +08:00
1 parent 09c7036e05
commit 67911ed176
3 files changed
+5 -2

No files matched your search

@@ -165,13 +165,15 @@ function resolveMode(config: ResolvedConfig): ExecutionMode {
const lifetime = config.scriptPersistence
? 'Variables, functions, and imported modules remain in memory for this Agent across calls.'
: 'Each call runs in a fresh Node process.'
const asynchronousFailure = 'Await asynchronous work: an uncaught callback exception or unhandled rejection terminates the process'
+ (config.scriptPersistence ? ' and clears its variables.' : '.')
const recovery = config.scriptPersistence
? ' ' + RETAINED_STATE_INSTRUCTIONS + ' If a native top-level let, const, or class initializer throws, its name may remain permanently uninitialized; use a new name or restart the environment.'
: ''
return {
format: 'script',
retainsState: config.scriptPersistence,
executionInstructions: 'The program contains TypeScript script statements; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level declarations and await are supported; top-level return is not supported. Emit output with console.log(...) or a final lossless JSON expression. The final expression is awaited if it is a Promise. Only printed values and that final expression become program output. ' + lifetime + ' Use await import(...) for modules. Relative paths use the supplied working directory. Direct filesystem access follows this execution\'s sandbox policy; process.env starts empty. Await asynchronous work: an uncaught callback exception or unhandled rejection terminates the process and clears its variables. Values from bindings and imports can belong to another realm; use Array.isArray for arrays and the supplied binding error classes for failures, because instanceof Array or Error may be false.' + recovery,
executionInstructions: 'The program contains TypeScript script statements; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level declarations and await are supported; top-level return is not supported. Emit output with console.log(...) or a final lossless JSON expression. The final expression is awaited if it is a Promise. Only printed values and that final expression become program output. ' + lifetime + ' Use await import(...) for modules. Relative paths use the supplied working directory. Direct filesystem access follows this execution\'s sandbox policy; process.env starts empty. ' + asynchronousFailure + ' Values from bindings and imports can belong to another realm; use Array.isArray for arrays and the supplied binding error classes for failures, because instanceof Array or Error may be false.' + recovery,
stripTypes: stripTypeScriptTypes,
}
}
@@ -64,6 +64,7 @@ it.each([false, true])('advertises Script syntax and its selected retention %s',
expect(runtime.executionInstructions).toContain('The final expression is awaited if it is a Promise')
expect(runtime.executionInstructions).toContain('uncaught callback exception or unhandled rejection terminates the process')
expect(runtime.executionInstructions).toContain('instanceof Array or Error may be false')
expect(runtime.executionInstructions.includes('clears its variables')).toBe(scriptPersistence)
expect(runtime.executionInstructions.includes('permanently uninitialized')).toBe(scriptPersistence)
expect(runtime.executionInstructions.includes('Each call runs in a fresh Node process')).toBe(!scriptPersistence)
const stateOwner = {}
@@ -2,7 +2,7 @@
"initial": [
{
"name": "run_code",
"description": "Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the program to execute, 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. The program contains TypeScript script statements; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level declarations and await are supported; top-level return is not supported. Emit output with console.log(...) or a final lossless JSON expression. The final expression is awaited if it is a Promise. Only printed values and that final expression become program output. Each call runs in a fresh Node process. Use await import(...) for modules. Relative paths use the supplied working directory. Direct filesystem access follows this execution's sandbox policy; process.env starts empty. Await asynchronous work: an uncaught callback exception or unhandled rejection terminates the process and clears its variables. Values from bindings and imports can belong to another realm; use Array.isArray for arrays and the supplied binding error classes for failures, because instanceof Array or Error may be false. Each program starts in the Session's current directory. Running programs keep their initial directory. A sandbox escalation approves this complete program for one execution only. Nested tools retain their own policies and approvals. Request wider access only after evidence of a denial. Earlier effects may already have completed: inspect them before explicitly retrying. Programs are never replayed automatically.",
"description": "Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the program to execute, 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. The program contains TypeScript script statements; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level declarations and await are supported; top-level return is not supported. Emit output with console.log(...) or a final lossless JSON expression. The final expression is awaited if it is a Promise. Only printed values and that final expression become program output. Each call runs in a fresh Node process. Use await import(...) for modules. Relative paths use the supplied working directory. Direct filesystem access follows this execution's sandbox policy; process.env starts empty. Await asynchronous work: an uncaught callback exception or unhandled rejection terminates the process. Values from bindings and imports can belong to another realm; use Array.isArray for arrays and the supplied binding error classes for failures, because instanceof Array or Error may be false. Each program starts in the Session's current directory. Running programs keep their initial directory. A sandbox escalation approves this complete program for one execution only. Nested tools retain their own policies and approvals. Request wider access only after evidence of a denial. Earlier effects may already have completed: inspect them before explicitly retrying. Programs are never replayed automatically.",
"parameters": {
"type": "object",
"properties": {