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
|
@@ -21,14 +21,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
}) : target, mod));
|
|
22
22
|
//#endregion
|
|
23
23
|
let langchain = require("langchain");
|
|
24
|
+
let _langchain_core_errors = require("@langchain/core/errors");
|
|
24
25
|
let _langchain_langgraph = require("@langchain/langgraph");
|
|
25
26
|
let zod_v4 = require("zod/v4");
|
|
26
27
|
let micromatch = require("micromatch");
|
|
27
28
|
micromatch = __toESM(micromatch, 1);
|
|
29
|
+
let node_crypto = require("node:crypto");
|
|
28
30
|
let _langchain_core_messages = require("@langchain/core/messages");
|
|
29
31
|
let zod = require("zod");
|
|
30
32
|
zod = __toESM(zod, 1);
|
|
31
|
-
let _langchain_core_errors = require("@langchain/core/errors");
|
|
32
33
|
let langchain_chat_models_universal = require("langchain/chat_models/universal");
|
|
33
34
|
let yaml = require("yaml");
|
|
34
35
|
yaml = __toESM(yaml, 1);
|
|
@@ -657,9 +658,18 @@ function adaptBackendProtocol(backend) {
|
|
|
657
658
|
return result;
|
|
658
659
|
}
|
|
659
660
|
};
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
value
|
|
661
|
+
const identityMarkers = [["routePrefixes", Array.isArray], ["backendKind", (value) => typeof value === "string"]];
|
|
662
|
+
for (const [key, isValid] of identityMarkers) {
|
|
663
|
+
const value = backend[key];
|
|
664
|
+
if (isValid(value)) Object.defineProperty(adapted, key, {
|
|
665
|
+
value,
|
|
666
|
+
enumerable: true,
|
|
667
|
+
configurable: true
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
const resolveBackendForPath = backend.resolveBackendForPath;
|
|
671
|
+
if (typeof resolveBackendForPath === "function") Object.defineProperty(adapted, "resolveBackendForPath", {
|
|
672
|
+
value: (path) => resolveBackendForPath.call(backend, path),
|
|
663
673
|
enumerable: true,
|
|
664
674
|
configurable: true
|
|
665
675
|
});
|
|
@@ -810,8 +820,14 @@ const PREGEL_READ_KEY = "__pregel_read";
|
|
|
810
820
|
* for the middleware to apply via Command.
|
|
811
821
|
*/
|
|
812
822
|
var StateBackend = class {
|
|
823
|
+
/** Class identity discriminant for {@link StateBackend.isInstance}. */
|
|
824
|
+
backendKind = "state";
|
|
813
825
|
runtime;
|
|
814
826
|
fileFormat;
|
|
827
|
+
/** Duck-typed so this survives the plain-object copies `adaptBackendProtocol` makes — a class check wouldn't. */
|
|
828
|
+
static isInstance(backend) {
|
|
829
|
+
return typeof backend === "object" && backend !== null && backend.backendKind === "state";
|
|
830
|
+
}
|
|
815
831
|
constructor(runtimeOrOptions, options) {
|
|
816
832
|
if (runtimeOrOptions != null && typeof runtimeOrOptions === "object" && "state" in runtimeOrOptions) {
|
|
817
833
|
this.runtime = runtimeOrOptions;
|
|
@@ -1111,6 +1127,466 @@ var StateBackend = class {
|
|
|
1111
1127
|
}
|
|
1112
1128
|
};
|
|
1113
1129
|
//#endregion
|
|
1130
|
+
//#region src/middleware/blobOffload.ts
|
|
1131
|
+
/**
|
|
1132
|
+
* Content-addressed offload of binary `read_file` and inline `HumanMessage`
|
|
1133
|
+
* blocks to the backend.
|
|
1134
|
+
*
|
|
1135
|
+
* Binary blocks are written to `/blobs/<sha256>` and replaced in state with a
|
|
1136
|
+
* `deepagents_blob` reference. Model requests are rehydrated from the backend
|
|
1137
|
+
* (or a per-run cache), so checkpoints never carry the base64 payload.
|
|
1138
|
+
*/
|
|
1139
|
+
/** Content block key holding the SHA-256 digest of an offloaded payload. */
|
|
1140
|
+
const BLOB_REF_KEY = "deepagents_blob";
|
|
1141
|
+
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.]";
|
|
1142
|
+
const DIGEST_RE = /^[0-9a-f]{64}$/;
|
|
1143
|
+
const BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
1144
|
+
/** Whether `reference` is a well-formed digest string. */
|
|
1145
|
+
function isDigest(reference) {
|
|
1146
|
+
return typeof reference === "string" && DIGEST_RE.test(reference);
|
|
1147
|
+
}
|
|
1148
|
+
function isValidBase64(value) {
|
|
1149
|
+
return value.length > 0 && value.length % 4 === 0 && BASE64_RE.test(value);
|
|
1150
|
+
}
|
|
1151
|
+
function sha256Hex(bytes) {
|
|
1152
|
+
return (0, node_crypto.createHash)("sha256").update(bytes).digest("hex");
|
|
1153
|
+
}
|
|
1154
|
+
const DEFAULT_BLOB_CACHE_BYTES = 268435456;
|
|
1155
|
+
/**
|
|
1156
|
+
* Content-addressed cache of base64 payloads, bounded by total payload size
|
|
1157
|
+
* (LRU-evicted past the bound). Safe to share across threads — every key is
|
|
1158
|
+
* a SHA-256 digest of its own value, so a hit is only reachable by a caller
|
|
1159
|
+
* who already has that exact reference, and an eviction just forces a
|
|
1160
|
+
* re-fetch from the backend, never a wrong result.
|
|
1161
|
+
*/
|
|
1162
|
+
var BlobCache = class extends Map {
|
|
1163
|
+
maxBytes;
|
|
1164
|
+
totalBytes = 0;
|
|
1165
|
+
constructor(maxBytes = DEFAULT_BLOB_CACHE_BYTES) {
|
|
1166
|
+
super();
|
|
1167
|
+
this.maxBytes = maxBytes;
|
|
1168
|
+
}
|
|
1169
|
+
/** Returns the cached payload for `digest`, marking it most recently used. */
|
|
1170
|
+
get(digest) {
|
|
1171
|
+
const payload = super.get(digest);
|
|
1172
|
+
if (payload === void 0) return void 0;
|
|
1173
|
+
super.delete(digest);
|
|
1174
|
+
super.set(digest, payload);
|
|
1175
|
+
return payload;
|
|
1176
|
+
}
|
|
1177
|
+
/** Caches `payload`, evicting least-recently-used entries past the size bound. */
|
|
1178
|
+
set(digest, payload) {
|
|
1179
|
+
if (payload.length > this.maxBytes) return this;
|
|
1180
|
+
const previous = super.get(digest);
|
|
1181
|
+
if (previous !== void 0) {
|
|
1182
|
+
this.totalBytes -= previous.length;
|
|
1183
|
+
super.delete(digest);
|
|
1184
|
+
}
|
|
1185
|
+
super.set(digest, payload);
|
|
1186
|
+
this.totalBytes += payload.length;
|
|
1187
|
+
while (this.totalBytes > this.maxBytes) {
|
|
1188
|
+
const oldestDigest = this.keys().next().value;
|
|
1189
|
+
if (oldestDigest === void 0) break;
|
|
1190
|
+
const oldest = super.get(oldestDigest);
|
|
1191
|
+
super.delete(oldestDigest);
|
|
1192
|
+
this.totalBytes -= oldest?.length ?? 0;
|
|
1193
|
+
}
|
|
1194
|
+
return this;
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
function blobPath(prefix, digest) {
|
|
1198
|
+
return `${prefix}/${digest}`;
|
|
1199
|
+
}
|
|
1200
|
+
function contentBlocks(message) {
|
|
1201
|
+
const content = message?.content;
|
|
1202
|
+
return Array.isArray(content) ? content : null;
|
|
1203
|
+
}
|
|
1204
|
+
/** Map each inline base64 payload found in `messages` to its digest and decoded bytes. */
|
|
1205
|
+
function pendingBlobs(messages) {
|
|
1206
|
+
const pending = /* @__PURE__ */ new Map();
|
|
1207
|
+
for (const message of messages) {
|
|
1208
|
+
const blocks = contentBlocks(message);
|
|
1209
|
+
if (!blocks) continue;
|
|
1210
|
+
for (const block of blocks) {
|
|
1211
|
+
if (block == null || typeof block !== "object") continue;
|
|
1212
|
+
const payload = block.data;
|
|
1213
|
+
if (typeof payload !== "string" || pending.has(payload) || !isValidBase64(payload)) continue;
|
|
1214
|
+
let raw;
|
|
1215
|
+
try {
|
|
1216
|
+
raw = new Uint8Array(Buffer.from(payload, "base64"));
|
|
1217
|
+
} catch {
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
pending.set(payload, {
|
|
1221
|
+
digest: sha256Hex(raw),
|
|
1222
|
+
raw
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
return pending;
|
|
1227
|
+
}
|
|
1228
|
+
/** Replace payloads found in `digests` with blob references; returns `messages` unchanged if nothing matched. */
|
|
1229
|
+
function stubMessages(messages, digests) {
|
|
1230
|
+
return messages.map((message) => {
|
|
1231
|
+
const blocks = contentBlocks(message);
|
|
1232
|
+
if (!blocks) return message;
|
|
1233
|
+
let changed = false;
|
|
1234
|
+
const newContent = blocks.map((block) => {
|
|
1235
|
+
const digest = typeof block.data === "string" ? digests.get(block.data) : void 0;
|
|
1236
|
+
if (digest === void 0) return block;
|
|
1237
|
+
changed = true;
|
|
1238
|
+
const { data: _data, ...rest } = block;
|
|
1239
|
+
return {
|
|
1240
|
+
...rest,
|
|
1241
|
+
[BLOB_REF_KEY]: digest
|
|
1242
|
+
};
|
|
1243
|
+
});
|
|
1244
|
+
if (!changed) return message;
|
|
1245
|
+
return withContent(message, newContent);
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Upload inline binary payloads found in `messages` and return messages carrying blob
|
|
1250
|
+
* references instead. Payloads that fail to upload stay inline — offload is best-effort.
|
|
1251
|
+
*/
|
|
1252
|
+
async function offloadMessages(messages, backend, prefix, cache) {
|
|
1253
|
+
const pending = pendingBlobs(messages);
|
|
1254
|
+
if (pending.size === 0) return [...messages];
|
|
1255
|
+
if (typeof backend.uploadFiles !== "function") {
|
|
1256
|
+
console.warn("Backend does not support uploadFiles; binary read_file content stays inline");
|
|
1257
|
+
return [...messages];
|
|
1258
|
+
}
|
|
1259
|
+
const entries = [...pending.entries()];
|
|
1260
|
+
let responses;
|
|
1261
|
+
try {
|
|
1262
|
+
responses = await backend.uploadFiles(entries.map(([, { digest, raw }]) => [blobPath(prefix, digest), raw]));
|
|
1263
|
+
} catch (error) {
|
|
1264
|
+
console.warn("Failed to offload binary read_file content; keeping it inline", error);
|
|
1265
|
+
return [...messages];
|
|
1266
|
+
}
|
|
1267
|
+
const digests = /* @__PURE__ */ new Map();
|
|
1268
|
+
entries.forEach(([payload, { digest }], index) => {
|
|
1269
|
+
if (responses[index]?.error == null) {
|
|
1270
|
+
digests.set(payload, digest);
|
|
1271
|
+
cache.set(digest, payload);
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
return stubMessages(messages, digests);
|
|
1275
|
+
}
|
|
1276
|
+
/** Apply `offloadMessages` to a tool result (a `ToolMessage`, or a `Command`-shaped update). */
|
|
1277
|
+
async function offloadToolResult(result, backend, prefix, cache) {
|
|
1278
|
+
if (langchain.ToolMessage.isInstance(result)) return (await offloadMessages([result], backend, prefix, cache))[0];
|
|
1279
|
+
const update = result?.update;
|
|
1280
|
+
if (update && Array.isArray(update.messages)) {
|
|
1281
|
+
const messages = await offloadMessages(update.messages, backend, prefix, cache);
|
|
1282
|
+
return new _langchain_langgraph.Command({
|
|
1283
|
+
...result,
|
|
1284
|
+
update: {
|
|
1285
|
+
...update,
|
|
1286
|
+
messages
|
|
1287
|
+
}
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
return result;
|
|
1291
|
+
}
|
|
1292
|
+
/** Return `HumanMessage`s with ids after the last `AIMessage`, preferring a version already queued in `pending`. */
|
|
1293
|
+
function humanCandidates({ stateMessages, pending }) {
|
|
1294
|
+
let lastAiIndex = -1;
|
|
1295
|
+
stateMessages.forEach((message, index) => {
|
|
1296
|
+
if (langchain.AIMessage.isInstance(message)) lastAiIndex = index;
|
|
1297
|
+
});
|
|
1298
|
+
const queued = /* @__PURE__ */ new Map();
|
|
1299
|
+
for (const message of pending) {
|
|
1300
|
+
const id = message?.id;
|
|
1301
|
+
if (typeof id === "string") queued.set(id, message);
|
|
1302
|
+
}
|
|
1303
|
+
const candidates = [];
|
|
1304
|
+
for (const message of stateMessages.slice(lastAiIndex + 1)) {
|
|
1305
|
+
if (!langchain.HumanMessage.isInstance(message) || typeof message.id !== "string") continue;
|
|
1306
|
+
candidates.push(queued.get(message.id) ?? message);
|
|
1307
|
+
}
|
|
1308
|
+
return candidates;
|
|
1309
|
+
}
|
|
1310
|
+
function mergeReplacements({ pending, offloaded, candidates }) {
|
|
1311
|
+
const replaced = offloaded.filter((next, index) => next !== candidates[index]);
|
|
1312
|
+
const replacedIds = new Set(replaced.map((message) => message?.id));
|
|
1313
|
+
return [...pending.filter((message) => !replacedIds.has(message?.id)), ...replaced];
|
|
1314
|
+
}
|
|
1315
|
+
/** Return `pending` plus stubbed replacements for `HumanMessage`s in state carrying inline media. */
|
|
1316
|
+
async function offloadHumanMessages({ stateMessages, pending }, backend, prefix, cache) {
|
|
1317
|
+
const candidates = humanCandidates({
|
|
1318
|
+
stateMessages,
|
|
1319
|
+
pending
|
|
1320
|
+
});
|
|
1321
|
+
if (candidates.length === 0) return [...pending];
|
|
1322
|
+
return mergeReplacements({
|
|
1323
|
+
pending,
|
|
1324
|
+
offloaded: await offloadMessages(candidates, backend, prefix, cache),
|
|
1325
|
+
candidates
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
/** Collect every well-formed `deepagents_blob` digest referenced in `messages`, deduplicated. */
|
|
1329
|
+
function referencedDigests(messages) {
|
|
1330
|
+
const digests = /* @__PURE__ */ new Set();
|
|
1331
|
+
for (const message of messages) {
|
|
1332
|
+
const blocks = contentBlocks(message);
|
|
1333
|
+
if (!blocks) continue;
|
|
1334
|
+
for (const block of blocks) {
|
|
1335
|
+
const ref = block?.[BLOB_REF_KEY];
|
|
1336
|
+
if (isDigest(ref)) digests.add(ref);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
return [...digests];
|
|
1340
|
+
}
|
|
1341
|
+
function cachedPayloads(digests, cache) {
|
|
1342
|
+
const payloads = /* @__PURE__ */ new Map();
|
|
1343
|
+
const missing = [];
|
|
1344
|
+
for (const digest of digests) {
|
|
1345
|
+
const payload = cache.get(digest);
|
|
1346
|
+
if (payload !== void 0) payloads.set(digest, payload);
|
|
1347
|
+
else missing.push(digest);
|
|
1348
|
+
}
|
|
1349
|
+
return {
|
|
1350
|
+
payloads,
|
|
1351
|
+
missing
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
/** Verify each downloaded blob's integrity before trusting it — blobs live on an agent-writable backend. */
|
|
1355
|
+
function acceptDownloads(missing, responses, payloads, cache) {
|
|
1356
|
+
missing.forEach((digest, index) => {
|
|
1357
|
+
const response = responses[index];
|
|
1358
|
+
if (!response || response.error != null || response.content == null) return;
|
|
1359
|
+
if (sha256Hex(response.content) !== digest) return;
|
|
1360
|
+
const payload = Buffer.from(response.content).toString("base64");
|
|
1361
|
+
cache.set(digest, payload);
|
|
1362
|
+
payloads.set(digest, payload);
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
function messageHasRefs(message) {
|
|
1366
|
+
const blocks = contentBlocks(message);
|
|
1367
|
+
return blocks != null && blocks.some((block) => block != null && typeof block === "object" && "deepagents_blob" in block);
|
|
1368
|
+
}
|
|
1369
|
+
function withContent(message, content) {
|
|
1370
|
+
if (langchain.ToolMessage.isInstance(message)) return new langchain.ToolMessage({
|
|
1371
|
+
content,
|
|
1372
|
+
tool_call_id: message.tool_call_id,
|
|
1373
|
+
name: message.name,
|
|
1374
|
+
id: message.id,
|
|
1375
|
+
artifact: message.artifact,
|
|
1376
|
+
status: message.status,
|
|
1377
|
+
additional_kwargs: message.additional_kwargs,
|
|
1378
|
+
response_metadata: message.response_metadata,
|
|
1379
|
+
metadata: message.metadata
|
|
1380
|
+
});
|
|
1381
|
+
if (langchain.HumanMessage.isInstance(message)) return new langchain.HumanMessage({
|
|
1382
|
+
content,
|
|
1383
|
+
id: message.id,
|
|
1384
|
+
additional_kwargs: message.additional_kwargs,
|
|
1385
|
+
response_metadata: message.response_metadata
|
|
1386
|
+
});
|
|
1387
|
+
if (langchain.AIMessage.isInstance(message)) return new langchain.AIMessage({
|
|
1388
|
+
content,
|
|
1389
|
+
id: message.id,
|
|
1390
|
+
tool_calls: message.tool_calls,
|
|
1391
|
+
invalid_tool_calls: message.invalid_tool_calls,
|
|
1392
|
+
usage_metadata: message.usage_metadata,
|
|
1393
|
+
additional_kwargs: message.additional_kwargs,
|
|
1394
|
+
response_metadata: message.response_metadata
|
|
1395
|
+
});
|
|
1396
|
+
if (langchain.SystemMessage.isInstance(message)) return new langchain.SystemMessage({
|
|
1397
|
+
content,
|
|
1398
|
+
id: message.id,
|
|
1399
|
+
additional_kwargs: message.additional_kwargs,
|
|
1400
|
+
response_metadata: message.response_metadata
|
|
1401
|
+
});
|
|
1402
|
+
console.warn(`blobOffload: left a blob reference unresolved on an unsupported message type (${message?.constructor?.name})`);
|
|
1403
|
+
return message;
|
|
1404
|
+
}
|
|
1405
|
+
/** Restore base64 payloads for blob references; a reference with no matching payload becomes a text notice. */
|
|
1406
|
+
function restorePayloads(messages, payloads) {
|
|
1407
|
+
const hydrate = (block) => {
|
|
1408
|
+
const ref = block[BLOB_REF_KEY];
|
|
1409
|
+
if (ref === void 0) return block;
|
|
1410
|
+
const payload = isDigest(ref) ? payloads.get(ref) : void 0;
|
|
1411
|
+
if (payload === void 0) return {
|
|
1412
|
+
type: "text",
|
|
1413
|
+
text: MISSING_BLOB_TEXT
|
|
1414
|
+
};
|
|
1415
|
+
const { [BLOB_REF_KEY]: _ref, ...rest } = block;
|
|
1416
|
+
return {
|
|
1417
|
+
...rest,
|
|
1418
|
+
data: payload
|
|
1419
|
+
};
|
|
1420
|
+
};
|
|
1421
|
+
return messages.map((message) => {
|
|
1422
|
+
if (!messageHasRefs(message)) return message;
|
|
1423
|
+
return withContent(message, (contentBlocks(message) ?? []).map(hydrate));
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Restore base64 payloads for blob references ahead of a model call.
|
|
1428
|
+
*
|
|
1429
|
+
* Only the returned array is used for the request — callers must not persist
|
|
1430
|
+
* the result back into state, or the checkpoint-size benefit of offloading is
|
|
1431
|
+
* lost the next time state is saved.
|
|
1432
|
+
*/
|
|
1433
|
+
async function hydrateMessages(messages, backend, prefix, cache) {
|
|
1434
|
+
if (!messages.some(messageHasRefs)) return [...messages];
|
|
1435
|
+
const { payloads, missing } = cachedPayloads(referencedDigests(messages), cache);
|
|
1436
|
+
if (missing.length > 0) if (typeof backend.downloadFiles !== "function") console.warn("Backend does not support downloadFiles; offloaded read_file content is unavailable");
|
|
1437
|
+
else {
|
|
1438
|
+
let responses = [];
|
|
1439
|
+
try {
|
|
1440
|
+
responses = await backend.downloadFiles(missing.map((digest) => blobPath(prefix, digest)));
|
|
1441
|
+
} catch (error) {
|
|
1442
|
+
console.warn("Failed to load offloaded read_file content", error);
|
|
1443
|
+
}
|
|
1444
|
+
acceptDownloads(missing, responses, payloads, cache);
|
|
1445
|
+
}
|
|
1446
|
+
return restorePayloads(messages, payloads);
|
|
1447
|
+
}
|
|
1448
|
+
//#endregion
|
|
1449
|
+
//#region src/middleware/unsupportedContent.ts
|
|
1450
|
+
const PDF_MIME_TYPE = "application/pdf";
|
|
1451
|
+
/** Content block types `read_file` may emit that require multimodal model support. */
|
|
1452
|
+
const MULTIMODAL_BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
1453
|
+
"image",
|
|
1454
|
+
"audio",
|
|
1455
|
+
"video",
|
|
1456
|
+
"file"
|
|
1457
|
+
]);
|
|
1458
|
+
const PROFILE_FIELD_BY_BLOCK_TYPE = {
|
|
1459
|
+
image: "imageInputs",
|
|
1460
|
+
audio: "audioInputs",
|
|
1461
|
+
video: "videoInputs"
|
|
1462
|
+
};
|
|
1463
|
+
const TOOL_MESSAGE_FIELD_BY_BLOCK_TYPE = { image: "imageToolMessage" };
|
|
1464
|
+
function hasInlineData(block) {
|
|
1465
|
+
return block.data != null || block.source_type === "base64";
|
|
1466
|
+
}
|
|
1467
|
+
function blockMimeType(block) {
|
|
1468
|
+
const mimeType = block.mimeType ?? block.mime_type;
|
|
1469
|
+
return typeof mimeType === "string" ? mimeType : void 0;
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Unlike the other block types, a missing `fileMimeTypes` defaults to
|
|
1473
|
+
* unsupported rather than supported: generic file support varies far more
|
|
1474
|
+
* across models than image/audio/video, so there's no safe assumption to
|
|
1475
|
+
* fall back on absent real profile data.
|
|
1476
|
+
*/
|
|
1477
|
+
function fileBlockSupported(block, profile, inToolMessage) {
|
|
1478
|
+
if (!hasInlineData(block)) return true;
|
|
1479
|
+
const mimeType = blockMimeType(block);
|
|
1480
|
+
if (mimeType === PDF_MIME_TYPE) {
|
|
1481
|
+
if (inToolMessage && profile.pdfToolMessage !== void 0) return profile.pdfToolMessage !== false;
|
|
1482
|
+
return profile.pdfInputs !== false;
|
|
1483
|
+
}
|
|
1484
|
+
if (mimeType == null) return false;
|
|
1485
|
+
const { fileMimeTypes } = profile;
|
|
1486
|
+
return Array.isArray(fileMimeTypes) && fileMimeTypes.includes(mimeType);
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Whether the model accepts a multimodal block.
|
|
1490
|
+
*
|
|
1491
|
+
* Missing profile fields default to supported, since profile coverage is
|
|
1492
|
+
* incomplete — except `file` blocks, where a missing `fileMimeTypes`
|
|
1493
|
+
* defaults to unsupported (see `fileBlockSupported`).
|
|
1494
|
+
*/
|
|
1495
|
+
function multimodalBlockSupported(block, profile, inToolMessage) {
|
|
1496
|
+
if (block.type === "file") return fileBlockSupported(block, profile, inToolMessage);
|
|
1497
|
+
const field = PROFILE_FIELD_BY_BLOCK_TYPE[block.type];
|
|
1498
|
+
if (field == null) return true;
|
|
1499
|
+
if (inToolMessage) {
|
|
1500
|
+
const toolField = TOOL_MESSAGE_FIELD_BY_BLOCK_TYPE[block.type];
|
|
1501
|
+
if (toolField != null && profile[toolField] !== void 0) return profile[toolField] !== false;
|
|
1502
|
+
}
|
|
1503
|
+
return profile[field] !== false;
|
|
1504
|
+
}
|
|
1505
|
+
function placeholder(block, path) {
|
|
1506
|
+
return {
|
|
1507
|
+
type: "text",
|
|
1508
|
+
text: `[read_file: ${path ?? "the requested file"} was not attached because this model does not support ${block.type} content (${blockMimeType(block) ?? "unknown"}).]`
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
function readFilePaths(messages) {
|
|
1512
|
+
const paths = /* @__PURE__ */ new Map();
|
|
1513
|
+
for (const message of messages) {
|
|
1514
|
+
if (!_langchain_core_messages.AIMessage.isInstance(message)) continue;
|
|
1515
|
+
for (const toolCall of message.tool_calls ?? []) {
|
|
1516
|
+
const path = toolCall.args?.file_path;
|
|
1517
|
+
if (toolCall.id != null && typeof path === "string") paths.set(toolCall.id, path);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return paths;
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Without this, a request carrying content the model can't accept (e.g. a
|
|
1524
|
+
* `.zip` file sent to a model without file support) fails with a
|
|
1525
|
+
* non-retryable 400, and since the content stays in history, every later
|
|
1526
|
+
* turn fails the same way. Only the request is changed; messages in state
|
|
1527
|
+
* are left untouched, so switching to a model that accepts the content
|
|
1528
|
+
* sends it again.
|
|
1529
|
+
*/
|
|
1530
|
+
function scrubUnsupportedMultimodalContent(messages, model) {
|
|
1531
|
+
const rawProfile = model?.profile;
|
|
1532
|
+
const profile = rawProfile != null && typeof rawProfile === "object" ? rawProfile : {};
|
|
1533
|
+
let paths;
|
|
1534
|
+
let changed = false;
|
|
1535
|
+
const result = messages.map((message) => {
|
|
1536
|
+
const isTool = _langchain_core_messages.ToolMessage.isInstance(message);
|
|
1537
|
+
if (!isTool && !_langchain_core_messages.HumanMessage.isInstance(message)) return message;
|
|
1538
|
+
let messageChanged = false;
|
|
1539
|
+
const content = message.contentBlocks.map((block) => {
|
|
1540
|
+
if (block == null || typeof block !== "object" || !MULTIMODAL_BLOCK_TYPES.has(block.type) || multimodalBlockSupported(block, profile, isTool)) return block;
|
|
1541
|
+
messageChanged = true;
|
|
1542
|
+
paths ??= readFilePaths(messages);
|
|
1543
|
+
return placeholder(block, isTool ? paths.get(message.tool_call_id) : void 0);
|
|
1544
|
+
});
|
|
1545
|
+
if (!messageChanged) return message;
|
|
1546
|
+
changed = true;
|
|
1547
|
+
if (isTool) return new _langchain_core_messages.ToolMessage({
|
|
1548
|
+
content,
|
|
1549
|
+
tool_call_id: message.tool_call_id,
|
|
1550
|
+
name: message.name,
|
|
1551
|
+
id: message.id,
|
|
1552
|
+
artifact: message.artifact,
|
|
1553
|
+
status: message.status,
|
|
1554
|
+
metadata: message.metadata,
|
|
1555
|
+
additional_kwargs: message.additional_kwargs,
|
|
1556
|
+
response_metadata: message.response_metadata
|
|
1557
|
+
});
|
|
1558
|
+
return new _langchain_core_messages.HumanMessage({
|
|
1559
|
+
content,
|
|
1560
|
+
name: message.name,
|
|
1561
|
+
id: message.id,
|
|
1562
|
+
additional_kwargs: message.additional_kwargs,
|
|
1563
|
+
response_metadata: message.response_metadata
|
|
1564
|
+
});
|
|
1565
|
+
});
|
|
1566
|
+
return changed ? result : messages;
|
|
1567
|
+
}
|
|
1568
|
+
/**
|
|
1569
|
+
* Support is read from `model.profile` (see
|
|
1570
|
+
* https://docs.langchain.com/oss/javascript/langchain/models#model-profiles).
|
|
1571
|
+
*
|
|
1572
|
+
* Place this middleware last in the agent's `middleware` list, so that if
|
|
1573
|
+
* some other middleware changes `request.model`, this one sees the model
|
|
1574
|
+
* that will actually receive the request.
|
|
1575
|
+
*/
|
|
1576
|
+
function createUnsupportedContentMiddleware() {
|
|
1577
|
+
return (0, langchain.createMiddleware)({
|
|
1578
|
+
name: "UnsupportedContentMiddleware",
|
|
1579
|
+
wrapModelCall: async (request, handler) => {
|
|
1580
|
+
const messages = scrubUnsupportedMultimodalContent(request.messages, request.model);
|
|
1581
|
+
if (messages === request.messages) return handler(request);
|
|
1582
|
+
return handler({
|
|
1583
|
+
...request,
|
|
1584
|
+
messages
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
});
|
|
1588
|
+
}
|
|
1589
|
+
//#endregion
|
|
1114
1590
|
//#region src/permissions/enforce.ts
|
|
1115
1591
|
/**
|
|
1116
1592
|
* Validate permission rule paths at setup time. Throws if any path is
|
|
@@ -1201,6 +1677,10 @@ var CompositeBackend = class {
|
|
|
1201
1677
|
static isInstance(backend) {
|
|
1202
1678
|
return typeof backend === "object" && backend !== null && Array.isArray(backend.routePrefixes);
|
|
1203
1679
|
}
|
|
1680
|
+
/** Returns the backend for `path`, with the matched prefix stripped from the returned path. */
|
|
1681
|
+
resolveBackendForPath(path) {
|
|
1682
|
+
return this.getBackendAndKey(path);
|
|
1683
|
+
}
|
|
1204
1684
|
/**
|
|
1205
1685
|
* Determine which backend handles this key and strip prefix.
|
|
1206
1686
|
*
|
|
@@ -1805,6 +2285,8 @@ const GREP_TRUNCATION_NOTE = "Note: the search stopped early because it hit the
|
|
|
1805
2285
|
* Set to null to disable the cap.
|
|
1806
2286
|
*/
|
|
1807
2287
|
const DEFAULT_GREP_MAX_COUNT = 1e3;
|
|
2288
|
+
/** Path prefix offloaded binary content blobs are written under. */
|
|
2289
|
+
const BLOBS_PREFIX = "/blobs";
|
|
1808
2290
|
/**
|
|
1809
2291
|
* Message template for evicted tool results.
|
|
1810
2292
|
*/
|
|
@@ -2587,6 +3069,68 @@ function allPathsScopedToRoutes(permissions, backend) {
|
|
|
2587
3069
|
return path === normalizedRoute.slice(0, -1) || path.startsWith(normalizedRoute);
|
|
2588
3070
|
})));
|
|
2589
3071
|
}
|
|
3072
|
+
/** Whether `path` resolves to a `StateBackend`, recursing through composite routing. */
|
|
3073
|
+
function routesToStateBackend(backend, path) {
|
|
3074
|
+
if (CompositeBackend.isInstance(backend)) {
|
|
3075
|
+
const [routed, routedPath] = backend.resolveBackendForPath(path);
|
|
3076
|
+
return routesToStateBackend(routed, routedPath);
|
|
3077
|
+
}
|
|
3078
|
+
return StateBackend.isInstance(backend);
|
|
3079
|
+
}
|
|
3080
|
+
/**
|
|
3081
|
+
* Whether `response` is the `{ structuredResponse, messages }` shape a
|
|
3082
|
+
* provider-strategy structured-output call can return instead of a plain
|
|
3083
|
+
* `AIMessage`. The agent framework only recognizes this shape at the
|
|
3084
|
+
* outermost `wrapModelCall` return value — returning a `Command` instead
|
|
3085
|
+
* discards `structuredResponse` with no way to carry it through the Command.
|
|
3086
|
+
*/
|
|
3087
|
+
function hasStructuredResponse(response) {
|
|
3088
|
+
return typeof response === "object" && response !== null && "structuredResponse" in response && "messages" in response;
|
|
3089
|
+
}
|
|
3090
|
+
const REJECTED_FILE_CONTENT_TEXT = "Unsupported content. The file may be invalid, too large, or of an unsupported mime-type.";
|
|
3091
|
+
/**
|
|
3092
|
+
* No LangChain error class captures "the provider rejected this request"
|
|
3093
|
+
* generically, so this checks the raw HTTP status providers' client SDKs set
|
|
3094
|
+
* on their errors instead. `ContextOverflowError` is excluded because it's a
|
|
3095
|
+
* different, already-handled problem, and retrying it with stripped file
|
|
3096
|
+
* content wouldn't fix an oversized prompt.
|
|
3097
|
+
*/
|
|
3098
|
+
function isRejectedRequestError(error) {
|
|
3099
|
+
if (_langchain_core_errors.ContextOverflowError.isInstance(error)) return false;
|
|
3100
|
+
return typeof error === "object" && error !== null && "status" in error && error.status === 400;
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* Only messages carrying multimodal blocks after the last `AIMessage` are
|
|
3104
|
+
* candidates for replacement, since anything earlier was already accepted by
|
|
3105
|
+
* the model in a prior turn. Returns `messages` unchanged if nothing
|
|
3106
|
+
* matched, so the caller can tell there was nothing to blame for the
|
|
3107
|
+
* rejection.
|
|
3108
|
+
*/
|
|
3109
|
+
function replaceRejectedFileContent(messages) {
|
|
3110
|
+
let lastResponseIndex = -1;
|
|
3111
|
+
for (let i = messages.length - 1; i >= 0; i--) if (langchain.AIMessage.isInstance(messages[i])) {
|
|
3112
|
+
lastResponseIndex = i;
|
|
3113
|
+
break;
|
|
3114
|
+
}
|
|
3115
|
+
let changed = false;
|
|
3116
|
+
const result = messages.map((message, index) => {
|
|
3117
|
+
if (index <= lastResponseIndex || !langchain.ToolMessage.isInstance(message) || message.name !== "read_file") return message;
|
|
3118
|
+
if (!message.contentBlocks.some((block) => MULTIMODAL_BLOCK_TYPES.has(block.type))) return message;
|
|
3119
|
+
changed = true;
|
|
3120
|
+
return new langchain.ToolMessage({
|
|
3121
|
+
content: REJECTED_FILE_CONTENT_TEXT,
|
|
3122
|
+
tool_call_id: message.tool_call_id,
|
|
3123
|
+
name: message.name,
|
|
3124
|
+
id: message.id,
|
|
3125
|
+
artifact: message.artifact,
|
|
3126
|
+
status: message.status,
|
|
3127
|
+
metadata: message.metadata,
|
|
3128
|
+
additional_kwargs: message.additional_kwargs,
|
|
3129
|
+
response_metadata: message.response_metadata
|
|
3130
|
+
});
|
|
3131
|
+
});
|
|
3132
|
+
return changed ? result : messages;
|
|
3133
|
+
}
|
|
2590
3134
|
/**
|
|
2591
3135
|
* Create middleware that provides built-in filesystem tools and optional custom
|
|
2592
3136
|
* prompt guidance.
|
|
@@ -2613,7 +3157,10 @@ function allPathsScopedToRoutes(permissions, backend) {
|
|
|
2613
3157
|
* ```
|
|
2614
3158
|
*/
|
|
2615
3159
|
function createFilesystemMiddleware(options = {}) {
|
|
2616
|
-
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;
|
|
3160
|
+
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;
|
|
3161
|
+
const backendIsStateBackend = StateBackend.isInstance(backend);
|
|
3162
|
+
if (offloadBinaryContent && backendIsStateBackend) console.warn("offloadBinaryContent has no effect: the backend is a StateBackend, which keeps files as part of checkpointed state.");
|
|
3163
|
+
const blobCache = offloadBinaryContent && !backendIsStateBackend ? new BlobCache() : null;
|
|
2617
3164
|
const enabledFilesystemTools = normalizeFilesystemTools(filesystemTools);
|
|
2618
3165
|
const executeToolEnabled = enabledFilesystemTools == null || enabledFilesystemTools.has("execute");
|
|
2619
3166
|
if (permissions.length > 0) validatePermissionPaths(permissions);
|
|
@@ -2750,18 +3297,59 @@ function createFilesystemMiddleware(options = {}) {
|
|
|
2750
3297
|
return msg;
|
|
2751
3298
|
});
|
|
2752
3299
|
}
|
|
2753
|
-
|
|
3300
|
+
let offloadedHuman = [];
|
|
3301
|
+
if (blobCache && !routesToStateBackend(resolvedBackend, `${BLOBS_PREFIX}/`)) {
|
|
3302
|
+
offloadedHuman = await offloadHumanMessages({
|
|
3303
|
+
stateMessages: request.state.messages ?? [],
|
|
3304
|
+
pending: []
|
|
3305
|
+
}, resolvedBackend, BLOBS_PREFIX, blobCache);
|
|
3306
|
+
messages = await hydrateMessages(messages, resolvedBackend, BLOBS_PREFIX, blobCache);
|
|
3307
|
+
}
|
|
3308
|
+
const finalRequest = {
|
|
2754
3309
|
...request,
|
|
2755
3310
|
tools,
|
|
2756
3311
|
messages,
|
|
2757
3312
|
systemMessage: newSystemMessage
|
|
2758
|
-
}
|
|
3313
|
+
};
|
|
3314
|
+
const foldOffload = (response, extra = []) => {
|
|
3315
|
+
if (offloadedHuman.length === 0 && extra.length === 0) return response;
|
|
3316
|
+
if (hasStructuredResponse(response)) return {
|
|
3317
|
+
...response,
|
|
3318
|
+
messages: [
|
|
3319
|
+
...extra,
|
|
3320
|
+
...offloadedHuman,
|
|
3321
|
+
...response.messages
|
|
3322
|
+
]
|
|
3323
|
+
};
|
|
3324
|
+
return new _langchain_langgraph.Command({ update: { messages: extra.length === 0 ? offloadedHuman : [
|
|
3325
|
+
...extra,
|
|
3326
|
+
...offloadedHuman,
|
|
3327
|
+
response
|
|
3328
|
+
] } });
|
|
3329
|
+
};
|
|
3330
|
+
try {
|
|
3331
|
+
return foldOffload(await handler(finalRequest));
|
|
3332
|
+
} catch (error) {
|
|
3333
|
+
if (!isRejectedRequestError(error)) throw error;
|
|
3334
|
+
const replaced = replaceRejectedFileContent(finalRequest.messages);
|
|
3335
|
+
if (replaced === finalRequest.messages) throw error;
|
|
3336
|
+
return foldOffload(await handler({
|
|
3337
|
+
...finalRequest,
|
|
3338
|
+
messages: replaced
|
|
3339
|
+
}), replaced.filter((msg, i) => msg !== finalRequest.messages[i]));
|
|
3340
|
+
}
|
|
2759
3341
|
},
|
|
2760
3342
|
wrapToolCall: async (request, handler) => {
|
|
2761
|
-
if (!toolTokenLimitBeforeEvict) return handler(request);
|
|
2762
3343
|
const toolName = request.toolCall?.name;
|
|
2763
|
-
|
|
2764
|
-
|
|
3344
|
+
let result = await handler(request);
|
|
3345
|
+
if (blobCache && toolName === "read_file") {
|
|
3346
|
+
const resolvedBackend = await resolveBackend(backend, {
|
|
3347
|
+
...request.runtime,
|
|
3348
|
+
state: request.state
|
|
3349
|
+
});
|
|
3350
|
+
if (!routesToStateBackend(resolvedBackend, `${BLOBS_PREFIX}/`)) result = await offloadToolResult(result, resolvedBackend, BLOBS_PREFIX, /* @__PURE__ */ new Map());
|
|
3351
|
+
}
|
|
3352
|
+
if (!toolTokenLimitBeforeEvict || toolName && TOOLS_EXCLUDED_FROM_EVICTION.includes(toolName)) return result;
|
|
2765
3353
|
if (langchain.ToolMessage.isInstance(result)) {
|
|
2766
3354
|
const processed = await processToolMessage(result, request.runtime, request.state, request.toolCall?.id);
|
|
2767
3355
|
if (processed.filesUpdate) return new _langchain_langgraph.Command({ update: {
|
|
@@ -3805,6 +4393,7 @@ function createSubAgent(spec, options) {
|
|
|
3805
4393
|
if (!spec.tools) throw new Error(`SubAgent '${spec.name}' must specify 'tools'`);
|
|
3806
4394
|
const middleware = [...spec.middleware ?? []];
|
|
3807
4395
|
if (spec.interruptOn) middleware.push((0, langchain.humanInTheLoopMiddleware)({ interruptOn: spec.interruptOn }));
|
|
4396
|
+
if (!middleware.some((m) => m.name === "UnsupportedContentMiddleware")) middleware.push(createUnsupportedContentMiddleware());
|
|
3808
4397
|
const selectedResponseFormat = options?.responseFormat ?? spec.responseFormat;
|
|
3809
4398
|
return (0, langchain.createAgent)({
|
|
3810
4399
|
model: spec.model,
|
|
@@ -6724,6 +7313,7 @@ function createDeepAgent(params = {}) {
|
|
|
6724
7313
|
]);
|
|
6725
7314
|
if (subagentProfile.excludedMiddleware.size > 0) subagentMiddleware = subagentMiddleware.filter((middleware) => !subagentProfile.excludedMiddleware.has(middleware.name));
|
|
6726
7315
|
if (subagentProfile.excludedTools.size > 0) subagentMiddleware.push(createToolExclusionMiddleware(subagentProfile.excludedTools));
|
|
7316
|
+
if (!subagentProfile.excludedMiddleware.has("UnsupportedContentMiddleware") && !subagentMiddleware.some((middleware) => middleware.name === "UnsupportedContentMiddleware")) subagentMiddleware.push(createUnsupportedContentMiddleware());
|
|
6727
7317
|
return subagentMiddleware;
|
|
6728
7318
|
};
|
|
6729
7319
|
const normalizeSubagentSpec = (input) => ({
|
|
@@ -6786,6 +7376,7 @@ function createDeepAgent(params = {}) {
|
|
|
6786
7376
|
middleware = middleware.filter((entry) => !excluded.has(entry.name));
|
|
6787
7377
|
}
|
|
6788
7378
|
if (harnessProfile.excludedTools.size > 0) middleware.push(createToolExclusionMiddleware(harnessProfile.excludedTools));
|
|
7379
|
+
if (!harnessProfile.excludedMiddleware.has("UnsupportedContentMiddleware") && !middleware.some((m) => m.name === "UnsupportedContentMiddleware")) middleware.push(createUnsupportedContentMiddleware());
|
|
6789
7380
|
/**
|
|
6790
7381
|
* Return as DeepAgent with proper DeepAgentTypeConfig
|
|
6791
7382
|
* - Response: InferStructuredResponse<TResponse> (unwraps ToolStrategy<T>/ProviderStrategy<T> → T)
|
|
@@ -8993,6 +9584,12 @@ Object.defineProperty(exports, "MAX_SKILL_NAME_LENGTH", {
|
|
|
8993
9584
|
return MAX_SKILL_NAME_LENGTH;
|
|
8994
9585
|
}
|
|
8995
9586
|
});
|
|
9587
|
+
Object.defineProperty(exports, "MULTIMODAL_BLOCK_TYPES", {
|
|
9588
|
+
enumerable: true,
|
|
9589
|
+
get: function() {
|
|
9590
|
+
return MULTIMODAL_BLOCK_TYPES;
|
|
9591
|
+
}
|
|
9592
|
+
});
|
|
8996
9593
|
Object.defineProperty(exports, "REQUIRED_MIDDLEWARE_NAMES", {
|
|
8997
9594
|
enumerable: true,
|
|
8998
9595
|
get: function() {
|
|
@@ -9131,6 +9728,12 @@ Object.defineProperty(exports, "createSummarizationMiddleware", {
|
|
|
9131
9728
|
return createSummarizationMiddleware;
|
|
9132
9729
|
}
|
|
9133
9730
|
});
|
|
9731
|
+
Object.defineProperty(exports, "createUnsupportedContentMiddleware", {
|
|
9732
|
+
enumerable: true,
|
|
9733
|
+
get: function() {
|
|
9734
|
+
return createUnsupportedContentMiddleware;
|
|
9735
|
+
}
|
|
9736
|
+
});
|
|
9134
9737
|
Object.defineProperty(exports, "filesValue", {
|
|
9135
9738
|
enumerable: true,
|
|
9136
9739
|
get: function() {
|
|
@@ -9185,6 +9788,12 @@ Object.defineProperty(exports, "isTextMimeType", {
|
|
|
9185
9788
|
return isTextMimeType;
|
|
9186
9789
|
}
|
|
9187
9790
|
});
|
|
9791
|
+
Object.defineProperty(exports, "multimodalBlockSupported", {
|
|
9792
|
+
enumerable: true,
|
|
9793
|
+
get: function() {
|
|
9794
|
+
return multimodalBlockSupported;
|
|
9795
|
+
}
|
|
9796
|
+
});
|
|
9188
9797
|
Object.defineProperty(exports, "normalizeReadPagination", {
|
|
9189
9798
|
enumerable: true,
|
|
9190
9799
|
get: function() {
|
|
@@ -9215,6 +9824,12 @@ Object.defineProperty(exports, "resolveBackend", {
|
|
|
9215
9824
|
return resolveBackend;
|
|
9216
9825
|
}
|
|
9217
9826
|
});
|
|
9827
|
+
Object.defineProperty(exports, "scrubUnsupportedMultimodalContent", {
|
|
9828
|
+
enumerable: true,
|
|
9829
|
+
get: function() {
|
|
9830
|
+
return scrubUnsupportedMultimodalContent;
|
|
9831
|
+
}
|
|
9832
|
+
});
|
|
9218
9833
|
Object.defineProperty(exports, "serializeProfile", {
|
|
9219
9834
|
enumerable: true,
|
|
9220
9835
|
get: function() {
|
|
@@ -9228,4 +9843,4 @@ Object.defineProperty(exports, "skillsMetadataValue", {
|
|
|
9228
9843
|
}
|
|
9229
9844
|
});
|
|
9230
9845
|
|
|
9231
|
-
//# sourceMappingURL=langsmith-
|
|
9846
|
+
//# sourceMappingURL=langsmith-CjOWZAS2.cjs.map
|