deepagents 1.14.1 → 1.14.2
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/{agent-B05mw_iK.d.cts → agent-3XynVB9Z.d.cts} +58 -2
- package/dist/{agent-CxEdojMv.d.ts → agent-BKShWAoi.d.ts} +58 -3
- package/dist/browser.cjs +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/index.cjs +6 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/{langsmith-Bgi_Ta-k.js → langsmith--RbtjNdQ.js} +603 -12
- package/dist/langsmith--RbtjNdQ.js.map +1 -0
- package/dist/{langsmith-Bhg_Q4ZO.cjs → langsmith-CjOWZAS2.cjs} +626 -11
- package/dist/langsmith-CjOWZAS2.cjs.map +1 -0
- package/dist/node.cjs +6 -2
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/node.js +3 -3
- package/dist/{src-CB_Eac87.cjs → src-BuYhtaIW.cjs} +2 -2
- package/dist/{src-CB_Eac87.cjs.map → src-BuYhtaIW.cjs.map} +1 -1
- package/dist/{src-BGwHTd6z.js → src-YqBMARBL.js} +2 -2
- package/dist/{src-BGwHTd6z.js.map → src-YqBMARBL.js.map} +1 -1
- package/package.json +7 -7
- package/dist/langsmith-Bgi_Ta-k.js.map +0 -1
- package/dist/langsmith-Bhg_Q4ZO.cjs.map +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AIMessage, HumanMessage, SystemMessage, ToolMessage, anthropicPromptCachingMiddleware, bedrockPromptCachingMiddleware, context, countTokensApproximately, createAgent, createMiddleware, humanInTheLoopMiddleware, todoListMiddleware, tool } from "langchain";
|
|
2
|
+
import { ContextOverflowError } from "@langchain/core/errors";
|
|
2
3
|
import { Command, REMOVE_ALL_MESSAGES, ReducedValue, StateSchema, getConfig, getCurrentTaskInput, getStore, isCommand } from "@langchain/langgraph";
|
|
3
4
|
import { z } from "zod/v4";
|
|
4
5
|
import micromatch from "micromatch";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
5
7
|
import { AIMessage as AIMessage$1, HumanMessage as HumanMessage$1, RemoveMessage, SystemMessage as SystemMessage$1, ToolMessage as ToolMessage$1, getBufferString } from "@langchain/core/messages";
|
|
6
8
|
import * as z$2 from "zod";
|
|
7
9
|
import { z as z$1 } from "zod";
|
|
8
|
-
import { ContextOverflowError } from "@langchain/core/errors";
|
|
9
10
|
import { initChatModel } from "langchain/chat_models/universal";
|
|
10
11
|
import yaml from "yaml";
|
|
11
12
|
import { Client } from "@langchain/langgraph-sdk";
|
|
@@ -633,9 +634,18 @@ function adaptBackendProtocol(backend) {
|
|
|
633
634
|
return result;
|
|
634
635
|
}
|
|
635
636
|
};
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
value
|
|
637
|
+
const identityMarkers = [["routePrefixes", Array.isArray], ["backendKind", (value) => typeof value === "string"]];
|
|
638
|
+
for (const [key, isValid] of identityMarkers) {
|
|
639
|
+
const value = backend[key];
|
|
640
|
+
if (isValid(value)) Object.defineProperty(adapted, key, {
|
|
641
|
+
value,
|
|
642
|
+
enumerable: true,
|
|
643
|
+
configurable: true
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
const resolveBackendForPath = backend.resolveBackendForPath;
|
|
647
|
+
if (typeof resolveBackendForPath === "function") Object.defineProperty(adapted, "resolveBackendForPath", {
|
|
648
|
+
value: (path) => resolveBackendForPath.call(backend, path),
|
|
639
649
|
enumerable: true,
|
|
640
650
|
configurable: true
|
|
641
651
|
});
|
|
@@ -786,8 +796,14 @@ const PREGEL_READ_KEY = "__pregel_read";
|
|
|
786
796
|
* for the middleware to apply via Command.
|
|
787
797
|
*/
|
|
788
798
|
var StateBackend = class {
|
|
799
|
+
/** Class identity discriminant for {@link StateBackend.isInstance}. */
|
|
800
|
+
backendKind = "state";
|
|
789
801
|
runtime;
|
|
790
802
|
fileFormat;
|
|
803
|
+
/** Duck-typed so this survives the plain-object copies `adaptBackendProtocol` makes — a class check wouldn't. */
|
|
804
|
+
static isInstance(backend) {
|
|
805
|
+
return typeof backend === "object" && backend !== null && backend.backendKind === "state";
|
|
806
|
+
}
|
|
791
807
|
constructor(runtimeOrOptions, options) {
|
|
792
808
|
if (runtimeOrOptions != null && typeof runtimeOrOptions === "object" && "state" in runtimeOrOptions) {
|
|
793
809
|
this.runtime = runtimeOrOptions;
|
|
@@ -1087,6 +1103,466 @@ var StateBackend = class {
|
|
|
1087
1103
|
}
|
|
1088
1104
|
};
|
|
1089
1105
|
//#endregion
|
|
1106
|
+
//#region src/middleware/blobOffload.ts
|
|
1107
|
+
/**
|
|
1108
|
+
* Content-addressed offload of binary `read_file` and inline `HumanMessage`
|
|
1109
|
+
* blocks to the backend.
|
|
1110
|
+
*
|
|
1111
|
+
* Binary blocks are written to `/blobs/<sha256>` and replaced in state with a
|
|
1112
|
+
* `deepagents_blob` reference. Model requests are rehydrated from the backend
|
|
1113
|
+
* (or a per-run cache), so checkpoints never carry the base64 payload.
|
|
1114
|
+
*/
|
|
1115
|
+
/** Content block key holding the SHA-256 digest of an offloaded payload. */
|
|
1116
|
+
const BLOB_REF_KEY = "deepagents_blob";
|
|
1117
|
+
const MISSING_BLOB_TEXT = "[Binary content from an earlier read_file call is no longer available. Re-read the file if you still need it.]";
|
|
1118
|
+
const DIGEST_RE = /^[0-9a-f]{64}$/;
|
|
1119
|
+
const BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
1120
|
+
/** Whether `reference` is a well-formed digest string. */
|
|
1121
|
+
function isDigest(reference) {
|
|
1122
|
+
return typeof reference === "string" && DIGEST_RE.test(reference);
|
|
1123
|
+
}
|
|
1124
|
+
function isValidBase64(value) {
|
|
1125
|
+
return value.length > 0 && value.length % 4 === 0 && BASE64_RE.test(value);
|
|
1126
|
+
}
|
|
1127
|
+
function sha256Hex(bytes) {
|
|
1128
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
1129
|
+
}
|
|
1130
|
+
const DEFAULT_BLOB_CACHE_BYTES = 268435456;
|
|
1131
|
+
/**
|
|
1132
|
+
* Content-addressed cache of base64 payloads, bounded by total payload size
|
|
1133
|
+
* (LRU-evicted past the bound). Safe to share across threads — every key is
|
|
1134
|
+
* a SHA-256 digest of its own value, so a hit is only reachable by a caller
|
|
1135
|
+
* who already has that exact reference, and an eviction just forces a
|
|
1136
|
+
* re-fetch from the backend, never a wrong result.
|
|
1137
|
+
*/
|
|
1138
|
+
var BlobCache = class extends Map {
|
|
1139
|
+
maxBytes;
|
|
1140
|
+
totalBytes = 0;
|
|
1141
|
+
constructor(maxBytes = DEFAULT_BLOB_CACHE_BYTES) {
|
|
1142
|
+
super();
|
|
1143
|
+
this.maxBytes = maxBytes;
|
|
1144
|
+
}
|
|
1145
|
+
/** Returns the cached payload for `digest`, marking it most recently used. */
|
|
1146
|
+
get(digest) {
|
|
1147
|
+
const payload = super.get(digest);
|
|
1148
|
+
if (payload === void 0) return void 0;
|
|
1149
|
+
super.delete(digest);
|
|
1150
|
+
super.set(digest, payload);
|
|
1151
|
+
return payload;
|
|
1152
|
+
}
|
|
1153
|
+
/** Caches `payload`, evicting least-recently-used entries past the size bound. */
|
|
1154
|
+
set(digest, payload) {
|
|
1155
|
+
if (payload.length > this.maxBytes) return this;
|
|
1156
|
+
const previous = super.get(digest);
|
|
1157
|
+
if (previous !== void 0) {
|
|
1158
|
+
this.totalBytes -= previous.length;
|
|
1159
|
+
super.delete(digest);
|
|
1160
|
+
}
|
|
1161
|
+
super.set(digest, payload);
|
|
1162
|
+
this.totalBytes += payload.length;
|
|
1163
|
+
while (this.totalBytes > this.maxBytes) {
|
|
1164
|
+
const oldestDigest = this.keys().next().value;
|
|
1165
|
+
if (oldestDigest === void 0) break;
|
|
1166
|
+
const oldest = super.get(oldestDigest);
|
|
1167
|
+
super.delete(oldestDigest);
|
|
1168
|
+
this.totalBytes -= oldest?.length ?? 0;
|
|
1169
|
+
}
|
|
1170
|
+
return this;
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
function blobPath(prefix, digest) {
|
|
1174
|
+
return `${prefix}/${digest}`;
|
|
1175
|
+
}
|
|
1176
|
+
function contentBlocks(message) {
|
|
1177
|
+
const content = message?.content;
|
|
1178
|
+
return Array.isArray(content) ? content : null;
|
|
1179
|
+
}
|
|
1180
|
+
/** Map each inline base64 payload found in `messages` to its digest and decoded bytes. */
|
|
1181
|
+
function pendingBlobs(messages) {
|
|
1182
|
+
const pending = /* @__PURE__ */ new Map();
|
|
1183
|
+
for (const message of messages) {
|
|
1184
|
+
const blocks = contentBlocks(message);
|
|
1185
|
+
if (!blocks) continue;
|
|
1186
|
+
for (const block of blocks) {
|
|
1187
|
+
if (block == null || typeof block !== "object") continue;
|
|
1188
|
+
const payload = block.data;
|
|
1189
|
+
if (typeof payload !== "string" || pending.has(payload) || !isValidBase64(payload)) continue;
|
|
1190
|
+
let raw;
|
|
1191
|
+
try {
|
|
1192
|
+
raw = new Uint8Array(Buffer.from(payload, "base64"));
|
|
1193
|
+
} catch {
|
|
1194
|
+
continue;
|
|
1195
|
+
}
|
|
1196
|
+
pending.set(payload, {
|
|
1197
|
+
digest: sha256Hex(raw),
|
|
1198
|
+
raw
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return pending;
|
|
1203
|
+
}
|
|
1204
|
+
/** Replace payloads found in `digests` with blob references; returns `messages` unchanged if nothing matched. */
|
|
1205
|
+
function stubMessages(messages, digests) {
|
|
1206
|
+
return messages.map((message) => {
|
|
1207
|
+
const blocks = contentBlocks(message);
|
|
1208
|
+
if (!blocks) return message;
|
|
1209
|
+
let changed = false;
|
|
1210
|
+
const newContent = blocks.map((block) => {
|
|
1211
|
+
const digest = typeof block.data === "string" ? digests.get(block.data) : void 0;
|
|
1212
|
+
if (digest === void 0) return block;
|
|
1213
|
+
changed = true;
|
|
1214
|
+
const { data: _data, ...rest } = block;
|
|
1215
|
+
return {
|
|
1216
|
+
...rest,
|
|
1217
|
+
[BLOB_REF_KEY]: digest
|
|
1218
|
+
};
|
|
1219
|
+
});
|
|
1220
|
+
if (!changed) return message;
|
|
1221
|
+
return withContent(message, newContent);
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Upload inline binary payloads found in `messages` and return messages carrying blob
|
|
1226
|
+
* references instead. Payloads that fail to upload stay inline — offload is best-effort.
|
|
1227
|
+
*/
|
|
1228
|
+
async function offloadMessages(messages, backend, prefix, cache) {
|
|
1229
|
+
const pending = pendingBlobs(messages);
|
|
1230
|
+
if (pending.size === 0) return [...messages];
|
|
1231
|
+
if (typeof backend.uploadFiles !== "function") {
|
|
1232
|
+
console.warn("Backend does not support uploadFiles; binary read_file content stays inline");
|
|
1233
|
+
return [...messages];
|
|
1234
|
+
}
|
|
1235
|
+
const entries = [...pending.entries()];
|
|
1236
|
+
let responses;
|
|
1237
|
+
try {
|
|
1238
|
+
responses = await backend.uploadFiles(entries.map(([, { digest, raw }]) => [blobPath(prefix, digest), raw]));
|
|
1239
|
+
} catch (error) {
|
|
1240
|
+
console.warn("Failed to offload binary read_file content; keeping it inline", error);
|
|
1241
|
+
return [...messages];
|
|
1242
|
+
}
|
|
1243
|
+
const digests = /* @__PURE__ */ new Map();
|
|
1244
|
+
entries.forEach(([payload, { digest }], index) => {
|
|
1245
|
+
if (responses[index]?.error == null) {
|
|
1246
|
+
digests.set(payload, digest);
|
|
1247
|
+
cache.set(digest, payload);
|
|
1248
|
+
}
|
|
1249
|
+
});
|
|
1250
|
+
return stubMessages(messages, digests);
|
|
1251
|
+
}
|
|
1252
|
+
/** Apply `offloadMessages` to a tool result (a `ToolMessage`, or a `Command`-shaped update). */
|
|
1253
|
+
async function offloadToolResult(result, backend, prefix, cache) {
|
|
1254
|
+
if (ToolMessage.isInstance(result)) return (await offloadMessages([result], backend, prefix, cache))[0];
|
|
1255
|
+
const update = result?.update;
|
|
1256
|
+
if (update && Array.isArray(update.messages)) {
|
|
1257
|
+
const messages = await offloadMessages(update.messages, backend, prefix, cache);
|
|
1258
|
+
return new Command({
|
|
1259
|
+
...result,
|
|
1260
|
+
update: {
|
|
1261
|
+
...update,
|
|
1262
|
+
messages
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
return result;
|
|
1267
|
+
}
|
|
1268
|
+
/** Return `HumanMessage`s with ids after the last `AIMessage`, preferring a version already queued in `pending`. */
|
|
1269
|
+
function humanCandidates({ stateMessages, pending }) {
|
|
1270
|
+
let lastAiIndex = -1;
|
|
1271
|
+
stateMessages.forEach((message, index) => {
|
|
1272
|
+
if (AIMessage.isInstance(message)) lastAiIndex = index;
|
|
1273
|
+
});
|
|
1274
|
+
const queued = /* @__PURE__ */ new Map();
|
|
1275
|
+
for (const message of pending) {
|
|
1276
|
+
const id = message?.id;
|
|
1277
|
+
if (typeof id === "string") queued.set(id, message);
|
|
1278
|
+
}
|
|
1279
|
+
const candidates = [];
|
|
1280
|
+
for (const message of stateMessages.slice(lastAiIndex + 1)) {
|
|
1281
|
+
if (!HumanMessage.isInstance(message) || typeof message.id !== "string") continue;
|
|
1282
|
+
candidates.push(queued.get(message.id) ?? message);
|
|
1283
|
+
}
|
|
1284
|
+
return candidates;
|
|
1285
|
+
}
|
|
1286
|
+
function mergeReplacements({ pending, offloaded, candidates }) {
|
|
1287
|
+
const replaced = offloaded.filter((next, index) => next !== candidates[index]);
|
|
1288
|
+
const replacedIds = new Set(replaced.map((message) => message?.id));
|
|
1289
|
+
return [...pending.filter((message) => !replacedIds.has(message?.id)), ...replaced];
|
|
1290
|
+
}
|
|
1291
|
+
/** Return `pending` plus stubbed replacements for `HumanMessage`s in state carrying inline media. */
|
|
1292
|
+
async function offloadHumanMessages({ stateMessages, pending }, backend, prefix, cache) {
|
|
1293
|
+
const candidates = humanCandidates({
|
|
1294
|
+
stateMessages,
|
|
1295
|
+
pending
|
|
1296
|
+
});
|
|
1297
|
+
if (candidates.length === 0) return [...pending];
|
|
1298
|
+
return mergeReplacements({
|
|
1299
|
+
pending,
|
|
1300
|
+
offloaded: await offloadMessages(candidates, backend, prefix, cache),
|
|
1301
|
+
candidates
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
/** Collect every well-formed `deepagents_blob` digest referenced in `messages`, deduplicated. */
|
|
1305
|
+
function referencedDigests(messages) {
|
|
1306
|
+
const digests = /* @__PURE__ */ new Set();
|
|
1307
|
+
for (const message of messages) {
|
|
1308
|
+
const blocks = contentBlocks(message);
|
|
1309
|
+
if (!blocks) continue;
|
|
1310
|
+
for (const block of blocks) {
|
|
1311
|
+
const ref = block?.[BLOB_REF_KEY];
|
|
1312
|
+
if (isDigest(ref)) digests.add(ref);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
return [...digests];
|
|
1316
|
+
}
|
|
1317
|
+
function cachedPayloads(digests, cache) {
|
|
1318
|
+
const payloads = /* @__PURE__ */ new Map();
|
|
1319
|
+
const missing = [];
|
|
1320
|
+
for (const digest of digests) {
|
|
1321
|
+
const payload = cache.get(digest);
|
|
1322
|
+
if (payload !== void 0) payloads.set(digest, payload);
|
|
1323
|
+
else missing.push(digest);
|
|
1324
|
+
}
|
|
1325
|
+
return {
|
|
1326
|
+
payloads,
|
|
1327
|
+
missing
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
/** Verify each downloaded blob's integrity before trusting it — blobs live on an agent-writable backend. */
|
|
1331
|
+
function acceptDownloads(missing, responses, payloads, cache) {
|
|
1332
|
+
missing.forEach((digest, index) => {
|
|
1333
|
+
const response = responses[index];
|
|
1334
|
+
if (!response || response.error != null || response.content == null) return;
|
|
1335
|
+
if (sha256Hex(response.content) !== digest) return;
|
|
1336
|
+
const payload = Buffer.from(response.content).toString("base64");
|
|
1337
|
+
cache.set(digest, payload);
|
|
1338
|
+
payloads.set(digest, payload);
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
function messageHasRefs(message) {
|
|
1342
|
+
const blocks = contentBlocks(message);
|
|
1343
|
+
return blocks != null && blocks.some((block) => block != null && typeof block === "object" && "deepagents_blob" in block);
|
|
1344
|
+
}
|
|
1345
|
+
function withContent(message, content) {
|
|
1346
|
+
if (ToolMessage.isInstance(message)) return new ToolMessage({
|
|
1347
|
+
content,
|
|
1348
|
+
tool_call_id: message.tool_call_id,
|
|
1349
|
+
name: message.name,
|
|
1350
|
+
id: message.id,
|
|
1351
|
+
artifact: message.artifact,
|
|
1352
|
+
status: message.status,
|
|
1353
|
+
additional_kwargs: message.additional_kwargs,
|
|
1354
|
+
response_metadata: message.response_metadata,
|
|
1355
|
+
metadata: message.metadata
|
|
1356
|
+
});
|
|
1357
|
+
if (HumanMessage.isInstance(message)) return new HumanMessage({
|
|
1358
|
+
content,
|
|
1359
|
+
id: message.id,
|
|
1360
|
+
additional_kwargs: message.additional_kwargs,
|
|
1361
|
+
response_metadata: message.response_metadata
|
|
1362
|
+
});
|
|
1363
|
+
if (AIMessage.isInstance(message)) return new AIMessage({
|
|
1364
|
+
content,
|
|
1365
|
+
id: message.id,
|
|
1366
|
+
tool_calls: message.tool_calls,
|
|
1367
|
+
invalid_tool_calls: message.invalid_tool_calls,
|
|
1368
|
+
usage_metadata: message.usage_metadata,
|
|
1369
|
+
additional_kwargs: message.additional_kwargs,
|
|
1370
|
+
response_metadata: message.response_metadata
|
|
1371
|
+
});
|
|
1372
|
+
if (SystemMessage.isInstance(message)) return new SystemMessage({
|
|
1373
|
+
content,
|
|
1374
|
+
id: message.id,
|
|
1375
|
+
additional_kwargs: message.additional_kwargs,
|
|
1376
|
+
response_metadata: message.response_metadata
|
|
1377
|
+
});
|
|
1378
|
+
console.warn(`blobOffload: left a blob reference unresolved on an unsupported message type (${message?.constructor?.name})`);
|
|
1379
|
+
return message;
|
|
1380
|
+
}
|
|
1381
|
+
/** Restore base64 payloads for blob references; a reference with no matching payload becomes a text notice. */
|
|
1382
|
+
function restorePayloads(messages, payloads) {
|
|
1383
|
+
const hydrate = (block) => {
|
|
1384
|
+
const ref = block[BLOB_REF_KEY];
|
|
1385
|
+
if (ref === void 0) return block;
|
|
1386
|
+
const payload = isDigest(ref) ? payloads.get(ref) : void 0;
|
|
1387
|
+
if (payload === void 0) return {
|
|
1388
|
+
type: "text",
|
|
1389
|
+
text: MISSING_BLOB_TEXT
|
|
1390
|
+
};
|
|
1391
|
+
const { [BLOB_REF_KEY]: _ref, ...rest } = block;
|
|
1392
|
+
return {
|
|
1393
|
+
...rest,
|
|
1394
|
+
data: payload
|
|
1395
|
+
};
|
|
1396
|
+
};
|
|
1397
|
+
return messages.map((message) => {
|
|
1398
|
+
if (!messageHasRefs(message)) return message;
|
|
1399
|
+
return withContent(message, (contentBlocks(message) ?? []).map(hydrate));
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Restore base64 payloads for blob references ahead of a model call.
|
|
1404
|
+
*
|
|
1405
|
+
* Only the returned array is used for the request — callers must not persist
|
|
1406
|
+
* the result back into state, or the checkpoint-size benefit of offloading is
|
|
1407
|
+
* lost the next time state is saved.
|
|
1408
|
+
*/
|
|
1409
|
+
async function hydrateMessages(messages, backend, prefix, cache) {
|
|
1410
|
+
if (!messages.some(messageHasRefs)) return [...messages];
|
|
1411
|
+
const { payloads, missing } = cachedPayloads(referencedDigests(messages), cache);
|
|
1412
|
+
if (missing.length > 0) if (typeof backend.downloadFiles !== "function") console.warn("Backend does not support downloadFiles; offloaded read_file content is unavailable");
|
|
1413
|
+
else {
|
|
1414
|
+
let responses = [];
|
|
1415
|
+
try {
|
|
1416
|
+
responses = await backend.downloadFiles(missing.map((digest) => blobPath(prefix, digest)));
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
console.warn("Failed to load offloaded read_file content", error);
|
|
1419
|
+
}
|
|
1420
|
+
acceptDownloads(missing, responses, payloads, cache);
|
|
1421
|
+
}
|
|
1422
|
+
return restorePayloads(messages, payloads);
|
|
1423
|
+
}
|
|
1424
|
+
//#endregion
|
|
1425
|
+
//#region src/middleware/unsupportedContent.ts
|
|
1426
|
+
const PDF_MIME_TYPE = "application/pdf";
|
|
1427
|
+
/** Content block types `read_file` may emit that require multimodal model support. */
|
|
1428
|
+
const MULTIMODAL_BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
1429
|
+
"image",
|
|
1430
|
+
"audio",
|
|
1431
|
+
"video",
|
|
1432
|
+
"file"
|
|
1433
|
+
]);
|
|
1434
|
+
const PROFILE_FIELD_BY_BLOCK_TYPE = {
|
|
1435
|
+
image: "imageInputs",
|
|
1436
|
+
audio: "audioInputs",
|
|
1437
|
+
video: "videoInputs"
|
|
1438
|
+
};
|
|
1439
|
+
const TOOL_MESSAGE_FIELD_BY_BLOCK_TYPE = { image: "imageToolMessage" };
|
|
1440
|
+
function hasInlineData(block) {
|
|
1441
|
+
return block.data != null || block.source_type === "base64";
|
|
1442
|
+
}
|
|
1443
|
+
function blockMimeType(block) {
|
|
1444
|
+
const mimeType = block.mimeType ?? block.mime_type;
|
|
1445
|
+
return typeof mimeType === "string" ? mimeType : void 0;
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* Unlike the other block types, a missing `fileMimeTypes` defaults to
|
|
1449
|
+
* unsupported rather than supported: generic file support varies far more
|
|
1450
|
+
* across models than image/audio/video, so there's no safe assumption to
|
|
1451
|
+
* fall back on absent real profile data.
|
|
1452
|
+
*/
|
|
1453
|
+
function fileBlockSupported(block, profile, inToolMessage) {
|
|
1454
|
+
if (!hasInlineData(block)) return true;
|
|
1455
|
+
const mimeType = blockMimeType(block);
|
|
1456
|
+
if (mimeType === PDF_MIME_TYPE) {
|
|
1457
|
+
if (inToolMessage && profile.pdfToolMessage !== void 0) return profile.pdfToolMessage !== false;
|
|
1458
|
+
return profile.pdfInputs !== false;
|
|
1459
|
+
}
|
|
1460
|
+
if (mimeType == null) return false;
|
|
1461
|
+
const { fileMimeTypes } = profile;
|
|
1462
|
+
return Array.isArray(fileMimeTypes) && fileMimeTypes.includes(mimeType);
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Whether the model accepts a multimodal block.
|
|
1466
|
+
*
|
|
1467
|
+
* Missing profile fields default to supported, since profile coverage is
|
|
1468
|
+
* incomplete — except `file` blocks, where a missing `fileMimeTypes`
|
|
1469
|
+
* defaults to unsupported (see `fileBlockSupported`).
|
|
1470
|
+
*/
|
|
1471
|
+
function multimodalBlockSupported(block, profile, inToolMessage) {
|
|
1472
|
+
if (block.type === "file") return fileBlockSupported(block, profile, inToolMessage);
|
|
1473
|
+
const field = PROFILE_FIELD_BY_BLOCK_TYPE[block.type];
|
|
1474
|
+
if (field == null) return true;
|
|
1475
|
+
if (inToolMessage) {
|
|
1476
|
+
const toolField = TOOL_MESSAGE_FIELD_BY_BLOCK_TYPE[block.type];
|
|
1477
|
+
if (toolField != null && profile[toolField] !== void 0) return profile[toolField] !== false;
|
|
1478
|
+
}
|
|
1479
|
+
return profile[field] !== false;
|
|
1480
|
+
}
|
|
1481
|
+
function placeholder(block, path) {
|
|
1482
|
+
return {
|
|
1483
|
+
type: "text",
|
|
1484
|
+
text: `[read_file: ${path ?? "the requested file"} was not attached because this model does not support ${block.type} content (${blockMimeType(block) ?? "unknown"}).]`
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
function readFilePaths(messages) {
|
|
1488
|
+
const paths = /* @__PURE__ */ new Map();
|
|
1489
|
+
for (const message of messages) {
|
|
1490
|
+
if (!AIMessage$1.isInstance(message)) continue;
|
|
1491
|
+
for (const toolCall of message.tool_calls ?? []) {
|
|
1492
|
+
const path = toolCall.args?.file_path;
|
|
1493
|
+
if (toolCall.id != null && typeof path === "string") paths.set(toolCall.id, path);
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return paths;
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Without this, a request carrying content the model can't accept (e.g. a
|
|
1500
|
+
* `.zip` file sent to a model without file support) fails with a
|
|
1501
|
+
* non-retryable 400, and since the content stays in history, every later
|
|
1502
|
+
* turn fails the same way. Only the request is changed; messages in state
|
|
1503
|
+
* are left untouched, so switching to a model that accepts the content
|
|
1504
|
+
* sends it again.
|
|
1505
|
+
*/
|
|
1506
|
+
function scrubUnsupportedMultimodalContent(messages, model) {
|
|
1507
|
+
const rawProfile = model?.profile;
|
|
1508
|
+
const profile = rawProfile != null && typeof rawProfile === "object" ? rawProfile : {};
|
|
1509
|
+
let paths;
|
|
1510
|
+
let changed = false;
|
|
1511
|
+
const result = messages.map((message) => {
|
|
1512
|
+
const isTool = ToolMessage$1.isInstance(message);
|
|
1513
|
+
if (!isTool && !HumanMessage$1.isInstance(message)) return message;
|
|
1514
|
+
let messageChanged = false;
|
|
1515
|
+
const content = message.contentBlocks.map((block) => {
|
|
1516
|
+
if (block == null || typeof block !== "object" || !MULTIMODAL_BLOCK_TYPES.has(block.type) || multimodalBlockSupported(block, profile, isTool)) return block;
|
|
1517
|
+
messageChanged = true;
|
|
1518
|
+
paths ??= readFilePaths(messages);
|
|
1519
|
+
return placeholder(block, isTool ? paths.get(message.tool_call_id) : void 0);
|
|
1520
|
+
});
|
|
1521
|
+
if (!messageChanged) return message;
|
|
1522
|
+
changed = true;
|
|
1523
|
+
if (isTool) return new ToolMessage$1({
|
|
1524
|
+
content,
|
|
1525
|
+
tool_call_id: message.tool_call_id,
|
|
1526
|
+
name: message.name,
|
|
1527
|
+
id: message.id,
|
|
1528
|
+
artifact: message.artifact,
|
|
1529
|
+
status: message.status,
|
|
1530
|
+
metadata: message.metadata,
|
|
1531
|
+
additional_kwargs: message.additional_kwargs,
|
|
1532
|
+
response_metadata: message.response_metadata
|
|
1533
|
+
});
|
|
1534
|
+
return new HumanMessage$1({
|
|
1535
|
+
content,
|
|
1536
|
+
name: message.name,
|
|
1537
|
+
id: message.id,
|
|
1538
|
+
additional_kwargs: message.additional_kwargs,
|
|
1539
|
+
response_metadata: message.response_metadata
|
|
1540
|
+
});
|
|
1541
|
+
});
|
|
1542
|
+
return changed ? result : messages;
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Support is read from `model.profile` (see
|
|
1546
|
+
* https://docs.langchain.com/oss/javascript/langchain/models#model-profiles).
|
|
1547
|
+
*
|
|
1548
|
+
* Place this middleware last in the agent's `middleware` list, so that if
|
|
1549
|
+
* some other middleware changes `request.model`, this one sees the model
|
|
1550
|
+
* that will actually receive the request.
|
|
1551
|
+
*/
|
|
1552
|
+
function createUnsupportedContentMiddleware() {
|
|
1553
|
+
return createMiddleware({
|
|
1554
|
+
name: "UnsupportedContentMiddleware",
|
|
1555
|
+
wrapModelCall: async (request, handler) => {
|
|
1556
|
+
const messages = scrubUnsupportedMultimodalContent(request.messages, request.model);
|
|
1557
|
+
if (messages === request.messages) return handler(request);
|
|
1558
|
+
return handler({
|
|
1559
|
+
...request,
|
|
1560
|
+
messages
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
//#endregion
|
|
1090
1566
|
//#region src/permissions/enforce.ts
|
|
1091
1567
|
/**
|
|
1092
1568
|
* Validate permission rule paths at setup time. Throws if any path is
|
|
@@ -1177,6 +1653,10 @@ var CompositeBackend = class {
|
|
|
1177
1653
|
static isInstance(backend) {
|
|
1178
1654
|
return typeof backend === "object" && backend !== null && Array.isArray(backend.routePrefixes);
|
|
1179
1655
|
}
|
|
1656
|
+
/** Returns the backend for `path`, with the matched prefix stripped from the returned path. */
|
|
1657
|
+
resolveBackendForPath(path) {
|
|
1658
|
+
return this.getBackendAndKey(path);
|
|
1659
|
+
}
|
|
1180
1660
|
/**
|
|
1181
1661
|
* Determine which backend handles this key and strip prefix.
|
|
1182
1662
|
*
|
|
@@ -1781,6 +2261,8 @@ const GREP_TRUNCATION_NOTE = "Note: the search stopped early because it hit the
|
|
|
1781
2261
|
* Set to null to disable the cap.
|
|
1782
2262
|
*/
|
|
1783
2263
|
const DEFAULT_GREP_MAX_COUNT = 1e3;
|
|
2264
|
+
/** Path prefix offloaded binary content blobs are written under. */
|
|
2265
|
+
const BLOBS_PREFIX = "/blobs";
|
|
1784
2266
|
/**
|
|
1785
2267
|
* Message template for evicted tool results.
|
|
1786
2268
|
*/
|
|
@@ -2563,6 +3045,68 @@ function allPathsScopedToRoutes(permissions, backend) {
|
|
|
2563
3045
|
return path === normalizedRoute.slice(0, -1) || path.startsWith(normalizedRoute);
|
|
2564
3046
|
})));
|
|
2565
3047
|
}
|
|
3048
|
+
/** Whether `path` resolves to a `StateBackend`, recursing through composite routing. */
|
|
3049
|
+
function routesToStateBackend(backend, path) {
|
|
3050
|
+
if (CompositeBackend.isInstance(backend)) {
|
|
3051
|
+
const [routed, routedPath] = backend.resolveBackendForPath(path);
|
|
3052
|
+
return routesToStateBackend(routed, routedPath);
|
|
3053
|
+
}
|
|
3054
|
+
return StateBackend.isInstance(backend);
|
|
3055
|
+
}
|
|
3056
|
+
/**
|
|
3057
|
+
* Whether `response` is the `{ structuredResponse, messages }` shape a
|
|
3058
|
+
* provider-strategy structured-output call can return instead of a plain
|
|
3059
|
+
* `AIMessage`. The agent framework only recognizes this shape at the
|
|
3060
|
+
* outermost `wrapModelCall` return value — returning a `Command` instead
|
|
3061
|
+
* discards `structuredResponse` with no way to carry it through the Command.
|
|
3062
|
+
*/
|
|
3063
|
+
function hasStructuredResponse(response) {
|
|
3064
|
+
return typeof response === "object" && response !== null && "structuredResponse" in response && "messages" in response;
|
|
3065
|
+
}
|
|
3066
|
+
const REJECTED_FILE_CONTENT_TEXT = "Unsupported content. The file may be invalid, too large, or of an unsupported mime-type.";
|
|
3067
|
+
/**
|
|
3068
|
+
* No LangChain error class captures "the provider rejected this request"
|
|
3069
|
+
* generically, so this checks the raw HTTP status providers' client SDKs set
|
|
3070
|
+
* on their errors instead. `ContextOverflowError` is excluded because it's a
|
|
3071
|
+
* different, already-handled problem, and retrying it with stripped file
|
|
3072
|
+
* content wouldn't fix an oversized prompt.
|
|
3073
|
+
*/
|
|
3074
|
+
function isRejectedRequestError(error) {
|
|
3075
|
+
if (ContextOverflowError.isInstance(error)) return false;
|
|
3076
|
+
return typeof error === "object" && error !== null && "status" in error && error.status === 400;
|
|
3077
|
+
}
|
|
3078
|
+
/**
|
|
3079
|
+
* Only messages carrying multimodal blocks after the last `AIMessage` are
|
|
3080
|
+
* candidates for replacement, since anything earlier was already accepted by
|
|
3081
|
+
* the model in a prior turn. Returns `messages` unchanged if nothing
|
|
3082
|
+
* matched, so the caller can tell there was nothing to blame for the
|
|
3083
|
+
* rejection.
|
|
3084
|
+
*/
|
|
3085
|
+
function replaceRejectedFileContent(messages) {
|
|
3086
|
+
let lastResponseIndex = -1;
|
|
3087
|
+
for (let i = messages.length - 1; i >= 0; i--) if (AIMessage.isInstance(messages[i])) {
|
|
3088
|
+
lastResponseIndex = i;
|
|
3089
|
+
break;
|
|
3090
|
+
}
|
|
3091
|
+
let changed = false;
|
|
3092
|
+
const result = messages.map((message, index) => {
|
|
3093
|
+
if (index <= lastResponseIndex || !ToolMessage.isInstance(message) || message.name !== "read_file") return message;
|
|
3094
|
+
if (!message.contentBlocks.some((block) => MULTIMODAL_BLOCK_TYPES.has(block.type))) return message;
|
|
3095
|
+
changed = true;
|
|
3096
|
+
return new ToolMessage({
|
|
3097
|
+
content: REJECTED_FILE_CONTENT_TEXT,
|
|
3098
|
+
tool_call_id: message.tool_call_id,
|
|
3099
|
+
name: message.name,
|
|
3100
|
+
id: message.id,
|
|
3101
|
+
artifact: message.artifact,
|
|
3102
|
+
status: message.status,
|
|
3103
|
+
metadata: message.metadata,
|
|
3104
|
+
additional_kwargs: message.additional_kwargs,
|
|
3105
|
+
response_metadata: message.response_metadata
|
|
3106
|
+
});
|
|
3107
|
+
});
|
|
3108
|
+
return changed ? result : messages;
|
|
3109
|
+
}
|
|
2566
3110
|
/**
|
|
2567
3111
|
* Create middleware that provides built-in filesystem tools and optional custom
|
|
2568
3112
|
* prompt guidance.
|
|
@@ -2589,7 +3133,10 @@ function allPathsScopedToRoutes(permissions, backend) {
|
|
|
2589
3133
|
* ```
|
|
2590
3134
|
*/
|
|
2591
3135
|
function createFilesystemMiddleware(options = {}) {
|
|
2592
|
-
const { backend = (runtime) => new StateBackend(runtime), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4, humanMessageTokenLimitBeforeEvict = 5e4, permissions = [], tools: filesystemTools = null, grepMaxCount = DEFAULT_GREP_MAX_COUNT } = options;
|
|
3136
|
+
const { backend = (runtime) => new StateBackend(runtime), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4, humanMessageTokenLimitBeforeEvict = 5e4, permissions = [], tools: filesystemTools = null, grepMaxCount = DEFAULT_GREP_MAX_COUNT, offloadBinaryContent = false } = options;
|
|
3137
|
+
const backendIsStateBackend = StateBackend.isInstance(backend);
|
|
3138
|
+
if (offloadBinaryContent && backendIsStateBackend) console.warn("offloadBinaryContent has no effect: the backend is a StateBackend, which keeps files as part of checkpointed state.");
|
|
3139
|
+
const blobCache = offloadBinaryContent && !backendIsStateBackend ? new BlobCache() : null;
|
|
2593
3140
|
const enabledFilesystemTools = normalizeFilesystemTools(filesystemTools);
|
|
2594
3141
|
const executeToolEnabled = enabledFilesystemTools == null || enabledFilesystemTools.has("execute");
|
|
2595
3142
|
if (permissions.length > 0) validatePermissionPaths(permissions);
|
|
@@ -2726,18 +3273,59 @@ function createFilesystemMiddleware(options = {}) {
|
|
|
2726
3273
|
return msg;
|
|
2727
3274
|
});
|
|
2728
3275
|
}
|
|
2729
|
-
|
|
3276
|
+
let offloadedHuman = [];
|
|
3277
|
+
if (blobCache && !routesToStateBackend(resolvedBackend, `${BLOBS_PREFIX}/`)) {
|
|
3278
|
+
offloadedHuman = await offloadHumanMessages({
|
|
3279
|
+
stateMessages: request.state.messages ?? [],
|
|
3280
|
+
pending: []
|
|
3281
|
+
}, resolvedBackend, BLOBS_PREFIX, blobCache);
|
|
3282
|
+
messages = await hydrateMessages(messages, resolvedBackend, BLOBS_PREFIX, blobCache);
|
|
3283
|
+
}
|
|
3284
|
+
const finalRequest = {
|
|
2730
3285
|
...request,
|
|
2731
3286
|
tools,
|
|
2732
3287
|
messages,
|
|
2733
3288
|
systemMessage: newSystemMessage
|
|
2734
|
-
}
|
|
3289
|
+
};
|
|
3290
|
+
const foldOffload = (response, extra = []) => {
|
|
3291
|
+
if (offloadedHuman.length === 0 && extra.length === 0) return response;
|
|
3292
|
+
if (hasStructuredResponse(response)) return {
|
|
3293
|
+
...response,
|
|
3294
|
+
messages: [
|
|
3295
|
+
...extra,
|
|
3296
|
+
...offloadedHuman,
|
|
3297
|
+
...response.messages
|
|
3298
|
+
]
|
|
3299
|
+
};
|
|
3300
|
+
return new Command({ update: { messages: extra.length === 0 ? offloadedHuman : [
|
|
3301
|
+
...extra,
|
|
3302
|
+
...offloadedHuman,
|
|
3303
|
+
response
|
|
3304
|
+
] } });
|
|
3305
|
+
};
|
|
3306
|
+
try {
|
|
3307
|
+
return foldOffload(await handler(finalRequest));
|
|
3308
|
+
} catch (error) {
|
|
3309
|
+
if (!isRejectedRequestError(error)) throw error;
|
|
3310
|
+
const replaced = replaceRejectedFileContent(finalRequest.messages);
|
|
3311
|
+
if (replaced === finalRequest.messages) throw error;
|
|
3312
|
+
return foldOffload(await handler({
|
|
3313
|
+
...finalRequest,
|
|
3314
|
+
messages: replaced
|
|
3315
|
+
}), replaced.filter((msg, i) => msg !== finalRequest.messages[i]));
|
|
3316
|
+
}
|
|
2735
3317
|
},
|
|
2736
3318
|
wrapToolCall: async (request, handler) => {
|
|
2737
|
-
if (!toolTokenLimitBeforeEvict) return handler(request);
|
|
2738
3319
|
const toolName = request.toolCall?.name;
|
|
2739
|
-
|
|
2740
|
-
|
|
3320
|
+
let result = await handler(request);
|
|
3321
|
+
if (blobCache && toolName === "read_file") {
|
|
3322
|
+
const resolvedBackend = await resolveBackend(backend, {
|
|
3323
|
+
...request.runtime,
|
|
3324
|
+
state: request.state
|
|
3325
|
+
});
|
|
3326
|
+
if (!routesToStateBackend(resolvedBackend, `${BLOBS_PREFIX}/`)) result = await offloadToolResult(result, resolvedBackend, BLOBS_PREFIX, /* @__PURE__ */ new Map());
|
|
3327
|
+
}
|
|
3328
|
+
if (!toolTokenLimitBeforeEvict || toolName && TOOLS_EXCLUDED_FROM_EVICTION.includes(toolName)) return result;
|
|
2741
3329
|
if (ToolMessage.isInstance(result)) {
|
|
2742
3330
|
const processed = await processToolMessage(result, request.runtime, request.state, request.toolCall?.id);
|
|
2743
3331
|
if (processed.filesUpdate) return new Command({ update: {
|
|
@@ -3781,6 +4369,7 @@ function createSubAgent(spec, options) {
|
|
|
3781
4369
|
if (!spec.tools) throw new Error(`SubAgent '${spec.name}' must specify 'tools'`);
|
|
3782
4370
|
const middleware = [...spec.middleware ?? []];
|
|
3783
4371
|
if (spec.interruptOn) middleware.push(humanInTheLoopMiddleware({ interruptOn: spec.interruptOn }));
|
|
4372
|
+
if (!middleware.some((m) => m.name === "UnsupportedContentMiddleware")) middleware.push(createUnsupportedContentMiddleware());
|
|
3784
4373
|
const selectedResponseFormat = options?.responseFormat ?? spec.responseFormat;
|
|
3785
4374
|
return createAgent({
|
|
3786
4375
|
model: spec.model,
|
|
@@ -6700,6 +7289,7 @@ function createDeepAgent(params = {}) {
|
|
|
6700
7289
|
]);
|
|
6701
7290
|
if (subagentProfile.excludedMiddleware.size > 0) subagentMiddleware = subagentMiddleware.filter((middleware) => !subagentProfile.excludedMiddleware.has(middleware.name));
|
|
6702
7291
|
if (subagentProfile.excludedTools.size > 0) subagentMiddleware.push(createToolExclusionMiddleware(subagentProfile.excludedTools));
|
|
7292
|
+
if (!subagentProfile.excludedMiddleware.has("UnsupportedContentMiddleware") && !subagentMiddleware.some((middleware) => middleware.name === "UnsupportedContentMiddleware")) subagentMiddleware.push(createUnsupportedContentMiddleware());
|
|
6703
7293
|
return subagentMiddleware;
|
|
6704
7294
|
};
|
|
6705
7295
|
const normalizeSubagentSpec = (input) => ({
|
|
@@ -6762,6 +7352,7 @@ function createDeepAgent(params = {}) {
|
|
|
6762
7352
|
middleware = middleware.filter((entry) => !excluded.has(entry.name));
|
|
6763
7353
|
}
|
|
6764
7354
|
if (harnessProfile.excludedTools.size > 0) middleware.push(createToolExclusionMiddleware(harnessProfile.excludedTools));
|
|
7355
|
+
if (!harnessProfile.excludedMiddleware.has("UnsupportedContentMiddleware") && !middleware.some((m) => m.name === "UnsupportedContentMiddleware")) middleware.push(createUnsupportedContentMiddleware());
|
|
6765
7356
|
/**
|
|
6766
7357
|
* Return as DeepAgent with proper DeepAgentTypeConfig
|
|
6767
7358
|
* - Response: InferStructuredResponse<TResponse> (unwraps ToolStrategy<T>/ProviderStrategy<T> → T)
|
|
@@ -8879,6 +9470,6 @@ var LangSmithSandbox = class LangSmithSandbox extends BaseSandbox {
|
|
|
8879
9470
|
}
|
|
8880
9471
|
};
|
|
8881
9472
|
//#endregion
|
|
8882
|
-
export {
|
|
9473
|
+
export { checkEmptyContent as $, createPatchToolCallsMiddleware as A, CompositeBackend as B, MAX_SKILL_DESCRIPTION_LENGTH as C, skillsMetadataValue as D, createSkillsMiddleware as E, createSubAgent as F, StateBackend as G, createUnsupportedContentMiddleware as H, createSubAgentMiddleware as I, isSandboxBackend as J, SandboxError as K, computeSummarizationDefaults as L, DEFAULT_SUBAGENT_PROMPT as M, GENERAL_PURPOSE_SUBAGENT as N, createMemoryMiddleware as O, SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY as P, adaptSandboxProtocol as Q, createSummarizationMiddleware as R, createCompletionCallbackMiddleware as S, MAX_SKILL_NAME_LENGTH as T, multimodalBlockSupported as U, MULTIMODAL_BLOCK_TYPES as V, scrubUnsupportedMultimodalContent as W, resolveBackend as X, isSandboxProtocol as Y, adaptBackendProtocol as Z, createHarnessProfile as _, ASYNC_TASK_SYSTEM_PROMPT as a, createAsyncSubAgentMiddleware as b, TASK_SYSTEM_PROMPT as c, registerHarnessProfile as d, getMimeType as et, generalPurposeSubagentConfigSchema as f, EMPTY_HARNESS_PROFILE as g, serializeProfile as h, StoreBackend as i, DEFAULT_GENERAL_PURPOSE_DESCRIPTION as j, filesValue as k, createDeepAgent as l, parseHarnessProfileConfig as m, BaseSandbox as n, normalizeReadPagination as nt, BASE_AGENT_PROMPT as o, harnessProfileConfigSchema as p, applyGrepMaxCount as q, ContextHubBackend as r, performStringReplacement as rt, EXECUTION_SYSTEM_PROMPT as s, LangSmithSandbox as t, isTextMimeType as tt, getHarnessProfile as u, REQUIRED_MIDDLEWARE_NAMES as v, MAX_SKILL_FILE_SIZE as w, isAsyncSubAgent as x, ConfigurationError as y, createFilesystemMiddleware as z };
|
|
8883
9474
|
|
|
8884
|
-
//# sourceMappingURL=langsmith
|
|
9475
|
+
//# sourceMappingURL=langsmith--RbtjNdQ.js.map
|