@langchain/openai 1.1.2 → 1.2.0-dev-1765431816670
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/CHANGELOG.md +6 -0
- package/README.md +583 -2
- package/dist/azure/chat_models/common.d.cts.map +1 -1
- package/dist/azure/chat_models/common.d.ts +1 -0
- package/dist/azure/chat_models/common.d.ts.map +1 -1
- package/dist/azure/chat_models/completions.d.cts.map +1 -1
- package/dist/azure/chat_models/completions.d.ts.map +1 -1
- package/dist/azure/chat_models/index.d.cts +1 -1
- package/dist/azure/chat_models/index.d.cts.map +1 -1
- package/dist/azure/chat_models/index.d.ts.map +1 -1
- package/dist/azure/chat_models/responses.d.cts.map +1 -1
- package/dist/azure/chat_models/responses.d.ts.map +1 -1
- package/dist/azure/embeddings.d.cts.map +1 -1
- package/dist/azure/embeddings.d.ts.map +1 -1
- package/dist/azure/llms.d.cts +0 -1
- package/dist/azure/llms.d.cts.map +1 -1
- package/dist/azure/llms.d.ts +0 -1
- package/dist/azure/llms.d.ts.map +1 -1
- package/dist/chat_models/base.cjs +5 -1
- package/dist/chat_models/base.cjs.map +1 -1
- package/dist/chat_models/base.d.cts +8 -22
- package/dist/chat_models/base.d.cts.map +1 -1
- package/dist/chat_models/base.d.ts +6 -20
- package/dist/chat_models/base.d.ts.map +1 -1
- package/dist/chat_models/base.js +6 -2
- package/dist/chat_models/base.js.map +1 -1
- package/dist/chat_models/completions.cjs.map +1 -1
- package/dist/chat_models/completions.d.cts +1 -3
- package/dist/chat_models/completions.d.cts.map +1 -1
- package/dist/chat_models/completions.d.ts +1 -3
- package/dist/chat_models/completions.d.ts.map +1 -1
- package/dist/chat_models/completions.js.map +1 -1
- package/dist/chat_models/index.d.cts +42 -4
- package/dist/chat_models/index.d.cts.map +1 -1
- package/dist/chat_models/index.d.ts +42 -4
- package/dist/chat_models/index.d.ts.map +1 -1
- package/dist/chat_models/responses.d.cts +2 -2
- package/dist/chat_models/responses.d.cts.map +1 -1
- package/dist/chat_models/responses.d.ts +2 -2
- package/dist/chat_models/responses.d.ts.map +1 -1
- package/dist/converters/completions.cjs +22 -12
- package/dist/converters/completions.cjs.map +1 -1
- package/dist/converters/completions.d.cts +0 -1
- package/dist/converters/completions.d.cts.map +1 -1
- package/dist/converters/completions.d.ts +0 -1
- package/dist/converters/completions.d.ts.map +1 -1
- package/dist/converters/completions.js +23 -13
- package/dist/converters/completions.js.map +1 -1
- package/dist/converters/index.d.ts +2 -0
- package/dist/converters/responses.cjs +37 -4
- package/dist/converters/responses.cjs.map +1 -1
- package/dist/converters/responses.d.cts.map +1 -1
- package/dist/converters/responses.d.ts.map +1 -1
- package/dist/converters/responses.js +39 -6
- package/dist/converters/responses.js.map +1 -1
- package/dist/embeddings.d.cts +0 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts +0 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +2 -2
- package/dist/llms.d.cts +0 -1
- package/dist/llms.d.cts.map +1 -1
- package/dist/llms.d.ts +0 -1
- package/dist/llms.d.ts.map +1 -1
- package/dist/tools/applyPatch.cjs +116 -0
- package/dist/tools/applyPatch.cjs.map +1 -0
- package/dist/tools/applyPatch.d.cts +148 -0
- package/dist/tools/applyPatch.d.cts.map +1 -0
- package/dist/tools/applyPatch.d.ts +148 -0
- package/dist/tools/applyPatch.d.ts.map +1 -0
- package/dist/tools/applyPatch.js +115 -0
- package/dist/tools/applyPatch.js.map +1 -0
- package/dist/tools/codeInterpreter.cjs +95 -0
- package/dist/tools/codeInterpreter.cjs.map +1 -0
- package/dist/tools/codeInterpreter.d.cts +125 -0
- package/dist/tools/codeInterpreter.d.cts.map +1 -0
- package/dist/tools/codeInterpreter.d.ts +125 -0
- package/dist/tools/codeInterpreter.d.ts.map +1 -0
- package/dist/tools/codeInterpreter.js +94 -0
- package/dist/tools/codeInterpreter.js.map +1 -0
- package/dist/tools/computerUse.cjs +240 -0
- package/dist/tools/computerUse.cjs.map +1 -0
- package/dist/tools/computerUse.d.cts +234 -0
- package/dist/tools/computerUse.d.cts.map +1 -0
- package/dist/tools/computerUse.d.ts +234 -0
- package/dist/tools/computerUse.d.ts.map +1 -0
- package/dist/tools/computerUse.js +239 -0
- package/dist/tools/computerUse.js.map +1 -0
- package/dist/tools/custom.d.cts +1 -1
- package/dist/tools/custom.d.cts.map +1 -1
- package/dist/tools/custom.d.ts.map +1 -1
- package/dist/tools/dalle.d.cts +1 -2
- package/dist/tools/dalle.d.cts.map +1 -1
- package/dist/tools/dalle.d.ts +1 -2
- package/dist/tools/dalle.d.ts.map +1 -1
- package/dist/tools/fileSearch.cjs +137 -0
- package/dist/tools/fileSearch.cjs.map +1 -0
- package/dist/tools/fileSearch.d.cts +224 -0
- package/dist/tools/fileSearch.d.cts.map +1 -0
- package/dist/tools/fileSearch.d.ts +224 -0
- package/dist/tools/fileSearch.d.ts.map +1 -0
- package/dist/tools/fileSearch.js +136 -0
- package/dist/tools/fileSearch.js.map +1 -0
- package/dist/tools/imageGeneration.cjs +128 -0
- package/dist/tools/imageGeneration.cjs.map +1 -0
- package/dist/tools/imageGeneration.d.cts +199 -0
- package/dist/tools/imageGeneration.d.cts.map +1 -0
- package/dist/tools/imageGeneration.d.ts +199 -0
- package/dist/tools/imageGeneration.d.ts.map +1 -0
- package/dist/tools/imageGeneration.js +127 -0
- package/dist/tools/imageGeneration.js.map +1 -0
- package/dist/tools/index.cjs +26 -0
- package/dist/tools/index.cjs.map +1 -0
- package/dist/tools/index.d.cts +27 -0
- package/dist/tools/index.d.cts.map +1 -0
- package/dist/tools/index.d.ts +27 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +26 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/localShell.cjs +145 -0
- package/dist/tools/localShell.cjs.map +1 -0
- package/dist/tools/localShell.d.cts +167 -0
- package/dist/tools/localShell.d.cts.map +1 -0
- package/dist/tools/localShell.d.ts +167 -0
- package/dist/tools/localShell.d.ts.map +1 -0
- package/dist/tools/localShell.js +144 -0
- package/dist/tools/localShell.js.map +1 -0
- package/dist/tools/mcp.cjs +53 -0
- package/dist/tools/mcp.cjs.map +1 -0
- package/dist/tools/mcp.d.cts +177 -0
- package/dist/tools/mcp.d.cts.map +1 -0
- package/dist/tools/mcp.d.ts +177 -0
- package/dist/tools/mcp.d.ts.map +1 -0
- package/dist/tools/mcp.js +52 -0
- package/dist/tools/mcp.js.map +1 -0
- package/dist/tools/shell.cjs +163 -0
- package/dist/tools/shell.cjs.map +1 -0
- package/dist/tools/shell.d.cts +221 -0
- package/dist/tools/shell.d.cts.map +1 -0
- package/dist/tools/shell.d.ts +221 -0
- package/dist/tools/shell.d.ts.map +1 -0
- package/dist/tools/shell.js +162 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/tools/webSearch.cjs +73 -0
- package/dist/tools/webSearch.cjs.map +1 -0
- package/dist/tools/webSearch.d.cts +130 -0
- package/dist/tools/webSearch.d.cts.map +1 -0
- package/dist/tools/webSearch.d.ts +130 -0
- package/dist/tools/webSearch.d.ts.map +1 -0
- package/dist/tools/webSearch.js +72 -0
- package/dist/tools/webSearch.js.map +1 -0
- package/dist/types.d.cts +2 -4
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +1 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/azure.d.cts +1 -5
- package/dist/utils/azure.d.cts.map +1 -1
- package/dist/utils/azure.d.ts +1 -5
- package/dist/utils/azure.d.ts.map +1 -1
- package/dist/utils/client.d.cts.map +1 -1
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/misc.cjs +6 -0
- package/dist/utils/misc.cjs.map +1 -1
- package/dist/utils/misc.d.cts +1 -1
- package/dist/utils/misc.d.cts.map +1 -1
- package/dist/utils/misc.d.ts +1 -1
- package/dist/utils/misc.d.ts.map +1 -1
- package/dist/utils/misc.js +6 -1
- package/dist/utils/misc.js.map +1 -1
- package/dist/utils/prompts.d.cts +0 -1
- package/dist/utils/prompts.d.cts.map +1 -1
- package/dist/utils/prompts.d.ts +0 -1
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/tools.cjs +39 -1
- package/dist/utils/tools.cjs.map +1 -1
- package/dist/utils/tools.d.cts.map +1 -1
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +37 -2
- package/dist/utils/tools.js.map +1 -1
- package/package.json +18 -15
- package/dist/langchain-core/dist/callbacks/base.d.ts +0 -1
- package/dist/langchain-core/dist/callbacks/manager.d.ts +0 -2
- package/dist/langchain-core/dist/language_models/base.d.ts +0 -5
- package/dist/langchain-core/dist/language_models/chat_models.d.cts +0 -13
- package/dist/langchain-core/dist/language_models/chat_models.d.cts.map +0 -1
- package/dist/langchain-core/dist/language_models/chat_models.d.ts +0 -20
- package/dist/langchain-core/dist/language_models/chat_models.d.ts.map +0 -1
- package/dist/langchain-core/dist/runnables/base.d.ts +0 -7
- package/dist/langchain-core/dist/runnables/graph.d.ts +0 -1
- package/dist/langchain-core/dist/runnables/types.d.ts +0 -2
- package/dist/langchain-core/dist/tools/types.d.ts +0 -5
- package/dist/langchain-core/dist/tracers/base.d.ts +0 -2
- package/dist/langchain-core/dist/tracers/event_stream.d.ts +0 -1
- package/dist/langchain-core/dist/tracers/log_stream.d.ts +0 -3
- package/dist/langchain-core/dist/types/_internal.d.cts +0 -11
- package/dist/langchain-core/dist/types/_internal.d.cts.map +0 -1
- package/dist/langchain-core/dist/types/_internal.d.ts +0 -11
- package/dist/langchain-core/dist/types/_internal.d.ts.map +0 -1
- package/dist/langchain-core/dist/utils/stream.d.cts +0 -26
- package/dist/langchain-core/dist/utils/stream.d.cts.map +0 -1
- package/dist/langchain-core/dist/utils/stream.d.ts +0 -26
- package/dist/langchain-core/dist/utils/stream.d.ts.map +0 -1
- package/dist/langchain-core/dist/utils/types/index.d.ts +0 -1
- package/dist/langchain-core/dist/utils/types/zod.d.ts +0 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const __langchain_core_tools = require_rolldown_runtime.__toESM(require("@langchain/core/tools"));
|
|
3
|
+
const zod_v4 = require_rolldown_runtime.__toESM(require("zod/v4"));
|
|
4
|
+
|
|
5
|
+
//#region src/tools/localShell.ts
|
|
6
|
+
const LocalShellExecActionSchema = zod_v4.z.object({
|
|
7
|
+
type: zod_v4.z.literal("exec"),
|
|
8
|
+
command: zod_v4.z.array(zod_v4.z.string()),
|
|
9
|
+
env: zod_v4.z.record(zod_v4.z.string(), zod_v4.z.string()).optional(),
|
|
10
|
+
working_directory: zod_v4.z.string().optional(),
|
|
11
|
+
timeout_ms: zod_v4.z.number().optional(),
|
|
12
|
+
user: zod_v4.z.string().optional()
|
|
13
|
+
});
|
|
14
|
+
const LocalShellActionSchema = zod_v4.z.discriminatedUnion("type", [LocalShellExecActionSchema]);
|
|
15
|
+
const TOOL_NAME = "local_shell";
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Local Shell tool that allows models to run shell commands locally
|
|
18
|
+
* on a machine you provide. Commands are executed inside your own runtime—
|
|
19
|
+
* the API only returns the instructions, but does not execute them on OpenAI infrastructure.
|
|
20
|
+
*
|
|
21
|
+
* **Important**: The local shell tool is designed to work with
|
|
22
|
+
* [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.
|
|
23
|
+
*
|
|
24
|
+
* **How it works**:
|
|
25
|
+
* The tool operates in a continuous loop:
|
|
26
|
+
* 1. Model sends shell commands (`local_shell_call` with `exec` action)
|
|
27
|
+
* 2. Your code executes the command locally
|
|
28
|
+
* 3. You return the output back to the model
|
|
29
|
+
* 4. Repeat until the task is complete
|
|
30
|
+
*
|
|
31
|
+
* **Security Warning**: Running arbitrary shell commands can be dangerous.
|
|
32
|
+
* Always sandbox execution or add strict allow/deny-lists before forwarding
|
|
33
|
+
* a command to the system shell.
|
|
34
|
+
*
|
|
35
|
+
* @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}
|
|
36
|
+
*
|
|
37
|
+
* @param options - Optional configuration for the Local Shell tool
|
|
38
|
+
* @returns A Local Shell tool that can be passed to `bindTools`
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { ChatOpenAI, tools } from "@langchain/openai";
|
|
43
|
+
* import { exec } from "child_process";
|
|
44
|
+
* import { promisify } from "util";
|
|
45
|
+
*
|
|
46
|
+
* const execAsync = promisify(exec);
|
|
47
|
+
* const model = new ChatOpenAI({ model: "codex-mini-latest" });
|
|
48
|
+
*
|
|
49
|
+
* // With execute callback for automatic command handling
|
|
50
|
+
* const shell = tools.localShell({
|
|
51
|
+
* execute: async (action) => {
|
|
52
|
+
* const { command, env, working_directory, timeout_ms } = action;
|
|
53
|
+
* const result = await execAsync(command.join(' '), {
|
|
54
|
+
* cwd: working_directory ?? process.cwd(),
|
|
55
|
+
* env: { ...process.env, ...env },
|
|
56
|
+
* timeout: timeout_ms ?? undefined,
|
|
57
|
+
* });
|
|
58
|
+
* return result.stdout + result.stderr;
|
|
59
|
+
* },
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* const llmWithShell = model.bindTools([shell]);
|
|
63
|
+
* const response = await llmWithShell.invoke(
|
|
64
|
+
* "List files in the current directory"
|
|
65
|
+
* );
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // Without execute callback (manual handling)
|
|
71
|
+
* const shell = tools.localShell();
|
|
72
|
+
*
|
|
73
|
+
* const response = await model.invoke("List files", {
|
|
74
|
+
* tools: [shell],
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* // Access the shell call from the response
|
|
78
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
79
|
+
* (output) => output.type === "local_shell_call"
|
|
80
|
+
* );
|
|
81
|
+
* if (shellCall) {
|
|
82
|
+
* console.log("Command to execute:", shellCall.action.command);
|
|
83
|
+
* // Execute the command manually, then send back the output
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* // Full shell loop example
|
|
90
|
+
* async function shellLoop(model, task) {
|
|
91
|
+
* let response = await model.invoke(task, {
|
|
92
|
+
* tools: [tools.localShell()],
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* while (true) {
|
|
96
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
97
|
+
* (output) => output.type === "local_shell_call"
|
|
98
|
+
* );
|
|
99
|
+
*
|
|
100
|
+
* if (!shellCall) break;
|
|
101
|
+
*
|
|
102
|
+
* // Execute command (with proper sandboxing!)
|
|
103
|
+
* const output = await executeCommand(shellCall.action);
|
|
104
|
+
*
|
|
105
|
+
* // Send output back to model
|
|
106
|
+
* response = await model.invoke([
|
|
107
|
+
* response,
|
|
108
|
+
* {
|
|
109
|
+
* type: "local_shell_call_output",
|
|
110
|
+
* id: shellCall.call_id,
|
|
111
|
+
* output: output,
|
|
112
|
+
* },
|
|
113
|
+
* ], {
|
|
114
|
+
* tools: [tools.localShell()],
|
|
115
|
+
* });
|
|
116
|
+
* }
|
|
117
|
+
*
|
|
118
|
+
* return response;
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* - Only available through the Responses API (not Chat Completions)
|
|
124
|
+
* - Designed for use with `codex-mini-latest` model
|
|
125
|
+
* - Commands are provided as argv tokens in `action.command`
|
|
126
|
+
* - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`
|
|
127
|
+
* - Always sandbox or validate commands before execution
|
|
128
|
+
* - The `timeout_ms` from the model is only a hint—enforce your own limits
|
|
129
|
+
*/
|
|
130
|
+
function localShell(options) {
|
|
131
|
+
const shellTool = (0, __langchain_core_tools.tool)(options.execute, {
|
|
132
|
+
name: TOOL_NAME,
|
|
133
|
+
description: "Execute shell commands locally on the machine. Commands are provided as argv tokens.",
|
|
134
|
+
schema: LocalShellActionSchema
|
|
135
|
+
});
|
|
136
|
+
shellTool.extras = {
|
|
137
|
+
...shellTool.extras ?? {},
|
|
138
|
+
providerToolDefinition: { type: "local_shell" }
|
|
139
|
+
};
|
|
140
|
+
return shellTool;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
144
|
+
exports.localShell = localShell;
|
|
145
|
+
//# sourceMappingURL=localShell.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localShell.cjs","names":["z","options: LocalShellOptions"],"sources":["../../src/tools/localShell.ts"],"sourcesContent":["import { z } from \"zod/v4\";\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { tool, type DynamicStructuredTool } from \"@langchain/core/tools\";\n\n/**\n * Re-export action type from OpenAI SDK for convenience.\n * The action contains command details like argv tokens, environment variables,\n * working directory, timeout, and user.\n */\nexport type LocalShellAction =\n OpenAIClient.Responses.ResponseOutputItem.LocalShellCall.Action;\n\n// Zod schema for local shell exec action\nexport const LocalShellExecActionSchema = z.object({\n type: z.literal(\"exec\"),\n command: z.array(z.string()),\n env: z.record(z.string(), z.string()).optional(),\n working_directory: z.string().optional(),\n timeout_ms: z.number().optional(),\n user: z.string().optional(),\n});\n\n// Schema for all local shell actions (currently only exec)\nexport const LocalShellActionSchema = z.discriminatedUnion(\"type\", [\n LocalShellExecActionSchema,\n]);\n\n/**\n * Options for the Local Shell tool.\n */\nexport interface LocalShellOptions {\n /**\n * Optional execute function that handles shell command execution.\n * This function receives the action input and should return the command output\n * (stdout + stderr combined).\n *\n * If not provided, you'll need to handle action execution manually by\n * checking `local_shell_call` outputs in the response.\n *\n * @example\n * ```typescript\n * execute: async (action) => {\n * const result = await exec(action.command.join(' '), {\n * cwd: action.working_directory,\n * env: { ...process.env, ...action.env },\n * timeout: action.timeout_ms,\n * });\n * return result.stdout + result.stderr;\n * }\n * ```\n */\n execute: (action: LocalShellAction) => string | Promise<string>;\n}\n\n/**\n * OpenAI Local Shell tool type for the Responses API.\n */\nexport type LocalShellTool = OpenAIClient.Responses.Tool.LocalShell;\n\nconst TOOL_NAME = \"local_shell\";\n\n/**\n * Creates a Local Shell tool that allows models to run shell commands locally\n * on a machine you provide. Commands are executed inside your own runtime—\n * the API only returns the instructions, but does not execute them on OpenAI infrastructure.\n *\n * **Important**: The local shell tool is designed to work with\n * [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.\n *\n * **How it works**:\n * The tool operates in a continuous loop:\n * 1. Model sends shell commands (`local_shell_call` with `exec` action)\n * 2. Your code executes the command locally\n * 3. You return the output back to the model\n * 4. Repeat until the task is complete\n *\n * **Security Warning**: Running arbitrary shell commands can be dangerous.\n * Always sandbox execution or add strict allow/deny-lists before forwarding\n * a command to the system shell.\n *\n * @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}\n *\n * @param options - Optional configuration for the Local Shell tool\n * @returns A Local Shell tool that can be passed to `bindTools`\n *\n * @example\n * ```typescript\n * import { ChatOpenAI, tools } from \"@langchain/openai\";\n * import { exec } from \"child_process\";\n * import { promisify } from \"util\";\n *\n * const execAsync = promisify(exec);\n * const model = new ChatOpenAI({ model: \"codex-mini-latest\" });\n *\n * // With execute callback for automatic command handling\n * const shell = tools.localShell({\n * execute: async (action) => {\n * const { command, env, working_directory, timeout_ms } = action;\n * const result = await execAsync(command.join(' '), {\n * cwd: working_directory ?? process.cwd(),\n * env: { ...process.env, ...env },\n * timeout: timeout_ms ?? undefined,\n * });\n * return result.stdout + result.stderr;\n * },\n * });\n *\n * const llmWithShell = model.bindTools([shell]);\n * const response = await llmWithShell.invoke(\n * \"List files in the current directory\"\n * );\n * ```\n *\n * @example\n * ```typescript\n * // Without execute callback (manual handling)\n * const shell = tools.localShell();\n *\n * const response = await model.invoke(\"List files\", {\n * tools: [shell],\n * });\n *\n * // Access the shell call from the response\n * const shellCall = response.additional_kwargs.tool_outputs?.find(\n * (output) => output.type === \"local_shell_call\"\n * );\n * if (shellCall) {\n * console.log(\"Command to execute:\", shellCall.action.command);\n * // Execute the command manually, then send back the output\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Full shell loop example\n * async function shellLoop(model, task) {\n * let response = await model.invoke(task, {\n * tools: [tools.localShell()],\n * });\n *\n * while (true) {\n * const shellCall = response.additional_kwargs.tool_outputs?.find(\n * (output) => output.type === \"local_shell_call\"\n * );\n *\n * if (!shellCall) break;\n *\n * // Execute command (with proper sandboxing!)\n * const output = await executeCommand(shellCall.action);\n *\n * // Send output back to model\n * response = await model.invoke([\n * response,\n * {\n * type: \"local_shell_call_output\",\n * id: shellCall.call_id,\n * output: output,\n * },\n * ], {\n * tools: [tools.localShell()],\n * });\n * }\n *\n * return response;\n * }\n * ```\n *\n * @remarks\n * - Only available through the Responses API (not Chat Completions)\n * - Designed for use with `codex-mini-latest` model\n * - Commands are provided as argv tokens in `action.command`\n * - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`\n * - Always sandbox or validate commands before execution\n * - The `timeout_ms` from the model is only a hint—enforce your own limits\n */\nexport function localShell(options: LocalShellOptions) {\n const shellTool = tool(options.execute, {\n name: TOOL_NAME,\n description:\n \"Execute shell commands locally on the machine. Commands are provided as argv tokens.\",\n schema: LocalShellActionSchema,\n });\n\n shellTool.extras = {\n ...(shellTool.extras ?? {}),\n providerToolDefinition: {\n type: \"local_shell\",\n } satisfies LocalShellTool,\n };\n\n return shellTool as DynamicStructuredTool<\n typeof LocalShellActionSchema,\n LocalShellAction,\n unknown,\n string\n >;\n}\n"],"mappings":";;;;;AAaA,MAAa,6BAA6BA,SAAE,OAAO;CACjD,MAAMA,SAAE,QAAQ,OAAO;CACvB,SAASA,SAAE,MAAMA,SAAE,QAAQ,CAAC;CAC5B,KAAKA,SAAE,OAAOA,SAAE,QAAQ,EAAEA,SAAE,QAAQ,CAAC,CAAC,UAAU;CAChD,mBAAmBA,SAAE,QAAQ,CAAC,UAAU;CACxC,YAAYA,SAAE,QAAQ,CAAC,UAAU;CACjC,MAAMA,SAAE,QAAQ,CAAC,UAAU;AAC5B,EAAC;AAGF,MAAa,yBAAyBA,SAAE,mBAAmB,QAAQ,CACjE,0BACD,EAAC;AAkCF,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHlB,SAAgB,WAAWC,SAA4B;CACrD,MAAM,6CAAiB,QAAQ,SAAS;EACtC,MAAM;EACN,aACE;EACF,QAAQ;CACT,EAAC;CAEF,UAAU,SAAS;EACjB,GAAI,UAAU,UAAU,CAAE;EAC1B,wBAAwB,EACtB,MAAM,cACP;CACF;AAED,QAAO;AAMR"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { OpenAI as OpenAI$1 } from "openai";
|
|
2
|
+
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
|
+
|
|
5
|
+
//#region src/tools/localShell.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Re-export action type from OpenAI SDK for convenience.
|
|
9
|
+
* The action contains command details like argv tokens, environment variables,
|
|
10
|
+
* working directory, timeout, and user.
|
|
11
|
+
*/
|
|
12
|
+
type LocalShellAction = OpenAI$1.Responses.ResponseOutputItem.LocalShellCall.Action;
|
|
13
|
+
/**
|
|
14
|
+
* Options for the Local Shell tool.
|
|
15
|
+
*/
|
|
16
|
+
interface LocalShellOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Optional execute function that handles shell command execution.
|
|
19
|
+
* This function receives the action input and should return the command output
|
|
20
|
+
* (stdout + stderr combined).
|
|
21
|
+
*
|
|
22
|
+
* If not provided, you'll need to handle action execution manually by
|
|
23
|
+
* checking `local_shell_call` outputs in the response.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* execute: async (action) => {
|
|
28
|
+
* const result = await exec(action.command.join(' '), {
|
|
29
|
+
* cwd: action.working_directory,
|
|
30
|
+
* env: { ...process.env, ...action.env },
|
|
31
|
+
* timeout: action.timeout_ms,
|
|
32
|
+
* });
|
|
33
|
+
* return result.stdout + result.stderr;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
execute: (action: LocalShellAction) => string | Promise<string>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* OpenAI Local Shell tool type for the Responses API.
|
|
41
|
+
*/
|
|
42
|
+
type LocalShellTool = OpenAI$1.Responses.Tool.LocalShell;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a Local Shell tool that allows models to run shell commands locally
|
|
45
|
+
* on a machine you provide. Commands are executed inside your own runtime—
|
|
46
|
+
* the API only returns the instructions, but does not execute them on OpenAI infrastructure.
|
|
47
|
+
*
|
|
48
|
+
* **Important**: The local shell tool is designed to work with
|
|
49
|
+
* [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.
|
|
50
|
+
*
|
|
51
|
+
* **How it works**:
|
|
52
|
+
* The tool operates in a continuous loop:
|
|
53
|
+
* 1. Model sends shell commands (`local_shell_call` with `exec` action)
|
|
54
|
+
* 2. Your code executes the command locally
|
|
55
|
+
* 3. You return the output back to the model
|
|
56
|
+
* 4. Repeat until the task is complete
|
|
57
|
+
*
|
|
58
|
+
* **Security Warning**: Running arbitrary shell commands can be dangerous.
|
|
59
|
+
* Always sandbox execution or add strict allow/deny-lists before forwarding
|
|
60
|
+
* a command to the system shell.
|
|
61
|
+
*
|
|
62
|
+
* @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}
|
|
63
|
+
*
|
|
64
|
+
* @param options - Optional configuration for the Local Shell tool
|
|
65
|
+
* @returns A Local Shell tool that can be passed to `bindTools`
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* import { ChatOpenAI, tools } from "@langchain/openai";
|
|
70
|
+
* import { exec } from "child_process";
|
|
71
|
+
* import { promisify } from "util";
|
|
72
|
+
*
|
|
73
|
+
* const execAsync = promisify(exec);
|
|
74
|
+
* const model = new ChatOpenAI({ model: "codex-mini-latest" });
|
|
75
|
+
*
|
|
76
|
+
* // With execute callback for automatic command handling
|
|
77
|
+
* const shell = tools.localShell({
|
|
78
|
+
* execute: async (action) => {
|
|
79
|
+
* const { command, env, working_directory, timeout_ms } = action;
|
|
80
|
+
* const result = await execAsync(command.join(' '), {
|
|
81
|
+
* cwd: working_directory ?? process.cwd(),
|
|
82
|
+
* env: { ...process.env, ...env },
|
|
83
|
+
* timeout: timeout_ms ?? undefined,
|
|
84
|
+
* });
|
|
85
|
+
* return result.stdout + result.stderr;
|
|
86
|
+
* },
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* const llmWithShell = model.bindTools([shell]);
|
|
90
|
+
* const response = await llmWithShell.invoke(
|
|
91
|
+
* "List files in the current directory"
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // Without execute callback (manual handling)
|
|
98
|
+
* const shell = tools.localShell();
|
|
99
|
+
*
|
|
100
|
+
* const response = await model.invoke("List files", {
|
|
101
|
+
* tools: [shell],
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* // Access the shell call from the response
|
|
105
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
106
|
+
* (output) => output.type === "local_shell_call"
|
|
107
|
+
* );
|
|
108
|
+
* if (shellCall) {
|
|
109
|
+
* console.log("Command to execute:", shellCall.action.command);
|
|
110
|
+
* // Execute the command manually, then send back the output
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // Full shell loop example
|
|
117
|
+
* async function shellLoop(model, task) {
|
|
118
|
+
* let response = await model.invoke(task, {
|
|
119
|
+
* tools: [tools.localShell()],
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* while (true) {
|
|
123
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
124
|
+
* (output) => output.type === "local_shell_call"
|
|
125
|
+
* );
|
|
126
|
+
*
|
|
127
|
+
* if (!shellCall) break;
|
|
128
|
+
*
|
|
129
|
+
* // Execute command (with proper sandboxing!)
|
|
130
|
+
* const output = await executeCommand(shellCall.action);
|
|
131
|
+
*
|
|
132
|
+
* // Send output back to model
|
|
133
|
+
* response = await model.invoke([
|
|
134
|
+
* response,
|
|
135
|
+
* {
|
|
136
|
+
* type: "local_shell_call_output",
|
|
137
|
+
* id: shellCall.call_id,
|
|
138
|
+
* output: output,
|
|
139
|
+
* },
|
|
140
|
+
* ], {
|
|
141
|
+
* tools: [tools.localShell()],
|
|
142
|
+
* });
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
* return response;
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @remarks
|
|
150
|
+
* - Only available through the Responses API (not Chat Completions)
|
|
151
|
+
* - Designed for use with `codex-mini-latest` model
|
|
152
|
+
* - Commands are provided as argv tokens in `action.command`
|
|
153
|
+
* - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`
|
|
154
|
+
* - Always sandbox or validate commands before execution
|
|
155
|
+
* - The `timeout_ms` from the model is only a hint—enforce your own limits
|
|
156
|
+
*/
|
|
157
|
+
declare function localShell(options: LocalShellOptions): DynamicStructuredTool<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
158
|
+
type: z.ZodLiteral<"exec">;
|
|
159
|
+
command: z.ZodArray<z.ZodString>;
|
|
160
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
161
|
+
working_directory: z.ZodOptional<z.ZodString>;
|
|
162
|
+
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
163
|
+
user: z.ZodOptional<z.ZodString>;
|
|
164
|
+
}, z.core.$strip>]>, OpenAI$1.Responses.ResponseOutputItem.LocalShellCall.Action, unknown, string>;
|
|
165
|
+
//#endregion
|
|
166
|
+
export { LocalShellAction, LocalShellOptions, LocalShellTool, localShell };
|
|
167
|
+
//# sourceMappingURL=localShell.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localShell.d.cts","names":["z","OpenAI","OpenAIClient","DynamicStructuredTool","LocalShellAction","Responses","ResponseOutputItem","LocalShellCall","Action","LocalShellExecActionSchema","ZodLiteral","ZodString","ZodArray","ZodRecord","ZodOptional","ZodNumber","core","$strip","ZodObject","LocalShellActionSchema","ZodDiscriminatedUnion","LocalShellOptions","Promise","LocalShellTool","Tool","LocalShell","localShell"],"sources":["../../src/tools/localShell.d.ts"],"sourcesContent":["import { z } from \"zod/v4\";\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { type DynamicStructuredTool } from \"@langchain/core/tools\";\n/**\n * Re-export action type from OpenAI SDK for convenience.\n * The action contains command details like argv tokens, environment variables,\n * working directory, timeout, and user.\n */\nexport type LocalShellAction = OpenAIClient.Responses.ResponseOutputItem.LocalShellCall.Action;\nexport declare const LocalShellExecActionSchema: z.ZodObject<{\n type: z.ZodLiteral<\"exec\">;\n command: z.ZodArray<z.ZodString>;\n env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;\n working_directory: z.ZodOptional<z.ZodString>;\n timeout_ms: z.ZodOptional<z.ZodNumber>;\n user: z.ZodOptional<z.ZodString>;\n}, z.core.$strip>;\nexport declare const LocalShellActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{\n type: z.ZodLiteral<\"exec\">;\n command: z.ZodArray<z.ZodString>;\n env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;\n working_directory: z.ZodOptional<z.ZodString>;\n timeout_ms: z.ZodOptional<z.ZodNumber>;\n user: z.ZodOptional<z.ZodString>;\n}, z.core.$strip>]>;\n/**\n * Options for the Local Shell tool.\n */\nexport interface LocalShellOptions {\n /**\n * Optional execute function that handles shell command execution.\n * This function receives the action input and should return the command output\n * (stdout + stderr combined).\n *\n * If not provided, you'll need to handle action execution manually by\n * checking `local_shell_call` outputs in the response.\n *\n * @example\n * ```typescript\n * execute: async (action) => {\n * const result = await exec(action.command.join(' '), {\n * cwd: action.working_directory,\n * env: { ...process.env, ...action.env },\n * timeout: action.timeout_ms,\n * });\n * return result.stdout + result.stderr;\n * }\n * ```\n */\n execute: (action: LocalShellAction) => string | Promise<string>;\n}\n/**\n * OpenAI Local Shell tool type for the Responses API.\n */\nexport type LocalShellTool = OpenAIClient.Responses.Tool.LocalShell;\n/**\n * Creates a Local Shell tool that allows models to run shell commands locally\n * on a machine you provide. Commands are executed inside your own runtime—\n * the API only returns the instructions, but does not execute them on OpenAI infrastructure.\n *\n * **Important**: The local shell tool is designed to work with\n * [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.\n *\n * **How it works**:\n * The tool operates in a continuous loop:\n * 1. Model sends shell commands (`local_shell_call` with `exec` action)\n * 2. Your code executes the command locally\n * 3. You return the output back to the model\n * 4. Repeat until the task is complete\n *\n * **Security Warning**: Running arbitrary shell commands can be dangerous.\n * Always sandbox execution or add strict allow/deny-lists before forwarding\n * a command to the system shell.\n *\n * @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}\n *\n * @param options - Optional configuration for the Local Shell tool\n * @returns A Local Shell tool that can be passed to `bindTools`\n *\n * @example\n * ```typescript\n * import { ChatOpenAI, tools } from \"@langchain/openai\";\n * import { exec } from \"child_process\";\n * import { promisify } from \"util\";\n *\n * const execAsync = promisify(exec);\n * const model = new ChatOpenAI({ model: \"codex-mini-latest\" });\n *\n * // With execute callback for automatic command handling\n * const shell = tools.localShell({\n * execute: async (action) => {\n * const { command, env, working_directory, timeout_ms } = action;\n * const result = await execAsync(command.join(' '), {\n * cwd: working_directory ?? process.cwd(),\n * env: { ...process.env, ...env },\n * timeout: timeout_ms ?? undefined,\n * });\n * return result.stdout + result.stderr;\n * },\n * });\n *\n * const llmWithShell = model.bindTools([shell]);\n * const response = await llmWithShell.invoke(\n * \"List files in the current directory\"\n * );\n * ```\n *\n * @example\n * ```typescript\n * // Without execute callback (manual handling)\n * const shell = tools.localShell();\n *\n * const response = await model.invoke(\"List files\", {\n * tools: [shell],\n * });\n *\n * // Access the shell call from the response\n * const shellCall = response.additional_kwargs.tool_outputs?.find(\n * (output) => output.type === \"local_shell_call\"\n * );\n * if (shellCall) {\n * console.log(\"Command to execute:\", shellCall.action.command);\n * // Execute the command manually, then send back the output\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Full shell loop example\n * async function shellLoop(model, task) {\n * let response = await model.invoke(task, {\n * tools: [tools.localShell()],\n * });\n *\n * while (true) {\n * const shellCall = response.additional_kwargs.tool_outputs?.find(\n * (output) => output.type === \"local_shell_call\"\n * );\n *\n * if (!shellCall) break;\n *\n * // Execute command (with proper sandboxing!)\n * const output = await executeCommand(shellCall.action);\n *\n * // Send output back to model\n * response = await model.invoke([\n * response,\n * {\n * type: \"local_shell_call_output\",\n * id: shellCall.call_id,\n * output: output,\n * },\n * ], {\n * tools: [tools.localShell()],\n * });\n * }\n *\n * return response;\n * }\n * ```\n *\n * @remarks\n * - Only available through the Responses API (not Chat Completions)\n * - Designed for use with `codex-mini-latest` model\n * - Commands are provided as argv tokens in `action.command`\n * - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`\n * - Always sandbox or validate commands before execution\n * - The `timeout_ms` from the model is only a hint—enforce your own limits\n */\nexport declare function localShell(options: LocalShellOptions): DynamicStructuredTool<z.ZodDiscriminatedUnion<[z.ZodObject<{\n type: z.ZodLiteral<\"exec\">;\n command: z.ZodArray<z.ZodString>;\n env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;\n working_directory: z.ZodOptional<z.ZodString>;\n timeout_ms: z.ZodOptional<z.ZodNumber>;\n user: z.ZodOptional<z.ZodString>;\n}, z.core.$strip>]>, OpenAIClient.Responses.ResponseOutputItem.LocalShellCall.Action, unknown, string>;\n//# sourceMappingURL=localShell.d.ts.map"],"mappings":";;;;;;;;AAQA;AAoBA;AA0BA;AAmHwB0B,KAjKZtB,gBAAAA,GAAmBF,QAAAA,CAAaG,SAAAA,CAAUC,kBAAAA,CAAmBC,cAAAA,CAAeC,MAiKtD;;;;AAAmD,UA7IpEa,iBAAAA,CA6IoE;;;;;;;;;;;;;;;;;;;;;oBAxH/DjB,8BAA8BkB;;;;;KAKxCC,cAAAA,GAAiBrB,QAAAA,CAAaG,SAAAA,CAAUmB,IAAAA,CAAKC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmHjCC,UAAAA,UAAoBL,oBAAoBlB,sBAAsBH,CAAAA,CAAEoB,uBAAuBpB,CAAAA,CAAEkB;QACvGlB,CAAAA,CAAEU;WACCV,CAAAA,CAAEY,SAASZ,CAAAA,CAAEW;OACjBX,CAAAA,CAAEc,YAAYd,CAAAA,CAAEa,UAAUb,CAAAA,CAAEW,WAAWX,CAAAA,CAAEW;qBAC3BX,CAAAA,CAAEc,YAAYd,CAAAA,CAAEW;cACvBX,CAAAA,CAAEc,YAAYd,CAAAA,CAAEe;QACtBf,CAAAA,CAAEc,YAAYd,CAAAA,CAAEW;GACvBX,CAAAA,CAAEgB,IAAAA,CAAKC,WAAWf,QAAAA,CAAaG,SAAAA,CAAUC,kBAAAA,CAAmBC,cAAAA,CAAeC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { OpenAI as OpenAI$1 } from "openai";
|
|
2
|
+
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
|
+
|
|
5
|
+
//#region src/tools/localShell.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Re-export action type from OpenAI SDK for convenience.
|
|
9
|
+
* The action contains command details like argv tokens, environment variables,
|
|
10
|
+
* working directory, timeout, and user.
|
|
11
|
+
*/
|
|
12
|
+
type LocalShellAction = OpenAI$1.Responses.ResponseOutputItem.LocalShellCall.Action;
|
|
13
|
+
/**
|
|
14
|
+
* Options for the Local Shell tool.
|
|
15
|
+
*/
|
|
16
|
+
interface LocalShellOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Optional execute function that handles shell command execution.
|
|
19
|
+
* This function receives the action input and should return the command output
|
|
20
|
+
* (stdout + stderr combined).
|
|
21
|
+
*
|
|
22
|
+
* If not provided, you'll need to handle action execution manually by
|
|
23
|
+
* checking `local_shell_call` outputs in the response.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* execute: async (action) => {
|
|
28
|
+
* const result = await exec(action.command.join(' '), {
|
|
29
|
+
* cwd: action.working_directory,
|
|
30
|
+
* env: { ...process.env, ...action.env },
|
|
31
|
+
* timeout: action.timeout_ms,
|
|
32
|
+
* });
|
|
33
|
+
* return result.stdout + result.stderr;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
execute: (action: LocalShellAction) => string | Promise<string>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* OpenAI Local Shell tool type for the Responses API.
|
|
41
|
+
*/
|
|
42
|
+
type LocalShellTool = OpenAI$1.Responses.Tool.LocalShell;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a Local Shell tool that allows models to run shell commands locally
|
|
45
|
+
* on a machine you provide. Commands are executed inside your own runtime—
|
|
46
|
+
* the API only returns the instructions, but does not execute them on OpenAI infrastructure.
|
|
47
|
+
*
|
|
48
|
+
* **Important**: The local shell tool is designed to work with
|
|
49
|
+
* [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.
|
|
50
|
+
*
|
|
51
|
+
* **How it works**:
|
|
52
|
+
* The tool operates in a continuous loop:
|
|
53
|
+
* 1. Model sends shell commands (`local_shell_call` with `exec` action)
|
|
54
|
+
* 2. Your code executes the command locally
|
|
55
|
+
* 3. You return the output back to the model
|
|
56
|
+
* 4. Repeat until the task is complete
|
|
57
|
+
*
|
|
58
|
+
* **Security Warning**: Running arbitrary shell commands can be dangerous.
|
|
59
|
+
* Always sandbox execution or add strict allow/deny-lists before forwarding
|
|
60
|
+
* a command to the system shell.
|
|
61
|
+
*
|
|
62
|
+
* @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}
|
|
63
|
+
*
|
|
64
|
+
* @param options - Optional configuration for the Local Shell tool
|
|
65
|
+
* @returns A Local Shell tool that can be passed to `bindTools`
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* import { ChatOpenAI, tools } from "@langchain/openai";
|
|
70
|
+
* import { exec } from "child_process";
|
|
71
|
+
* import { promisify } from "util";
|
|
72
|
+
*
|
|
73
|
+
* const execAsync = promisify(exec);
|
|
74
|
+
* const model = new ChatOpenAI({ model: "codex-mini-latest" });
|
|
75
|
+
*
|
|
76
|
+
* // With execute callback for automatic command handling
|
|
77
|
+
* const shell = tools.localShell({
|
|
78
|
+
* execute: async (action) => {
|
|
79
|
+
* const { command, env, working_directory, timeout_ms } = action;
|
|
80
|
+
* const result = await execAsync(command.join(' '), {
|
|
81
|
+
* cwd: working_directory ?? process.cwd(),
|
|
82
|
+
* env: { ...process.env, ...env },
|
|
83
|
+
* timeout: timeout_ms ?? undefined,
|
|
84
|
+
* });
|
|
85
|
+
* return result.stdout + result.stderr;
|
|
86
|
+
* },
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* const llmWithShell = model.bindTools([shell]);
|
|
90
|
+
* const response = await llmWithShell.invoke(
|
|
91
|
+
* "List files in the current directory"
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // Without execute callback (manual handling)
|
|
98
|
+
* const shell = tools.localShell();
|
|
99
|
+
*
|
|
100
|
+
* const response = await model.invoke("List files", {
|
|
101
|
+
* tools: [shell],
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* // Access the shell call from the response
|
|
105
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
106
|
+
* (output) => output.type === "local_shell_call"
|
|
107
|
+
* );
|
|
108
|
+
* if (shellCall) {
|
|
109
|
+
* console.log("Command to execute:", shellCall.action.command);
|
|
110
|
+
* // Execute the command manually, then send back the output
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // Full shell loop example
|
|
117
|
+
* async function shellLoop(model, task) {
|
|
118
|
+
* let response = await model.invoke(task, {
|
|
119
|
+
* tools: [tools.localShell()],
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* while (true) {
|
|
123
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
124
|
+
* (output) => output.type === "local_shell_call"
|
|
125
|
+
* );
|
|
126
|
+
*
|
|
127
|
+
* if (!shellCall) break;
|
|
128
|
+
*
|
|
129
|
+
* // Execute command (with proper sandboxing!)
|
|
130
|
+
* const output = await executeCommand(shellCall.action);
|
|
131
|
+
*
|
|
132
|
+
* // Send output back to model
|
|
133
|
+
* response = await model.invoke([
|
|
134
|
+
* response,
|
|
135
|
+
* {
|
|
136
|
+
* type: "local_shell_call_output",
|
|
137
|
+
* id: shellCall.call_id,
|
|
138
|
+
* output: output,
|
|
139
|
+
* },
|
|
140
|
+
* ], {
|
|
141
|
+
* tools: [tools.localShell()],
|
|
142
|
+
* });
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
* return response;
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @remarks
|
|
150
|
+
* - Only available through the Responses API (not Chat Completions)
|
|
151
|
+
* - Designed for use with `codex-mini-latest` model
|
|
152
|
+
* - Commands are provided as argv tokens in `action.command`
|
|
153
|
+
* - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`
|
|
154
|
+
* - Always sandbox or validate commands before execution
|
|
155
|
+
* - The `timeout_ms` from the model is only a hint—enforce your own limits
|
|
156
|
+
*/
|
|
157
|
+
declare function localShell(options: LocalShellOptions): DynamicStructuredTool<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
158
|
+
type: z.ZodLiteral<"exec">;
|
|
159
|
+
command: z.ZodArray<z.ZodString>;
|
|
160
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
161
|
+
working_directory: z.ZodOptional<z.ZodString>;
|
|
162
|
+
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
163
|
+
user: z.ZodOptional<z.ZodString>;
|
|
164
|
+
}, z.core.$strip>]>, OpenAI$1.Responses.ResponseOutputItem.LocalShellCall.Action, unknown, string>;
|
|
165
|
+
//#endregion
|
|
166
|
+
export { LocalShellAction, LocalShellOptions, LocalShellTool, localShell };
|
|
167
|
+
//# sourceMappingURL=localShell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localShell.d.ts","names":["z","OpenAI","OpenAIClient","DynamicStructuredTool","LocalShellAction","Responses","ResponseOutputItem","LocalShellCall","Action","LocalShellExecActionSchema","ZodLiteral","ZodString","ZodArray","ZodRecord","ZodOptional","ZodNumber","core","$strip","ZodObject","LocalShellActionSchema","ZodDiscriminatedUnion","LocalShellOptions","Promise","LocalShellTool","Tool","LocalShell","localShell"],"sources":["../../src/tools/localShell.d.ts"],"sourcesContent":["import { z } from \"zod/v4\";\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { type DynamicStructuredTool } from \"@langchain/core/tools\";\n/**\n * Re-export action type from OpenAI SDK for convenience.\n * The action contains command details like argv tokens, environment variables,\n * working directory, timeout, and user.\n */\nexport type LocalShellAction = OpenAIClient.Responses.ResponseOutputItem.LocalShellCall.Action;\nexport declare const LocalShellExecActionSchema: z.ZodObject<{\n type: z.ZodLiteral<\"exec\">;\n command: z.ZodArray<z.ZodString>;\n env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;\n working_directory: z.ZodOptional<z.ZodString>;\n timeout_ms: z.ZodOptional<z.ZodNumber>;\n user: z.ZodOptional<z.ZodString>;\n}, z.core.$strip>;\nexport declare const LocalShellActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{\n type: z.ZodLiteral<\"exec\">;\n command: z.ZodArray<z.ZodString>;\n env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;\n working_directory: z.ZodOptional<z.ZodString>;\n timeout_ms: z.ZodOptional<z.ZodNumber>;\n user: z.ZodOptional<z.ZodString>;\n}, z.core.$strip>]>;\n/**\n * Options for the Local Shell tool.\n */\nexport interface LocalShellOptions {\n /**\n * Optional execute function that handles shell command execution.\n * This function receives the action input and should return the command output\n * (stdout + stderr combined).\n *\n * If not provided, you'll need to handle action execution manually by\n * checking `local_shell_call` outputs in the response.\n *\n * @example\n * ```typescript\n * execute: async (action) => {\n * const result = await exec(action.command.join(' '), {\n * cwd: action.working_directory,\n * env: { ...process.env, ...action.env },\n * timeout: action.timeout_ms,\n * });\n * return result.stdout + result.stderr;\n * }\n * ```\n */\n execute: (action: LocalShellAction) => string | Promise<string>;\n}\n/**\n * OpenAI Local Shell tool type for the Responses API.\n */\nexport type LocalShellTool = OpenAIClient.Responses.Tool.LocalShell;\n/**\n * Creates a Local Shell tool that allows models to run shell commands locally\n * on a machine you provide. Commands are executed inside your own runtime—\n * the API only returns the instructions, but does not execute them on OpenAI infrastructure.\n *\n * **Important**: The local shell tool is designed to work with\n * [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.\n *\n * **How it works**:\n * The tool operates in a continuous loop:\n * 1. Model sends shell commands (`local_shell_call` with `exec` action)\n * 2. Your code executes the command locally\n * 3. You return the output back to the model\n * 4. Repeat until the task is complete\n *\n * **Security Warning**: Running arbitrary shell commands can be dangerous.\n * Always sandbox execution or add strict allow/deny-lists before forwarding\n * a command to the system shell.\n *\n * @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}\n *\n * @param options - Optional configuration for the Local Shell tool\n * @returns A Local Shell tool that can be passed to `bindTools`\n *\n * @example\n * ```typescript\n * import { ChatOpenAI, tools } from \"@langchain/openai\";\n * import { exec } from \"child_process\";\n * import { promisify } from \"util\";\n *\n * const execAsync = promisify(exec);\n * const model = new ChatOpenAI({ model: \"codex-mini-latest\" });\n *\n * // With execute callback for automatic command handling\n * const shell = tools.localShell({\n * execute: async (action) => {\n * const { command, env, working_directory, timeout_ms } = action;\n * const result = await execAsync(command.join(' '), {\n * cwd: working_directory ?? process.cwd(),\n * env: { ...process.env, ...env },\n * timeout: timeout_ms ?? undefined,\n * });\n * return result.stdout + result.stderr;\n * },\n * });\n *\n * const llmWithShell = model.bindTools([shell]);\n * const response = await llmWithShell.invoke(\n * \"List files in the current directory\"\n * );\n * ```\n *\n * @example\n * ```typescript\n * // Without execute callback (manual handling)\n * const shell = tools.localShell();\n *\n * const response = await model.invoke(\"List files\", {\n * tools: [shell],\n * });\n *\n * // Access the shell call from the response\n * const shellCall = response.additional_kwargs.tool_outputs?.find(\n * (output) => output.type === \"local_shell_call\"\n * );\n * if (shellCall) {\n * console.log(\"Command to execute:\", shellCall.action.command);\n * // Execute the command manually, then send back the output\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Full shell loop example\n * async function shellLoop(model, task) {\n * let response = await model.invoke(task, {\n * tools: [tools.localShell()],\n * });\n *\n * while (true) {\n * const shellCall = response.additional_kwargs.tool_outputs?.find(\n * (output) => output.type === \"local_shell_call\"\n * );\n *\n * if (!shellCall) break;\n *\n * // Execute command (with proper sandboxing!)\n * const output = await executeCommand(shellCall.action);\n *\n * // Send output back to model\n * response = await model.invoke([\n * response,\n * {\n * type: \"local_shell_call_output\",\n * id: shellCall.call_id,\n * output: output,\n * },\n * ], {\n * tools: [tools.localShell()],\n * });\n * }\n *\n * return response;\n * }\n * ```\n *\n * @remarks\n * - Only available through the Responses API (not Chat Completions)\n * - Designed for use with `codex-mini-latest` model\n * - Commands are provided as argv tokens in `action.command`\n * - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`\n * - Always sandbox or validate commands before execution\n * - The `timeout_ms` from the model is only a hint—enforce your own limits\n */\nexport declare function localShell(options: LocalShellOptions): DynamicStructuredTool<z.ZodDiscriminatedUnion<[z.ZodObject<{\n type: z.ZodLiteral<\"exec\">;\n command: z.ZodArray<z.ZodString>;\n env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;\n working_directory: z.ZodOptional<z.ZodString>;\n timeout_ms: z.ZodOptional<z.ZodNumber>;\n user: z.ZodOptional<z.ZodString>;\n}, z.core.$strip>]>, OpenAIClient.Responses.ResponseOutputItem.LocalShellCall.Action, unknown, string>;\n//# sourceMappingURL=localShell.d.ts.map"],"mappings":";;;;;;;;AAQA;AAoBA;AA0BA;AAmHwB0B,KAjKZtB,gBAAAA,GAAmBF,QAAAA,CAAaG,SAAAA,CAAUC,kBAAAA,CAAmBC,cAAAA,CAAeC,MAiKtD;;;;AAAmD,UA7IpEa,iBAAAA,CA6IoE;;;;;;;;;;;;;;;;;;;;;oBAxH/DjB,8BAA8BkB;;;;;KAKxCC,cAAAA,GAAiBrB,QAAAA,CAAaG,SAAAA,CAAUmB,IAAAA,CAAKC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmHjCC,UAAAA,UAAoBL,oBAAoBlB,sBAAsBH,CAAAA,CAAEoB,uBAAuBpB,CAAAA,CAAEkB;QACvGlB,CAAAA,CAAEU;WACCV,CAAAA,CAAEY,SAASZ,CAAAA,CAAEW;OACjBX,CAAAA,CAAEc,YAAYd,CAAAA,CAAEa,UAAUb,CAAAA,CAAEW,WAAWX,CAAAA,CAAEW;qBAC3BX,CAAAA,CAAEc,YAAYd,CAAAA,CAAEW;cACvBX,CAAAA,CAAEc,YAAYd,CAAAA,CAAEe;QACtBf,CAAAA,CAAEc,YAAYd,CAAAA,CAAEW;GACvBX,CAAAA,CAAEgB,IAAAA,CAAKC,WAAWf,QAAAA,CAAaG,SAAAA,CAAUC,kBAAAA,CAAmBC,cAAAA,CAAeC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { tool } from "@langchain/core/tools";
|
|
2
|
+
import { z } from "zod/v4";
|
|
3
|
+
|
|
4
|
+
//#region src/tools/localShell.ts
|
|
5
|
+
const LocalShellExecActionSchema = z.object({
|
|
6
|
+
type: z.literal("exec"),
|
|
7
|
+
command: z.array(z.string()),
|
|
8
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
9
|
+
working_directory: z.string().optional(),
|
|
10
|
+
timeout_ms: z.number().optional(),
|
|
11
|
+
user: z.string().optional()
|
|
12
|
+
});
|
|
13
|
+
const LocalShellActionSchema = z.discriminatedUnion("type", [LocalShellExecActionSchema]);
|
|
14
|
+
const TOOL_NAME = "local_shell";
|
|
15
|
+
/**
|
|
16
|
+
* Creates a Local Shell tool that allows models to run shell commands locally
|
|
17
|
+
* on a machine you provide. Commands are executed inside your own runtime—
|
|
18
|
+
* the API only returns the instructions, but does not execute them on OpenAI infrastructure.
|
|
19
|
+
*
|
|
20
|
+
* **Important**: The local shell tool is designed to work with
|
|
21
|
+
* [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model.
|
|
22
|
+
*
|
|
23
|
+
* **How it works**:
|
|
24
|
+
* The tool operates in a continuous loop:
|
|
25
|
+
* 1. Model sends shell commands (`local_shell_call` with `exec` action)
|
|
26
|
+
* 2. Your code executes the command locally
|
|
27
|
+
* 3. You return the output back to the model
|
|
28
|
+
* 4. Repeat until the task is complete
|
|
29
|
+
*
|
|
30
|
+
* **Security Warning**: Running arbitrary shell commands can be dangerous.
|
|
31
|
+
* Always sandbox execution or add strict allow/deny-lists before forwarding
|
|
32
|
+
* a command to the system shell.
|
|
33
|
+
*
|
|
34
|
+
* @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation}
|
|
35
|
+
*
|
|
36
|
+
* @param options - Optional configuration for the Local Shell tool
|
|
37
|
+
* @returns A Local Shell tool that can be passed to `bindTools`
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { ChatOpenAI, tools } from "@langchain/openai";
|
|
42
|
+
* import { exec } from "child_process";
|
|
43
|
+
* import { promisify } from "util";
|
|
44
|
+
*
|
|
45
|
+
* const execAsync = promisify(exec);
|
|
46
|
+
* const model = new ChatOpenAI({ model: "codex-mini-latest" });
|
|
47
|
+
*
|
|
48
|
+
* // With execute callback for automatic command handling
|
|
49
|
+
* const shell = tools.localShell({
|
|
50
|
+
* execute: async (action) => {
|
|
51
|
+
* const { command, env, working_directory, timeout_ms } = action;
|
|
52
|
+
* const result = await execAsync(command.join(' '), {
|
|
53
|
+
* cwd: working_directory ?? process.cwd(),
|
|
54
|
+
* env: { ...process.env, ...env },
|
|
55
|
+
* timeout: timeout_ms ?? undefined,
|
|
56
|
+
* });
|
|
57
|
+
* return result.stdout + result.stderr;
|
|
58
|
+
* },
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* const llmWithShell = model.bindTools([shell]);
|
|
62
|
+
* const response = await llmWithShell.invoke(
|
|
63
|
+
* "List files in the current directory"
|
|
64
|
+
* );
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* // Without execute callback (manual handling)
|
|
70
|
+
* const shell = tools.localShell();
|
|
71
|
+
*
|
|
72
|
+
* const response = await model.invoke("List files", {
|
|
73
|
+
* tools: [shell],
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* // Access the shell call from the response
|
|
77
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
78
|
+
* (output) => output.type === "local_shell_call"
|
|
79
|
+
* );
|
|
80
|
+
* if (shellCall) {
|
|
81
|
+
* console.log("Command to execute:", shellCall.action.command);
|
|
82
|
+
* // Execute the command manually, then send back the output
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* // Full shell loop example
|
|
89
|
+
* async function shellLoop(model, task) {
|
|
90
|
+
* let response = await model.invoke(task, {
|
|
91
|
+
* tools: [tools.localShell()],
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* while (true) {
|
|
95
|
+
* const shellCall = response.additional_kwargs.tool_outputs?.find(
|
|
96
|
+
* (output) => output.type === "local_shell_call"
|
|
97
|
+
* );
|
|
98
|
+
*
|
|
99
|
+
* if (!shellCall) break;
|
|
100
|
+
*
|
|
101
|
+
* // Execute command (with proper sandboxing!)
|
|
102
|
+
* const output = await executeCommand(shellCall.action);
|
|
103
|
+
*
|
|
104
|
+
* // Send output back to model
|
|
105
|
+
* response = await model.invoke([
|
|
106
|
+
* response,
|
|
107
|
+
* {
|
|
108
|
+
* type: "local_shell_call_output",
|
|
109
|
+
* id: shellCall.call_id,
|
|
110
|
+
* output: output,
|
|
111
|
+
* },
|
|
112
|
+
* ], {
|
|
113
|
+
* tools: [tools.localShell()],
|
|
114
|
+
* });
|
|
115
|
+
* }
|
|
116
|
+
*
|
|
117
|
+
* return response;
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* - Only available through the Responses API (not Chat Completions)
|
|
123
|
+
* - Designed for use with `codex-mini-latest` model
|
|
124
|
+
* - Commands are provided as argv tokens in `action.command`
|
|
125
|
+
* - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user`
|
|
126
|
+
* - Always sandbox or validate commands before execution
|
|
127
|
+
* - The `timeout_ms` from the model is only a hint—enforce your own limits
|
|
128
|
+
*/
|
|
129
|
+
function localShell(options) {
|
|
130
|
+
const shellTool = tool(options.execute, {
|
|
131
|
+
name: TOOL_NAME,
|
|
132
|
+
description: "Execute shell commands locally on the machine. Commands are provided as argv tokens.",
|
|
133
|
+
schema: LocalShellActionSchema
|
|
134
|
+
});
|
|
135
|
+
shellTool.extras = {
|
|
136
|
+
...shellTool.extras ?? {},
|
|
137
|
+
providerToolDefinition: { type: "local_shell" }
|
|
138
|
+
};
|
|
139
|
+
return shellTool;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
export { localShell };
|
|
144
|
+
//# sourceMappingURL=localShell.js.map
|