deepagents 1.8.3 → 1.8.5
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/index.cjs +323 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +191 -45
- package/dist/index.d.ts +191 -45
- package/dist/index.js +315 -130
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value:
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -7,16 +7,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
9
|
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
}
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
20
16
|
}
|
|
21
17
|
return to;
|
|
22
18
|
};
|
|
@@ -24,7 +20,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
20
|
value: mod,
|
|
25
21
|
enumerable: true
|
|
26
22
|
}) : target, mod));
|
|
27
|
-
|
|
28
23
|
//#endregion
|
|
29
24
|
let langchain = require("langchain");
|
|
30
25
|
let _langchain_core_runnables = require("@langchain/core/runnables");
|
|
@@ -37,7 +32,6 @@ let _langchain_core_messages = require("@langchain/core/messages");
|
|
|
37
32
|
let zod = require("zod");
|
|
38
33
|
let yaml = require("yaml");
|
|
39
34
|
yaml = __toESM(yaml);
|
|
40
|
-
let uuid = require("uuid");
|
|
41
35
|
let _langchain_core_errors = require("@langchain/core/errors");
|
|
42
36
|
let langchain_chat_models_universal = require("langchain/chat_models/universal");
|
|
43
37
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -50,9 +44,9 @@ let node_child_process = require("node:child_process");
|
|
|
50
44
|
node_child_process = __toESM(node_child_process);
|
|
51
45
|
let fast_glob = require("fast-glob");
|
|
52
46
|
fast_glob = __toESM(fast_glob);
|
|
47
|
+
let langsmith_experimental_sandbox = require("langsmith/experimental/sandbox");
|
|
53
48
|
let node_os = require("node:os");
|
|
54
49
|
node_os = __toESM(node_os);
|
|
55
|
-
|
|
56
50
|
//#region src/backends/protocol.ts
|
|
57
51
|
/**
|
|
58
52
|
* Type guard to check if a backend supports execution.
|
|
@@ -61,7 +55,7 @@ node_os = __toESM(node_os);
|
|
|
61
55
|
* @returns True if the backend implements SandboxBackendProtocol
|
|
62
56
|
*/
|
|
63
57
|
function isSandboxBackend(backend) {
|
|
64
|
-
return typeof backend.execute === "function" && typeof backend.id === "string";
|
|
58
|
+
return typeof backend.execute === "function" && typeof backend.id === "string" && backend.id !== "";
|
|
65
59
|
}
|
|
66
60
|
const SANDBOX_ERROR_SYMBOL = Symbol.for("sandbox.error");
|
|
67
61
|
/**
|
|
@@ -112,7 +106,6 @@ var SandboxError = class SandboxError extends Error {
|
|
|
112
106
|
return typeof error === "object" && error !== null && error[SANDBOX_ERROR_SYMBOL] === true;
|
|
113
107
|
}
|
|
114
108
|
};
|
|
115
|
-
|
|
116
109
|
//#endregion
|
|
117
110
|
//#region src/backends/utils.ts
|
|
118
111
|
/**
|
|
@@ -124,7 +117,6 @@ var SandboxError = class SandboxError extends Error {
|
|
|
124
117
|
*/
|
|
125
118
|
const EMPTY_CONTENT_WARNING = "System reminder: File exists but has empty contents";
|
|
126
119
|
const MAX_LINE_LENGTH = 1e4;
|
|
127
|
-
const LINE_NUMBER_WIDTH = 6;
|
|
128
120
|
const TOOL_RESULT_TOKEN_LIMIT = 2e4;
|
|
129
121
|
const TRUNCATION_GUIDANCE = "... [results truncated, try being more specific with your parameters]";
|
|
130
122
|
/**
|
|
@@ -154,17 +146,17 @@ function formatContentWithLineNumbers(content, startLine = 1) {
|
|
|
154
146
|
for (let i = 0; i < lines.length; i++) {
|
|
155
147
|
const line = lines[i];
|
|
156
148
|
const lineNum = i + startLine;
|
|
157
|
-
if (line.length <=
|
|
149
|
+
if (line.length <= 1e4) resultLines.push(`${lineNum.toString().padStart(6)}\t${line}`);
|
|
158
150
|
else {
|
|
159
151
|
const numChunks = Math.ceil(line.length / MAX_LINE_LENGTH);
|
|
160
152
|
for (let chunkIdx = 0; chunkIdx < numChunks; chunkIdx++) {
|
|
161
153
|
const start = chunkIdx * MAX_LINE_LENGTH;
|
|
162
154
|
const end = Math.min(start + MAX_LINE_LENGTH, line.length);
|
|
163
155
|
const chunk = line.substring(start, end);
|
|
164
|
-
if (chunkIdx === 0) resultLines.push(`${lineNum.toString().padStart(
|
|
156
|
+
if (chunkIdx === 0) resultLines.push(`${lineNum.toString().padStart(6)}\t${chunk}`);
|
|
165
157
|
else {
|
|
166
158
|
const continuationMarker = `${lineNum}.${chunkIdx}`;
|
|
167
|
-
resultLines.push(`${continuationMarker.padStart(
|
|
159
|
+
resultLines.push(`${continuationMarker.padStart(6)}\t${chunk}`);
|
|
168
160
|
}
|
|
169
161
|
}
|
|
170
162
|
}
|
|
@@ -267,13 +259,13 @@ function performStringReplacement(content, oldString, newString, replaceAll) {
|
|
|
267
259
|
function truncateIfTooLong(result) {
|
|
268
260
|
if (Array.isArray(result)) {
|
|
269
261
|
const totalChars = result.reduce((sum, item) => sum + item.length, 0);
|
|
270
|
-
if (totalChars >
|
|
262
|
+
if (totalChars > 2e4 * 4) {
|
|
271
263
|
const truncateAt = Math.floor(result.length * TOOL_RESULT_TOKEN_LIMIT * 4 / totalChars);
|
|
272
264
|
return [...result.slice(0, truncateAt), TRUNCATION_GUIDANCE];
|
|
273
265
|
}
|
|
274
266
|
return result;
|
|
275
267
|
}
|
|
276
|
-
if (result.length >
|
|
268
|
+
if (result.length > 2e4 * 4) return result.substring(0, TOOL_RESULT_TOKEN_LIMIT * 4) + "\n... [results truncated, try being more specific with your parameters]";
|
|
277
269
|
return result;
|
|
278
270
|
}
|
|
279
271
|
/**
|
|
@@ -381,7 +373,6 @@ function grepMatchesFromFiles(files, pattern, path$9 = null, glob = null) {
|
|
|
381
373
|
}
|
|
382
374
|
return matches;
|
|
383
375
|
}
|
|
384
|
-
|
|
385
376
|
//#endregion
|
|
386
377
|
//#region src/backends/state.ts
|
|
387
378
|
/**
|
|
@@ -581,7 +572,6 @@ var StateBackend = class {
|
|
|
581
572
|
return responses;
|
|
582
573
|
}
|
|
583
574
|
};
|
|
584
|
-
|
|
585
575
|
//#endregion
|
|
586
576
|
//#region src/middleware/fs.ts
|
|
587
577
|
/**
|
|
@@ -614,6 +604,20 @@ var StateBackend = class {
|
|
|
614
604
|
* These tools return minimal confirmation messages and are never expected to produce
|
|
615
605
|
* output large enough to exceed token limits, so checking them would be unnecessary.
|
|
616
606
|
*/
|
|
607
|
+
/**
|
|
608
|
+
* All tool names registered by FilesystemMiddleware.
|
|
609
|
+
* This is the single source of truth — used by createDeepAgent to detect
|
|
610
|
+
* collisions with user-supplied tools at construction time.
|
|
611
|
+
*/
|
|
612
|
+
const FILESYSTEM_TOOL_NAMES = [
|
|
613
|
+
"ls",
|
|
614
|
+
"read_file",
|
|
615
|
+
"write_file",
|
|
616
|
+
"edit_file",
|
|
617
|
+
"glob",
|
|
618
|
+
"grep",
|
|
619
|
+
"execute"
|
|
620
|
+
];
|
|
617
621
|
const TOOLS_EXCLUDED_FROM_EVICTION = [
|
|
618
622
|
"ls",
|
|
619
623
|
"glob",
|
|
@@ -623,17 +627,6 @@ const TOOLS_EXCLUDED_FROM_EVICTION = [
|
|
|
623
627
|
"write_file"
|
|
624
628
|
];
|
|
625
629
|
/**
|
|
626
|
-
* Approximate number of characters per token for truncation calculations.
|
|
627
|
-
* Using 4 chars per token as a conservative approximation (actual ratio varies by content)
|
|
628
|
-
* This errs on the high side to avoid premature eviction of content that might fit.
|
|
629
|
-
*/
|
|
630
|
-
const NUM_CHARS_PER_TOKEN = 4;
|
|
631
|
-
/**
|
|
632
|
-
* Default values for read_file tool pagination (in lines).
|
|
633
|
-
*/
|
|
634
|
-
const DEFAULT_READ_LINE_OFFSET = 0;
|
|
635
|
-
const DEFAULT_READ_LINE_LIMIT = 100;
|
|
636
|
-
/**
|
|
637
630
|
* Template for truncation message in read_file.
|
|
638
631
|
* {file_path} will be filled in at runtime.
|
|
639
632
|
*/
|
|
@@ -875,13 +868,13 @@ function createReadFileTool(backend, options) {
|
|
|
875
868
|
state: (0, _langchain_langgraph.getCurrentTaskInput)(config),
|
|
876
869
|
store: config.store
|
|
877
870
|
});
|
|
878
|
-
const { file_path, offset =
|
|
871
|
+
const { file_path, offset = 0, limit = 100 } = input;
|
|
879
872
|
let result = await resolvedBackend.read(file_path, offset, limit);
|
|
880
873
|
const lines = result.split("\n");
|
|
881
874
|
if (lines.length > limit) result = lines.slice(0, limit).join("\n");
|
|
882
|
-
if (toolTokenLimitBeforeEvict && result.length >=
|
|
875
|
+
if (toolTokenLimitBeforeEvict && result.length >= 4 * toolTokenLimitBeforeEvict) {
|
|
883
876
|
const truncationMsg = READ_FILE_TRUNCATION_MSG.replace("{file_path}", file_path);
|
|
884
|
-
const maxContentLength =
|
|
877
|
+
const maxContentLength = 4 * toolTokenLimitBeforeEvict - truncationMsg.length;
|
|
885
878
|
result = result.substring(0, maxContentLength) + truncationMsg;
|
|
886
879
|
}
|
|
887
880
|
return result;
|
|
@@ -890,8 +883,8 @@ function createReadFileTool(backend, options) {
|
|
|
890
883
|
description: customDescription || READ_FILE_TOOL_DESCRIPTION,
|
|
891
884
|
schema: zod_v4.z.object({
|
|
892
885
|
file_path: zod_v4.z.string().describe("Absolute path to the file to read"),
|
|
893
|
-
offset: zod_v4.z.coerce.number().optional().default(
|
|
894
|
-
limit: zod_v4.z.coerce.number().optional().default(
|
|
886
|
+
offset: zod_v4.z.coerce.number().optional().default(0).describe("Line offset to start reading from (0-indexed)"),
|
|
887
|
+
limit: zod_v4.z.coerce.number().optional().default(100).describe("Maximum number of lines to read")
|
|
895
888
|
})
|
|
896
889
|
});
|
|
897
890
|
}
|
|
@@ -1055,25 +1048,26 @@ function createExecuteTool(backend, options) {
|
|
|
1055
1048
|
function createFilesystemMiddleware(options = {}) {
|
|
1056
1049
|
const { backend = (stateAndStore) => new StateBackend(stateAndStore), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4 } = options;
|
|
1057
1050
|
const baseSystemPrompt = customSystemPrompt || FILESYSTEM_SYSTEM_PROMPT;
|
|
1051
|
+
const allToolsByName = {
|
|
1052
|
+
ls: createLsTool(backend, { customDescription: customToolDescriptions?.ls }),
|
|
1053
|
+
read_file: createReadFileTool(backend, {
|
|
1054
|
+
customDescription: customToolDescriptions?.read_file,
|
|
1055
|
+
toolTokenLimitBeforeEvict
|
|
1056
|
+
}),
|
|
1057
|
+
write_file: createWriteFileTool(backend, { customDescription: customToolDescriptions?.write_file }),
|
|
1058
|
+
edit_file: createEditFileTool(backend, { customDescription: customToolDescriptions?.edit_file }),
|
|
1059
|
+
glob: createGlobTool(backend, { customDescription: customToolDescriptions?.glob }),
|
|
1060
|
+
grep: createGrepTool(backend, { customDescription: customToolDescriptions?.grep }),
|
|
1061
|
+
execute: createExecuteTool(backend, { customDescription: customToolDescriptions?.execute })
|
|
1062
|
+
};
|
|
1058
1063
|
return (0, langchain.createMiddleware)({
|
|
1059
1064
|
name: "FilesystemMiddleware",
|
|
1060
1065
|
stateSchema: FilesystemStateSchema,
|
|
1061
|
-
tools:
|
|
1062
|
-
createLsTool(backend, { customDescription: customToolDescriptions?.ls }),
|
|
1063
|
-
createReadFileTool(backend, {
|
|
1064
|
-
customDescription: customToolDescriptions?.read_file,
|
|
1065
|
-
toolTokenLimitBeforeEvict
|
|
1066
|
-
}),
|
|
1067
|
-
createWriteFileTool(backend, { customDescription: customToolDescriptions?.write_file }),
|
|
1068
|
-
createEditFileTool(backend, { customDescription: customToolDescriptions?.edit_file }),
|
|
1069
|
-
createGlobTool(backend, { customDescription: customToolDescriptions?.glob }),
|
|
1070
|
-
createGrepTool(backend, { customDescription: customToolDescriptions?.grep }),
|
|
1071
|
-
createExecuteTool(backend, { customDescription: customToolDescriptions?.execute })
|
|
1072
|
-
],
|
|
1066
|
+
tools: Object.values(allToolsByName),
|
|
1073
1067
|
wrapModelCall: async (request, handler) => {
|
|
1074
1068
|
const supportsExecution = isSandboxBackend(getBackend(backend, {
|
|
1075
1069
|
state: request.state || {},
|
|
1076
|
-
store: request.
|
|
1070
|
+
store: request.runtime?.store
|
|
1077
1071
|
}));
|
|
1078
1072
|
let tools = request.tools;
|
|
1079
1073
|
if (!supportsExecution) tools = tools.filter((t) => t.name !== "execute");
|
|
@@ -1092,10 +1086,10 @@ function createFilesystemMiddleware(options = {}) {
|
|
|
1092
1086
|
if (toolName && TOOLS_EXCLUDED_FROM_EVICTION.includes(toolName)) return handler(request);
|
|
1093
1087
|
const result = await handler(request);
|
|
1094
1088
|
async function processToolMessage(msg, toolTokenLimitBeforeEvict) {
|
|
1095
|
-
if (typeof msg.content === "string" && msg.content.length > toolTokenLimitBeforeEvict *
|
|
1089
|
+
if (typeof msg.content === "string" && msg.content.length > toolTokenLimitBeforeEvict * 4) {
|
|
1096
1090
|
const resolvedBackend = getBackend(backend, {
|
|
1097
1091
|
state: request.state || {},
|
|
1098
|
-
store: request.
|
|
1092
|
+
store: request.runtime?.store
|
|
1099
1093
|
});
|
|
1100
1094
|
const evictPath = `/large_tool_results/${sanitizeToolCallId(request.toolCall?.id || msg.tool_call_id)}`;
|
|
1101
1095
|
const writeResult = await resolvedBackend.write(evictPath, msg.content);
|
|
@@ -1156,7 +1150,6 @@ function createFilesystemMiddleware(options = {}) {
|
|
|
1156
1150
|
}
|
|
1157
1151
|
});
|
|
1158
1152
|
}
|
|
1159
|
-
|
|
1160
1153
|
//#endregion
|
|
1161
1154
|
//#region src/middleware/subagents.ts
|
|
1162
1155
|
/**
|
|
@@ -1404,11 +1397,15 @@ const INVALID_TOOL_MESSAGE_BLOCK_TYPES = [
|
|
|
1404
1397
|
*/
|
|
1405
1398
|
function returnCommandWithStateUpdate(result, toolCallId) {
|
|
1406
1399
|
const stateUpdate = filterStateForSubagent(result);
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1400
|
+
let content;
|
|
1401
|
+
if (result.structuredResponse != null) content = JSON.stringify(result.structuredResponse);
|
|
1402
|
+
else {
|
|
1403
|
+
const messages = result.messages;
|
|
1404
|
+
content = (messages?.[messages.length - 1])?.content || "Task completed";
|
|
1405
|
+
if (Array.isArray(content)) {
|
|
1406
|
+
content = content.filter((block) => !INVALID_TOOL_MESSAGE_BLOCK_TYPES.includes(block.type));
|
|
1407
|
+
if (content.length === 0) content = "Task completed";
|
|
1408
|
+
}
|
|
1412
1409
|
}
|
|
1413
1410
|
return new _langchain_langgraph.Command({ update: {
|
|
1414
1411
|
...stateUpdate,
|
|
@@ -1452,7 +1449,8 @@ function getSubagents(options) {
|
|
|
1452
1449
|
systemPrompt: agentParams.systemPrompt,
|
|
1453
1450
|
tools: agentParams.tools ?? defaultTools,
|
|
1454
1451
|
middleware,
|
|
1455
|
-
name: agentParams.name
|
|
1452
|
+
name: agentParams.name,
|
|
1453
|
+
...agentParams.responseFormat != null && { responseFormat: agentParams.responseFormat }
|
|
1456
1454
|
});
|
|
1457
1455
|
}
|
|
1458
1456
|
}
|
|
@@ -1486,6 +1484,7 @@ function createTaskTool(options) {
|
|
|
1486
1484
|
subagentState.messages = [new _langchain_core_messages.HumanMessage({ content: description })];
|
|
1487
1485
|
const result = await subagent.invoke(subagentState, config);
|
|
1488
1486
|
if (!config.toolCall?.id) {
|
|
1487
|
+
if (result.structuredResponse != null) return JSON.stringify(result.structuredResponse);
|
|
1489
1488
|
const messages = result.messages;
|
|
1490
1489
|
let content = (messages?.[messages.length - 1])?.content || "Task completed";
|
|
1491
1490
|
if (Array.isArray(content)) {
|
|
@@ -1531,12 +1530,23 @@ function createSubAgentMiddleware(options) {
|
|
|
1531
1530
|
}
|
|
1532
1531
|
});
|
|
1533
1532
|
}
|
|
1534
|
-
|
|
1535
1533
|
//#endregion
|
|
1536
1534
|
//#region src/middleware/patch_tool_calls.ts
|
|
1537
1535
|
/**
|
|
1538
|
-
* Patch
|
|
1539
|
-
*
|
|
1536
|
+
* Patch tool call / tool response parity in a messages array.
|
|
1537
|
+
*
|
|
1538
|
+
* Ensures strict 1:1 correspondence between AIMessage tool_calls and
|
|
1539
|
+
* ToolMessage responses:
|
|
1540
|
+
*
|
|
1541
|
+
* 1. **Dangling tool_calls** — an AIMessage contains a tool_call with no
|
|
1542
|
+
* matching ToolMessage anywhere after it. A synthetic cancellation
|
|
1543
|
+
* ToolMessage is inserted immediately after the AIMessage.
|
|
1544
|
+
*
|
|
1545
|
+
* 2. **Orphaned ToolMessages** — a ToolMessage whose `tool_call_id` does not
|
|
1546
|
+
* match any tool_call in a preceding AIMessage. The ToolMessage is removed.
|
|
1547
|
+
*
|
|
1548
|
+
* Both directions are required for providers that enforce strict parity
|
|
1549
|
+
* (e.g. Google Gemini returns 400 INVALID_ARGUMENT otherwise).
|
|
1540
1550
|
*
|
|
1541
1551
|
* @param messages - The messages array to patch
|
|
1542
1552
|
* @returns Object with patched messages and needsPatch flag
|
|
@@ -1546,13 +1556,23 @@ function patchDanglingToolCalls(messages) {
|
|
|
1546
1556
|
patchedMessages: [],
|
|
1547
1557
|
needsPatch: false
|
|
1548
1558
|
};
|
|
1559
|
+
const allToolCallIds = /* @__PURE__ */ new Set();
|
|
1560
|
+
for (const msg of messages) if (langchain.AIMessage.isInstance(msg) && msg.tool_calls != null) {
|
|
1561
|
+
for (const tc of msg.tool_calls) if (tc.id) allToolCallIds.add(tc.id);
|
|
1562
|
+
}
|
|
1549
1563
|
const patchedMessages = [];
|
|
1550
1564
|
let needsPatch = false;
|
|
1551
1565
|
for (let i = 0; i < messages.length; i++) {
|
|
1552
1566
|
const msg = messages[i];
|
|
1567
|
+
if (langchain.ToolMessage.isInstance(msg)) {
|
|
1568
|
+
if (!allToolCallIds.has(msg.tool_call_id)) {
|
|
1569
|
+
needsPatch = true;
|
|
1570
|
+
continue;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1553
1573
|
patchedMessages.push(msg);
|
|
1554
1574
|
if (langchain.AIMessage.isInstance(msg) && msg.tool_calls != null) {
|
|
1555
|
-
for (const toolCall of msg.tool_calls) if (!messages.slice(i).find((m) => langchain.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id)) {
|
|
1575
|
+
for (const toolCall of msg.tool_calls) if (!messages.slice(i + 1).find((m) => langchain.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id)) {
|
|
1556
1576
|
needsPatch = true;
|
|
1557
1577
|
const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
|
|
1558
1578
|
patchedMessages.push(new langchain.ToolMessage({
|
|
@@ -1569,11 +1589,18 @@ function patchDanglingToolCalls(messages) {
|
|
|
1569
1589
|
};
|
|
1570
1590
|
}
|
|
1571
1591
|
/**
|
|
1572
|
-
* Create middleware that
|
|
1592
|
+
* Create middleware that enforces strict tool call / tool response parity in
|
|
1593
|
+
* the messages history.
|
|
1594
|
+
*
|
|
1595
|
+
* Two kinds of violations are repaired:
|
|
1596
|
+
* 1. **Dangling tool_calls** — an AIMessage contains tool_calls with no
|
|
1597
|
+
* matching ToolMessage responses. Synthetic cancellation ToolMessages are
|
|
1598
|
+
* injected so every tool_call has a response.
|
|
1599
|
+
* 2. **Orphaned ToolMessages** — a ToolMessage exists whose `tool_call_id`
|
|
1600
|
+
* does not match any tool_call in a preceding AIMessage. These are removed.
|
|
1573
1601
|
*
|
|
1574
|
-
*
|
|
1575
|
-
*
|
|
1576
|
-
* ToolMessages saying the tool call was cancelled.
|
|
1602
|
+
* This is critical for providers like Google Gemini that reject requests with
|
|
1603
|
+
* mismatched function call / function response counts (400 INVALID_ARGUMENT).
|
|
1577
1604
|
*
|
|
1578
1605
|
* This middleware patches in two places:
|
|
1579
1606
|
* 1. `beforeAgent`: Patches state at the start of the agent loop (handles most cases)
|
|
@@ -1581,7 +1608,7 @@ function patchDanglingToolCalls(messages) {
|
|
|
1581
1608
|
* edge cases like HITL rejection during graph resume where state updates from
|
|
1582
1609
|
* beforeAgent may not be applied in time)
|
|
1583
1610
|
*
|
|
1584
|
-
* @returns AgentMiddleware that
|
|
1611
|
+
* @returns AgentMiddleware that enforces tool call / response parity
|
|
1585
1612
|
*
|
|
1586
1613
|
* @example
|
|
1587
1614
|
* ```typescript
|
|
@@ -1619,7 +1646,6 @@ function createPatchToolCallsMiddleware() {
|
|
|
1619
1646
|
}
|
|
1620
1647
|
});
|
|
1621
1648
|
}
|
|
1622
|
-
|
|
1623
1649
|
//#endregion
|
|
1624
1650
|
//#region src/values.ts
|
|
1625
1651
|
/**
|
|
@@ -1654,7 +1680,6 @@ const filesValue = new _langchain_langgraph.ReducedValue(zod.z.record(zod.z.stri
|
|
|
1654
1680
|
inputSchema: zod.z.record(zod.z.string(), FileDataSchema.nullable()).optional(),
|
|
1655
1681
|
reducer: fileDataReducer
|
|
1656
1682
|
});
|
|
1657
|
-
|
|
1658
1683
|
//#endregion
|
|
1659
1684
|
//#region src/middleware/memory.ts
|
|
1660
1685
|
/**
|
|
@@ -1873,7 +1898,6 @@ function createMemoryMiddleware(options) {
|
|
|
1873
1898
|
}
|
|
1874
1899
|
});
|
|
1875
1900
|
}
|
|
1876
|
-
|
|
1877
1901
|
//#endregion
|
|
1878
1902
|
//#region src/middleware/skills.ts
|
|
1879
1903
|
/**
|
|
@@ -1919,7 +1943,6 @@ function createMemoryMiddleware(options) {
|
|
|
1919
1943
|
const MAX_SKILL_FILE_SIZE = 10 * 1024 * 1024;
|
|
1920
1944
|
const MAX_SKILL_NAME_LENGTH = 64;
|
|
1921
1945
|
const MAX_SKILL_DESCRIPTION_LENGTH = 1024;
|
|
1922
|
-
const MAX_SKILL_COMPATIBILITY_LENGTH = 500;
|
|
1923
1946
|
/**
|
|
1924
1947
|
* Zod schema for a single skill metadata entry.
|
|
1925
1948
|
*/
|
|
@@ -2029,7 +2052,7 @@ function validateSkillName$1(name, directoryName) {
|
|
|
2029
2052
|
valid: false,
|
|
2030
2053
|
error: "name is required"
|
|
2031
2054
|
};
|
|
2032
|
-
if (name.length >
|
|
2055
|
+
if (name.length > 64) return {
|
|
2033
2056
|
valid: false,
|
|
2034
2057
|
error: "name exceeds 64 characters"
|
|
2035
2058
|
};
|
|
@@ -2103,7 +2126,7 @@ function formatSkillAnnotations(skill) {
|
|
|
2103
2126
|
* validation errors occur
|
|
2104
2127
|
*/
|
|
2105
2128
|
function parseSkillMetadataFromContent(content, skillPath, directoryName) {
|
|
2106
|
-
if (content.length >
|
|
2129
|
+
if (content.length > 10485760) {
|
|
2107
2130
|
console.warn(`Skipping ${skillPath}: content too large (${content.length} bytes)`);
|
|
2108
2131
|
return null;
|
|
2109
2132
|
}
|
|
@@ -2133,7 +2156,7 @@ function parseSkillMetadataFromContent(content, skillPath, directoryName) {
|
|
|
2133
2156
|
const validation = validateSkillName$1(name, directoryName);
|
|
2134
2157
|
if (!validation.valid) console.warn(`Skill '${name}' in ${skillPath} does not follow Agent Skills specification: ${validation.error}. Consider renaming for spec compliance.`);
|
|
2135
2158
|
let descriptionStr = description;
|
|
2136
|
-
if (descriptionStr.length >
|
|
2159
|
+
if (descriptionStr.length > 1024) {
|
|
2137
2160
|
console.warn(`Description exceeds ${MAX_SKILL_DESCRIPTION_LENGTH} characters in ${skillPath}, truncating`);
|
|
2138
2161
|
descriptionStr = descriptionStr.slice(0, MAX_SKILL_DESCRIPTION_LENGTH);
|
|
2139
2162
|
}
|
|
@@ -2143,9 +2166,9 @@ function parseSkillMetadataFromContent(content, skillPath, directoryName) {
|
|
|
2143
2166
|
else allowedTools = String(rawTools).split(/\s+/).filter(Boolean);
|
|
2144
2167
|
else allowedTools = [];
|
|
2145
2168
|
let compatibilityStr = String(frontmatterData.compatibility ?? "").trim() || null;
|
|
2146
|
-
if (compatibilityStr && compatibilityStr.length >
|
|
2147
|
-
console.warn(`Compatibility exceeds
|
|
2148
|
-
compatibilityStr = compatibilityStr.slice(0,
|
|
2169
|
+
if (compatibilityStr && compatibilityStr.length > 500) {
|
|
2170
|
+
console.warn(`Compatibility exceeds 500 characters in ${skillPath}, truncating`);
|
|
2171
|
+
compatibilityStr = compatibilityStr.slice(0, 500);
|
|
2149
2172
|
}
|
|
2150
2173
|
return {
|
|
2151
2174
|
name,
|
|
@@ -2288,7 +2311,6 @@ function createSkillsMiddleware(options) {
|
|
|
2288
2311
|
}
|
|
2289
2312
|
});
|
|
2290
2313
|
}
|
|
2291
|
-
|
|
2292
2314
|
//#endregion
|
|
2293
2315
|
//#region src/middleware/utils.ts
|
|
2294
2316
|
/**
|
|
@@ -2296,7 +2318,6 @@ function createSkillsMiddleware(options) {
|
|
|
2296
2318
|
*
|
|
2297
2319
|
* This module provides shared helpers used across middleware implementations.
|
|
2298
2320
|
*/
|
|
2299
|
-
|
|
2300
2321
|
//#endregion
|
|
2301
2322
|
//#region src/middleware/summarization.ts
|
|
2302
2323
|
/**
|
|
@@ -2501,7 +2522,7 @@ function createSummarizationMiddleware(options) {
|
|
|
2501
2522
|
*/
|
|
2502
2523
|
function getSessionId(state) {
|
|
2503
2524
|
if (state._summarizationSessionId) return state._summarizationSessionId;
|
|
2504
|
-
if (!sessionId) sessionId = `session_${
|
|
2525
|
+
if (!sessionId) sessionId = `session_${crypto.randomUUID().substring(0, 8)}`;
|
|
2505
2526
|
return sessionId;
|
|
2506
2527
|
}
|
|
2507
2528
|
/**
|
|
@@ -2986,7 +3007,6 @@ ${summary}
|
|
|
2986
3007
|
}
|
|
2987
3008
|
});
|
|
2988
3009
|
}
|
|
2989
|
-
|
|
2990
3010
|
//#endregion
|
|
2991
3011
|
//#region src/backends/store.ts
|
|
2992
3012
|
const NAMESPACE_COMPONENT_RE = /^[A-Za-z0-9\-_.@+:~]+$/;
|
|
@@ -3330,7 +3350,6 @@ var StoreBackend = class {
|
|
|
3330
3350
|
return responses;
|
|
3331
3351
|
}
|
|
3332
3352
|
};
|
|
3333
|
-
|
|
3334
3353
|
//#endregion
|
|
3335
3354
|
//#region src/backends/filesystem.ts
|
|
3336
3355
|
/**
|
|
@@ -3849,7 +3868,6 @@ var FilesystemBackend = class {
|
|
|
3849
3868
|
return responses;
|
|
3850
3869
|
}
|
|
3851
3870
|
};
|
|
3852
|
-
|
|
3853
3871
|
//#endregion
|
|
3854
3872
|
//#region src/backends/composite.ts
|
|
3855
3873
|
/**
|
|
@@ -4098,7 +4116,6 @@ var CompositeBackend = class {
|
|
|
4098
4116
|
return results;
|
|
4099
4117
|
}
|
|
4100
4118
|
};
|
|
4101
|
-
|
|
4102
4119
|
//#endregion
|
|
4103
4120
|
//#region src/backends/local-shell.ts
|
|
4104
4121
|
/**
|
|
@@ -4403,7 +4420,6 @@ var LocalShellBackend = class LocalShellBackend extends FilesystemBackend {
|
|
|
4403
4420
|
return backend;
|
|
4404
4421
|
}
|
|
4405
4422
|
};
|
|
4406
|
-
|
|
4407
4423
|
//#endregion
|
|
4408
4424
|
//#region src/backends/sandbox.ts
|
|
4409
4425
|
/**
|
|
@@ -4802,7 +4818,197 @@ var BaseSandbox = class {
|
|
|
4802
4818
|
};
|
|
4803
4819
|
}
|
|
4804
4820
|
};
|
|
4805
|
-
|
|
4821
|
+
//#endregion
|
|
4822
|
+
//#region src/backends/langsmith.ts
|
|
4823
|
+
/**
|
|
4824
|
+
* LangSmith Sandbox backend for deepagents.
|
|
4825
|
+
*
|
|
4826
|
+
* @example
|
|
4827
|
+
* ```typescript
|
|
4828
|
+
* import { LangSmithSandbox, createDeepAgent } from "deepagents";
|
|
4829
|
+
*
|
|
4830
|
+
* const sandbox = await LangSmithSandbox.create({ templateName: "deepagents-cli" });
|
|
4831
|
+
*
|
|
4832
|
+
* const agent = createDeepAgent({ model, backend: sandbox });
|
|
4833
|
+
*
|
|
4834
|
+
* try {
|
|
4835
|
+
* await agent.invoke({ messages: [...] });
|
|
4836
|
+
* } finally {
|
|
4837
|
+
* await sandbox.close();
|
|
4838
|
+
* }
|
|
4839
|
+
* ```
|
|
4840
|
+
*/
|
|
4841
|
+
/**
|
|
4842
|
+
* LangSmith Sandbox backend for deepagents.
|
|
4843
|
+
*
|
|
4844
|
+
* Extends `BaseSandbox` to provide command execution and file operations
|
|
4845
|
+
* via the LangSmith Sandbox API.
|
|
4846
|
+
*
|
|
4847
|
+
* Use the static `LangSmithSandbox.create()` factory for the simplest setup,
|
|
4848
|
+
* or construct directly with an existing `Sandbox` instance.
|
|
4849
|
+
*/
|
|
4850
|
+
var LangSmithSandbox = class LangSmithSandbox extends BaseSandbox {
|
|
4851
|
+
#sandbox;
|
|
4852
|
+
#defaultTimeout;
|
|
4853
|
+
#isRunning = true;
|
|
4854
|
+
constructor(options) {
|
|
4855
|
+
super();
|
|
4856
|
+
this.#sandbox = options.sandbox;
|
|
4857
|
+
this.#defaultTimeout = options.defaultTimeout ?? 1800;
|
|
4858
|
+
}
|
|
4859
|
+
/** Whether the sandbox is currently active. */
|
|
4860
|
+
get isRunning() {
|
|
4861
|
+
return this.#isRunning;
|
|
4862
|
+
}
|
|
4863
|
+
/** Return the LangSmith sandbox name as the unique identifier. */
|
|
4864
|
+
get id() {
|
|
4865
|
+
return this.#sandbox.name;
|
|
4866
|
+
}
|
|
4867
|
+
/**
|
|
4868
|
+
* Execute a shell command in the LangSmith sandbox.
|
|
4869
|
+
*
|
|
4870
|
+
* @param command - Shell command string to execute
|
|
4871
|
+
* @param options.timeout - Override timeout in seconds; 0 disables timeout
|
|
4872
|
+
*/
|
|
4873
|
+
async execute(command, options) {
|
|
4874
|
+
const effectiveTimeout = options?.timeout !== void 0 ? options.timeout : this.#defaultTimeout;
|
|
4875
|
+
const result = await this.#sandbox.run(command, { timeout: effectiveTimeout });
|
|
4876
|
+
const out = result.stdout ?? "";
|
|
4877
|
+
return {
|
|
4878
|
+
output: result.stderr ? out ? `${out}\n${result.stderr}` : result.stderr : out,
|
|
4879
|
+
exitCode: result.exit_code,
|
|
4880
|
+
truncated: false
|
|
4881
|
+
};
|
|
4882
|
+
}
|
|
4883
|
+
/**
|
|
4884
|
+
* Download files from the sandbox using LangSmith's native file read API.
|
|
4885
|
+
* @param paths - List of file paths to download
|
|
4886
|
+
* @returns List of FileDownloadResponse objects, one per input path
|
|
4887
|
+
*/
|
|
4888
|
+
async downloadFiles(paths) {
|
|
4889
|
+
const responses = [];
|
|
4890
|
+
for (const path of paths) try {
|
|
4891
|
+
const content = await this.#sandbox.read(path);
|
|
4892
|
+
responses.push({
|
|
4893
|
+
path,
|
|
4894
|
+
content,
|
|
4895
|
+
error: null
|
|
4896
|
+
});
|
|
4897
|
+
} catch (err) {
|
|
4898
|
+
if (err instanceof langsmith_experimental_sandbox.LangSmithResourceNotFoundError) responses.push({
|
|
4899
|
+
path,
|
|
4900
|
+
content: null,
|
|
4901
|
+
error: "file_not_found"
|
|
4902
|
+
});
|
|
4903
|
+
else if (err instanceof langsmith_experimental_sandbox.LangSmithSandboxError) {
|
|
4904
|
+
const error = String(err.message).toLowerCase().includes("is a directory") ? "is_directory" : "file_not_found";
|
|
4905
|
+
responses.push({
|
|
4906
|
+
path,
|
|
4907
|
+
content: null,
|
|
4908
|
+
error
|
|
4909
|
+
});
|
|
4910
|
+
} else responses.push({
|
|
4911
|
+
path,
|
|
4912
|
+
content: null,
|
|
4913
|
+
error: "invalid_path"
|
|
4914
|
+
});
|
|
4915
|
+
}
|
|
4916
|
+
return responses;
|
|
4917
|
+
}
|
|
4918
|
+
/**
|
|
4919
|
+
* Upload files to the sandbox using LangSmith's native file write API.
|
|
4920
|
+
* @param files - List of [path, content] tuples to upload
|
|
4921
|
+
* @returns List of FileUploadResponse objects, one per input file
|
|
4922
|
+
*/
|
|
4923
|
+
async uploadFiles(files) {
|
|
4924
|
+
const responses = [];
|
|
4925
|
+
for (const [path, content] of files) try {
|
|
4926
|
+
await this.#sandbox.write(path, content);
|
|
4927
|
+
responses.push({
|
|
4928
|
+
path,
|
|
4929
|
+
error: null
|
|
4930
|
+
});
|
|
4931
|
+
} catch {
|
|
4932
|
+
responses.push({
|
|
4933
|
+
path,
|
|
4934
|
+
error: "permission_denied"
|
|
4935
|
+
});
|
|
4936
|
+
}
|
|
4937
|
+
return responses;
|
|
4938
|
+
}
|
|
4939
|
+
/**
|
|
4940
|
+
* Delete this sandbox and mark it as no longer running.
|
|
4941
|
+
*
|
|
4942
|
+
* After calling this, `isRunning` will be `false` and the sandbox
|
|
4943
|
+
* cannot be used again.
|
|
4944
|
+
*/
|
|
4945
|
+
async close() {
|
|
4946
|
+
await this.#sandbox.delete();
|
|
4947
|
+
this.#isRunning = false;
|
|
4948
|
+
}
|
|
4949
|
+
/**
|
|
4950
|
+
* Create and return a new LangSmithSandbox in one step.
|
|
4951
|
+
*
|
|
4952
|
+
* This is the recommended way to create a sandbox — no need to import
|
|
4953
|
+
* anything from `langsmith/experimental/sandbox` directly.
|
|
4954
|
+
*
|
|
4955
|
+
* @example
|
|
4956
|
+
* ```typescript
|
|
4957
|
+
* const sandbox = await LangSmithSandbox.create({ templateName: "deepagents" });
|
|
4958
|
+
* try {
|
|
4959
|
+
* const agent = createDeepAgent({ model, backend: sandbox });
|
|
4960
|
+
* await agent.invoke({ messages: [...] });
|
|
4961
|
+
* } finally {
|
|
4962
|
+
* await sandbox.close();
|
|
4963
|
+
* }
|
|
4964
|
+
* ```
|
|
4965
|
+
*/
|
|
4966
|
+
static async create(options = {}) {
|
|
4967
|
+
const { templateName = "deepagents", apiKey = process.env.LANGSMITH_API_KEY, defaultTimeout } = options;
|
|
4968
|
+
return new LangSmithSandbox({
|
|
4969
|
+
sandbox: await new langsmith_experimental_sandbox.SandboxClient({ apiKey }).createSandbox(templateName),
|
|
4970
|
+
defaultTimeout
|
|
4971
|
+
});
|
|
4972
|
+
}
|
|
4973
|
+
};
|
|
4974
|
+
//#endregion
|
|
4975
|
+
//#region src/errors.ts
|
|
4976
|
+
const CONFIGURATION_ERROR_SYMBOL = Symbol.for("deepagents.configuration_error");
|
|
4977
|
+
/**
|
|
4978
|
+
* Thrown when `createDeepAgent` receives invalid configuration.
|
|
4979
|
+
*
|
|
4980
|
+
* Follows the same pattern as {@link SandboxError}: a human-readable
|
|
4981
|
+
* `message`, a structured `code` for programmatic handling, and a
|
|
4982
|
+
* static `isInstance` guard that works across realms.
|
|
4983
|
+
*
|
|
4984
|
+
* @example
|
|
4985
|
+
* ```typescript
|
|
4986
|
+
* try {
|
|
4987
|
+
* createDeepAgent({ tools: [myTool] });
|
|
4988
|
+
* } catch (error) {
|
|
4989
|
+
* if (ConfigurationError.isInstance(error)) {
|
|
4990
|
+
* switch (error.code) {
|
|
4991
|
+
* case "TOOL_NAME_COLLISION":
|
|
4992
|
+
* console.error("Rename your tool:", error.message);
|
|
4993
|
+
* break;
|
|
4994
|
+
* }
|
|
4995
|
+
* }
|
|
4996
|
+
* }
|
|
4997
|
+
* ```
|
|
4998
|
+
*/
|
|
4999
|
+
var ConfigurationError = class ConfigurationError extends Error {
|
|
5000
|
+
[CONFIGURATION_ERROR_SYMBOL] = true;
|
|
5001
|
+
name = "ConfigurationError";
|
|
5002
|
+
constructor(message, code, cause) {
|
|
5003
|
+
super(message);
|
|
5004
|
+
this.code = code;
|
|
5005
|
+
this.cause = cause;
|
|
5006
|
+
Object.setPrototypeOf(this, ConfigurationError.prototype);
|
|
5007
|
+
}
|
|
5008
|
+
static isInstance(error) {
|
|
5009
|
+
return typeof error === "object" && error !== null && error[CONFIGURATION_ERROR_SYMBOL] === true;
|
|
5010
|
+
}
|
|
5011
|
+
};
|
|
4806
5012
|
//#endregion
|
|
4807
5013
|
//#region src/middleware/cache.ts
|
|
4808
5014
|
/**
|
|
@@ -4846,10 +5052,14 @@ function createCacheBreakpointMiddleware() {
|
|
|
4846
5052
|
}
|
|
4847
5053
|
});
|
|
4848
5054
|
}
|
|
4849
|
-
|
|
4850
5055
|
//#endregion
|
|
4851
5056
|
//#region src/agent.ts
|
|
4852
5057
|
const BASE_PROMPT = `In order to complete the objective that the user asks of you, you have access to a number of standard tools.`;
|
|
5058
|
+
const BUILTIN_TOOL_NAMES = new Set([
|
|
5059
|
+
...FILESYSTEM_TOOL_NAMES,
|
|
5060
|
+
"task",
|
|
5061
|
+
"write_todos"
|
|
5062
|
+
]);
|
|
4853
5063
|
/**
|
|
4854
5064
|
* Detect whether a model is an Anthropic model.
|
|
4855
5065
|
* Used to gate Anthropic-specific prompt caching optimizations (cache_control breakpoints).
|
|
@@ -4895,6 +5105,8 @@ function isAnthropicModel(model) {
|
|
|
4895
5105
|
*/
|
|
4896
5106
|
function createDeepAgent(params = {}) {
|
|
4897
5107
|
const { model = "claude-sonnet-4-5-20250929", tools = [], systemPrompt, middleware: customMiddleware = [], subagents = [], responseFormat, contextSchema, checkpointer, store, backend, interruptOn, name, memory, skills } = params;
|
|
5108
|
+
const collidingTools = tools.map((t) => t.name).filter((n) => typeof n === "string" && BUILTIN_TOOL_NAMES.has(n));
|
|
5109
|
+
if (collidingTools.length > 0) throw new ConfigurationError(`Tool name(s) [${collidingTools.join(", ")}] conflict with built-in tools. Rename your custom tools to avoid this.`, "TOOL_NAME_COLLISION");
|
|
4898
5110
|
const anthropicModel = isAnthropicModel(model);
|
|
4899
5111
|
const finalSystemPrompt = new langchain.SystemMessage({ content: systemPrompt ? typeof systemPrompt === "string" ? [{
|
|
4900
5112
|
type: "text",
|
|
@@ -4976,10 +5188,6 @@ function createDeepAgent(params = {}) {
|
|
|
4976
5188
|
model,
|
|
4977
5189
|
backend: filesystemBackend
|
|
4978
5190
|
}),
|
|
4979
|
-
(0, langchain.anthropicPromptCachingMiddleware)({
|
|
4980
|
-
unsupportedModelBehavior: "ignore",
|
|
4981
|
-
minMessagesToCache: 1
|
|
4982
|
-
}),
|
|
4983
5191
|
createPatchToolCallsMiddleware()
|
|
4984
5192
|
];
|
|
4985
5193
|
/**
|
|
@@ -5002,11 +5210,17 @@ function createDeepAgent(params = {}) {
|
|
|
5002
5210
|
createSubAgentMiddleware({
|
|
5003
5211
|
defaultModel: model,
|
|
5004
5212
|
defaultTools: tools,
|
|
5005
|
-
defaultMiddleware: [...subagentMiddleware, ...anthropicModel ? [
|
|
5213
|
+
defaultMiddleware: [...subagentMiddleware, ...anthropicModel ? [(0, langchain.anthropicPromptCachingMiddleware)({
|
|
5214
|
+
unsupportedModelBehavior: "ignore",
|
|
5215
|
+
minMessagesToCache: 1
|
|
5216
|
+
}), createCacheBreakpointMiddleware()] : []],
|
|
5006
5217
|
generalPurposeMiddleware: [
|
|
5007
5218
|
...subagentMiddleware,
|
|
5008
5219
|
...skillsMiddlewareArray,
|
|
5009
|
-
...anthropicModel ? [
|
|
5220
|
+
...anthropicModel ? [(0, langchain.anthropicPromptCachingMiddleware)({
|
|
5221
|
+
unsupportedModelBehavior: "ignore",
|
|
5222
|
+
minMessagesToCache: 1
|
|
5223
|
+
}), createCacheBreakpointMiddleware()] : []
|
|
5010
5224
|
],
|
|
5011
5225
|
defaultInterruptOn: interruptOn,
|
|
5012
5226
|
subagents: processedSubagents,
|
|
@@ -5016,17 +5230,16 @@ function createDeepAgent(params = {}) {
|
|
|
5016
5230
|
model,
|
|
5017
5231
|
backend: filesystemBackend
|
|
5018
5232
|
}),
|
|
5019
|
-
(0, langchain.anthropicPromptCachingMiddleware)({
|
|
5020
|
-
unsupportedModelBehavior: "ignore",
|
|
5021
|
-
minMessagesToCache: 1
|
|
5022
|
-
}),
|
|
5023
5233
|
createPatchToolCallsMiddleware()
|
|
5024
5234
|
],
|
|
5025
5235
|
...skillsMiddlewareArray,
|
|
5026
|
-
...
|
|
5236
|
+
...customMiddleware,
|
|
5237
|
+
...anthropicModel ? [(0, langchain.anthropicPromptCachingMiddleware)({
|
|
5238
|
+
unsupportedModelBehavior: "ignore",
|
|
5239
|
+
minMessagesToCache: 1
|
|
5240
|
+
}), createCacheBreakpointMiddleware()] : [],
|
|
5027
5241
|
...memoryMiddlewareArray,
|
|
5028
|
-
...interruptOn ? [(0, langchain.humanInTheLoopMiddleware)({ interruptOn })] : []
|
|
5029
|
-
...customMiddleware
|
|
5242
|
+
...interruptOn ? [(0, langchain.humanInTheLoopMiddleware)({ interruptOn })] : []
|
|
5030
5243
|
],
|
|
5031
5244
|
...responseFormat != null && { responseFormat },
|
|
5032
5245
|
contextSchema,
|
|
@@ -5038,7 +5251,6 @@ function createDeepAgent(params = {}) {
|
|
|
5038
5251
|
metadata: { ls_integration: "deepagents" }
|
|
5039
5252
|
});
|
|
5040
5253
|
}
|
|
5041
|
-
|
|
5042
5254
|
//#endregion
|
|
5043
5255
|
//#region src/config.ts
|
|
5044
5256
|
/**
|
|
@@ -5132,7 +5344,6 @@ function createSettings(options = {}) {
|
|
|
5132
5344
|
}
|
|
5133
5345
|
};
|
|
5134
5346
|
}
|
|
5135
|
-
|
|
5136
5347
|
//#endregion
|
|
5137
5348
|
//#region src/middleware/agent-memory.ts
|
|
5138
5349
|
/**
|
|
@@ -5359,38 +5570,6 @@ function createAgentMemoryMiddleware(options) {
|
|
|
5359
5570
|
}
|
|
5360
5571
|
});
|
|
5361
5572
|
}
|
|
5362
|
-
|
|
5363
|
-
//#endregion
|
|
5364
|
-
//#region src/skills/loader.ts
|
|
5365
|
-
/**
|
|
5366
|
-
* Skill loader for parsing and loading agent skills from SKILL.md files.
|
|
5367
|
-
*
|
|
5368
|
-
* This module implements Anthropic's agent skills pattern with YAML frontmatter parsing.
|
|
5369
|
-
* Each skill is a directory containing a SKILL.md file with:
|
|
5370
|
-
* - YAML frontmatter (name, description required)
|
|
5371
|
-
* - Markdown instructions for the agent
|
|
5372
|
-
* - Optional supporting files (scripts, configs, etc.)
|
|
5373
|
-
*
|
|
5374
|
-
* @example
|
|
5375
|
-
* ```markdown
|
|
5376
|
-
* ---
|
|
5377
|
-
* name: web-research
|
|
5378
|
-
* description: Structured approach to conducting thorough web research
|
|
5379
|
-
* ---
|
|
5380
|
-
*
|
|
5381
|
-
* # Web Research Skill
|
|
5382
|
-
*
|
|
5383
|
-
* ## When to Use
|
|
5384
|
-
* - User asks you to research a topic
|
|
5385
|
-
* ...
|
|
5386
|
-
* ```
|
|
5387
|
-
*
|
|
5388
|
-
* @see https://agentskills.io/specification
|
|
5389
|
-
*/
|
|
5390
|
-
/** Maximum size for SKILL.md files (10MB) */
|
|
5391
|
-
const MAX_SKILL_FILE_SIZE$1 = 10 * 1024 * 1024;
|
|
5392
|
-
/** Agent Skills spec constraints */
|
|
5393
|
-
const MAX_SKILL_NAME_LENGTH$1 = 64;
|
|
5394
5573
|
const MAX_SKILL_DESCRIPTION_LENGTH$1 = 1024;
|
|
5395
5574
|
/** Pattern for validating skill names per Agent Skills spec */
|
|
5396
5575
|
const SKILL_NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
@@ -5435,7 +5614,7 @@ function validateSkillName(name, directoryName) {
|
|
|
5435
5614
|
valid: false,
|
|
5436
5615
|
error: "name is required"
|
|
5437
5616
|
};
|
|
5438
|
-
if (name.length >
|
|
5617
|
+
if (name.length > 64) return {
|
|
5439
5618
|
valid: false,
|
|
5440
5619
|
error: "name exceeds 64 characters"
|
|
5441
5620
|
};
|
|
@@ -5475,7 +5654,7 @@ function parseFrontmatter(content) {
|
|
|
5475
5654
|
function parseSkillMetadata(skillMdPath, source) {
|
|
5476
5655
|
try {
|
|
5477
5656
|
const stats = node_fs.default.statSync(skillMdPath);
|
|
5478
|
-
if (stats.size >
|
|
5657
|
+
if (stats.size > 10485760) {
|
|
5479
5658
|
console.warn(`Skipping ${skillMdPath}: file too large (${stats.size} bytes)`);
|
|
5480
5659
|
return null;
|
|
5481
5660
|
}
|
|
@@ -5494,7 +5673,7 @@ function parseSkillMetadata(skillMdPath, source) {
|
|
|
5494
5673
|
const validation = validateSkillName(String(name), directoryName);
|
|
5495
5674
|
if (!validation.valid) console.warn(`Skill '${name}' in ${skillMdPath} does not follow Agent Skills spec: ${validation.error}. Consider renaming to be spec-compliant.`);
|
|
5496
5675
|
let descriptionStr = String(description);
|
|
5497
|
-
if (descriptionStr.length >
|
|
5676
|
+
if (descriptionStr.length > 1024) {
|
|
5498
5677
|
console.warn(`Description exceeds ${MAX_SKILL_DESCRIPTION_LENGTH$1} chars in ${skillMdPath}, truncating`);
|
|
5499
5678
|
descriptionStr = descriptionStr.slice(0, MAX_SKILL_DESCRIPTION_LENGTH$1);
|
|
5500
5679
|
}
|
|
@@ -5582,14 +5761,15 @@ function listSkills(options) {
|
|
|
5582
5761
|
}
|
|
5583
5762
|
return Array.from(allSkills.values());
|
|
5584
5763
|
}
|
|
5585
|
-
|
|
5586
5764
|
//#endregion
|
|
5587
5765
|
exports.BaseSandbox = BaseSandbox;
|
|
5588
5766
|
exports.CompositeBackend = CompositeBackend;
|
|
5767
|
+
exports.ConfigurationError = ConfigurationError;
|
|
5589
5768
|
exports.DEFAULT_GENERAL_PURPOSE_DESCRIPTION = DEFAULT_GENERAL_PURPOSE_DESCRIPTION;
|
|
5590
5769
|
exports.DEFAULT_SUBAGENT_PROMPT = DEFAULT_SUBAGENT_PROMPT;
|
|
5591
5770
|
exports.FilesystemBackend = FilesystemBackend;
|
|
5592
5771
|
exports.GENERAL_PURPOSE_SUBAGENT = GENERAL_PURPOSE_SUBAGENT;
|
|
5772
|
+
exports.LangSmithSandbox = LangSmithSandbox;
|
|
5593
5773
|
exports.LocalShellBackend = LocalShellBackend;
|
|
5594
5774
|
exports.MAX_SKILL_DESCRIPTION_LENGTH = MAX_SKILL_DESCRIPTION_LENGTH;
|
|
5595
5775
|
exports.MAX_SKILL_FILE_SIZE = MAX_SKILL_FILE_SIZE;
|
|
@@ -5613,4 +5793,5 @@ exports.findProjectRoot = findProjectRoot;
|
|
|
5613
5793
|
exports.isSandboxBackend = isSandboxBackend;
|
|
5614
5794
|
exports.listSkills = listSkills;
|
|
5615
5795
|
exports.parseSkillMetadata = parseSkillMetadata;
|
|
5796
|
+
|
|
5616
5797
|
//# sourceMappingURL=index.cjs.map
|