@librechat/agents 3.1.77-dev.1 → 3.1.78-dev.0
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/common/enum.cjs +54 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +148 -4
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +291 -0
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +317 -1
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +90 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/anthropicToolCache.cjs +102 -0
- package/dist/cjs/messages/anthropicToolCache.cjs.map +1 -0
- package/dist/cjs/messages/prune.cjs +27 -0
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/messages/recency.cjs +99 -0
- package/dist/cjs/messages/recency.cjs.map +1 -0
- package/dist/cjs/run.cjs +30 -0
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +100 -6
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +635 -23
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/local/CompileCheckTool.cjs +227 -0
- package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -0
- package/dist/cjs/tools/local/FileCheckpointer.cjs +90 -0
- package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalCodingTools.cjs +1098 -0
- package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +1042 -0
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalExecutionTools.cjs +122 -0
- package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +453 -0
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -0
- package/dist/cjs/tools/local/attachments.cjs +183 -0
- package/dist/cjs/tools/local/attachments.cjs.map +1 -0
- package/dist/cjs/tools/local/bashAst.cjs +129 -0
- package/dist/cjs/tools/local/bashAst.cjs.map +1 -0
- package/dist/cjs/tools/local/editStrategies.cjs +188 -0
- package/dist/cjs/tools/local/editStrategies.cjs.map +1 -0
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +141 -0
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -0
- package/dist/cjs/tools/local/syntaxCheck.cjs +182 -0
- package/dist/cjs/tools/local/syntaxCheck.cjs.map +1 -0
- package/dist/cjs/tools/local/textEncoding.cjs +30 -0
- package/dist/cjs/tools/local/textEncoding.cjs.map +1 -0
- package/dist/cjs/tools/local/workspaceFS.cjs +51 -0
- package/dist/cjs/tools/local/workspaceFS.cjs.map +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +53 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +149 -5
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs +289 -0
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +318 -2
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +17 -2
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/anthropicToolCache.mjs +99 -0
- package/dist/esm/messages/anthropicToolCache.mjs.map +1 -0
- package/dist/esm/messages/prune.mjs +26 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/messages/recency.mjs +97 -0
- package/dist/esm/messages/recency.mjs.map +1 -0
- package/dist/esm/run.mjs +30 -0
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +100 -6
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +635 -23
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/local/CompileCheckTool.mjs +223 -0
- package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -0
- package/dist/esm/tools/local/FileCheckpointer.mjs +87 -0
- package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -0
- package/dist/esm/tools/local/LocalCodingTools.mjs +1075 -0
- package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -0
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +1022 -0
- package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -0
- package/dist/esm/tools/local/LocalExecutionTools.mjs +117 -0
- package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -0
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +448 -0
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -0
- package/dist/esm/tools/local/attachments.mjs +180 -0
- package/dist/esm/tools/local/attachments.mjs.map +1 -0
- package/dist/esm/tools/local/bashAst.mjs +126 -0
- package/dist/esm/tools/local/bashAst.mjs.map +1 -0
- package/dist/esm/tools/local/editStrategies.mjs +185 -0
- package/dist/esm/tools/local/editStrategies.mjs.map +1 -0
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +137 -0
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -0
- package/dist/esm/tools/local/syntaxCheck.mjs +179 -0
- package/dist/esm/tools/local/syntaxCheck.mjs.map +1 -0
- package/dist/esm/tools/local/textEncoding.mjs +27 -0
- package/dist/esm/tools/local/textEncoding.mjs.map +1 -0
- package/dist/esm/tools/local/workspaceFS.mjs +49 -0
- package/dist/esm/tools/local/workspaceFS.mjs.map +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +39 -1
- package/dist/types/graphs/Graph.d.ts +34 -0
- package/dist/types/hooks/createWorkspacePolicyHook.d.ts +95 -0
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/llm/openai/index.d.ts +17 -0
- package/dist/types/messages/anthropicToolCache.d.ts +51 -0
- package/dist/types/messages/index.d.ts +2 -0
- package/dist/types/messages/prune.d.ts +11 -0
- package/dist/types/messages/recency.d.ts +64 -0
- package/dist/types/run.d.ts +21 -0
- package/dist/types/tools/ToolNode.d.ts +145 -2
- package/dist/types/tools/local/CompileCheckTool.d.ts +31 -0
- package/dist/types/tools/local/FileCheckpointer.d.ts +39 -0
- package/dist/types/tools/local/LocalCodingTools.d.ts +57 -0
- package/dist/types/tools/local/LocalExecutionEngine.d.ts +149 -0
- package/dist/types/tools/local/LocalExecutionTools.d.ts +9 -0
- package/dist/types/tools/local/LocalProgrammaticToolCalling.d.ts +21 -0
- package/dist/types/tools/local/attachments.d.ts +84 -0
- package/dist/types/tools/local/bashAst.d.ts +11 -0
- package/dist/types/tools/local/editStrategies.d.ts +28 -0
- package/dist/types/tools/local/index.d.ts +12 -0
- package/dist/types/tools/local/resolveLocalExecutionTools.d.ts +38 -0
- package/dist/types/tools/local/syntaxCheck.d.ts +42 -0
- package/dist/types/tools/local/textEncoding.d.ts +21 -0
- package/dist/types/tools/local/workspaceFS.d.ts +49 -0
- package/dist/types/types/hitl.d.ts +56 -27
- package/dist/types/types/run.d.ts +8 -1
- package/dist/types/types/summarize.d.ts +30 -0
- package/dist/types/types/tools.d.ts +341 -6
- package/package.json +21 -2
- package/src/common/enum.ts +54 -0
- package/src/graphs/Graph.ts +164 -6
- package/src/hooks/__tests__/compactHooks.test.ts +38 -2
- package/src/hooks/__tests__/createWorkspacePolicyHook.test.ts +393 -0
- package/src/hooks/createWorkspacePolicyHook.ts +355 -0
- package/src/hooks/index.ts +6 -0
- package/src/index.ts +1 -0
- package/src/llm/openai/deepseek.test.ts +479 -0
- package/src/llm/openai/index.ts +484 -1
- package/src/messages/__tests__/anthropicToolCache.test.ts +125 -0
- package/src/messages/__tests__/recency.test.ts +267 -0
- package/src/messages/anthropicToolCache.ts +116 -0
- package/src/messages/index.ts +2 -0
- package/src/messages/prune.ts +27 -1
- package/src/messages/recency.ts +155 -0
- package/src/run.ts +31 -0
- package/src/scripts/compare_pi_vs_ours.ts +840 -0
- package/src/scripts/local_engine.ts +166 -0
- package/src/scripts/local_engine_checkpointer.ts +205 -0
- package/src/scripts/local_engine_compile.ts +263 -0
- package/src/scripts/local_engine_hooks.ts +226 -0
- package/src/scripts/local_engine_image.ts +201 -0
- package/src/scripts/local_engine_ptc.ts +151 -0
- package/src/scripts/local_engine_workspace.ts +258 -0
- package/src/scripts/summarization-recency.ts +462 -0
- package/src/specs/prune.test.ts +39 -0
- package/src/summarization/__tests__/node.test.ts +499 -3
- package/src/summarization/node.ts +124 -7
- package/src/tools/ToolNode.ts +769 -20
- package/src/tools/__tests__/LocalExecutionTools.test.ts +2647 -0
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +175 -0
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +114 -0
- package/src/tools/__tests__/ToolNode.session.test.ts +84 -0
- package/src/tools/__tests__/directToolHITLResumeScope.test.ts +467 -0
- package/src/tools/__tests__/directToolHooks.test.ts +411 -0
- package/src/tools/__tests__/localToolNames.test.ts +73 -0
- package/src/tools/__tests__/workspaceSeam.test.ts +134 -0
- package/src/tools/local/CompileCheckTool.ts +278 -0
- package/src/tools/local/FileCheckpointer.ts +93 -0
- package/src/tools/local/LocalCodingTools.ts +1342 -0
- package/src/tools/local/LocalExecutionEngine.ts +1329 -0
- package/src/tools/local/LocalExecutionTools.ts +167 -0
- package/src/tools/local/LocalProgrammaticToolCalling.ts +594 -0
- package/src/tools/local/__tests__/FileCheckpointer.test.ts +120 -0
- package/src/tools/local/__tests__/editStrategies.test.ts +134 -0
- package/src/tools/local/attachments.ts +251 -0
- package/src/tools/local/bashAst.ts +151 -0
- package/src/tools/local/editStrategies.ts +188 -0
- package/src/tools/local/index.ts +12 -0
- package/src/tools/local/resolveLocalExecutionTools.ts +208 -0
- package/src/tools/local/syntaxCheck.ts +243 -0
- package/src/tools/local/textEncoding.ts +37 -0
- package/src/tools/local/workspaceFS.ts +89 -0
- package/src/types/hitl.ts +56 -27
- package/src/types/run.ts +12 -1
- package/src/types/summarize.ts +31 -0
- package/src/types/tools.ts +359 -7
|
@@ -2,7 +2,7 @@ import { ToolCall } from '@langchain/core/messages/tool';
|
|
|
2
2
|
import { END, Command, MessagesAnnotation } from '@langchain/langgraph';
|
|
3
3
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
4
4
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
5
|
-
import type { ResolvedArgsByCallId } from '@/tools/toolOutputReferences';
|
|
5
|
+
import type { ToolOutputResolveView, ResolvedArgsByCallId } from '@/tools/toolOutputReferences';
|
|
6
6
|
import type * as t from '@/types';
|
|
7
7
|
import { RunnableCallable } from '@/utils';
|
|
8
8
|
import { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
|
|
@@ -20,6 +20,36 @@ type RunToolBatchContext = {
|
|
|
20
20
|
batchScopeId?: string;
|
|
21
21
|
/** Batch-local sink for post-substitution args. */
|
|
22
22
|
resolvedArgsByCallId?: ResolvedArgsByCallId;
|
|
23
|
+
/**
|
|
24
|
+
* Frozen pre-batch view of the tool-output registry. When supplied,
|
|
25
|
+
* `runTool` resolves `{{tool…turn…}}` placeholders against this
|
|
26
|
+
* snapshot instead of the live registry, so a slow `PreToolUse`
|
|
27
|
+
* hook on one direct call cannot cause a sibling's just-registered
|
|
28
|
+
* output to leak into this call's args mid-batch (Codex P1 #18 —
|
|
29
|
+
* `Promise.all`-induced ordering would otherwise be observable).
|
|
30
|
+
*/
|
|
31
|
+
preBatchSnapshot?: ToolOutputResolveView;
|
|
32
|
+
/**
|
|
33
|
+
* Pre-incremented per-tool usage counter. Set by
|
|
34
|
+
* `runDirectToolWithLifecycleHooks` so PreToolUse hooks observe
|
|
35
|
+
* the same `turn` the tool will actually execute under (Codex P2
|
|
36
|
+
* #27 — without this, parallel direct calls of the same tool in
|
|
37
|
+
* one Promise.all batch all read `turn=N` for the hook but
|
|
38
|
+
* actually executed as `turn=N`, `N+1`, `N+2`). When supplied,
|
|
39
|
+
* `runTool` skips its own counter increment.
|
|
40
|
+
*/
|
|
41
|
+
usageCount?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Per-batch sink for `additionalContext` strings returned by
|
|
44
|
+
* direct-path PreToolUse / PostToolUse / PostToolUseFailure hooks.
|
|
45
|
+
* The caller in `run()` materializes the accumulated strings as a
|
|
46
|
+
* `HumanMessage` appended to outputs so the next model turn sees
|
|
47
|
+
* them — same shape as the event-driven path's `injected[]`.
|
|
48
|
+
* Codex P2 #39: pre-fix the direct path called `executeHooks` and
|
|
49
|
+
* discarded `additionalContexts`, silently breaking the hook API
|
|
50
|
+
* contract for hosts relying on it for policy / recovery guidance.
|
|
51
|
+
*/
|
|
52
|
+
additionalContextsSink?: string[];
|
|
23
53
|
};
|
|
24
54
|
export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
25
55
|
private toolMap;
|
|
@@ -31,6 +61,17 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
31
61
|
private toolUsageCount;
|
|
32
62
|
/** Maps toolCallId → turn captured in runTool, used by handleRunToolCompletions */
|
|
33
63
|
private toolCallTurns;
|
|
64
|
+
/**
|
|
65
|
+
* `call.id → turn` map dedicated to the direct-path lifecycle so the
|
|
66
|
+
* turn assigned on first entry is REUSED on LangGraph resume.
|
|
67
|
+
* Distinct from `toolCallTurns` (which is cleared at the start of
|
|
68
|
+
* every `run()` to keep per-batch event-dispatch metadata fresh) —
|
|
69
|
+
* the direct path needs stability across re-entries triggered by
|
|
70
|
+
* `interrupt()` resumes (Codex P2 #30). Cleared with the rest of
|
|
71
|
+
* the per-Run state in `clearHeavyState`-equivalent flushes when
|
|
72
|
+
* the Run ends.
|
|
73
|
+
*/
|
|
74
|
+
private directPathTurns;
|
|
34
75
|
/** Tool registry for filtering (lazy computation of programmatic maps) */
|
|
35
76
|
private toolRegistry?;
|
|
36
77
|
/** Cached programmatic tools (computed once on first PTC call) */
|
|
@@ -43,6 +84,13 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
43
84
|
private agentId?;
|
|
44
85
|
/** Tool names that bypass event dispatch and execute directly (e.g., graph-managed handoff tools) */
|
|
45
86
|
private directToolNames?;
|
|
87
|
+
/**
|
|
88
|
+
* File checkpointer extracted from the local coding tool bundle when
|
|
89
|
+
* `toolExecution.local.fileCheckpointing === true`. Exposed via
|
|
90
|
+
* {@link getFileCheckpointer}. Undefined when checkpointing is off
|
|
91
|
+
* or the local coding suite isn't bound to this node.
|
|
92
|
+
*/
|
|
93
|
+
private fileCheckpointer?;
|
|
46
94
|
/** Maximum characters allowed in a single tool result before truncation. */
|
|
47
95
|
private maxToolResultChars;
|
|
48
96
|
/** Hook registry for PreToolUse/PostToolUse lifecycle hooks */
|
|
@@ -65,6 +113,8 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
65
113
|
* ToolNode building its own.
|
|
66
114
|
*/
|
|
67
115
|
private toolOutputRegistry?;
|
|
116
|
+
/** Run-scoped selection for swapping remote code tools to local executors. */
|
|
117
|
+
private toolExecution?;
|
|
68
118
|
/**
|
|
69
119
|
* Monotonic counter used to mint a unique scope id for anonymous
|
|
70
120
|
* batches (ones invoked without a `run_id` in
|
|
@@ -73,7 +123,7 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
73
123
|
* other's in-flight state.
|
|
74
124
|
*/
|
|
75
125
|
private anonBatchCounter;
|
|
76
|
-
constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, agentId, directToolNames, maxContextTokens, maxToolResultChars, hookRegistry, humanInTheLoop, toolOutputReferences, toolOutputRegistry, }: t.ToolNodeConstructorParams);
|
|
126
|
+
constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, agentId, directToolNames, maxContextTokens, maxToolResultChars, hookRegistry, humanInTheLoop, toolOutputReferences, toolOutputRegistry, toolExecution, fileCheckpointer, }: t.ToolNodeConstructorParams);
|
|
77
127
|
/**
|
|
78
128
|
* Returns the run-scoped tool output registry, or `undefined` when
|
|
79
129
|
* the feature is disabled.
|
|
@@ -83,6 +133,35 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
83
133
|
* not mutate the registry directly.
|
|
84
134
|
*/
|
|
85
135
|
_unsafeGetToolOutputRegistry(): ToolOutputReferenceRegistry | undefined;
|
|
136
|
+
/**
|
|
137
|
+
* Replaces known remote Code API tools with local-process tools when
|
|
138
|
+
* `RunConfig.toolExecution.engine === 'local'`. In event-driven mode those
|
|
139
|
+
* names are also marked direct so the SDK executes them locally instead of
|
|
140
|
+
* dispatching the batch to a host-side remote sandbox handler. When the
|
|
141
|
+
* local coding suite is enabled, this also injects file/search/edit tools.
|
|
142
|
+
*/
|
|
143
|
+
private applyToolExecutionOverrides;
|
|
144
|
+
/**
|
|
145
|
+
* Returns the per-Run file checkpointer when
|
|
146
|
+
* `toolExecution.local.fileCheckpointing === true`. Hosts call
|
|
147
|
+
* `rewind()` on the returned object to restore captured pre-write
|
|
148
|
+
* file contents — the standard "undo a tool batch" pattern. Returns
|
|
149
|
+
* undefined when checkpointing is disabled or the local coding suite
|
|
150
|
+
* isn't bound. Manual review (finding E): without this getter, the
|
|
151
|
+
* config flag was a silent no-op outside of direct
|
|
152
|
+
* `createLocalCodingToolBundle()` use.
|
|
153
|
+
*/
|
|
154
|
+
getFileCheckpointer(): t.LocalFileCheckpointer | undefined;
|
|
155
|
+
/**
|
|
156
|
+
* Flush the per-Run direct-path turn cache. Called by the Graph at
|
|
157
|
+
* end-of-Run via `clearHeavyState`. The map intentionally survives
|
|
158
|
+
* `run()` re-entry so an interrupt + resume reuses the original
|
|
159
|
+
* slot (Codex P2 #30), but it would otherwise grow linearly with
|
|
160
|
+
* tool calls and could collide across Runs if a provider reused
|
|
161
|
+
* call IDs (Codex P2 #33). Hosts can also call this directly if
|
|
162
|
+
* they reuse a ToolNode across batches outside of a Graph.
|
|
163
|
+
*/
|
|
164
|
+
clearDirectPathTurns(): void;
|
|
86
165
|
/**
|
|
87
166
|
* Returns cached programmatic tools, computing once on first access.
|
|
88
167
|
* Single iteration builds both toolMap and toolDefs simultaneously.
|
|
@@ -102,6 +181,70 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
102
181
|
* substitutions. Omit when no registration should occur.
|
|
103
182
|
*/
|
|
104
183
|
protected runTool(call: ToolCall, config: RunnableConfig, batchContext?: RunToolBatchContext): Promise<BaseMessage | Command>;
|
|
184
|
+
/**
|
|
185
|
+
* Runs a single in-process tool call with the same lifecycle hooks
|
|
186
|
+
* the event-dispatch path fires (`PreToolUse`, `PermissionDenied`,
|
|
187
|
+
* `PostToolUse`, `PostToolUseFailure`). Used for any tool whose
|
|
188
|
+
* implementation lives in the SDK process — i.e. every entry in
|
|
189
|
+
* `directToolNames` — so host-supplied policy hooks gate
|
|
190
|
+
* direct-invoked tools the same way they gate dispatched ones.
|
|
191
|
+
*
|
|
192
|
+
* Fast path: when the registry has none of the relevant events
|
|
193
|
+
* registered for this run, falls through to `runTool` with zero
|
|
194
|
+
* extra work. The hook list is also checked via
|
|
195
|
+
* `hasHookFor(event, runId)`, which performs the registry's own
|
|
196
|
+
* O(1) shortcut.
|
|
197
|
+
*
|
|
198
|
+
* Hook semantics intentionally mirror `dispatchToolEvents` for the
|
|
199
|
+
* single-call case:
|
|
200
|
+
* - `PreToolUse` returning `decision: 'deny'` synthesizes an error
|
|
201
|
+
* `ToolMessage` and fires `PermissionDenied` (observational).
|
|
202
|
+
* - `PreToolUse` returning `decision: 'ask'`:
|
|
203
|
+
* • When `humanInTheLoop.enabled === true`: raises a real
|
|
204
|
+
* `tool_approval` interrupt for this single tool call (the
|
|
205
|
+
* same payload shape the event path produces). On resume:
|
|
206
|
+
* `approve` runs the tool, `reject` blocks via
|
|
207
|
+
* `blockDirectCall`, `respond` returns the host-supplied
|
|
208
|
+
* `responseText` as a synthetic success ToolMessage,
|
|
209
|
+
* `edit` re-runs with edited args. LangGraph re-enters
|
|
210
|
+
* ToolNode.run from the start on resume; the hook fires
|
|
211
|
+
* again and the resume value distinguishes "first ask" from
|
|
212
|
+
* "second pass with decision".
|
|
213
|
+
* • When HITL is off: collapses to a fail-closed deny (matches
|
|
214
|
+
* the rest of the SDK's HITL-disabled default). One-time
|
|
215
|
+
* warning logged so hosts notice the gap.
|
|
216
|
+
* - `PreToolUse.updatedInput` is applied to the call before
|
|
217
|
+
* `runTool` runs; placeholder resolution inside `runTool` is
|
|
218
|
+
* idempotent on already-resolved args.
|
|
219
|
+
* - `PostToolUse.updatedOutput` replaces the returned
|
|
220
|
+
* `ToolMessage` content (preserving id/name/status).
|
|
221
|
+
* - `PostToolUseFailure` fires when `runTool` returns a
|
|
222
|
+
* `ToolMessage` whose `status === 'error'`. Observational only;
|
|
223
|
+
* the error message stays the source of truth.
|
|
224
|
+
*
|
|
225
|
+
* `PostToolBatch` aggregation across direct + dispatched outcomes is
|
|
226
|
+
* a separate concern: `dispatchToolEvents` accumulates batch entries
|
|
227
|
+
* locally and fires `PostToolBatch` at the end of its scope. Wiring
|
|
228
|
+
* direct-call entries into that aggregation crosses the two paths'
|
|
229
|
+
* scopes and is left to a follow-up.
|
|
230
|
+
*/
|
|
231
|
+
private runDirectToolWithLifecycleHooks;
|
|
232
|
+
/**
|
|
233
|
+
* `ask` decisions on direct-path tools collapse to fail-closed deny
|
|
234
|
+
* only when `humanInTheLoop.enabled !== true` (i.e. there's no host
|
|
235
|
+
* UI configured to actually prompt the user). Logged once per process
|
|
236
|
+
* so the gap is visible. When HITL IS enabled, `ask` raises a real
|
|
237
|
+
* LangGraph `interrupt()` instead — see `runDirectToolWithLifecycleHooks`.
|
|
238
|
+
*/
|
|
239
|
+
private askDirectWarningEmitted;
|
|
240
|
+
private resolveAskDecisionForDirectTool;
|
|
241
|
+
/**
|
|
242
|
+
* Synthesize a Blocked ToolMessage AND fire `PermissionDenied`
|
|
243
|
+
* (observational) for a direct-path tool call. Centralised so the
|
|
244
|
+
* deny path looks identical whether the block came from `'deny'` or
|
|
245
|
+
* from a fail-closed/`'reject'`/policy-violation path.
|
|
246
|
+
*/
|
|
247
|
+
private blockDirectCall;
|
|
105
248
|
/**
|
|
106
249
|
* Registers the full, raw output under `refKey` (when provided) and
|
|
107
250
|
* builds the per-message ref metadata stamped onto the resulting
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `compile_check` — a thin LLM-callable wrapper around the project's
|
|
3
|
+
* standard typecheck/lint command. Lets the agent answer "did my
|
|
4
|
+
* change break anything?" without us shipping a real LSP client.
|
|
5
|
+
*
|
|
6
|
+
* Auto-detection priority (first hit wins):
|
|
7
|
+
*
|
|
8
|
+
* 1. `local.compileCheck.command` — explicit override
|
|
9
|
+
* 2. `tsconfig.json` → `npx --no-install tsc --noEmit`
|
|
10
|
+
* 3. `package.json` with a typescript dep → same as 2
|
|
11
|
+
* 4. `pyproject.toml` or `setup.py` / `setup.cfg`
|
|
12
|
+
* with a dev dep on mypy → `python3 -m mypy .`
|
|
13
|
+
* else → `python3 -m py_compile <every .py>`
|
|
14
|
+
* (bounded by find-walk so node_modules
|
|
15
|
+
* and `.venv` don't blow up)
|
|
16
|
+
* 5. `Cargo.toml` → `cargo check --message-format=short`
|
|
17
|
+
* 6. `go.mod` → `go vet ./...`
|
|
18
|
+
* 7. otherwise → tells the agent there's
|
|
19
|
+
* no detected toolchain.
|
|
20
|
+
*
|
|
21
|
+
* Output is the spawn process's stdout/stderr passed through
|
|
22
|
+
* `truncateLocalOutput` so a 10MB tsc dump can't blow context. The
|
|
23
|
+
* exit code is reported.
|
|
24
|
+
*/
|
|
25
|
+
import type { DynamicStructuredTool } from '@langchain/core/tools';
|
|
26
|
+
import type * as t from '@/types';
|
|
27
|
+
import { Constants } from '@/common';
|
|
28
|
+
/** Back-compat alias; canonical name lives on `Constants.COMPILE_CHECK`. */
|
|
29
|
+
export declare const CompileCheckToolName = Constants.COMPILE_CHECK;
|
|
30
|
+
export declare function createCompileCheckTool(config?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
31
|
+
export declare function createCompileCheckToolDefinition(): t.LCTool;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { WorkspaceFS } from './workspaceFS';
|
|
2
|
+
import type * as t from '@/types';
|
|
3
|
+
/**
|
|
4
|
+
* Per-Run snapshot store for write_file / edit_file. Captures the
|
|
5
|
+
* pre-write byte content of every path the local engine is about to
|
|
6
|
+
* mutate so a later `rewind()` can restore the working tree to its
|
|
7
|
+
* original state. Notes:
|
|
8
|
+
*
|
|
9
|
+
* - Idempotent per path: subsequent captures preserve the first
|
|
10
|
+
* snapshot (so rewind always restores the *original* content).
|
|
11
|
+
* - Captures missing files as `{ kind: 'absent' }`; rewind deletes
|
|
12
|
+
* those paths so created files are removed.
|
|
13
|
+
* - In-memory: snapshots live for the lifetime of this instance and
|
|
14
|
+
* are not persisted across processes. Tie the lifetime to a Run.
|
|
15
|
+
* - Bounded by `maxBytesPerFile` (default 32 MiB) to bound memory.
|
|
16
|
+
* A file larger than the cap is recorded but not snapshotted; the
|
|
17
|
+
* rewind of that path is best-effort and the caller is told via
|
|
18
|
+
* the result count not to trust it.
|
|
19
|
+
*/
|
|
20
|
+
export declare class LocalFileCheckpointerImpl implements t.LocalFileCheckpointer {
|
|
21
|
+
private readonly maxBytesPerFile;
|
|
22
|
+
private readonly fs;
|
|
23
|
+
private snapshots;
|
|
24
|
+
private oversizePaths;
|
|
25
|
+
constructor(maxBytesPerFile?: number, fs?: WorkspaceFS);
|
|
26
|
+
captureBeforeWrite(absolutePath: string): Promise<void>;
|
|
27
|
+
rewind(): Promise<number>;
|
|
28
|
+
capturedPaths(): string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Convenience factory so callers don't have to reach for the impl
|
|
32
|
+
* class directly. Accepts an optional `WorkspaceFS` so a host using a
|
|
33
|
+
* non-default engine (remote sandbox, in-memory test FS, etc.) can
|
|
34
|
+
* route the checkpointer through the same I/O.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createLocalFileCheckpointer(options?: {
|
|
37
|
+
maxBytesPerFile?: number;
|
|
38
|
+
fs?: WorkspaceFS;
|
|
39
|
+
}): t.LocalFileCheckpointer;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { DynamicStructuredTool } from '@langchain/core/tools';
|
|
2
|
+
import type * as t from '@/types';
|
|
3
|
+
import { Constants } from '@/common';
|
|
4
|
+
/**
|
|
5
|
+
* Tool name aliases retained for back-compat with consumers that imported
|
|
6
|
+
* the per-file `Local*ToolName` constants. The canonical names live on
|
|
7
|
+
* `Constants.*` (see `src/common/enum.ts`); these aliases just point at
|
|
8
|
+
* them so a typo upstream gets caught at the type level.
|
|
9
|
+
*/
|
|
10
|
+
export declare const LocalWriteFileToolName = Constants.WRITE_FILE;
|
|
11
|
+
export declare const LocalEditFileToolName = Constants.EDIT_FILE;
|
|
12
|
+
export declare const LocalGrepSearchToolName = Constants.GREP_SEARCH;
|
|
13
|
+
export declare const LocalGlobSearchToolName = Constants.GLOB_SEARCH;
|
|
14
|
+
export declare const LocalListDirectoryToolName = Constants.LIST_DIRECTORY;
|
|
15
|
+
export declare const LocalReadFileToolSchema: t.JsonSchemaType;
|
|
16
|
+
export declare const LocalWriteFileToolSchema: t.JsonSchemaType;
|
|
17
|
+
export declare const LocalEditFileToolSchema: t.JsonSchemaType;
|
|
18
|
+
export declare const LocalGrepSearchToolSchema: t.JsonSchemaType;
|
|
19
|
+
export declare const LocalGlobSearchToolSchema: t.JsonSchemaType;
|
|
20
|
+
export declare const LocalListDirectoryToolSchema: t.JsonSchemaType;
|
|
21
|
+
export declare function createLocalReadFileTool(config?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
22
|
+
export declare function createLocalWriteFileTool(config?: t.LocalExecutionConfig, checkpointer?: t.LocalFileCheckpointer): DynamicStructuredTool;
|
|
23
|
+
export declare function createLocalEditFileTool(config?: t.LocalExecutionConfig, checkpointer?: t.LocalFileCheckpointer): DynamicStructuredTool;
|
|
24
|
+
/**
|
|
25
|
+
* Test-only reset hook. Clears the ripgrep-availability cache so
|
|
26
|
+
* tests can swap in mocked spawn backends and reprobe deterministically.
|
|
27
|
+
*
|
|
28
|
+
* @internal Not part of the public SDK surface; the leading underscore
|
|
29
|
+
* and `@internal` tag together signal that consumers should not call
|
|
30
|
+
* this. Tests import it via the module path directly.
|
|
31
|
+
*/
|
|
32
|
+
export declare function _resetRipgrepCacheForTests(): void;
|
|
33
|
+
export declare function createLocalGrepSearchTool(config?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
34
|
+
export declare function createLocalGlobSearchTool(config?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
35
|
+
export declare function createLocalListDirectoryTool(config?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
36
|
+
export type LocalCodingToolBundle = {
|
|
37
|
+
tools: DynamicStructuredTool[];
|
|
38
|
+
/**
|
|
39
|
+
* Present when `config.fileCheckpointing === true` or a `checkpointer`
|
|
40
|
+
* was passed in. Callers can call `rewind()` to restore captured
|
|
41
|
+
* pre-write contents.
|
|
42
|
+
*/
|
|
43
|
+
checkpointer?: t.LocalFileCheckpointer;
|
|
44
|
+
};
|
|
45
|
+
export declare function createLocalCodingTools(config?: t.LocalExecutionConfig, options?: {
|
|
46
|
+
checkpointer?: t.LocalFileCheckpointer;
|
|
47
|
+
}): DynamicStructuredTool[];
|
|
48
|
+
/**
|
|
49
|
+
* Variant of `createLocalCodingTools` that returns the bundle alongside
|
|
50
|
+
* the file checkpointer so callers can later call
|
|
51
|
+
* `bundle.checkpointer?.rewind()`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function createLocalCodingToolBundle(config?: t.LocalExecutionConfig, options?: {
|
|
54
|
+
checkpointer?: t.LocalFileCheckpointer;
|
|
55
|
+
}): LocalCodingToolBundle;
|
|
56
|
+
export declare function createLocalCodingToolDefinitions(): t.LCTool[];
|
|
57
|
+
export declare function createLocalCodingToolRegistry(): t.LCToolRegistry;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { WorkspaceFS } from './workspaceFS';
|
|
2
|
+
import type * as t from '@/types';
|
|
3
|
+
type SpawnResult = {
|
|
4
|
+
stdout: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
exitCode: number | null;
|
|
7
|
+
timedOut: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* True when the process was force-killed because total streamed bytes
|
|
10
|
+
* exceeded `maxSpawnedBytes`. Distinct from `timedOut`. Without this
|
|
11
|
+
* flag, callers (`bash_tool`, `execute_code`, etc.) would see a
|
|
12
|
+
* SIGKILL'd process with `exitCode: null` and treat it as success
|
|
13
|
+
* (Codex P1 — runaway commands like `yes` or noisy builds silently
|
|
14
|
+
* looked successful even though their output was truncated).
|
|
15
|
+
*/
|
|
16
|
+
overflowKilled?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Signal name (e.g. `'SIGKILL'`, `'SIGSEGV'`) when the process was
|
|
19
|
+
* terminated by a signal. Distinct from the overflow-kill path:
|
|
20
|
+
* this captures `kill -9 $$` from inside the script, native crashes,
|
|
21
|
+
* OS OOM killer, etc. Without this, signal-killed processes
|
|
22
|
+
* reported `exitCode: null` and looked like clean runs (Codex P2 —
|
|
23
|
+
* generalization of the overflow-kill fix). When present, the
|
|
24
|
+
* exitCode field is also synthesized to `128 + signum` per the
|
|
25
|
+
* POSIX convention so non-null-exit-code consumers see a failure.
|
|
26
|
+
*/
|
|
27
|
+
signal?: string;
|
|
28
|
+
/** Path to the full untruncated stdout/stderr when output exceeded `maxOutputChars`. */
|
|
29
|
+
fullOutputPath?: string;
|
|
30
|
+
};
|
|
31
|
+
export type BashValidationResult = {
|
|
32
|
+
valid: boolean;
|
|
33
|
+
errors: string[];
|
|
34
|
+
warnings: string[];
|
|
35
|
+
};
|
|
36
|
+
export declare function resolveLocalExecutionConfig(config?: t.ToolExecutionConfig | t.LocalExecutionConfig): t.LocalExecutionConfig;
|
|
37
|
+
export declare function getLocalCwd(config?: t.LocalExecutionConfig): string;
|
|
38
|
+
/**
|
|
39
|
+
* Resolves the effective workspace boundary: a list of absolute roots
|
|
40
|
+
* that file operations are allowed to touch. The first entry is always
|
|
41
|
+
* the canonical root (`getLocalCwd`); subsequent entries come from
|
|
42
|
+
* `workspace.additionalRoots` when provided.
|
|
43
|
+
*
|
|
44
|
+
* Returns plain absolute paths — callers symlink-resolve when they
|
|
45
|
+
* need realpath equality (see `resolveWorkspacePathSafe`).
|
|
46
|
+
*/
|
|
47
|
+
export declare function getWorkspaceRoots(config?: t.LocalExecutionConfig): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Pluggable spawn resolver. Honours `local.exec.spawn` first, falls
|
|
50
|
+
* back to the legacy top-level `local.spawn`, then to Node's
|
|
51
|
+
* `child_process.spawn`. Centralised so engine swapping is one knob.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getSpawn(config?: t.LocalExecutionConfig): t.LocalSpawn;
|
|
54
|
+
/**
|
|
55
|
+
* Pluggable filesystem resolver. Honours `local.exec.fs`, falls back
|
|
56
|
+
* to the Node-host implementation. A future remote engine supplies
|
|
57
|
+
* its own implementation here and inherits every file-touching tool.
|
|
58
|
+
*/
|
|
59
|
+
export declare function getWorkspaceFS(config?: t.LocalExecutionConfig): WorkspaceFS;
|
|
60
|
+
/**
|
|
61
|
+
* Resolves the workspace boundary for *write* operations. Honours
|
|
62
|
+
* `workspace.allowWriteOutside` (and the deprecated
|
|
63
|
+
* `allowOutsideWorkspace`) by returning `null`, which the path-safety
|
|
64
|
+
* helpers interpret as "skip the write clamp".
|
|
65
|
+
*/
|
|
66
|
+
export declare function getWriteRoots(config?: t.LocalExecutionConfig): string[] | null;
|
|
67
|
+
/**
|
|
68
|
+
* Resolves the workspace boundary for *read* operations. Honours
|
|
69
|
+
* `workspace.allowReadOutside` (and the deprecated
|
|
70
|
+
* `allowOutsideWorkspace`) by returning `null`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function getReadRoots(config?: t.LocalExecutionConfig): string[] | null;
|
|
73
|
+
export declare function getLocalSessionId(config?: t.LocalExecutionConfig): string;
|
|
74
|
+
/**
|
|
75
|
+
* Test-only reset hook for the sandbox-off warning latch.
|
|
76
|
+
*
|
|
77
|
+
* @internal Not part of the public SDK surface.
|
|
78
|
+
*/
|
|
79
|
+
export declare function _resetLocalEngineWarningsForTests(): void;
|
|
80
|
+
export declare function truncateLocalOutput(value: string, maxChars?: number): string;
|
|
81
|
+
export declare function validateBashCommand(command: string, config?: t.LocalExecutionConfig): Promise<BashValidationResult>;
|
|
82
|
+
/**
|
|
83
|
+
* Structural shape of the sandbox-runtime config we hand to
|
|
84
|
+
* `SandboxManager.initialize()`. Intentionally NOT typed as the peer
|
|
85
|
+
* `SandboxRuntimeConfig` from `@anthropic-ai/sandbox-runtime`: that
|
|
86
|
+
* package is an OPTIONAL peer dep, and exporting a function whose
|
|
87
|
+
* return type references it would make our generated `.d.ts` import
|
|
88
|
+
* a module the consumer may not have installed (Codex P1 #22 — type-
|
|
89
|
+
* checking would fail with `Cannot find module
|
|
90
|
+
* '@anthropic-ai/sandbox-runtime'` for any host that doesn't enable
|
|
91
|
+
* local sandboxing). The shape here is a structural subset; assignable
|
|
92
|
+
* to the real `SandboxRuntimeConfig` at the one runtime call site.
|
|
93
|
+
*
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
export interface BuiltSandboxRuntimeConfig {
|
|
97
|
+
network: {
|
|
98
|
+
allowedDomains: string[];
|
|
99
|
+
deniedDomains: string[];
|
|
100
|
+
allowUnixSockets?: string[];
|
|
101
|
+
allowAllUnixSockets?: boolean;
|
|
102
|
+
allowLocalBinding?: boolean;
|
|
103
|
+
allowMachLookup?: string[];
|
|
104
|
+
};
|
|
105
|
+
filesystem: {
|
|
106
|
+
denyRead: string[];
|
|
107
|
+
allowRead?: string[];
|
|
108
|
+
allowWrite: string[];
|
|
109
|
+
denyWrite: string[];
|
|
110
|
+
allowGitConfig?: boolean;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export declare function buildSandboxRuntimeConfig(config: t.LocalExecutionConfig, cwd: string, getDefaultWritePaths: () => string[]): BuiltSandboxRuntimeConfig;
|
|
114
|
+
/**
|
|
115
|
+
* Internal options for {@link spawnLocalProcess} that we don't want
|
|
116
|
+
* exposed on the public `LocalExecutionConfig` type.
|
|
117
|
+
*
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
export interface SpawnLocalProcessOptions {
|
|
121
|
+
/**
|
|
122
|
+
* When true, suppress the "sandbox is off" warning AND its latch
|
|
123
|
+
* for this spawn. Use for SDK-internal probes (`bash -n` syntax
|
|
124
|
+
* preflight, `rg --version`, etc.) that intentionally run with
|
|
125
|
+
* the sandbox forced off — the warning is noise for those, and
|
|
126
|
+
* letting the latch flip would hide the warning when a *real*
|
|
127
|
+
* unsandboxed execution happens later in the same process.
|
|
128
|
+
*/
|
|
129
|
+
internal?: boolean;
|
|
130
|
+
}
|
|
131
|
+
export declare function spawnLocalProcess(command: string, args: string[], config?: t.LocalExecutionConfig, options?: SpawnLocalProcessOptions): Promise<SpawnResult>;
|
|
132
|
+
export declare function executeLocalBash(command: string, config?: t.LocalExecutionConfig): Promise<SpawnResult>;
|
|
133
|
+
export declare function executeLocalBashWithArgs(command: string, args: readonly string[], config?: t.LocalExecutionConfig): Promise<SpawnResult>;
|
|
134
|
+
export declare function executeLocalCode(input: {
|
|
135
|
+
lang: string;
|
|
136
|
+
code: string;
|
|
137
|
+
args?: string[];
|
|
138
|
+
}, config?: t.LocalExecutionConfig): Promise<SpawnResult>;
|
|
139
|
+
export declare function shellQuote(value: string): string;
|
|
140
|
+
export declare function resolveWorkspacePath(filePath: string, config?: t.LocalExecutionConfig, intent?: 'read' | 'write'): string;
|
|
141
|
+
/**
|
|
142
|
+
* Resolves a workspace path AND follows any symlinks before checking
|
|
143
|
+
* containment, so a symlink inside the workspace pointing outside is
|
|
144
|
+
* rejected even though the lexical path looks safe. Handles paths that
|
|
145
|
+
* don't yet exist (e.g. write_file targets) by realpath-resolving the
|
|
146
|
+
* nearest existing ancestor and re-attaching the unresolved suffix.
|
|
147
|
+
*/
|
|
148
|
+
export declare function resolveWorkspacePathSafe(filePath: string, config?: t.LocalExecutionConfig, intent?: 'read' | 'write'): Promise<string>;
|
|
149
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DynamicStructuredTool } from '@langchain/core/tools';
|
|
2
|
+
import type * as t from '@/types';
|
|
3
|
+
export declare const LocalCodeExecutionToolDescription: string;
|
|
4
|
+
export declare const LocalBashExecutionToolDescription: string;
|
|
5
|
+
export declare function createLocalCodeExecutionTool(config?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
6
|
+
export declare function createLocalBashExecutionTool(options?: {
|
|
7
|
+
config?: t.LocalExecutionConfig;
|
|
8
|
+
enableToolOutputReferences?: boolean;
|
|
9
|
+
}): DynamicStructuredTool;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DynamicStructuredTool } from '@langchain/core/tools';
|
|
2
|
+
import type * as t from '@/types';
|
|
3
|
+
/**
|
|
4
|
+
* Run the host's `PreToolUse` hook chain for a single bridge call.
|
|
5
|
+
* Returns the (possibly rewritten) input and a `denyReason` if any
|
|
6
|
+
* matcher returned `decision: 'deny'` or `'ask'`. `'ask'` collapses
|
|
7
|
+
* to deny because the bridge can't raise a LangGraph interrupt from
|
|
8
|
+
* inside an HTTP handler — fail-closed matches the rest of the SDK
|
|
9
|
+
* when HITL is unavailable.
|
|
10
|
+
*
|
|
11
|
+
* @internal Exported for tests so the deny / allow / updatedInput /
|
|
12
|
+
* ask branches can be exercised without standing up the full HTTP
|
|
13
|
+
* bridge.
|
|
14
|
+
*/
|
|
15
|
+
export declare function applyPreToolUseHooksForBridge(hookContext: t.ProgrammaticHookContext, toolName: string, toolUseId: string, toolInput: Record<string, unknown>): Promise<{
|
|
16
|
+
input: Record<string, unknown>;
|
|
17
|
+
denyReason?: string;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function _createBashProgramForTests(code: string, toolDefs: t.LCTool[], bridgeUrl: string, bridgeToken: string): string;
|
|
20
|
+
export declare function createLocalProgrammaticToolCallingTool(localConfig?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
21
|
+
export declare function createLocalBashProgrammaticToolCallingTool(localConfig?: t.LocalExecutionConfig): DynamicStructuredTool;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects whether a file on disk is an LLM-renderable attachment
|
|
3
|
+
* (image / PDF) and produces the LangChain `MessageContentComplex[]`
|
|
4
|
+
* payload a `ToolMessage` needs to actually surface those bytes to
|
|
5
|
+
* the vision-capable model.
|
|
6
|
+
*
|
|
7
|
+
* Same approach as LibreChat's `api/server/utils/files.js`: sniff the
|
|
8
|
+
* magic bytes (NOT the extension) so a mislabelled `.png` that's
|
|
9
|
+
* really a binary blob doesn't get embedded as an image. Inlined for
|
|
10
|
+
* the five formats we actually care about (PNG / JPEG / GIF / WebP /
|
|
11
|
+
* PDF) instead of pulling the ESM-only `file-type` package — keeps
|
|
12
|
+
* the test setup CJS-clean.
|
|
13
|
+
*
|
|
14
|
+
* Provider compatibility:
|
|
15
|
+
* - Anthropic: tool_result content arrays accept `image` / `image_url`
|
|
16
|
+
* blocks; LangChain's anthropic adapter at
|
|
17
|
+
* `node_modules/@langchain/anthropic/dist/utils/message_inputs.js`
|
|
18
|
+
* converts them to native `image` source blocks.
|
|
19
|
+
* - OpenAI Chat Completions: image_url blocks in tool messages are
|
|
20
|
+
* accepted on vision-capable models.
|
|
21
|
+
* - OpenAI Responses API: tool messages are flattened to plain text;
|
|
22
|
+
* image_url blocks degrade to a JSON description (still useful as
|
|
23
|
+
* a textual hint to the model).
|
|
24
|
+
* - Google: image blocks in tool responses are accepted on Gemini
|
|
25
|
+
* vision models.
|
|
26
|
+
*
|
|
27
|
+
* Configuration:
|
|
28
|
+
* - `local.attachReadAttachments` (default `'images-only'`) controls
|
|
29
|
+
* which file kinds are returned as inline attachments. Other kinds
|
|
30
|
+
* fall through to the existing binary-stub path.
|
|
31
|
+
* - `local.maxAttachmentBytes` (default 5 MB) caps the pre-encoding
|
|
32
|
+
* size; oversize attachments degrade to a stub describing the
|
|
33
|
+
* refusal so the model isn't surprised.
|
|
34
|
+
*/
|
|
35
|
+
import type { WorkspaceFS } from './workspaceFS';
|
|
36
|
+
export type AttachmentMode = 'images-only' | 'images-and-pdf' | 'off';
|
|
37
|
+
export type Attachment = {
|
|
38
|
+
kind: 'image';
|
|
39
|
+
mime: string;
|
|
40
|
+
bytes: number;
|
|
41
|
+
dataUrl: string;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'pdf';
|
|
44
|
+
mime: 'application/pdf';
|
|
45
|
+
bytes: number;
|
|
46
|
+
dataUrl: string;
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'binary';
|
|
49
|
+
mime: string;
|
|
50
|
+
bytes: number;
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'oversize';
|
|
53
|
+
mime: string;
|
|
54
|
+
bytes: number;
|
|
55
|
+
maxBytes: number;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'text-or-unknown';
|
|
58
|
+
bytes: number;
|
|
59
|
+
};
|
|
60
|
+
export declare function classifyAttachment(args: {
|
|
61
|
+
path: string;
|
|
62
|
+
bytes: number;
|
|
63
|
+
mode: AttachmentMode;
|
|
64
|
+
maxBytes: number;
|
|
65
|
+
/**
|
|
66
|
+
* WorkspaceFS to route I/O through — defaults to host fs/promises
|
|
67
|
+
* for backward compat. Manual review (finding F): without this
|
|
68
|
+
* routing, custom/remote FS implementations could either fail to
|
|
69
|
+
* embed valid attachments or accidentally read a host path with
|
|
70
|
+
* the same absolute name (since `read_file` itself does go through
|
|
71
|
+
* the configured WorkspaceFS).
|
|
72
|
+
*/
|
|
73
|
+
fs?: WorkspaceFS;
|
|
74
|
+
}): Promise<Attachment>;
|
|
75
|
+
/** Build the LangChain content array for an image attachment. */
|
|
76
|
+
export declare function imageAttachmentContent(path: string, attachment: Extract<Attachment, {
|
|
77
|
+
kind: 'image';
|
|
78
|
+
}>): Array<{
|
|
79
|
+
type: 'text' | 'image_url';
|
|
80
|
+
text?: string;
|
|
81
|
+
image_url?: {
|
|
82
|
+
url: string;
|
|
83
|
+
};
|
|
84
|
+
}>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as t from '@/types';
|
|
2
|
+
export type BashAstFinding = {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
severity: 'warn' | 'deny';
|
|
6
|
+
};
|
|
7
|
+
export declare function runBashAstChecks(command: string, mode?: t.LocalBashAstMode): BashAstFinding[];
|
|
8
|
+
export declare function bashAstFindingsToErrors(findings: BashAstFinding[]): {
|
|
9
|
+
errors: string[];
|
|
10
|
+
warnings: string[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-occurrence string-replacement strategies for `edit_file`.
|
|
3
|
+
*
|
|
4
|
+
* The LLM frequently emits an `oldString` whose whitespace, indentation,
|
|
5
|
+
* or escape sequences are slightly off from the on-disk content. Rather
|
|
6
|
+
* than failing the call (which forces a re-read + retry round-trip),
|
|
7
|
+
* we walk a chain of progressively looser matchers, stopping at the
|
|
8
|
+
* first one that locates exactly one match. The matched on-disk slice
|
|
9
|
+
* is then literally replaced with `newString` — we never modify
|
|
10
|
+
* `newString`, only the search.
|
|
11
|
+
*
|
|
12
|
+
* Strategies are ordered from strict to lenient so we don't accidentally
|
|
13
|
+
* over-match a more specific pattern with a looser one. Inspired by
|
|
14
|
+
* opencode's nine-strategy chain (sst/opencode), trimmed to the four
|
|
15
|
+
* highest-yield strategies for a first cut. Add more (block-anchor +
|
|
16
|
+
* Levenshtein, escape-normalized, etc.) as needed.
|
|
17
|
+
*/
|
|
18
|
+
export interface EditMatch {
|
|
19
|
+
/** Strategy name that produced the match, for telemetry/diagnostics. */
|
|
20
|
+
strategy: string;
|
|
21
|
+
/** Starting offset in the source. */
|
|
22
|
+
start: number;
|
|
23
|
+
/** Ending offset (exclusive). */
|
|
24
|
+
end: number;
|
|
25
|
+
}
|
|
26
|
+
export type EditStrategy = (source: string, oldString: string) => EditMatch | null;
|
|
27
|
+
export declare function locateEdit(source: string, oldString: string): EditMatch | null;
|
|
28
|
+
export declare function applyEdit(source: string, match: EditMatch, newString: string): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './CompileCheckTool';
|
|
2
|
+
export * from './FileCheckpointer';
|
|
3
|
+
export * from './LocalCodingTools';
|
|
4
|
+
export * from './LocalExecutionEngine';
|
|
5
|
+
export * from './LocalExecutionTools';
|
|
6
|
+
export * from './LocalProgrammaticToolCalling';
|
|
7
|
+
export * from './resolveLocalExecutionTools';
|
|
8
|
+
export * from './attachments';
|
|
9
|
+
export * from './bashAst';
|
|
10
|
+
export * from './editStrategies';
|
|
11
|
+
export * from './syntaxCheck';
|
|
12
|
+
export * from './textEncoding';
|