@librechat/agents 3.1.89 → 3.1.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +7 -0
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hooks/executeHooks.cjs +14 -7
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs +8 -2
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +34 -0
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/main.cjs +9 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +10 -9
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +12 -8
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +35 -11
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/CodeSessionFileSummary.cjs +63 -0
- package/dist/cjs/tools/CodeSessionFileSummary.cjs.map +1 -0
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +16 -12
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +8 -5
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +319 -29
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +7 -0
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hooks/executeHooks.mjs +14 -7
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +9 -3
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +33 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/main.mjs +2 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +11 -10
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +13 -9
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +29 -12
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/CodeSessionFileSummary.mjs +60 -0
- package/dist/esm/tools/CodeSessionFileSummary.mjs.map +1 -0
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +17 -13
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +8 -5
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +320 -31
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/types/llm/anthropic/index.d.ts +3 -1
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +4 -0
- package/dist/types/tools/BashExecutor.d.ts +3 -3
- package/dist/types/tools/CodeExecutor.d.ts +10 -3
- package/dist/types/tools/CodeSessionFileSummary.d.ts +3 -0
- package/dist/types/tools/ProgrammaticToolCalling.d.ts +4 -4
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +8 -5
- package/dist/types/types/tools.d.ts +2 -3
- package/package.json +1 -1
- package/src/graphs/Graph.ts +7 -0
- package/src/hooks/__tests__/executeHooks.test.ts +38 -0
- package/src/hooks/executeHooks.ts +27 -7
- package/src/llm/anthropic/index.ts +27 -3
- package/src/llm/anthropic/llm.spec.ts +60 -1
- package/src/llm/anthropic/utils/message_inputs.ts +46 -0
- package/src/tools/BashExecutor.ts +21 -10
- package/src/tools/BashProgrammaticToolCalling.ts +21 -9
- package/src/tools/CodeExecutor.ts +55 -12
- package/src/tools/CodeSessionFileSummary.ts +80 -0
- package/src/tools/ProgrammaticToolCalling.ts +25 -12
- package/src/tools/ToolNode.ts +8 -5
- package/src/tools/__tests__/BashExecutor.test.ts +9 -0
- package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +43 -0
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +100 -16
- package/src/tools/__tests__/SubagentExecutor.test.ts +540 -6
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +52 -0
- package/src/tools/__tests__/subagentHooks.test.ts +237 -0
- package/src/tools/subagent/SubagentExecutor.ts +514 -36
- package/src/types/tools.ts +2 -3
|
@@ -5,12 +5,32 @@ var fetch = require('node-fetch');
|
|
|
5
5
|
var httpsProxyAgent = require('https-proxy-agent');
|
|
6
6
|
var tools = require('@langchain/core/tools');
|
|
7
7
|
var env = require('@langchain/core/utils/env');
|
|
8
|
+
var CodeSessionFileSummary = require('./CodeSessionFileSummary.cjs');
|
|
8
9
|
var _enum = require('../common/enum.cjs');
|
|
9
10
|
|
|
10
11
|
dotenv.config();
|
|
11
12
|
const getCodeBaseURL = () => env.getEnvironmentVariable(_enum.EnvVar.CODE_BASEURL) ??
|
|
12
13
|
_enum.Constants.OFFICIAL_CODE_BASEURL;
|
|
13
14
|
const emptyOutputMessage = 'stdout: Empty. Ensure you\'re writing output explicitly.\n';
|
|
15
|
+
const CODE_ARTIFACT_PATH_GUIDANCE = 'Persist handoff artifacts in `/mnt/data` with standard extensions (.json/.txt/.csv/.tsv/.log/.parquet/.png/.jpg/.pdf/.xlsx); failed executions do not register new files; `/tmp` and odd extensions are same-call scratch only, not later-call storage.';
|
|
16
|
+
const BASH_SHELL_GUIDANCE = 'Bash: multi-line files use heredoc/printf; run Python via python3 -c/heredoc, not bare Python.';
|
|
17
|
+
const TMP_PATH_PATTERN = /(^|[^A-Za-z0-9_])\/tmp(?:\/|\b)/;
|
|
18
|
+
const MNT_DATA_PATH_PATTERN = /(^|[^A-Za-z0-9_])\/mnt\/data(?:\/|\b)/;
|
|
19
|
+
const TMP_SCRATCH_OUTPUT_REMINDER = 'Note: /tmp files are same-call scratch only and were not persisted; use /mnt/data for files needed later.';
|
|
20
|
+
const FAILED_EXECUTION_FILE_REMINDER = 'Note: any files written during this failed call were not registered for later calls; fix the error and rerun before relying on them.';
|
|
21
|
+
function appendTmpScratchReminder(output, code) {
|
|
22
|
+
if (!TMP_PATH_PATTERN.test(code)) {
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
25
|
+
return `${output.trimEnd()}\n${TMP_SCRATCH_OUTPUT_REMINDER}\n`;
|
|
26
|
+
}
|
|
27
|
+
function appendFailedExecutionFileReminder(output, code) {
|
|
28
|
+
if (!MNT_DATA_PATH_PATTERN.test(code) ||
|
|
29
|
+
output.includes(FAILED_EXECUTION_FILE_REMINDER)) {
|
|
30
|
+
return output;
|
|
31
|
+
}
|
|
32
|
+
return `${output.trimEnd()}\n${FAILED_EXECUTION_FILE_REMINDER}\n`;
|
|
33
|
+
}
|
|
14
34
|
const SUPPORTED_LANGUAGES = [
|
|
15
35
|
'py',
|
|
16
36
|
'js',
|
|
@@ -38,8 +58,8 @@ const CodeExecutionToolSchema = {
|
|
|
38
58
|
type: 'string',
|
|
39
59
|
description: `The complete, self-contained code to execute, without any truncation or minimization.
|
|
40
60
|
- The environment is stateless; variables and imports don't persist between executions.
|
|
41
|
-
-
|
|
42
|
-
-
|
|
61
|
+
- Prior /mnt/data files are available and can be modified in place.
|
|
62
|
+
- ${CODE_ARTIFACT_PATH_GUIDANCE}
|
|
43
63
|
- Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.
|
|
44
64
|
- Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.
|
|
45
65
|
- IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.
|
|
@@ -86,6 +106,7 @@ Runs code and returns stdout/stderr output from a stateless execution environmen
|
|
|
86
106
|
Usage:
|
|
87
107
|
- No network access available.
|
|
88
108
|
- Generated files are automatically delivered; **DO NOT** provide download links.
|
|
109
|
+
- ${CODE_ARTIFACT_PATH_GUIDANCE}
|
|
89
110
|
- NEVER use this tool to execute malicious code.
|
|
90
111
|
`.trim();
|
|
91
112
|
const CodeExecutionToolName = _enum.Constants.EXECUTE_CODE;
|
|
@@ -145,13 +166,6 @@ function createCodeExecutionTool(params = {}) {
|
|
|
145
166
|
throw new Error(await buildCodeApiHttpErrorMessage('POST', EXEC_ENDPOINT, response));
|
|
146
167
|
}
|
|
147
168
|
const result = await response.json();
|
|
148
|
-
/* Output is stdout/stderr only — file listings were removed
|
|
149
|
-
* because the LLM-facing summary (split inherited/generated
|
|
150
|
-
* with prescriptive notes) caused more confusion than help,
|
|
151
|
-
* especially for bash where models naturally explore
|
|
152
|
-
* `/mnt/data/` themselves. The artifact still carries every
|
|
153
|
-
* file so the host's session map stays in sync; the LLM
|
|
154
|
-
* doesn't see them in the tool result text. */
|
|
155
169
|
let formattedOutput = '';
|
|
156
170
|
if (result.stdout) {
|
|
157
171
|
formattedOutput += `stdout:\n${result.stdout}\n`;
|
|
@@ -161,9 +175,10 @@ function createCodeExecutionTool(params = {}) {
|
|
|
161
175
|
}
|
|
162
176
|
if (result.stderr)
|
|
163
177
|
formattedOutput += `stderr:\n${result.stderr}\n`;
|
|
178
|
+
const outputWithReminder = appendTmpScratchReminder(formattedOutput, code);
|
|
164
179
|
const hasFiles = result.files != null && result.files.length > 0;
|
|
165
180
|
return [
|
|
166
|
-
|
|
181
|
+
CodeSessionFileSummary.appendCodeSessionFileSummary(outputWithReminder, result.files),
|
|
167
182
|
(hasFiles
|
|
168
183
|
? { session_id: result.session_id, files: result.files }
|
|
169
184
|
: {
|
|
@@ -172,7 +187,8 @@ function createCodeExecutionTool(params = {}) {
|
|
|
172
187
|
];
|
|
173
188
|
}
|
|
174
189
|
catch (error) {
|
|
175
|
-
|
|
190
|
+
const messageWithReminder = appendFailedExecutionFileReminder(error?.message ?? '', code);
|
|
191
|
+
throw new Error(`Execution error:\n\n${messageWithReminder}`);
|
|
176
192
|
}
|
|
177
193
|
}, {
|
|
178
194
|
name: CodeExecutionToolName,
|
|
@@ -182,10 +198,18 @@ function createCodeExecutionTool(params = {}) {
|
|
|
182
198
|
});
|
|
183
199
|
}
|
|
184
200
|
|
|
201
|
+
exports.appendCodeSessionFileSummary = CodeSessionFileSummary.appendCodeSessionFileSummary;
|
|
202
|
+
exports.stripCodeSessionFileSummary = CodeSessionFileSummary.stripCodeSessionFileSummary;
|
|
203
|
+
exports.BASH_SHELL_GUIDANCE = BASH_SHELL_GUIDANCE;
|
|
204
|
+
exports.CODE_ARTIFACT_PATH_GUIDANCE = CODE_ARTIFACT_PATH_GUIDANCE;
|
|
185
205
|
exports.CodeExecutionToolDefinition = CodeExecutionToolDefinition;
|
|
186
206
|
exports.CodeExecutionToolDescription = CodeExecutionToolDescription;
|
|
187
207
|
exports.CodeExecutionToolName = CodeExecutionToolName;
|
|
188
208
|
exports.CodeExecutionToolSchema = CodeExecutionToolSchema;
|
|
209
|
+
exports.FAILED_EXECUTION_FILE_REMINDER = FAILED_EXECUTION_FILE_REMINDER;
|
|
210
|
+
exports.TMP_SCRATCH_OUTPUT_REMINDER = TMP_SCRATCH_OUTPUT_REMINDER;
|
|
211
|
+
exports.appendFailedExecutionFileReminder = appendFailedExecutionFileReminder;
|
|
212
|
+
exports.appendTmpScratchReminder = appendTmpScratchReminder;
|
|
189
213
|
exports.buildCodeApiHttpErrorMessage = buildCodeApiHttpErrorMessage;
|
|
190
214
|
exports.createCodeExecutionTool = createCodeExecutionTool;
|
|
191
215
|
exports.emptyOutputMessage = emptyOutputMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeExecutor.cjs","sources":["../../../src/tools/CodeExecutor.ts"],"sourcesContent":["import { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport type * as t from '@/types';\nimport { EnvVar, Constants } from '@/common';\n\nconfig();\n\nexport const getCodeBaseURL = (): string =>\n getEnvironmentVariable(EnvVar.CODE_BASEURL) ??\n Constants.OFFICIAL_CODE_BASEURL;\n\nexport const emptyOutputMessage =\n 'stdout: Empty. Ensure you\\'re writing output explicitly.\\n';\n\nconst SUPPORTED_LANGUAGES = [\n 'py',\n 'js',\n 'ts',\n 'c',\n 'cpp',\n 'java',\n 'php',\n 'rs',\n 'go',\n 'd',\n 'f90',\n 'r',\n 'bash',\n] as const;\n\nexport const CodeExecutionToolSchema = {\n type: 'object',\n properties: {\n lang: {\n type: 'string',\n enum: SUPPORTED_LANGUAGES,\n description:\n 'The programming language or runtime to execute the code in.',\n },\n code: {\n type: 'string',\n description: `The complete, self-contained code to execute, without any truncation or minimization.\n- The environment is stateless; variables and imports don't persist between executions.\n- Generated files from previous executions are automatically available in \"/mnt/data/\".\n- Files from previous executions are automatically available and can be modified in place.\n- Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.\n- Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.\n- IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.\n- py: This is not a Jupyter notebook environment. Use \\`print()\\` for all outputs.\n- py: Matplotlib: Use \\`plt.savefig()\\` to save plots as files.\n- js: use the \\`console\\` or \\`process\\` methods for all outputs.\n- r: IMPORTANT: No X11 display available. ALL graphics MUST use Cairo library (library(Cairo)).\n- Other languages: use appropriate output functions.`,\n },\n args: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Additional arguments to execute the code with. This should only be used if the input code requires additional arguments to run.',\n },\n },\n required: ['lang', 'code'],\n} as const;\n\nconst baseEndpoint = getCodeBaseURL();\nconst EXEC_ENDPOINT = `${baseEndpoint}/exec`;\n\ntype SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];\n\nexport async function resolveCodeApiAuthHeaders(\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeApiAuthHeaderMap> {\n if (authHeaders == null) {\n return {};\n }\n if (typeof authHeaders === 'function') {\n return authHeaders();\n }\n return authHeaders;\n}\n\nexport async function buildCodeApiHttpErrorMessage(\n method: string,\n endpoint: string,\n response: { status: number; text: () => Promise<string> }\n): Promise<string> {\n let responseBody = '';\n try {\n responseBody = await response.text();\n } catch {\n responseBody = '';\n }\n const body = responseBody.trim();\n const bodySuffix = body === '' ? '' : `, body: ${body.slice(0, 1000)}`;\n return `CodeAPI request failed: ${method} ${endpoint} returned ${response.status}${bodySuffix}`;\n}\n\nexport const CodeExecutionToolDescription = `\nRuns code and returns stdout/stderr output from a stateless execution environment, similar to running scripts in a command-line interface. Each execution is isolated and independent.\n\nUsage:\n- No network access available.\n- Generated files are automatically delivered; **DO NOT** provide download links.\n- NEVER use this tool to execute malicious code.\n`.trim();\n\nexport const CodeExecutionToolName = Constants.EXECUTE_CODE;\n\nexport const CodeExecutionToolDefinition = {\n name: CodeExecutionToolName,\n description: CodeExecutionToolDescription,\n schema: CodeExecutionToolSchema,\n} as const;\n\nfunction createCodeExecutionTool(\n params: t.CodeExecutionToolParams = {}\n): DynamicStructuredTool {\n return tool(\n async (rawInput, config) => {\n const { authHeaders, ...executionParams } = params ?? {};\n const { lang, code, ...rest } = rawInput as {\n lang: SupportedLanguage;\n code: string;\n args?: string[];\n };\n /**\n * Extract session context from config.toolCall (injected by ToolNode).\n * - session_id: associates with the previous run.\n * - _injected_files: File refs to pass directly (avoids /files endpoint race condition).\n */\n const { session_id, _injected_files } = (config.toolCall ?? {}) as {\n session_id?: string;\n _injected_files?: t.CodeEnvFile[];\n };\n\n const postData: Record<string, unknown> = {\n lang,\n code,\n ...rest,\n ...executionParams,\n };\n\n /* File injection: `_injected_files` from ToolNode (set when host\n * primes a CodeSessionContext) or `params.files` from tool\n * factory (set by hosts that pre-resolve at construction time).\n * The legacy `/files/<session_id>` HTTP fallback was removed —\n * codeapi's `sessionAuth` middleware now requires kind/id query\n * params the tool can't supply at this point, so the fetch 400'd\n * silently and the catch swallowed the failure. */\n if (_injected_files && _injected_files.length > 0) {\n postData.files = _injected_files;\n } else if (\n session_id != null &&\n session_id.length > 0 &&\n !Array.isArray(postData.files)\n ) {\n // eslint-disable-next-line no-console\n console.debug(\n `[CodeExecutor] No injected files for session_id=${session_id} — exec will run without input files`\n );\n }\n\n try {\n const resolvedAuthHeaders =\n await resolveCodeApiAuthHeaders(authHeaders);\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'LibreChat/1.0',\n ...resolvedAuthHeaders,\n },\n body: JSON.stringify(postData),\n };\n\n if (process.env.PROXY != null && process.env.PROXY !== '') {\n fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n }\n const response = await fetch(EXEC_ENDPOINT, fetchOptions);\n if (!response.ok) {\n throw new Error(\n await buildCodeApiHttpErrorMessage('POST', EXEC_ENDPOINT, response)\n );\n }\n\n const result: t.ExecuteResult = await response.json();\n /* Output is stdout/stderr only — file listings were removed\n * because the LLM-facing summary (split inherited/generated\n * with prescriptive notes) caused more confusion than help,\n * especially for bash where models naturally explore\n * `/mnt/data/` themselves. The artifact still carries every\n * file so the host's session map stays in sync; the LLM\n * doesn't see them in the tool result text. */\n let formattedOutput = '';\n if (result.stdout) {\n formattedOutput += `stdout:\\n${result.stdout}\\n`;\n } else {\n formattedOutput += emptyOutputMessage;\n }\n if (result.stderr) formattedOutput += `stderr:\\n${result.stderr}\\n`;\n\n const hasFiles = result.files != null && result.files.length > 0;\n return [\n formattedOutput.trim(),\n (hasFiles\n ? { session_id: result.session_id, files: result.files }\n : {\n session_id: result.session_id,\n }) satisfies t.CodeExecutionArtifact,\n ];\n } catch (error) {\n throw new Error(\n `Execution error:\\n\\n${(error as Error | undefined)?.message}`\n );\n }\n },\n {\n name: CodeExecutionToolName,\n description: CodeExecutionToolDescription,\n schema: CodeExecutionToolSchema,\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n\nexport { createCodeExecutionTool };\n"],"names":["config","getEnvironmentVariable","EnvVar","Constants","tool","HttpsProxyAgent"],"mappings":";;;;;;;;;AAQAA,aAAM,EAAE;AAED,MAAM,cAAc,GAAG,MAC5BC,0BAAsB,CAACC,YAAM,CAAC,YAAY,CAAC;IAC3CC,eAAS,CAAC;AAEL,MAAM,kBAAkB,GAC7B;AAEF,MAAM,mBAAmB,GAAG;IAC1B,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,GAAG;IACH,KAAK;IACL,MAAM;IACN,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,GAAG;IACH,KAAK;IACL,GAAG;IACH,MAAM;CACE;AAEH,MAAM,uBAAuB,GAAG;AACrC,IAAA,IAAI,EAAE,QAAQ;AACd,IAAA,UAAU,EAAE;AACV,QAAA,IAAI,EAAE;AACJ,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,IAAI,EAAE,mBAAmB;AACzB,YAAA,WAAW,EACT,6DAA6D;AAChE,SAAA;AACD,QAAA,IAAI,EAAE;AACJ,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,WAAW,EAAE,CAAA;;;;;;;;;;;AAWkC,oDAAA,CAAA;AAChD,SAAA;AACD,QAAA,IAAI,EAAE;AACJ,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AACzB,YAAA,WAAW,EACT,iIAAiI;AACpI,SAAA;AACF,KAAA;AACD,IAAA,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;;AAG5B,MAAM,YAAY,GAAG,cAAc,EAAE;AACrC,MAAM,aAAa,GAAG,CAAA,EAAG,YAAY,OAAO;AAIrC,eAAe,yBAAyB,CAC7C,WAAkC,EAAA;AAElC,IAAA,IAAI,WAAW,IAAI,IAAI,EAAE;AACvB,QAAA,OAAO,EAAE;IACX;AACA,IAAA,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE;QACrC,OAAO,WAAW,EAAE;IACtB;AACA,IAAA,OAAO,WAAW;AACpB;AAEO,eAAe,4BAA4B,CAChD,MAAc,EACd,QAAgB,EAChB,QAAyD,EAAA;IAEzD,IAAI,YAAY,GAAG,EAAE;AACrB,IAAA,IAAI;AACF,QAAA,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;IACtC;AAAE,IAAA,MAAM;QACN,YAAY,GAAG,EAAE;IACnB;AACA,IAAA,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE;IAChC,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,GAAG,EAAE,GAAG,CAAA,QAAA,EAAW,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA,CAAE;IACtE,OAAO,CAAA,wBAAA,EAA2B,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAA,UAAA,EAAa,QAAQ,CAAC,MAAM,CAAA,EAAG,UAAU,CAAA,CAAE;AACjG;AAEO,MAAM,4BAA4B,GAAG;;;;;;;CAO3C,CAAC,IAAI;AAEC,MAAM,qBAAqB,GAAGA,eAAS,CAAC;AAExC,MAAM,2BAA2B,GAAG;AACzC,IAAA,IAAI,EAAE,qBAAqB;AAC3B,IAAA,WAAW,EAAE,4BAA4B;AACzC,IAAA,MAAM,EAAE,uBAAuB;;AAGjC,SAAS,uBAAuB,CAC9B,MAAA,GAAoC,EAAE,EAAA;IAEtC,OAAOC,UAAI,CACT,OAAO,QAAQ,EAAE,MAAM,KAAI;QACzB,MAAM,EAAE,WAAW,EAAE,GAAG,eAAe,EAAE,GAAG,MAAM,IAAI,EAAE;QACxD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAI/B;AACD;;;;AAIG;AACH,QAAA,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,CAG7D;AAED,QAAA,MAAM,QAAQ,GAA4B;YACxC,IAAI;YACJ,IAAI;AACJ,YAAA,GAAG,IAAI;AACP,YAAA,GAAG,eAAe;SACnB;AAED;;;;;;AAMmD;QACnD,IAAI,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE;AACjD,YAAA,QAAQ,CAAC,KAAK,GAAG,eAAe;QAClC;aAAO,IACL,UAAU,IAAI,IAAI;YAClB,UAAU,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAC9B;;AAEA,YAAA,OAAO,CAAC,KAAK,CACX,mDAAmD,UAAU,CAAA,oCAAA,CAAsC,CACpG;QACH;AAEA,QAAA,IAAI;AACF,YAAA,MAAM,mBAAmB,GACvB,MAAM,yBAAyB,CAAC,WAAW,CAAC;AAC9C,YAAA,MAAM,YAAY,GAAgB;AAChC,gBAAA,MAAM,EAAE,MAAM;AACd,gBAAA,OAAO,EAAE;AACP,oBAAA,cAAc,EAAE,kBAAkB;AAClC,oBAAA,YAAY,EAAE,eAAe;AAC7B,oBAAA,GAAG,mBAAmB;AACvB,iBAAA;AACD,gBAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC/B;AAED,YAAA,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,EAAE;AACzD,gBAAA,YAAY,CAAC,KAAK,GAAG,IAAIC,+BAAe,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAC7D;YACA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC;AACzD,YAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,gBAAA,MAAM,IAAI,KAAK,CACb,MAAM,4BAA4B,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,CACpE;YACH;AAEA,YAAA,MAAM,MAAM,GAAoB,MAAM,QAAQ,CAAC,IAAI,EAAE;AACrD;;;;;;AAM+C;YAC/C,IAAI,eAAe,GAAG,EAAE;AACxB,YAAA,IAAI,MAAM,CAAC,MAAM,EAAE;AACjB,gBAAA,eAAe,IAAI,CAAA,SAAA,EAAY,MAAM,CAAC,MAAM,IAAI;YAClD;iBAAO;gBACL,eAAe,IAAI,kBAAkB;YACvC;YACA,IAAI,MAAM,CAAC,MAAM;AAAE,gBAAA,eAAe,IAAI,CAAA,SAAA,EAAY,MAAM,CAAC,MAAM,IAAI;AAEnE,YAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAChE,OAAO;gBACL,eAAe,CAAC,IAAI,EAAE;AACtB,iBAAC;AACC,sBAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK;AACtD,sBAAE;wBACA,UAAU,EAAE,MAAM,CAAC,UAAU;qBAC9B;aACJ;QACH;QAAE,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,KAAK,CACb,CAAA,oBAAA,EAAwB,KAA2B,EAAE,OAAO,CAAA,CAAE,CAC/D;QACH;AACF,IAAA,CAAC,EACD;AACE,QAAA,IAAI,EAAE,qBAAqB;AAC3B,QAAA,WAAW,EAAE,4BAA4B;AACzC,QAAA,MAAM,EAAE,uBAAuB;QAC/B,cAAc,EAAEF,eAAS,CAAC,oBAAoB;AAC/C,KAAA,CACF;AACH;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"CodeExecutor.cjs","sources":["../../../src/tools/CodeExecutor.ts"],"sourcesContent":["import { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport type * as t from '@/types';\nimport { appendCodeSessionFileSummary } from '@/tools/CodeSessionFileSummary';\nimport { EnvVar, Constants } from '@/common';\n\nexport {\n appendCodeSessionFileSummary,\n stripCodeSessionFileSummary,\n} from '@/tools/CodeSessionFileSummary';\n\nconfig();\n\nexport const getCodeBaseURL = (): string =>\n getEnvironmentVariable(EnvVar.CODE_BASEURL) ??\n Constants.OFFICIAL_CODE_BASEURL;\n\nexport const emptyOutputMessage =\n 'stdout: Empty. Ensure you\\'re writing output explicitly.\\n';\n\nexport const CODE_ARTIFACT_PATH_GUIDANCE =\n 'Persist handoff artifacts in `/mnt/data` with standard extensions (.json/.txt/.csv/.tsv/.log/.parquet/.png/.jpg/.pdf/.xlsx); failed executions do not register new files; `/tmp` and odd extensions are same-call scratch only, not later-call storage.';\n\nexport const BASH_SHELL_GUIDANCE =\n 'Bash: multi-line files use heredoc/printf; run Python via python3 -c/heredoc, not bare Python.';\n\nconst TMP_PATH_PATTERN = /(^|[^A-Za-z0-9_])\\/tmp(?:\\/|\\b)/;\nconst MNT_DATA_PATH_PATTERN = /(^|[^A-Za-z0-9_])\\/mnt\\/data(?:\\/|\\b)/;\n\nexport const TMP_SCRATCH_OUTPUT_REMINDER =\n 'Note: /tmp files are same-call scratch only and were not persisted; use /mnt/data for files needed later.';\n\nexport const FAILED_EXECUTION_FILE_REMINDER =\n 'Note: any files written during this failed call were not registered for later calls; fix the error and rerun before relying on them.';\n\nexport function appendTmpScratchReminder(output: string, code: string): string {\n if (!TMP_PATH_PATTERN.test(code)) {\n return output;\n }\n return `${output.trimEnd()}\\n${TMP_SCRATCH_OUTPUT_REMINDER}\\n`;\n}\n\nexport function appendFailedExecutionFileReminder(\n output: string,\n code: string\n): string {\n if (\n !MNT_DATA_PATH_PATTERN.test(code) ||\n output.includes(FAILED_EXECUTION_FILE_REMINDER)\n ) {\n return output;\n }\n return `${output.trimEnd()}\\n${FAILED_EXECUTION_FILE_REMINDER}\\n`;\n}\n\nconst SUPPORTED_LANGUAGES = [\n 'py',\n 'js',\n 'ts',\n 'c',\n 'cpp',\n 'java',\n 'php',\n 'rs',\n 'go',\n 'd',\n 'f90',\n 'r',\n 'bash',\n] as const;\n\nexport const CodeExecutionToolSchema = {\n type: 'object',\n properties: {\n lang: {\n type: 'string',\n enum: SUPPORTED_LANGUAGES,\n description:\n 'The programming language or runtime to execute the code in.',\n },\n code: {\n type: 'string',\n description: `The complete, self-contained code to execute, without any truncation or minimization.\n- The environment is stateless; variables and imports don't persist between executions.\n- Prior /mnt/data files are available and can be modified in place.\n- ${CODE_ARTIFACT_PATH_GUIDANCE}\n- Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.\n- Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.\n- IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.\n- py: This is not a Jupyter notebook environment. Use \\`print()\\` for all outputs.\n- py: Matplotlib: Use \\`plt.savefig()\\` to save plots as files.\n- js: use the \\`console\\` or \\`process\\` methods for all outputs.\n- r: IMPORTANT: No X11 display available. ALL graphics MUST use Cairo library (library(Cairo)).\n- Other languages: use appropriate output functions.`,\n },\n args: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Additional arguments to execute the code with. This should only be used if the input code requires additional arguments to run.',\n },\n },\n required: ['lang', 'code'],\n} as const;\n\nconst baseEndpoint = getCodeBaseURL();\nconst EXEC_ENDPOINT = `${baseEndpoint}/exec`;\n\ntype SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];\n\nexport async function resolveCodeApiAuthHeaders(\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeApiAuthHeaderMap> {\n if (authHeaders == null) {\n return {};\n }\n if (typeof authHeaders === 'function') {\n return authHeaders();\n }\n return authHeaders;\n}\n\nexport async function buildCodeApiHttpErrorMessage(\n method: string,\n endpoint: string,\n response: { status: number; text: () => Promise<string> }\n): Promise<string> {\n let responseBody = '';\n try {\n responseBody = await response.text();\n } catch {\n responseBody = '';\n }\n const body = responseBody.trim();\n const bodySuffix = body === '' ? '' : `, body: ${body.slice(0, 1000)}`;\n return `CodeAPI request failed: ${method} ${endpoint} returned ${response.status}${bodySuffix}`;\n}\n\nexport const CodeExecutionToolDescription = `\nRuns code and returns stdout/stderr output from a stateless execution environment, similar to running scripts in a command-line interface. Each execution is isolated and independent.\n\nUsage:\n- No network access available.\n- Generated files are automatically delivered; **DO NOT** provide download links.\n- ${CODE_ARTIFACT_PATH_GUIDANCE}\n- NEVER use this tool to execute malicious code.\n`.trim();\n\nexport const CodeExecutionToolName = Constants.EXECUTE_CODE;\n\nexport const CodeExecutionToolDefinition = {\n name: CodeExecutionToolName,\n description: CodeExecutionToolDescription,\n schema: CodeExecutionToolSchema,\n} as const;\n\nfunction createCodeExecutionTool(\n params: t.CodeExecutionToolParams | null = {}\n): DynamicStructuredTool {\n return tool(\n async (rawInput, config) => {\n const { authHeaders, ...executionParams } = params ?? {};\n const { lang, code, ...rest } = rawInput as {\n lang: SupportedLanguage;\n code: string;\n args?: string[];\n };\n /**\n * Extract session context from config.toolCall (injected by ToolNode).\n * - session_id: associates with the previous run.\n * - _injected_files: File refs to pass directly (avoids /files endpoint race condition).\n */\n const { session_id, _injected_files } = (config.toolCall ?? {}) as {\n session_id?: string;\n _injected_files?: t.CodeEnvFile[];\n };\n\n const postData: Record<string, unknown> = {\n lang,\n code,\n ...rest,\n ...executionParams,\n };\n\n /* File injection: `_injected_files` from ToolNode (set when host\n * primes a CodeSessionContext) or `params.files` from tool\n * factory (set by hosts that pre-resolve at construction time).\n * The legacy `/files/<session_id>` HTTP fallback was removed —\n * codeapi's `sessionAuth` middleware now requires kind/id query\n * params the tool can't supply at this point, so the fetch 400'd\n * silently and the catch swallowed the failure. */\n if (_injected_files && _injected_files.length > 0) {\n postData.files = _injected_files;\n } else if (\n session_id != null &&\n session_id.length > 0 &&\n !Array.isArray(postData.files)\n ) {\n // eslint-disable-next-line no-console\n console.debug(\n `[CodeExecutor] No injected files for session_id=${session_id} — exec will run without input files`\n );\n }\n\n try {\n const resolvedAuthHeaders =\n await resolveCodeApiAuthHeaders(authHeaders);\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'LibreChat/1.0',\n ...resolvedAuthHeaders,\n },\n body: JSON.stringify(postData),\n };\n\n if (process.env.PROXY != null && process.env.PROXY !== '') {\n fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n }\n const response = await fetch(EXEC_ENDPOINT, fetchOptions);\n if (!response.ok) {\n throw new Error(\n await buildCodeApiHttpErrorMessage('POST', EXEC_ENDPOINT, response)\n );\n }\n\n const result: t.ExecuteResult = await response.json();\n let formattedOutput = '';\n if (result.stdout) {\n formattedOutput += `stdout:\\n${result.stdout}\\n`;\n } else {\n formattedOutput += emptyOutputMessage;\n }\n if (result.stderr) formattedOutput += `stderr:\\n${result.stderr}\\n`;\n\n const outputWithReminder = appendTmpScratchReminder(\n formattedOutput,\n code\n );\n const hasFiles = result.files != null && result.files.length > 0;\n return [\n appendCodeSessionFileSummary(outputWithReminder, result.files),\n (hasFiles\n ? { session_id: result.session_id, files: result.files }\n : {\n session_id: result.session_id,\n }) satisfies t.CodeExecutionArtifact,\n ];\n } catch (error) {\n const messageWithReminder = appendFailedExecutionFileReminder(\n (error as Error | undefined)?.message ?? '',\n code\n );\n throw new Error(\n `Execution error:\\n\\n${messageWithReminder}`\n );\n }\n },\n {\n name: CodeExecutionToolName,\n description: CodeExecutionToolDescription,\n schema: CodeExecutionToolSchema,\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n\nexport { createCodeExecutionTool };\n"],"names":["config","getEnvironmentVariable","EnvVar","Constants","tool","HttpsProxyAgent","appendCodeSessionFileSummary"],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const IMAGE_FILE_EXTENSIONS = new Set([
|
|
4
|
+
'.avif',
|
|
5
|
+
'.bmp',
|
|
6
|
+
'.gif',
|
|
7
|
+
'.ico',
|
|
8
|
+
'.jpeg',
|
|
9
|
+
'.jpg',
|
|
10
|
+
'.png',
|
|
11
|
+
'.tif',
|
|
12
|
+
'.tiff',
|
|
13
|
+
'.webp',
|
|
14
|
+
]);
|
|
15
|
+
const CODE_SESSION_FILE_SUMMARY_PATTERN = /^Generated files:\nSession files: \d+ persisted file\(s\) are available in \/mnt\/data, including \d+ image\(s\)\. Use known \/mnt\/data paths directly in later code-tool calls\. The app displays files\/images automatically; do not invent download links or wrap generated images in Markdown\.$/;
|
|
16
|
+
function getFileExtension(name) {
|
|
17
|
+
const lastSlash = name.lastIndexOf('/');
|
|
18
|
+
const basename = lastSlash >= 0 ? name.slice(lastSlash + 1) : name;
|
|
19
|
+
const lastDot = basename.lastIndexOf('.');
|
|
20
|
+
return lastDot >= 0 ? basename.slice(lastDot).toLowerCase() : '';
|
|
21
|
+
}
|
|
22
|
+
function isImageFile(file) {
|
|
23
|
+
const name = file?.name;
|
|
24
|
+
return (typeof name === 'string' &&
|
|
25
|
+
IMAGE_FILE_EXTENSIONS.has(getFileExtension(name)));
|
|
26
|
+
}
|
|
27
|
+
function buildCodeSessionFileSummary(fileCount, imageCount) {
|
|
28
|
+
return ('Generated files:\n' +
|
|
29
|
+
`Session files: ${fileCount} persisted file(s) are available in /mnt/data, including ${imageCount} image(s). ` +
|
|
30
|
+
'Use known /mnt/data paths directly in later code-tool calls. ' +
|
|
31
|
+
'The app displays files/images automatically; do not invent download links or wrap generated images in Markdown.');
|
|
32
|
+
}
|
|
33
|
+
function isGeneratedFile(file) {
|
|
34
|
+
return file?.inherited !== true;
|
|
35
|
+
}
|
|
36
|
+
function stripCodeSessionFileSummary(output) {
|
|
37
|
+
const summaryStart = output.lastIndexOf('Generated files:');
|
|
38
|
+
if (summaryStart < 0)
|
|
39
|
+
return output;
|
|
40
|
+
const beforeSummary = output.slice(0, summaryStart);
|
|
41
|
+
if (beforeSummary !== '' && !beforeSummary.endsWith('\n\n'))
|
|
42
|
+
return output;
|
|
43
|
+
const maybeSummary = output.slice(summaryStart);
|
|
44
|
+
if (!CODE_SESSION_FILE_SUMMARY_PATTERN.test(maybeSummary))
|
|
45
|
+
return output;
|
|
46
|
+
return beforeSummary.trimEnd();
|
|
47
|
+
}
|
|
48
|
+
function appendCodeSessionFileSummary(output, files) {
|
|
49
|
+
if (files == null || files.length === 0) {
|
|
50
|
+
return output.trim();
|
|
51
|
+
}
|
|
52
|
+
const generatedFiles = files.filter(isGeneratedFile);
|
|
53
|
+
if (generatedFiles.length === 0) {
|
|
54
|
+
return output.trim();
|
|
55
|
+
}
|
|
56
|
+
const imageCount = generatedFiles.filter(isImageFile).length;
|
|
57
|
+
const summary = buildCodeSessionFileSummary(generatedFiles.length, imageCount);
|
|
58
|
+
return `${output.trimEnd()}\n\n${summary}`.trim();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exports.appendCodeSessionFileSummary = appendCodeSessionFileSummary;
|
|
62
|
+
exports.stripCodeSessionFileSummary = stripCodeSessionFileSummary;
|
|
63
|
+
//# sourceMappingURL=CodeSessionFileSummary.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeSessionFileSummary.cjs","sources":["../../../src/tools/CodeSessionFileSummary.ts"],"sourcesContent":["import type * as t from '@/types';\n\nconst IMAGE_FILE_EXTENSIONS = new Set([\n '.avif',\n '.bmp',\n '.gif',\n '.ico',\n '.jpeg',\n '.jpg',\n '.png',\n '.tif',\n '.tiff',\n '.webp',\n]);\n\nconst CODE_SESSION_FILE_SUMMARY_PATTERN =\n /^Generated files:\\nSession files: \\d+ persisted file\\(s\\) are available in \\/mnt\\/data, including \\d+ image\\(s\\)\\. Use known \\/mnt\\/data paths directly in later code-tool calls\\. The app displays files\\/images automatically; do not invent download links or wrap generated images in Markdown\\.$/;\n\nfunction getFileExtension(name: string): string {\n const lastSlash = name.lastIndexOf('/');\n const basename = lastSlash >= 0 ? name.slice(lastSlash + 1) : name;\n const lastDot = basename.lastIndexOf('.');\n return lastDot >= 0 ? basename.slice(lastDot).toLowerCase() : '';\n}\n\nfunction isImageFile(file: Partial<t.FileRef> | null | undefined): boolean {\n const name = file?.name;\n return (\n typeof name === 'string' &&\n IMAGE_FILE_EXTENSIONS.has(getFileExtension(name))\n );\n}\n\nfunction buildCodeSessionFileSummary(\n fileCount: number,\n imageCount: number\n): string {\n return (\n 'Generated files:\\n' +\n `Session files: ${fileCount} persisted file(s) are available in /mnt/data, including ${imageCount} image(s). ` +\n 'Use known /mnt/data paths directly in later code-tool calls. ' +\n 'The app displays files/images automatically; do not invent download links or wrap generated images in Markdown.'\n );\n}\n\nfunction isGeneratedFile(file: Partial<t.FileRef> | null | undefined): boolean {\n return file?.inherited !== true;\n}\n\nexport function stripCodeSessionFileSummary(output: string): string {\n const summaryStart = output.lastIndexOf('Generated files:');\n if (summaryStart < 0) return output;\n const beforeSummary = output.slice(0, summaryStart);\n if (beforeSummary !== '' && !beforeSummary.endsWith('\\n\\n')) return output;\n const maybeSummary = output.slice(summaryStart);\n if (!CODE_SESSION_FILE_SUMMARY_PATTERN.test(maybeSummary)) return output;\n return beforeSummary.trimEnd();\n}\n\nexport function appendCodeSessionFileSummary(\n output: string,\n files: t.FileRefs | undefined\n): string {\n if (files == null || files.length === 0) {\n return output.trim();\n }\n\n const generatedFiles = files.filter(isGeneratedFile);\n if (generatedFiles.length === 0) {\n return output.trim();\n }\n\n const imageCount = generatedFiles.filter(isImageFile).length;\n const summary = buildCodeSessionFileSummary(\n generatedFiles.length,\n imageCount\n );\n\n return `${output.trimEnd()}\\n\\n${summary}`.trim();\n}\n"],"names":[],"mappings":";;AAEA,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;AACR,CAAA,CAAC;AAEF,MAAM,iCAAiC,GACrC,uSAAuS;AAEzS,SAAS,gBAAgB,CAAC,IAAY,EAAA;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;IACvC,MAAM,QAAQ,GAAG,SAAS,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,IAAI;IAClE,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC;AACzC,IAAA,OAAO,OAAO,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE;AAClE;AAEA,SAAS,WAAW,CAAC,IAA2C,EAAA;AAC9D,IAAA,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI;AACvB,IAAA,QACE,OAAO,IAAI,KAAK,QAAQ;QACxB,qBAAqB,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAErD;AAEA,SAAS,2BAA2B,CAClC,SAAiB,EACjB,UAAkB,EAAA;AAElB,IAAA,QACE,oBAAoB;QACpB,CAAA,eAAA,EAAkB,SAAS,CAAA,yDAAA,EAA4D,UAAU,CAAA,WAAA,CAAa;QAC9G,+DAA+D;AAC/D,QAAA,iHAAiH;AAErH;AAEA,SAAS,eAAe,CAAC,IAA2C,EAAA;AAClE,IAAA,OAAO,IAAI,EAAE,SAAS,KAAK,IAAI;AACjC;AAEM,SAAU,2BAA2B,CAAC,MAAc,EAAA;IACxD,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC;IAC3D,IAAI,YAAY,GAAG,CAAC;AAAE,QAAA,OAAO,MAAM;IACnC,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;IACnD,IAAI,aAAa,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;AAAE,QAAA,OAAO,MAAM;IAC1E,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC;AAC/C,IAAA,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,YAAY,CAAC;AAAE,QAAA,OAAO,MAAM;AACxE,IAAA,OAAO,aAAa,CAAC,OAAO,EAAE;AAChC;AAEM,SAAU,4BAA4B,CAC1C,MAAc,EACd,KAA6B,EAAA;IAE7B,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;AACvC,QAAA,OAAO,MAAM,CAAC,IAAI,EAAE;IACtB;IAEA,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC;AACpD,IAAA,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;AAC/B,QAAA,OAAO,MAAM,CAAC,IAAI,EAAE;IACtB;IAEA,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM;IAC5D,MAAM,OAAO,GAAG,2BAA2B,CACzC,cAAc,CAAC,MAAM,EACrB,UAAU,CACX;IAED,OAAO,CAAA,EAAG,MAAM,CAAC,OAAO,EAAE,CAAA,IAAA,EAAO,OAAO,CAAA,CAAE,CAAC,IAAI,EAAE;AACnD;;;;;"}
|
|
@@ -7,6 +7,7 @@ var tools = require('@langchain/core/tools');
|
|
|
7
7
|
var CodeExecutor = require('./CodeExecutor.cjs');
|
|
8
8
|
var ptcTimeout = require('./ptcTimeout.cjs');
|
|
9
9
|
var _enum = require('../common/enum.cjs');
|
|
10
|
+
var CodeSessionFileSummary = require('./CodeSessionFileSummary.cjs');
|
|
10
11
|
|
|
11
12
|
// src/tools/ProgrammaticToolCalling.ts
|
|
12
13
|
dotenv.config();
|
|
@@ -21,14 +22,15 @@ Each call is a fresh Python interpreter. Variables, imports, and data do NOT per
|
|
|
21
22
|
You MUST complete your entire workflow in ONE code block: query → process → output.
|
|
22
23
|
DO NOT split work across multiple calls expecting to reuse variables.`;
|
|
23
24
|
const CORE_RULES = `Rules:
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- DO NOT define async def main() or call asyncio.run()
|
|
25
|
+
- One call: state does not persist
|
|
26
|
+
- Auto-wrapped async; use await, no main()/asyncio.run()
|
|
27
27
|
- Tools are pre-defined—DO NOT write function definitions
|
|
28
|
+
- Call tools with keyword args only (await tool(arg=value), never pass a dict)
|
|
29
|
+
- Tool results are decoded Python values (dict/list/str)
|
|
28
30
|
- Only print() output returns to the model
|
|
31
|
+
- ${CodeExecutor.CODE_ARTIFACT_PATH_GUIDANCE}
|
|
29
32
|
- timeout caps one sandbox run/replay iteration, not the total multi-round-trip workflow`;
|
|
30
|
-
const ADDITIONAL_RULES =
|
|
31
|
-
- Tool names normalized: hyphens→underscores, keywords get \`_tool\` suffix`;
|
|
33
|
+
const ADDITIONAL_RULES = '- Tool names normalized: hyphens→underscores, keywords get `_tool` suffix';
|
|
32
34
|
const EXAMPLES = `Example (Complete workflow in one call):
|
|
33
35
|
# Query data
|
|
34
36
|
data = await query_database(sql="SELECT * FROM users")
|
|
@@ -507,14 +509,14 @@ async function executeTools(toolCalls, toolMap, programmaticToolName = _enum.Con
|
|
|
507
509
|
/**
|
|
508
510
|
* Formats the completed response for the agent.
|
|
509
511
|
*
|
|
510
|
-
* Output
|
|
511
|
-
*
|
|
512
|
-
*
|
|
512
|
+
* Output includes stdout/stderr plus a compact session-file summary
|
|
513
|
+
* when artifacts were persisted. The artifact still carries every
|
|
514
|
+
* file so the host's session map stays in sync.
|
|
513
515
|
*
|
|
514
516
|
* @param response - The completed API response
|
|
515
517
|
* @returns Tuple of [formatted string, artifact]
|
|
516
518
|
*/
|
|
517
|
-
function formatCompletedResponse(response) {
|
|
519
|
+
function formatCompletedResponse(response, sourceCode = '') {
|
|
518
520
|
let formatted = '';
|
|
519
521
|
if (response.stdout != null && response.stdout !== '') {
|
|
520
522
|
formatted += `stdout:\n${response.stdout}\n`;
|
|
@@ -525,8 +527,9 @@ function formatCompletedResponse(response) {
|
|
|
525
527
|
if (response.stderr != null && response.stderr !== '') {
|
|
526
528
|
formatted += `stderr:\n${response.stderr}\n`;
|
|
527
529
|
}
|
|
530
|
+
const outputWithReminder = CodeExecutor.appendTmpScratchReminder(formatted, sourceCode);
|
|
528
531
|
return [
|
|
529
|
-
|
|
532
|
+
CodeSessionFileSummary.appendCodeSessionFileSummary(outputWithReminder, response.files),
|
|
530
533
|
{
|
|
531
534
|
session_id: response.session_id,
|
|
532
535
|
files: response.files,
|
|
@@ -633,7 +636,7 @@ function createProgrammaticToolCallingTool(initParams = {}) {
|
|
|
633
636
|
// Phase 3: Handle final state
|
|
634
637
|
// ====================================================================
|
|
635
638
|
if (response.status === 'completed') {
|
|
636
|
-
return formatCompletedResponse(response);
|
|
639
|
+
return formatCompletedResponse(response, code);
|
|
637
640
|
}
|
|
638
641
|
if (response.status === 'error') {
|
|
639
642
|
throw new Error(`Execution error: ${response.error}` +
|
|
@@ -644,7 +647,8 @@ function createProgrammaticToolCallingTool(initParams = {}) {
|
|
|
644
647
|
throw new Error(`Unexpected response status: ${response.status}`);
|
|
645
648
|
}
|
|
646
649
|
catch (error) {
|
|
647
|
-
|
|
650
|
+
const messageWithReminder = CodeExecutor.appendFailedExecutionFileReminder(error.message, code);
|
|
651
|
+
throw new Error(`Programmatic execution failed: ${messageWithReminder}`);
|
|
648
652
|
}
|
|
649
653
|
}, {
|
|
650
654
|
name: _enum.Constants.PROGRAMMATIC_TOOL_CALLING,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProgrammaticToolCalling.cjs","sources":["../../../src/tools/ProgrammaticToolCalling.ts"],"sourcesContent":["// src/tools/ProgrammaticToolCalling.ts\nimport { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type { ProgrammaticToolCallingJsonSchema } from './ptcTimeout';\nimport type * as t from '@/types';\nimport {\n buildCodeApiHttpErrorMessage,\n emptyOutputMessage,\n getCodeBaseURL,\n resolveCodeApiAuthHeaders,\n} from './CodeExecutor';\nimport {\n clampCodeApiRunTimeoutMs,\n createCodeApiRunTimeoutSchema,\n resolveCodeApiRunTimeoutMs,\n} from './ptcTimeout';\nimport { Constants } from '@/common';\n\nconfig();\n\n/** Default max round-trips to prevent infinite loops */\nconst DEFAULT_MAX_ROUND_TRIPS = 20;\n\nconst DEFAULT_RUN_TIMEOUT_MS = resolveCodeApiRunTimeoutMs();\n\n// ============================================================================\n// Description Components (Single Source of Truth)\n// ============================================================================\n\nconst STATELESS_WARNING = `CRITICAL - STATELESS EXECUTION:\nEach call is a fresh Python interpreter. Variables, imports, and data do NOT persist between calls.\nYou MUST complete your entire workflow in ONE code block: query → process → output.\nDO NOT split work across multiple calls expecting to reuse variables.`;\n\nconst CORE_RULES = `Rules:\n- EVERYTHING in one call—no state persists between executions\n- Just write code with await—auto-wrapped in async context\n- DO NOT define async def main() or call asyncio.run()\n- Tools are pre-defined—DO NOT write function definitions\n- Only print() output returns to the model\n- timeout caps one sandbox run/replay iteration, not the total multi-round-trip workflow`;\n\nconst ADDITIONAL_RULES = `- Generated files are automatically available in /mnt/data/ for subsequent executions\n- Tool names normalized: hyphens→underscores, keywords get \\`_tool\\` suffix`;\n\nconst EXAMPLES = `Example (Complete workflow in one call):\n # Query data\n data = await query_database(sql=\"SELECT * FROM users\")\n # Process it\n df = pd.DataFrame(data)\n summary = df.groupby('region').sum()\n # Output results\n await write_to_sheet(spreadsheet_id=sid, data=summary.to_dict())\n print(f\"Wrote {len(summary)} rows\")\n\nExample (Parallel calls):\n sf, ny = await asyncio.gather(get_weather(city=\"SF\"), get_weather(city=\"NY\"))\n print(f\"SF: {sf}, NY: {ny}\")`;\n\n// ============================================================================\n// Schema\n// ============================================================================\n\nconst CODE_PARAM_DESCRIPTION = `Python code that calls tools programmatically. Tools are available as async functions.\n\n${STATELESS_WARNING}\n\nYour code is auto-wrapped in async context. Just write logic with await—no boilerplate needed.\n\n${EXAMPLES}\n\n${CORE_RULES}`;\n\nexport function createProgrammaticToolCallingSchema(\n maxRunTimeoutMs = DEFAULT_RUN_TIMEOUT_MS\n): ProgrammaticToolCallingJsonSchema {\n return {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n minLength: 1,\n description: CODE_PARAM_DESCRIPTION,\n },\n timeout: createCodeApiRunTimeoutSchema(maxRunTimeoutMs),\n },\n required: ['code'],\n } as const;\n}\n\nexport const ProgrammaticToolCallingSchema =\n createProgrammaticToolCallingSchema();\n\nexport const ProgrammaticToolCallingName = Constants.PROGRAMMATIC_TOOL_CALLING;\n\nexport const ProgrammaticToolCallingDescription = `\nRun tools via Python code. Auto-wrapped in async context—just use \\`await\\` directly.\n\n${STATELESS_WARNING}\n\n${CORE_RULES}\n${ADDITIONAL_RULES}\n\nWhen to use: loops, conditionals, parallel (\\`asyncio.gather\\`), multi-step pipelines.\n\n${EXAMPLES}\n`.trim();\n\nexport const ProgrammaticToolCallingDefinition = {\n name: ProgrammaticToolCallingName,\n description: ProgrammaticToolCallingDescription,\n schema: ProgrammaticToolCallingSchema,\n} as const;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/** Python reserved keywords that get `_tool` suffix in Code API */\nconst PYTHON_KEYWORDS = new Set([\n 'False',\n 'None',\n 'True',\n 'and',\n 'as',\n 'assert',\n 'async',\n 'await',\n 'break',\n 'class',\n 'continue',\n 'def',\n 'del',\n 'elif',\n 'else',\n 'except',\n 'finally',\n 'for',\n 'from',\n 'global',\n 'if',\n 'import',\n 'in',\n 'is',\n 'lambda',\n 'nonlocal',\n 'not',\n 'or',\n 'pass',\n 'raise',\n 'return',\n 'try',\n 'while',\n 'with',\n 'yield',\n]);\n\nexport type FetchSessionFilesScope =\n | { kind: 'skill'; id: string; version: number }\n | { kind: 'agent' | 'user'; id: string; version?: never };\n\ntype CodeApiSessionFileWire = {\n id?: unknown;\n name?: unknown;\n metadata?: unknown;\n resource_id?: unknown;\n storage_session_id?: unknown;\n};\n\ntype CodeApiSessionFileMetadata = {\n 'original-filename'?: unknown;\n};\n\nfunction isFetchSessionFilesScope(\n value: unknown\n): value is FetchSessionFilesScope {\n if (value == null || typeof value !== 'object') {\n return false;\n }\n const scope = value as { kind?: unknown; id?: unknown; version?: unknown };\n if (\n (scope.kind === 'agent' || scope.kind === 'user') &&\n typeof scope.id === 'string'\n ) {\n return true;\n }\n return (\n scope.kind === 'skill' &&\n typeof scope.id === 'string' &&\n typeof scope.version === 'number'\n );\n}\n\nfunction isCodeApiAuthHeaders(\n value: string | t.CodeApiAuthHeaders | undefined\n): value is t.CodeApiAuthHeaders {\n return value != null && typeof value !== 'string';\n}\n\nfunction isCodeApiSessionFileWire(\n value: unknown\n): value is CodeApiSessionFileWire {\n return value != null && typeof value === 'object';\n}\n\nfunction isCodeApiSessionFileMetadata(\n value: unknown\n): value is CodeApiSessionFileMetadata {\n return value != null && typeof value === 'object';\n}\n\nfunction normalizeSessionFile(\n file: CodeApiSessionFileWire,\n sessionId: string,\n scope?: FetchSessionFilesScope\n): t.CodeEnvFile {\n const metadata = isCodeApiSessionFileMetadata(file.metadata)\n ? file.metadata\n : undefined;\n const rawName = typeof file.name === 'string' ? file.name : '';\n const nameParts = rawName.split('/');\n const fallbackId = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';\n const id =\n typeof file.id === 'string' && file.id !== '' ? file.id : fallbackId;\n const originalFilename = metadata?.['original-filename'];\n const name =\n typeof originalFilename === 'string' ? originalFilename : rawName;\n const storage_session_id =\n typeof file.storage_session_id === 'string'\n ? file.storage_session_id\n : sessionId;\n const resource_id =\n typeof file.resource_id === 'string' && file.resource_id !== ''\n ? file.resource_id\n : (scope?.id ?? id);\n\n if (scope?.kind === 'skill') {\n return {\n storage_session_id,\n kind: 'skill',\n id,\n resource_id,\n name,\n version: scope.version,\n };\n }\n if (scope != null) {\n return {\n storage_session_id,\n kind: scope.kind,\n id,\n resource_id,\n name,\n };\n }\n return {\n storage_session_id,\n kind: 'user',\n id,\n resource_id: id,\n name,\n };\n}\n\n/**\n * Normalizes a tool name to Python identifier format.\n * Must match the Code API's `normalizePythonFunctionName` exactly:\n * 1. Replace hyphens and spaces with underscores\n * 2. Remove any other invalid characters\n * 3. Prefix with underscore if starts with number\n * 4. Append `_tool` if it's a Python keyword\n * @param name - The tool name to normalize\n * @returns Normalized Python-safe identifier\n */\nexport function normalizeToPythonIdentifier(name: string): string {\n let normalized = name.replace(/[-\\s]/g, '_');\n\n normalized = normalized.replace(/[^a-zA-Z0-9_]/g, '');\n\n if (/^[0-9]/.test(normalized)) {\n normalized = '_' + normalized;\n }\n\n if (PYTHON_KEYWORDS.has(normalized)) {\n normalized = normalized + '_tool';\n }\n\n return normalized;\n}\n\n/**\n * Extracts tool names that are actually called in the Python code.\n * Handles hyphen/underscore conversion since Python identifiers use underscores.\n * @param code - The Python code to analyze\n * @param toolNameMap - Map from normalized Python name to original tool name\n * @returns Set of original tool names found in the code\n */\nexport function extractUsedToolNames(\n code: string,\n toolNameMap: Map<string, string>\n): Set<string> {\n const usedTools = new Set<string>();\n\n for (const [pythonName, originalName] of toolNameMap) {\n const escapedName = pythonName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`\\\\b${escapedName}\\\\s*\\\\(`, 'g');\n\n if (pattern.test(code)) {\n usedTools.add(originalName);\n }\n }\n\n return usedTools;\n}\n\n/**\n * Filters tool definitions to only include tools actually used in the code.\n * Handles the hyphen-to-underscore conversion for Python compatibility.\n * @param toolDefs - All available tool definitions\n * @param code - The Python code to analyze\n * @param debug - Enable debug logging\n * @returns Filtered array of tool definitions\n */\nexport function filterToolsByUsage(\n toolDefs: t.LCTool[],\n code: string,\n debug = false\n): t.LCTool[] {\n const toolNameMap = new Map<string, string>();\n for (const tool of toolDefs) {\n const pythonName = normalizeToPythonIdentifier(tool.name);\n toolNameMap.set(pythonName, tool.name);\n }\n\n const usedToolNames = extractUsedToolNames(code, toolNameMap);\n\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Tool filtering: found ${usedToolNames.size}/${toolDefs.length} tools in code`\n );\n if (usedToolNames.size > 0) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Matched tools: ${Array.from(usedToolNames).join(', ')}`\n );\n }\n }\n\n if (usedToolNames.size === 0) {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n '[PTC Debug] No tools detected in code - sending all tools as fallback'\n );\n }\n return toolDefs;\n }\n\n return toolDefs.filter((tool) => usedToolNames.has(tool.name));\n}\n\n/**\n * Fetches files from a previous session to make them available for the current execution.\n * Files are returned as CodeEnvFile references to be included in the request.\n * @param baseUrl - The base URL for the Code API\n * @param sessionId - The session ID to fetch files from\n * @param scope - Resource scope used by CodeAPI to authorize the session\n * @param proxy - Optional HTTP proxy URL\n * @returns Array of CodeEnvFile references, or empty array if fetch fails\n */\nexport async function fetchSessionFiles(\n baseUrl: string,\n sessionId: string,\n proxy?: string,\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeEnvFile[]>;\nexport async function fetchSessionFiles(\n baseUrl: string,\n sessionId: string,\n scope: FetchSessionFilesScope,\n proxyOrAuthHeaders?: string | t.CodeApiAuthHeaders,\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeEnvFile[]>;\nexport async function fetchSessionFiles(\n baseUrl: string,\n sessionId: string,\n scopeOrProxy?: FetchSessionFilesScope | string,\n proxyOrAuthHeaders?: string | t.CodeApiAuthHeaders,\n scopedAuthHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeEnvFile[]> {\n try {\n const scope = isFetchSessionFilesScope(scopeOrProxy)\n ? scopeOrProxy\n : undefined;\n let proxy: string | undefined;\n let authHeaders: t.CodeApiAuthHeaders | undefined;\n if (scope == null) {\n proxy = typeof scopeOrProxy === 'string' ? scopeOrProxy : undefined;\n authHeaders = isCodeApiAuthHeaders(proxyOrAuthHeaders)\n ? proxyOrAuthHeaders\n : undefined;\n } else if (typeof proxyOrAuthHeaders === 'string') {\n proxy = proxyOrAuthHeaders;\n authHeaders = scopedAuthHeaders;\n } else {\n authHeaders = proxyOrAuthHeaders ?? scopedAuthHeaders;\n }\n const query = new URLSearchParams({ detail: 'full' });\n if (scope != null) {\n query.set('kind', scope.kind);\n query.set('id', scope.id);\n if (scope.kind === 'skill') {\n query.set('version', String(scope.version));\n }\n }\n const filesEndpoint = `${baseUrl}/files/${encodeURIComponent(sessionId)}?${query.toString()}`;\n const resolvedAuthHeaders = await resolveCodeApiAuthHeaders(authHeaders);\n const fetchOptions: RequestInit = {\n method: 'GET',\n headers: {\n 'User-Agent': 'LibreChat/1.0',\n ...resolvedAuthHeaders,\n },\n };\n\n if (proxy != null && proxy !== '') {\n fetchOptions.agent = new HttpsProxyAgent(proxy);\n }\n\n const response = await fetch(filesEndpoint, fetchOptions);\n if (!response.ok) {\n throw new Error(\n await buildCodeApiHttpErrorMessage('GET', filesEndpoint, response)\n );\n }\n\n const files = await response.json();\n if (!Array.isArray(files) || files.length === 0) {\n return [];\n }\n\n return files\n .filter(isCodeApiSessionFileWire)\n .map((file) => normalizeSessionFile(file, sessionId, scope));\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to fetch files for session: ${sessionId}, ${(error as Error).message}`\n );\n return [];\n }\n}\n\n/**\n * Makes an HTTP request to the Code API.\n * @param endpoint - The API endpoint URL\n * @param body - The request body\n * @param proxy - Optional HTTP proxy URL\n * @returns The parsed API response\n */\nexport async function makeRequest(\n endpoint: string,\n body: Record<string, unknown>,\n proxy?: string,\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.ProgrammaticExecutionResponse> {\n const resolvedAuthHeaders = await resolveCodeApiAuthHeaders(authHeaders);\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'LibreChat/1.0',\n ...resolvedAuthHeaders,\n },\n body: JSON.stringify(body),\n };\n\n if (proxy != null && proxy !== '') {\n fetchOptions.agent = new HttpsProxyAgent(proxy);\n }\n\n const response = await fetch(endpoint, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n await buildCodeApiHttpErrorMessage('POST', endpoint, response)\n );\n }\n\n return (await response.json()) as t.ProgrammaticExecutionResponse;\n}\n\n/**\n * Unwraps tool responses that may be formatted as tuples or content blocks.\n * MCP tools return [content, artifacts], we need to extract the raw data.\n * @param result - The raw result from tool.invoke()\n * @param isMCPTool - Whether this is an MCP tool (has mcp property)\n * @returns Unwrapped raw data (string, object, or parsed JSON)\n */\nexport function unwrapToolResponse(\n result: unknown,\n isMCPTool: boolean\n): unknown {\n // Only unwrap if this is an MCP tool and result is a tuple\n if (!isMCPTool) {\n return result;\n }\n\n /**\n * Checks if a value is a content block object (has type and text).\n */\n const isContentBlock = (value: unknown): boolean => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return typeof obj.type === 'string';\n };\n\n /**\n * Checks if an array is an array of content blocks.\n */\n const isContentBlockArray = (arr: unknown[]): boolean => {\n return arr.length > 0 && arr.every(isContentBlock);\n };\n\n /**\n * Extracts text from a single content block object.\n * Returns the text if it's a text block, otherwise returns null.\n */\n const extractTextFromBlock = (block: unknown): string | null => {\n if (typeof block !== 'object' || block === null) return null;\n const b = block as Record<string, unknown>;\n if (b.type === 'text' && typeof b.text === 'string') {\n return b.text;\n }\n return null;\n };\n\n /**\n * Extracts text from content blocks (array or single object).\n * Returns combined text or null if no text blocks found.\n */\n const extractTextFromContent = (content: unknown): string | null => {\n // Single content block object: { type: 'text', text: '...' }\n if (\n typeof content === 'object' &&\n content !== null &&\n !Array.isArray(content)\n ) {\n const text = extractTextFromBlock(content);\n if (text !== null) return text;\n }\n\n // Array of content blocks: [{ type: 'text', text: '...' }, ...]\n if (Array.isArray(content) && content.length > 0) {\n const texts = content\n .map(extractTextFromBlock)\n .filter((t): t is string => t !== null);\n if (texts.length > 0) {\n return texts.join('\\n');\n }\n }\n\n return null;\n };\n\n /**\n * Tries to parse a string as JSON if it looks like JSON.\n */\n const maybeParseJSON = (str: string): unknown => {\n const trimmed = str.trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n return JSON.parse(trimmed);\n } catch {\n return str;\n }\n }\n return str;\n };\n\n // Handle array of content blocks at top level FIRST\n // (before checking for tuple, since both are arrays)\n if (Array.isArray(result) && isContentBlockArray(result)) {\n const extractedText = extractTextFromContent(result);\n if (extractedText !== null) {\n return maybeParseJSON(extractedText);\n }\n }\n\n // Check if result is a tuple/array with [content, artifacts]\n if (Array.isArray(result) && result.length >= 1) {\n const [content] = result;\n\n // If first element is a string, return it (possibly parsed as JSON)\n if (typeof content === 'string') {\n return maybeParseJSON(content);\n }\n\n // Try to extract text from content blocks\n const extractedText = extractTextFromContent(content);\n if (extractedText !== null) {\n return maybeParseJSON(extractedText);\n }\n\n // If first element is an object (but not a text block), return it\n if (typeof content === 'object' && content !== null) {\n return content;\n }\n }\n\n // Handle single content block object at top level (not in tuple)\n const extractedText = extractTextFromContent(result);\n if (extractedText !== null) {\n return maybeParseJSON(extractedText);\n }\n\n // Not a formatted response, return as-is\n return result;\n}\n\n/**\n * Executes tools in parallel when requested by the API.\n * Uses Promise.all for parallel execution, catching individual errors.\n * Unwraps formatted responses (e.g., MCP tool tuples) to raw data.\n * @param toolCalls - Array of tool calls from the API\n * @param toolMap - Map of tool names to executable tools\n * @returns Array of tool results\n */\nexport async function executeTools(\n toolCalls: t.PTCToolCall[],\n toolMap: t.ToolMap,\n programmaticToolName = Constants.PROGRAMMATIC_TOOL_CALLING\n): Promise<t.PTCToolResult[]> {\n const executions = toolCalls.map(async (call): Promise<t.PTCToolResult> => {\n const tool = toolMap.get(call.name);\n\n if (!tool) {\n return {\n call_id: call.id,\n result: null,\n is_error: true,\n error_message: `Tool '${call.name}' not found. Available tools: ${Array.from(toolMap.keys()).join(', ')}`,\n };\n }\n\n try {\n const result = await tool.invoke(call.input, {\n metadata: { [programmaticToolName]: true },\n });\n\n const isMCPTool = tool.mcp === true;\n const unwrappedResult = unwrapToolResponse(result, isMCPTool);\n\n return {\n call_id: call.id,\n result: unwrappedResult,\n is_error: false,\n };\n } catch (error) {\n return {\n call_id: call.id,\n result: null,\n is_error: true,\n error_message: (error as Error).message || 'Tool execution failed',\n };\n }\n });\n\n return await Promise.all(executions);\n}\n\n/**\n * Formats the completed response for the agent.\n *\n * Output is stdout/stderr only — see `CodeExecutor.ts`. The\n * artifact still carries every file so the host's session map\n * stays in sync; the LLM doesn't see them in the tool result text.\n *\n * @param response - The completed API response\n * @returns Tuple of [formatted string, artifact]\n */\nexport function formatCompletedResponse(\n response: t.ProgrammaticExecutionResponse\n): [string, t.ProgrammaticExecutionArtifact] {\n let formatted = '';\n\n if (response.stdout != null && response.stdout !== '') {\n formatted += `stdout:\\n${response.stdout}\\n`;\n } else {\n formatted += emptyOutputMessage;\n }\n\n if (response.stderr != null && response.stderr !== '') {\n formatted += `stderr:\\n${response.stderr}\\n`;\n }\n\n return [\n formatted.trim(),\n {\n session_id: response.session_id,\n files: response.files,\n } satisfies t.ProgrammaticExecutionArtifact,\n ];\n}\n\n// ============================================================================\n// Tool Factory\n// ============================================================================\n\n/**\n * Creates a Programmatic Tool Calling tool for complex multi-tool workflows.\n *\n * This tool enables AI agents to write Python code that orchestrates multiple\n * tool calls programmatically, reducing LLM round-trips and token usage.\n *\n * The tool map must be provided at runtime via config.configurable.toolMap.\n *\n * @param params - Configuration parameters (baseUrl, maxRoundTrips, proxy)\n * @returns A LangChain DynamicStructuredTool for programmatic tool calling\n *\n * @example\n * const ptcTool = createProgrammaticToolCallingTool({ maxRoundTrips: 20 });\n *\n * const [output, artifact] = await ptcTool.invoke(\n * { code, tools },\n * { configurable: { toolMap } }\n * );\n */\nexport function createProgrammaticToolCallingTool(\n initParams: t.ProgrammaticToolCallingParams = {}\n): DynamicStructuredTool {\n const baseUrl = initParams.baseUrl ?? getCodeBaseURL();\n const maxRoundTrips = initParams.maxRoundTrips ?? DEFAULT_MAX_ROUND_TRIPS;\n const maxRunTimeoutMs = resolveCodeApiRunTimeoutMs(initParams.runTimeoutMs);\n const proxy = initParams.proxy ?? process.env.PROXY;\n const debug = initParams.debug ?? process.env.PTC_DEBUG === 'true';\n const EXEC_ENDPOINT = `${baseUrl}/exec/programmatic`;\n\n return tool(\n async (rawParams, config) => {\n const params = rawParams as { code: string; timeout?: number };\n const { code } = params;\n const timeout = clampCodeApiRunTimeoutMs(params.timeout, maxRunTimeoutMs);\n\n // Extra params injected by ToolNode (follows web_search pattern).\n const toolCall = (config.toolCall ?? {}) as ToolCall &\n Partial<t.ProgrammaticCache> & {\n session_id?: string;\n _injected_files?: t.CodeEnvFile[];\n };\n const { toolMap, toolDefs, session_id, _injected_files } = toolCall;\n\n if (toolMap == null || toolMap.size === 0) {\n throw new Error(\n 'No toolMap provided. ' +\n 'ToolNode should inject this from AgentContext when invoked through the graph.'\n );\n }\n\n if (toolDefs == null || toolDefs.length === 0) {\n throw new Error(\n 'No tool definitions provided. ' +\n 'Either pass tools in the input or ensure ToolNode injects toolDefs.'\n );\n }\n\n let roundTrip = 0;\n\n try {\n // ====================================================================\n // Phase 1: Filter tools and make initial request\n // ====================================================================\n\n const effectiveTools = filterToolsByUsage(toolDefs, code, debug);\n\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Sending ${effectiveTools.length} tools to API ` +\n `(filtered from ${toolDefs.length})`\n );\n }\n\n /**\n * File injection: `_injected_files` from ToolNode session\n * context. The legacy `/files/<session_id>` HTTP fallback was\n * removed (see `CodeExecutor.ts`) — codeapi's sessionAuth now\n * requires kind/id query params unavailable at this point.\n */\n let files: t.CodeEnvFile[] | undefined;\n if (_injected_files && _injected_files.length > 0) {\n files = _injected_files;\n } else if (session_id != null && session_id.length > 0) {\n // eslint-disable-next-line no-console\n console.debug(\n `[ProgrammaticToolCalling] No injected files for session_id=${session_id} — exec will run without input files`\n );\n }\n\n let response = await makeRequest(\n EXEC_ENDPOINT,\n {\n code,\n tools: effectiveTools,\n session_id,\n timeout,\n ...(files && files.length > 0 ? { files } : {}),\n },\n proxy,\n initParams.authHeaders\n );\n\n // ====================================================================\n // Phase 2: Handle response loop\n // ====================================================================\n\n while (response.status === 'tool_call_required') {\n roundTrip++;\n\n if (roundTrip > maxRoundTrips) {\n throw new Error(\n `Exceeded maximum round trips (${maxRoundTrips}). ` +\n 'This may indicate an infinite loop, excessive tool calls, ' +\n 'or a logic error in your code.'\n );\n }\n\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Round trip ${roundTrip}: ${response.tool_calls?.length ?? 0} tool(s) to execute`\n );\n }\n\n const toolResults = await executeTools(\n response.tool_calls ?? [],\n toolMap\n );\n\n response = await makeRequest(\n EXEC_ENDPOINT,\n {\n continuation_token: response.continuation_token,\n tool_results: toolResults,\n },\n proxy,\n initParams.authHeaders\n );\n }\n\n // ====================================================================\n // Phase 3: Handle final state\n // ====================================================================\n\n if (response.status === 'completed') {\n return formatCompletedResponse(response);\n }\n\n if (response.status === 'error') {\n throw new Error(\n `Execution error: ${response.error}` +\n (response.stderr != null && response.stderr !== ''\n ? `\\n\\nStderr:\\n${response.stderr}`\n : '')\n );\n }\n\n throw new Error(`Unexpected response status: ${response.status}`);\n } catch (error) {\n throw new Error(\n `Programmatic execution failed: ${(error as Error).message}`\n );\n }\n },\n {\n name: Constants.PROGRAMMATIC_TOOL_CALLING,\n description: ProgrammaticToolCallingDescription,\n schema: createProgrammaticToolCallingSchema(maxRunTimeoutMs),\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n"],"names":["config","resolveCodeApiRunTimeoutMs","createCodeApiRunTimeoutSchema","Constants","resolveCodeApiAuthHeaders","HttpsProxyAgent","buildCodeApiHttpErrorMessage","emptyOutputMessage","getCodeBaseURL","tool","clampCodeApiRunTimeoutMs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProgrammaticToolCalling.cjs","sources":["../../../src/tools/ProgrammaticToolCalling.ts"],"sourcesContent":["// src/tools/ProgrammaticToolCalling.ts\nimport { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type { ProgrammaticToolCallingJsonSchema } from './ptcTimeout';\nimport type * as t from '@/types';\nimport {\n CODE_ARTIFACT_PATH_GUIDANCE,\n appendCodeSessionFileSummary,\n appendFailedExecutionFileReminder,\n buildCodeApiHttpErrorMessage,\n emptyOutputMessage,\n getCodeBaseURL,\n appendTmpScratchReminder,\n resolveCodeApiAuthHeaders,\n} from './CodeExecutor';\nimport {\n clampCodeApiRunTimeoutMs,\n createCodeApiRunTimeoutSchema,\n resolveCodeApiRunTimeoutMs,\n} from './ptcTimeout';\nimport { Constants } from '@/common';\n\nconfig();\n\n/** Default max round-trips to prevent infinite loops */\nconst DEFAULT_MAX_ROUND_TRIPS = 20;\n\nconst DEFAULT_RUN_TIMEOUT_MS = resolveCodeApiRunTimeoutMs();\n\n// ============================================================================\n// Description Components (Single Source of Truth)\n// ============================================================================\n\nconst STATELESS_WARNING = `CRITICAL - STATELESS EXECUTION:\nEach call is a fresh Python interpreter. Variables, imports, and data do NOT persist between calls.\nYou MUST complete your entire workflow in ONE code block: query → process → output.\nDO NOT split work across multiple calls expecting to reuse variables.`;\n\nconst CORE_RULES = `Rules:\n- One call: state does not persist\n- Auto-wrapped async; use await, no main()/asyncio.run()\n- Tools are pre-defined—DO NOT write function definitions\n- Call tools with keyword args only (await tool(arg=value), never pass a dict)\n- Tool results are decoded Python values (dict/list/str)\n- Only print() output returns to the model\n- ${CODE_ARTIFACT_PATH_GUIDANCE}\n- timeout caps one sandbox run/replay iteration, not the total multi-round-trip workflow`;\n\nconst ADDITIONAL_RULES =\n '- Tool names normalized: hyphens→underscores, keywords get `_tool` suffix';\n\nconst EXAMPLES = `Example (Complete workflow in one call):\n # Query data\n data = await query_database(sql=\"SELECT * FROM users\")\n # Process it\n df = pd.DataFrame(data)\n summary = df.groupby('region').sum()\n # Output results\n await write_to_sheet(spreadsheet_id=sid, data=summary.to_dict())\n print(f\"Wrote {len(summary)} rows\")\n\nExample (Parallel calls):\n sf, ny = await asyncio.gather(get_weather(city=\"SF\"), get_weather(city=\"NY\"))\n print(f\"SF: {sf}, NY: {ny}\")`;\n\n// ============================================================================\n// Schema\n// ============================================================================\n\nconst CODE_PARAM_DESCRIPTION = `Python code that calls tools programmatically. Tools are available as async functions.\n\n${STATELESS_WARNING}\n\nYour code is auto-wrapped in async context. Just write logic with await—no boilerplate needed.\n\n${EXAMPLES}\n\n${CORE_RULES}`;\n\nexport function createProgrammaticToolCallingSchema(\n maxRunTimeoutMs = DEFAULT_RUN_TIMEOUT_MS\n): ProgrammaticToolCallingJsonSchema {\n return {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n minLength: 1,\n description: CODE_PARAM_DESCRIPTION,\n },\n timeout: createCodeApiRunTimeoutSchema(maxRunTimeoutMs),\n },\n required: ['code'],\n } as const;\n}\n\nexport const ProgrammaticToolCallingSchema =\n createProgrammaticToolCallingSchema();\n\nexport const ProgrammaticToolCallingName = Constants.PROGRAMMATIC_TOOL_CALLING;\n\nexport const ProgrammaticToolCallingDescription = `\nRun tools via Python code. Auto-wrapped in async context—just use \\`await\\` directly.\n\n${STATELESS_WARNING}\n\n${CORE_RULES}\n${ADDITIONAL_RULES}\n\nWhen to use: loops, conditionals, parallel (\\`asyncio.gather\\`), multi-step pipelines.\n\n${EXAMPLES}\n`.trim();\n\nexport const ProgrammaticToolCallingDefinition = {\n name: ProgrammaticToolCallingName,\n description: ProgrammaticToolCallingDescription,\n schema: ProgrammaticToolCallingSchema,\n} as const;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/** Python reserved keywords that get `_tool` suffix in Code API */\nconst PYTHON_KEYWORDS = new Set([\n 'False',\n 'None',\n 'True',\n 'and',\n 'as',\n 'assert',\n 'async',\n 'await',\n 'break',\n 'class',\n 'continue',\n 'def',\n 'del',\n 'elif',\n 'else',\n 'except',\n 'finally',\n 'for',\n 'from',\n 'global',\n 'if',\n 'import',\n 'in',\n 'is',\n 'lambda',\n 'nonlocal',\n 'not',\n 'or',\n 'pass',\n 'raise',\n 'return',\n 'try',\n 'while',\n 'with',\n 'yield',\n]);\n\nexport type FetchSessionFilesScope =\n | { kind: 'skill'; id: string; version: number }\n | { kind: 'agent' | 'user'; id: string; version?: never };\n\ntype CodeApiSessionFileWire = {\n id?: unknown;\n name?: unknown;\n metadata?: unknown;\n resource_id?: unknown;\n storage_session_id?: unknown;\n};\n\ntype CodeApiSessionFileMetadata = {\n 'original-filename'?: unknown;\n};\n\nfunction isFetchSessionFilesScope(\n value: unknown\n): value is FetchSessionFilesScope {\n if (value == null || typeof value !== 'object') {\n return false;\n }\n const scope = value as { kind?: unknown; id?: unknown; version?: unknown };\n if (\n (scope.kind === 'agent' || scope.kind === 'user') &&\n typeof scope.id === 'string'\n ) {\n return true;\n }\n return (\n scope.kind === 'skill' &&\n typeof scope.id === 'string' &&\n typeof scope.version === 'number'\n );\n}\n\nfunction isCodeApiAuthHeaders(\n value: string | t.CodeApiAuthHeaders | undefined\n): value is t.CodeApiAuthHeaders {\n return value != null && typeof value !== 'string';\n}\n\nfunction isCodeApiSessionFileWire(\n value: unknown\n): value is CodeApiSessionFileWire {\n return value != null && typeof value === 'object';\n}\n\nfunction isCodeApiSessionFileMetadata(\n value: unknown\n): value is CodeApiSessionFileMetadata {\n return value != null && typeof value === 'object';\n}\n\nfunction normalizeSessionFile(\n file: CodeApiSessionFileWire,\n sessionId: string,\n scope?: FetchSessionFilesScope\n): t.CodeEnvFile {\n const metadata = isCodeApiSessionFileMetadata(file.metadata)\n ? file.metadata\n : undefined;\n const rawName = typeof file.name === 'string' ? file.name : '';\n const nameParts = rawName.split('/');\n const fallbackId = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';\n const id =\n typeof file.id === 'string' && file.id !== '' ? file.id : fallbackId;\n const originalFilename = metadata?.['original-filename'];\n const name =\n typeof originalFilename === 'string' ? originalFilename : rawName;\n const storage_session_id =\n typeof file.storage_session_id === 'string'\n ? file.storage_session_id\n : sessionId;\n const resource_id =\n typeof file.resource_id === 'string' && file.resource_id !== ''\n ? file.resource_id\n : (scope?.id ?? id);\n\n if (scope?.kind === 'skill') {\n return {\n storage_session_id,\n kind: 'skill',\n id,\n resource_id,\n name,\n version: scope.version,\n };\n }\n if (scope != null) {\n return {\n storage_session_id,\n kind: scope.kind,\n id,\n resource_id,\n name,\n };\n }\n return {\n storage_session_id,\n kind: 'user',\n id,\n resource_id: id,\n name,\n };\n}\n\n/**\n * Normalizes a tool name to Python identifier format.\n * Must match the Code API's `normalizePythonFunctionName` exactly:\n * 1. Replace hyphens and spaces with underscores\n * 2. Remove any other invalid characters\n * 3. Prefix with underscore if starts with number\n * 4. Append `_tool` if it's a Python keyword\n * @param name - The tool name to normalize\n * @returns Normalized Python-safe identifier\n */\nexport function normalizeToPythonIdentifier(name: string): string {\n let normalized = name.replace(/[-\\s]/g, '_');\n\n normalized = normalized.replace(/[^a-zA-Z0-9_]/g, '');\n\n if (/^[0-9]/.test(normalized)) {\n normalized = '_' + normalized;\n }\n\n if (PYTHON_KEYWORDS.has(normalized)) {\n normalized = normalized + '_tool';\n }\n\n return normalized;\n}\n\n/**\n * Extracts tool names that are actually called in the Python code.\n * Handles hyphen/underscore conversion since Python identifiers use underscores.\n * @param code - The Python code to analyze\n * @param toolNameMap - Map from normalized Python name to original tool name\n * @returns Set of original tool names found in the code\n */\nexport function extractUsedToolNames(\n code: string,\n toolNameMap: Map<string, string>\n): Set<string> {\n const usedTools = new Set<string>();\n\n for (const [pythonName, originalName] of toolNameMap) {\n const escapedName = pythonName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`\\\\b${escapedName}\\\\s*\\\\(`, 'g');\n\n if (pattern.test(code)) {\n usedTools.add(originalName);\n }\n }\n\n return usedTools;\n}\n\n/**\n * Filters tool definitions to only include tools actually used in the code.\n * Handles the hyphen-to-underscore conversion for Python compatibility.\n * @param toolDefs - All available tool definitions\n * @param code - The Python code to analyze\n * @param debug - Enable debug logging\n * @returns Filtered array of tool definitions\n */\nexport function filterToolsByUsage(\n toolDefs: t.LCTool[],\n code: string,\n debug = false\n): t.LCTool[] {\n const toolNameMap = new Map<string, string>();\n for (const tool of toolDefs) {\n const pythonName = normalizeToPythonIdentifier(tool.name);\n toolNameMap.set(pythonName, tool.name);\n }\n\n const usedToolNames = extractUsedToolNames(code, toolNameMap);\n\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Tool filtering: found ${usedToolNames.size}/${toolDefs.length} tools in code`\n );\n if (usedToolNames.size > 0) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Matched tools: ${Array.from(usedToolNames).join(', ')}`\n );\n }\n }\n\n if (usedToolNames.size === 0) {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n '[PTC Debug] No tools detected in code - sending all tools as fallback'\n );\n }\n return toolDefs;\n }\n\n return toolDefs.filter((tool) => usedToolNames.has(tool.name));\n}\n\n/**\n * Fetches files from a previous session to make them available for the current execution.\n * Files are returned as CodeEnvFile references to be included in the request.\n * @param baseUrl - The base URL for the Code API\n * @param sessionId - The session ID to fetch files from\n * @param scope - Resource scope used by CodeAPI to authorize the session\n * @param proxy - Optional HTTP proxy URL\n * @returns Array of CodeEnvFile references, or empty array if fetch fails\n */\nexport async function fetchSessionFiles(\n baseUrl: string,\n sessionId: string,\n proxy?: string,\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeEnvFile[]>;\nexport async function fetchSessionFiles(\n baseUrl: string,\n sessionId: string,\n scope: FetchSessionFilesScope,\n proxyOrAuthHeaders?: string | t.CodeApiAuthHeaders,\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeEnvFile[]>;\nexport async function fetchSessionFiles(\n baseUrl: string,\n sessionId: string,\n scopeOrProxy?: FetchSessionFilesScope | string,\n proxyOrAuthHeaders?: string | t.CodeApiAuthHeaders,\n scopedAuthHeaders?: t.CodeApiAuthHeaders\n): Promise<t.CodeEnvFile[]> {\n try {\n const scope = isFetchSessionFilesScope(scopeOrProxy)\n ? scopeOrProxy\n : undefined;\n let proxy: string | undefined;\n let authHeaders: t.CodeApiAuthHeaders | undefined;\n if (scope == null) {\n proxy = typeof scopeOrProxy === 'string' ? scopeOrProxy : undefined;\n authHeaders = isCodeApiAuthHeaders(proxyOrAuthHeaders)\n ? proxyOrAuthHeaders\n : undefined;\n } else if (typeof proxyOrAuthHeaders === 'string') {\n proxy = proxyOrAuthHeaders;\n authHeaders = scopedAuthHeaders;\n } else {\n authHeaders = proxyOrAuthHeaders ?? scopedAuthHeaders;\n }\n const query = new URLSearchParams({ detail: 'full' });\n if (scope != null) {\n query.set('kind', scope.kind);\n query.set('id', scope.id);\n if (scope.kind === 'skill') {\n query.set('version', String(scope.version));\n }\n }\n const filesEndpoint = `${baseUrl}/files/${encodeURIComponent(sessionId)}?${query.toString()}`;\n const resolvedAuthHeaders = await resolveCodeApiAuthHeaders(authHeaders);\n const fetchOptions: RequestInit = {\n method: 'GET',\n headers: {\n 'User-Agent': 'LibreChat/1.0',\n ...resolvedAuthHeaders,\n },\n };\n\n if (proxy != null && proxy !== '') {\n fetchOptions.agent = new HttpsProxyAgent(proxy);\n }\n\n const response = await fetch(filesEndpoint, fetchOptions);\n if (!response.ok) {\n throw new Error(\n await buildCodeApiHttpErrorMessage('GET', filesEndpoint, response)\n );\n }\n\n const files = await response.json();\n if (!Array.isArray(files) || files.length === 0) {\n return [];\n }\n\n return files\n .filter(isCodeApiSessionFileWire)\n .map((file) => normalizeSessionFile(file, sessionId, scope));\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to fetch files for session: ${sessionId}, ${(error as Error).message}`\n );\n return [];\n }\n}\n\n/**\n * Makes an HTTP request to the Code API.\n * @param endpoint - The API endpoint URL\n * @param body - The request body\n * @param proxy - Optional HTTP proxy URL\n * @returns The parsed API response\n */\nexport async function makeRequest(\n endpoint: string,\n body: Record<string, unknown>,\n proxy?: string,\n authHeaders?: t.CodeApiAuthHeaders\n): Promise<t.ProgrammaticExecutionResponse> {\n const resolvedAuthHeaders = await resolveCodeApiAuthHeaders(authHeaders);\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'LibreChat/1.0',\n ...resolvedAuthHeaders,\n },\n body: JSON.stringify(body),\n };\n\n if (proxy != null && proxy !== '') {\n fetchOptions.agent = new HttpsProxyAgent(proxy);\n }\n\n const response = await fetch(endpoint, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n await buildCodeApiHttpErrorMessage('POST', endpoint, response)\n );\n }\n\n return (await response.json()) as t.ProgrammaticExecutionResponse;\n}\n\n/**\n * Unwraps tool responses that may be formatted as tuples or content blocks.\n * MCP tools return [content, artifacts], we need to extract the raw data.\n * @param result - The raw result from tool.invoke()\n * @param isMCPTool - Whether this is an MCP tool (has mcp property)\n * @returns Unwrapped raw data (string, object, or parsed JSON)\n */\nexport function unwrapToolResponse(\n result: unknown,\n isMCPTool: boolean\n): unknown {\n // Only unwrap if this is an MCP tool and result is a tuple\n if (!isMCPTool) {\n return result;\n }\n\n /**\n * Checks if a value is a content block object (has type and text).\n */\n const isContentBlock = (value: unknown): boolean => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return typeof obj.type === 'string';\n };\n\n /**\n * Checks if an array is an array of content blocks.\n */\n const isContentBlockArray = (arr: unknown[]): boolean => {\n return arr.length > 0 && arr.every(isContentBlock);\n };\n\n /**\n * Extracts text from a single content block object.\n * Returns the text if it's a text block, otherwise returns null.\n */\n const extractTextFromBlock = (block: unknown): string | null => {\n if (typeof block !== 'object' || block === null) return null;\n const b = block as Record<string, unknown>;\n if (b.type === 'text' && typeof b.text === 'string') {\n return b.text;\n }\n return null;\n };\n\n /**\n * Extracts text from content blocks (array or single object).\n * Returns combined text or null if no text blocks found.\n */\n const extractTextFromContent = (content: unknown): string | null => {\n // Single content block object: { type: 'text', text: '...' }\n if (\n typeof content === 'object' &&\n content !== null &&\n !Array.isArray(content)\n ) {\n const text = extractTextFromBlock(content);\n if (text !== null) return text;\n }\n\n // Array of content blocks: [{ type: 'text', text: '...' }, ...]\n if (Array.isArray(content) && content.length > 0) {\n const texts = content\n .map(extractTextFromBlock)\n .filter((t): t is string => t !== null);\n if (texts.length > 0) {\n return texts.join('\\n');\n }\n }\n\n return null;\n };\n\n /**\n * Tries to parse a string as JSON if it looks like JSON.\n */\n const maybeParseJSON = (str: string): unknown => {\n const trimmed = str.trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n return JSON.parse(trimmed);\n } catch {\n return str;\n }\n }\n return str;\n };\n\n // Handle array of content blocks at top level FIRST\n // (before checking for tuple, since both are arrays)\n if (Array.isArray(result) && isContentBlockArray(result)) {\n const extractedText = extractTextFromContent(result);\n if (extractedText !== null) {\n return maybeParseJSON(extractedText);\n }\n }\n\n // Check if result is a tuple/array with [content, artifacts]\n if (Array.isArray(result) && result.length >= 1) {\n const [content] = result;\n\n // If first element is a string, return it (possibly parsed as JSON)\n if (typeof content === 'string') {\n return maybeParseJSON(content);\n }\n\n // Try to extract text from content blocks\n const extractedText = extractTextFromContent(content);\n if (extractedText !== null) {\n return maybeParseJSON(extractedText);\n }\n\n // If first element is an object (but not a text block), return it\n if (typeof content === 'object' && content !== null) {\n return content;\n }\n }\n\n // Handle single content block object at top level (not in tuple)\n const extractedText = extractTextFromContent(result);\n if (extractedText !== null) {\n return maybeParseJSON(extractedText);\n }\n\n // Not a formatted response, return as-is\n return result;\n}\n\n/**\n * Executes tools in parallel when requested by the API.\n * Uses Promise.all for parallel execution, catching individual errors.\n * Unwraps formatted responses (e.g., MCP tool tuples) to raw data.\n * @param toolCalls - Array of tool calls from the API\n * @param toolMap - Map of tool names to executable tools\n * @returns Array of tool results\n */\nexport async function executeTools(\n toolCalls: t.PTCToolCall[],\n toolMap: t.ToolMap,\n programmaticToolName = Constants.PROGRAMMATIC_TOOL_CALLING\n): Promise<t.PTCToolResult[]> {\n const executions = toolCalls.map(async (call): Promise<t.PTCToolResult> => {\n const tool = toolMap.get(call.name);\n\n if (!tool) {\n return {\n call_id: call.id,\n result: null,\n is_error: true,\n error_message: `Tool '${call.name}' not found. Available tools: ${Array.from(toolMap.keys()).join(', ')}`,\n };\n }\n\n try {\n const result = await tool.invoke(call.input, {\n metadata: { [programmaticToolName]: true },\n });\n\n const isMCPTool = tool.mcp === true;\n const unwrappedResult = unwrapToolResponse(result, isMCPTool);\n\n return {\n call_id: call.id,\n result: unwrappedResult,\n is_error: false,\n };\n } catch (error) {\n return {\n call_id: call.id,\n result: null,\n is_error: true,\n error_message: (error as Error).message || 'Tool execution failed',\n };\n }\n });\n\n return await Promise.all(executions);\n}\n\n/**\n * Formats the completed response for the agent.\n *\n * Output includes stdout/stderr plus a compact session-file summary\n * when artifacts were persisted. The artifact still carries every\n * file so the host's session map stays in sync.\n *\n * @param response - The completed API response\n * @returns Tuple of [formatted string, artifact]\n */\nexport function formatCompletedResponse(\n response: t.ProgrammaticExecutionResponse,\n sourceCode = ''\n): [string, t.ProgrammaticExecutionArtifact] {\n let formatted = '';\n\n if (response.stdout != null && response.stdout !== '') {\n formatted += `stdout:\\n${response.stdout}\\n`;\n } else {\n formatted += emptyOutputMessage;\n }\n\n if (response.stderr != null && response.stderr !== '') {\n formatted += `stderr:\\n${response.stderr}\\n`;\n }\n\n const outputWithReminder = appendTmpScratchReminder(formatted, sourceCode);\n\n return [\n appendCodeSessionFileSummary(outputWithReminder, response.files),\n {\n session_id: response.session_id,\n files: response.files,\n } satisfies t.ProgrammaticExecutionArtifact,\n ];\n}\n\n// ============================================================================\n// Tool Factory\n// ============================================================================\n\n/**\n * Creates a Programmatic Tool Calling tool for complex multi-tool workflows.\n *\n * This tool enables AI agents to write Python code that orchestrates multiple\n * tool calls programmatically, reducing LLM round-trips and token usage.\n *\n * The tool map must be provided at runtime via config.configurable.toolMap.\n *\n * @param params - Configuration parameters (baseUrl, maxRoundTrips, proxy)\n * @returns A LangChain DynamicStructuredTool for programmatic tool calling\n *\n * @example\n * const ptcTool = createProgrammaticToolCallingTool({ maxRoundTrips: 20 });\n *\n * const [output, artifact] = await ptcTool.invoke(\n * { code, tools },\n * { configurable: { toolMap } }\n * );\n */\nexport function createProgrammaticToolCallingTool(\n initParams: t.ProgrammaticToolCallingParams = {}\n): DynamicStructuredTool {\n const baseUrl = initParams.baseUrl ?? getCodeBaseURL();\n const maxRoundTrips = initParams.maxRoundTrips ?? DEFAULT_MAX_ROUND_TRIPS;\n const maxRunTimeoutMs = resolveCodeApiRunTimeoutMs(initParams.runTimeoutMs);\n const proxy = initParams.proxy ?? process.env.PROXY;\n const debug = initParams.debug ?? process.env.PTC_DEBUG === 'true';\n const EXEC_ENDPOINT = `${baseUrl}/exec/programmatic`;\n\n return tool(\n async (rawParams, config) => {\n const params = rawParams as { code: string; timeout?: number };\n const { code } = params;\n const timeout = clampCodeApiRunTimeoutMs(params.timeout, maxRunTimeoutMs);\n\n // Extra params injected by ToolNode (follows web_search pattern).\n const toolCall = (config.toolCall ?? {}) as ToolCall &\n Partial<t.ProgrammaticCache> & {\n session_id?: string;\n _injected_files?: t.CodeEnvFile[];\n };\n const { toolMap, toolDefs, session_id, _injected_files } = toolCall;\n\n if (toolMap == null || toolMap.size === 0) {\n throw new Error(\n 'No toolMap provided. ' +\n 'ToolNode should inject this from AgentContext when invoked through the graph.'\n );\n }\n\n if (toolDefs == null || toolDefs.length === 0) {\n throw new Error(\n 'No tool definitions provided. ' +\n 'Either pass tools in the input or ensure ToolNode injects toolDefs.'\n );\n }\n\n let roundTrip = 0;\n\n try {\n // ====================================================================\n // Phase 1: Filter tools and make initial request\n // ====================================================================\n\n const effectiveTools = filterToolsByUsage(toolDefs, code, debug);\n\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Sending ${effectiveTools.length} tools to API ` +\n `(filtered from ${toolDefs.length})`\n );\n }\n\n /**\n * File injection: `_injected_files` from ToolNode session\n * context. The legacy `/files/<session_id>` HTTP fallback was\n * removed (see `CodeExecutor.ts`) — codeapi's sessionAuth now\n * requires kind/id query params unavailable at this point.\n */\n let files: t.CodeEnvFile[] | undefined;\n if (_injected_files && _injected_files.length > 0) {\n files = _injected_files;\n } else if (session_id != null && session_id.length > 0) {\n // eslint-disable-next-line no-console\n console.debug(\n `[ProgrammaticToolCalling] No injected files for session_id=${session_id} — exec will run without input files`\n );\n }\n\n let response = await makeRequest(\n EXEC_ENDPOINT,\n {\n code,\n tools: effectiveTools,\n session_id,\n timeout,\n ...(files && files.length > 0 ? { files } : {}),\n },\n proxy,\n initParams.authHeaders\n );\n\n // ====================================================================\n // Phase 2: Handle response loop\n // ====================================================================\n\n while (response.status === 'tool_call_required') {\n roundTrip++;\n\n if (roundTrip > maxRoundTrips) {\n throw new Error(\n `Exceeded maximum round trips (${maxRoundTrips}). ` +\n 'This may indicate an infinite loop, excessive tool calls, ' +\n 'or a logic error in your code.'\n );\n }\n\n if (debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[PTC Debug] Round trip ${roundTrip}: ${response.tool_calls?.length ?? 0} tool(s) to execute`\n );\n }\n\n const toolResults = await executeTools(\n response.tool_calls ?? [],\n toolMap\n );\n\n response = await makeRequest(\n EXEC_ENDPOINT,\n {\n continuation_token: response.continuation_token,\n tool_results: toolResults,\n },\n proxy,\n initParams.authHeaders\n );\n }\n\n // ====================================================================\n // Phase 3: Handle final state\n // ====================================================================\n\n if (response.status === 'completed') {\n return formatCompletedResponse(response, code);\n }\n\n if (response.status === 'error') {\n throw new Error(\n `Execution error: ${response.error}` +\n (response.stderr != null && response.stderr !== ''\n ? `\\n\\nStderr:\\n${response.stderr}`\n : '')\n );\n }\n\n throw new Error(`Unexpected response status: ${response.status}`);\n } catch (error) {\n const messageWithReminder = appendFailedExecutionFileReminder(\n (error as Error).message,\n code\n );\n throw new Error(\n `Programmatic execution failed: ${messageWithReminder}`\n );\n }\n },\n {\n name: Constants.PROGRAMMATIC_TOOL_CALLING,\n description: ProgrammaticToolCallingDescription,\n schema: createProgrammaticToolCallingSchema(maxRunTimeoutMs),\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n"],"names":["config","resolveCodeApiRunTimeoutMs","CODE_ARTIFACT_PATH_GUIDANCE","createCodeApiRunTimeoutSchema","Constants","resolveCodeApiAuthHeaders","HttpsProxyAgent","buildCodeApiHttpErrorMessage","emptyOutputMessage","appendTmpScratchReminder","appendCodeSessionFileSummary","getCodeBaseURL","tool","clampCodeApiRunTimeoutMs","appendFailedExecutionFileReminder"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ var executeHooks = require('../hooks/executeHooks.cjs');
|
|
|
14
14
|
require('../hooks/createWorkspacePolicyHook.cjs');
|
|
15
15
|
var langchain = require('../messages/langchain.cjs');
|
|
16
16
|
var toolOutputReferences = require('./toolOutputReferences.cjs');
|
|
17
|
+
var CodeSessionFileSummary = require('./CodeSessionFileSummary.cjs');
|
|
17
18
|
require('./local/CompileCheckTool.cjs');
|
|
18
19
|
require('path');
|
|
19
20
|
require('fs/promises');
|
|
@@ -647,8 +648,9 @@ class ToolNode extends run.RunnableCallable {
|
|
|
647
648
|
* Both session_id and _injected_files are injected directly to invokeParams
|
|
648
649
|
* (not inside args) so they bypass Zod schema validation and reach config.toolCall.
|
|
649
650
|
*
|
|
650
|
-
* session_id is always injected when available
|
|
651
|
-
*
|
|
651
|
+
* session_id is always injected when available, but concrete file refs
|
|
652
|
+
* still need to travel through `_injected_files`; the legacy
|
|
653
|
+
* `/files/<session_id>` fallback was removed from the executors.
|
|
652
654
|
*/
|
|
653
655
|
if (_enum.CODE_EXECUTION_TOOLS.has(call.name)) {
|
|
654
656
|
const codeSession = this.sessions?.get(_enum.Constants.EXECUTE_CODE);
|
|
@@ -689,9 +691,10 @@ class ToolNode extends run.RunnableCallable {
|
|
|
689
691
|
if (this.toolOutputRegistry != null || unresolvedRefs.length > 0) {
|
|
690
692
|
if (typeof toolMsg.content === 'string') {
|
|
691
693
|
const rawContent = toolMsg.content;
|
|
694
|
+
const registryContent = CodeSessionFileSummary.stripCodeSessionFileSummary(rawContent);
|
|
692
695
|
const llmContent = truncation.truncateToolResultContent(rawContent, this.maxToolResultChars);
|
|
693
696
|
toolMsg.content = llmContent;
|
|
694
|
-
const refMeta = this.recordOutputReference(runId,
|
|
697
|
+
const refMeta = this.recordOutputReference(runId, registryContent, refKey, unresolvedRefs);
|
|
695
698
|
if (refMeta != null) {
|
|
696
699
|
toolMsg.additional_kwargs = {
|
|
697
700
|
...toolMsg.additional_kwargs,
|
|
@@ -728,7 +731,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
728
731
|
}
|
|
729
732
|
const rawContent = typeof output === 'string' ? output : JSON.stringify(output);
|
|
730
733
|
const truncated = truncation.truncateToolResultContent(rawContent, this.maxToolResultChars);
|
|
731
|
-
const refMeta = this.recordOutputReference(runId, rawContent, refKey, unresolvedRefs);
|
|
734
|
+
const refMeta = this.recordOutputReference(runId, CodeSessionFileSummary.stripCodeSessionFileSummary(rawContent), refKey, unresolvedRefs);
|
|
732
735
|
return new messages.ToolMessage({
|
|
733
736
|
status: 'success',
|
|
734
737
|
name: tool.name,
|
|
@@ -2058,7 +2061,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2058
2061
|
turn != null
|
|
2059
2062
|
? toolOutputReferences.buildReferenceKey(batchIndex, turn)
|
|
2060
2063
|
: undefined;
|
|
2061
|
-
const successRefMeta = this.recordOutputReference(registryRunId, registryRaw, refKey, unresolved);
|
|
2064
|
+
const successRefMeta = this.recordOutputReference(registryRunId, CodeSessionFileSummary.stripCodeSessionFileSummary(registryRaw), refKey, unresolved);
|
|
2062
2065
|
toolMessage = new messages.ToolMessage({
|
|
2063
2066
|
status: 'success',
|
|
2064
2067
|
name: toolName,
|