( runtimeFactory: IJSRuntimeFactory, toolBridge: ToolBridge, emitNestedEvent?: (event: PTCEventWithParent) => void )
| 42 | * @param emitNestedEvent Callback for streaming nested tool events (includes parentToolCallId) |
| 43 | */ |
| 44 | export async function createCodeExecutionTool( |
| 45 | runtimeFactory: IJSRuntimeFactory, |
| 46 | toolBridge: ToolBridge, |
| 47 | emitNestedEvent?: (event: PTCEventWithParent) => void |
| 48 | ): Promise<Tool> { |
| 49 | const bridgeableTools = toolBridge.getBridgeableTools(); |
| 50 | |
| 51 | // Generate mux types for type validation and documentation (cached by tool set hash) |
| 52 | const muxTypes = await getCachedMuxTypes(bridgeableTools); |
| 53 | |
| 54 | return tool({ |
| 55 | description: `Execute sandboxed JavaScript to batch tools and transform outputs. |
| 56 | |
| 57 | **When to use:** Prefer this tool when making 2+ tool calls, especially when later calls depend on earlier results. Reduces round-trip latency. |
| 58 | |
| 59 | **Available tools (TypeScript definitions):** |
| 60 | \`\`\`typescript |
| 61 | ${muxTypes} |
| 62 | \`\`\` |
| 63 | |
| 64 | **Usage notes:** |
| 65 | - \`mux.*\` functions are synchronous—do not use \`await\` |
| 66 | - Use \`return\` to provide a final result to the model |
| 67 | - Use \`console.log/warn/error\` for debugging - output is captured |
| 68 | - Results are JSON-serialized; non-serializable values return \`{ error: "..." }\` |
| 69 | - On failure, partial results (completed tool calls) are returned for debugging |
| 70 | |
| 71 | **Security:** The sandbox has no access to \`require\`, \`import\`, \`process\`, \`fetch\`, or filesystem outside of \`mux.*\` tools.`, |
| 72 | |
| 73 | inputSchema: z.object({ |
| 74 | code: z |
| 75 | .string() |
| 76 | .min(1) |
| 77 | .describe( |
| 78 | "JavaScript code to execute. mux.* calls are synchronous—do not use await. Use 'return' for final result." |
| 79 | ), |
| 80 | timeout_secs: z |
| 81 | .number() |
| 82 | .int() |
| 83 | .positive() |
| 84 | .nullish() |
| 85 | .describe( |
| 86 | "Execution timeout in seconds (default: 300, max: 3600). " + |
| 87 | "Increase when spawning subagents that may take 5-15+ minutes." |
| 88 | ), |
| 89 | }), |
| 90 | |
| 91 | execute: async ( |
| 92 | { code, timeout_secs }, |
| 93 | { abortSignal, toolCallId } |
| 94 | ): Promise<PTCExecutionResult> => { |
| 95 | const execStartTime = Date.now(); |
| 96 | |
| 97 | // Static analysis before execution - catch syntax errors and sandbox-forbidden patterns. |
| 98 | // TypeScript typing issues are intentionally non-blocking for one-off runtime scripts. |
| 99 | const analysis = await analyzeCode(code); |
| 100 | if (!analysis.valid) { |
| 101 | const errorMessages = analysis.errors.map((e) => { |
no test coverage detected