@ai-sdk/harness-deepagents 1.0.133 → 1.0.135

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.
@@ -1,2481 +1,1431 @@
1
- // src/bridge/index.ts
2
- import { randomUUID as randomUUID3 } from "crypto";
3
- import { argv, env as procEnv2 } from "process";
4
-
5
- // ../harness/dist/bridge/index.js
6
- import { appendFile, mkdir, writeFile } from "fs/promises";
7
- import { existsSync, readFileSync } from "fs";
8
- import { randomUUID } from "crypto";
9
- import { env as procEnv, pid, stdout } from "process";
1
+ import { randomUUID } from "node:crypto";
2
+ import { argv, env, pid, stdout } from "node:process";
3
+ import { appendFile, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
4
+ import { existsSync, readFileSync } from "node:fs";
10
5
  import { WebSocketServer } from "ws";
11
- var DEBUG_LEVEL_WEIGHT = {
12
- error: 0,
13
- warn: 1,
14
- info: 2,
15
- debug: 3,
16
- trace: 4
6
+ import { ChatAnthropic } from "@langchain/anthropic";
7
+ import { tool } from "@langchain/core/tools";
8
+ import { Command, MemorySaver, Overwrite } from "@langchain/langgraph";
9
+ import { MultiServerMCPClient } from "@langchain/mcp-adapters";
10
+ import { LocalShellBackend, createDeepAgent } from "deepagents";
11
+ import { createMiddleware, toolStrategy } from "langchain";
12
+ import { z } from "zod/v4";
13
+ import { dirname } from "node:path";
14
+ import { AIMessage, ToolMessage } from "@langchain/core/messages";
15
+ //#region ../harness/dist/bridge/index.js
16
+ const DEBUG_LEVEL_WEIGHT = {
17
+ error: 0,
18
+ warn: 1,
19
+ info: 2,
20
+ debug: 3,
21
+ trace: 4
17
22
  };
23
+ /** Exact-or-dotted-prefix subsystem match (`'bridge'` matches `'bridge.turn'`). */
18
24
  function subsystemMatches(filters, subsystem) {
19
- if (!filters || filters.length === 0) return true;
20
- return filters.some(
21
- (filter) => subsystem === filter || subsystem.startsWith(`${filter}.`)
22
- );
25
+ if (!filters || filters.length === 0) return true;
26
+ return filters.some((filter) => subsystem === filter || subsystem.startsWith(`${filter}.`));
23
27
  }
24
28
  function formatBridgeError(err) {
25
- if (err instanceof Error) {
26
- return { name: err.name, message: err.message, stack: err.stack };
27
- }
28
- if (typeof err === "string") {
29
- return { message: err };
30
- }
31
- if (err !== null && typeof err === "object") {
32
- try {
33
- return { message: JSON.stringify(err) };
34
- } catch {
35
- }
36
- }
37
- return { message: String(err) };
29
+ if (err instanceof Error) return {
30
+ name: err.name,
31
+ message: err.message,
32
+ stack: err.stack
33
+ };
34
+ if (typeof err === "string") return { message: err };
35
+ if (err !== null && typeof err === "object") try {
36
+ return { message: JSON.stringify(err) };
37
+ } catch {}
38
+ return { message: String(err) };
38
39
  }
39
40
  function createBridgeUserMessageQueue(options) {
40
- const messages = [];
41
- const waiters = [];
42
- const entries = /* @__PURE__ */ new Map();
43
- let closed = false;
44
- let pendingCount = 0;
45
- const enqueue = (input) => {
46
- const existing = entries.get(input.messageId);
47
- if (existing != null) {
48
- if (existing.response != null) {
49
- options.respond(existing.response);
50
- }
51
- return;
52
- }
53
- let settled = false;
54
- const settle = (response) => {
55
- if (settled) return;
56
- settled = true;
57
- pendingCount--;
58
- const entry = entries.get(input.messageId);
59
- if (entry != null) entry.response = response;
60
- options.respond(response);
61
- };
62
- const message = {
63
- messageId: input.messageId,
64
- text: input.text,
65
- accept: () => {
66
- settle({
67
- type: "user-message-response",
68
- messageId: input.messageId,
69
- accepted: true
70
- });
71
- },
72
- reject: (error) => {
73
- settle({
74
- type: "user-message-response",
75
- messageId: input.messageId,
76
- accepted: false,
77
- error: { message: formatBridgeError(error).message }
78
- });
79
- }
80
- };
81
- entries.set(input.messageId, {
82
- reject: message.reject
83
- });
84
- pendingCount++;
85
- if (closed) {
86
- message.reject(
87
- new Error("The bridge turn is no longer accepting user messages.")
88
- );
89
- return;
90
- }
91
- const waiter = waiters.shift();
92
- if (waiter != null) {
93
- waiter({ done: false, value: message });
94
- } else {
95
- messages.push(message);
96
- }
97
- };
98
- const close = (error) => {
99
- if (closed) return;
100
- closed = true;
101
- const reason = error ?? new Error("The bridge turn ended before accepting the user message.");
102
- for (const entry of entries.values()) {
103
- if (entry.response == null) entry.reject(reason);
104
- }
105
- messages.length = 0;
106
- while (waiters.length > 0) {
107
- waiters.shift()({ done: true, value: void 0 });
108
- }
109
- };
110
- return {
111
- get pendingCount() {
112
- return pendingCount;
113
- },
114
- enqueue,
115
- close,
116
- [Symbol.asyncIterator]() {
117
- return {
118
- next: () => {
119
- const message = messages.shift();
120
- if (message != null) {
121
- return Promise.resolve({ done: false, value: message });
122
- }
123
- if (closed) {
124
- return Promise.resolve({
125
- done: true,
126
- value: void 0
127
- });
128
- }
129
- return new Promise(
130
- (resolve) => {
131
- waiters.push(resolve);
132
- }
133
- );
134
- }
135
- };
136
- }
137
- };
41
+ const messages = [];
42
+ const waiters = [];
43
+ const entries = /* @__PURE__ */ new Map();
44
+ let closed = false;
45
+ let pendingCount = 0;
46
+ const enqueue = (input) => {
47
+ const existing = entries.get(input.messageId);
48
+ if (existing != null) {
49
+ if (existing.response != null) options.respond(existing.response);
50
+ return;
51
+ }
52
+ let settled = false;
53
+ const settle = (response) => {
54
+ if (settled) return;
55
+ settled = true;
56
+ pendingCount--;
57
+ const entry = entries.get(input.messageId);
58
+ if (entry != null) entry.response = response;
59
+ options.respond(response);
60
+ };
61
+ const message = {
62
+ messageId: input.messageId,
63
+ text: input.text,
64
+ accept: () => {
65
+ settle({
66
+ type: "user-message-response",
67
+ messageId: input.messageId,
68
+ accepted: true
69
+ });
70
+ },
71
+ reject: (error) => {
72
+ settle({
73
+ type: "user-message-response",
74
+ messageId: input.messageId,
75
+ accepted: false,
76
+ error: { message: formatBridgeError(error).message }
77
+ });
78
+ }
79
+ };
80
+ entries.set(input.messageId, { reject: message.reject });
81
+ pendingCount++;
82
+ if (closed) {
83
+ message.reject(/* @__PURE__ */ new Error("The bridge turn is no longer accepting user messages."));
84
+ return;
85
+ }
86
+ const waiter = waiters.shift();
87
+ if (waiter != null) waiter({
88
+ done: false,
89
+ value: message
90
+ });
91
+ else messages.push(message);
92
+ };
93
+ const close = (error) => {
94
+ if (closed) return;
95
+ closed = true;
96
+ const reason = error ?? /* @__PURE__ */ new Error("The bridge turn ended before accepting the user message.");
97
+ for (const entry of entries.values()) if (entry.response == null) entry.reject(reason);
98
+ messages.length = 0;
99
+ while (waiters.length > 0) waiters.shift()({
100
+ done: true,
101
+ value: void 0
102
+ });
103
+ };
104
+ return {
105
+ get pendingCount() {
106
+ return pendingCount;
107
+ },
108
+ enqueue,
109
+ close,
110
+ [Symbol.asyncIterator]() {
111
+ return { next: () => {
112
+ const message = messages.shift();
113
+ if (message != null) return Promise.resolve({
114
+ done: false,
115
+ value: message
116
+ });
117
+ if (closed) return Promise.resolve({
118
+ done: true,
119
+ value: void 0
120
+ });
121
+ return new Promise((resolve) => {
122
+ waiters.push(resolve);
123
+ });
124
+ } };
125
+ }
126
+ };
138
127
  }
139
128
  function parseEnvList(value) {
140
- if (!value) return void 0;
141
- const items = value.split(",").map((item) => item.trim()).filter(Boolean);
142
- return items.length > 0 ? items : void 0;
129
+ if (!value) return void 0;
130
+ const items = value.split(",").map((item) => item.trim()).filter(Boolean);
131
+ return items.length > 0 ? items : void 0;
143
132
  }
144
- var ENV_TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
145
- var WS_OPEN = 1;
133
+ const ENV_TRUTHY = /* @__PURE__ */ new Set([
134
+ "1",
135
+ "true",
136
+ "yes",
137
+ "on"
138
+ ]);
139
+ const WS_OPEN = 1;
146
140
  async function runBridge(options) {
147
- const { bridgeType, bridgeStateDir: bridgeStateDir2, onStart, onStop, onDestroy } = options;
148
- const teardownGraceMs = options.turnTeardownGraceMs ?? 1e4;
149
- const expectedToken = options.token ?? procEnv.BRIDGE_CHANNEL_TOKEN ?? "";
150
- const bridgeWsPort = options.port ?? parseInt(procEnv.BRIDGE_WS_PORT ?? "0", 10);
151
- const bridgeMetaPath = `${bridgeStateDir2}/bridge-meta.json`;
152
- const startConfigPath = `${bridgeStateDir2}/start-config.json`;
153
- const rerunStartConfigPath = `${bridgeStateDir2}/rerun-start-config.json`;
154
- const eventLogPath = `${bridgeStateDir2}/event-log.ndjson`;
155
- try {
156
- await mkdir(bridgeStateDir2, { recursive: true });
157
- } catch {
158
- }
159
- let currentBoundPort = 0;
160
- let currentTurnState = "init";
161
- let activeSocket;
162
- let isFirstTurn = true;
163
- let turnAbort;
164
- let currentUserMessages;
165
- let activeTurn;
166
- let debugConfig;
167
- let consoleCaptureInstalled = false;
168
- const envDebugEnabled = ENV_TRUTHY.has(
169
- (procEnv.HARNESS_DEBUG ?? "").toLowerCase()
170
- );
171
- let seqCounter = 0;
172
- let eventLog = [];
173
- let diskBuffer = "";
174
- let flushPromise = null;
175
- const flushEventsToDisk = async () => {
176
- while (diskBuffer.length > 0) {
177
- const buf = diskBuffer;
178
- diskBuffer = "";
179
- await appendFile(eventLogPath, buf).catch(() => {
180
- });
181
- }
182
- };
183
- const scheduleEventFlush = () => {
184
- if (flushPromise) return;
185
- flushPromise = new Promise((resolve) => {
186
- setImmediate(() => {
187
- void flushEventsToDisk().finally(resolve);
188
- });
189
- }).finally(() => {
190
- flushPromise = null;
191
- if (diskBuffer.length > 0) {
192
- scheduleEventFlush();
193
- }
194
- });
195
- };
196
- const flushPendingEventsToDisk = async () => {
197
- if (diskBuffer.length > 0 && !flushPromise) {
198
- scheduleEventFlush();
199
- }
200
- let inFlight = flushPromise;
201
- while (inFlight) {
202
- await inFlight;
203
- inFlight = flushPromise;
204
- }
205
- };
206
- const replayFromDisk = procEnv.BRIDGE_REPLAY_FROM_DISK === "1";
207
- if (replayFromDisk && existsSync(eventLogPath)) {
208
- try {
209
- const lines = readFileSync(eventLogPath, "utf8").split("\n").map((line) => line.trim()).filter(Boolean);
210
- eventLog = lines.map((line) => ({
211
- seq: JSON.parse(line).seq,
212
- line
213
- }));
214
- seqCounter = eventLog.at(-1)?.seq ?? 0;
215
- } catch {
216
- eventLog = [];
217
- seqCounter = 0;
218
- }
219
- }
220
- const pendingToolResults = /* @__PURE__ */ new Map();
221
- const bufferedToolResults = [];
222
- const pendingToolApprovals = /* @__PURE__ */ new Map();
223
- const writeBridgeMeta = async (state) => {
224
- try {
225
- await writeFile(
226
- bridgeMetaPath,
227
- JSON.stringify({
228
- type: bridgeType,
229
- port: currentBoundPort,
230
- state,
231
- pid
232
- })
233
- );
234
- } catch {
235
- }
236
- };
237
- const writeStartConfig = async (start) => {
238
- try {
239
- const serialized = JSON.stringify(start);
240
- await writeFile(startConfigPath, serialized);
241
- if (!existsSync(rerunStartConfigPath)) {
242
- await writeFile(rerunStartConfigPath, serialized);
243
- }
244
- } catch {
245
- }
246
- };
247
- const emit = (event) => {
248
- const seq = ++seqCounter;
249
- const line = JSON.stringify({ ...event, seq });
250
- eventLog.push({ seq, line });
251
- diskBuffer += `${line}
252
- `;
253
- scheduleEventFlush();
254
- if (activeSocket?.readyState === WS_OPEN) {
255
- try {
256
- activeSocket.send(line);
257
- } catch {
258
- }
259
- }
260
- };
261
- const replay = (ws, afterSeq) => {
262
- for (const entry of eventLog) {
263
- if (entry.seq > afterSeq && ws.readyState === WS_OPEN) {
264
- ws.send(entry.line);
265
- }
266
- }
267
- };
268
- const shouldEmitDebugEvent = (level, subsystem) => {
269
- if (!debugConfig?.enabled) return false;
270
- const threshold = debugConfig.level ?? "debug";
271
- if (DEBUG_LEVEL_WEIGHT[level] > DEBUG_LEVEL_WEIGHT[threshold]) return false;
272
- return subsystemMatches(debugConfig.subsystems, subsystem);
273
- };
274
- const rawStdoutWrite = process.stdout.write.bind(process.stdout);
275
- const rawStderrWrite = process.stderr.write.bind(process.stderr);
276
- const writeErrorToStderr = (input) => {
277
- try {
278
- const formatted = formatBridgeError(input.error);
279
- rawStderrWrite(
280
- `[harness:${bridgeType}:error] ${input.message}: ${formatted.message}
281
- `
282
- );
283
- if (formatted.stack) {
284
- rawStderrWrite(`${formatted.stack}
285
- `);
286
- }
287
- } catch {
288
- }
289
- };
290
- const emitWarning = (input) => {
291
- try {
292
- for (const line of input.message.split("\n")) {
293
- if (line.trim().length > 0) {
294
- rawStderrWrite(`[harness:${bridgeType}:warn] ${line}
295
- `);
296
- }
297
- }
298
- } catch {
299
- }
300
- };
301
- const emitError = (input) => {
302
- writeErrorToStderr({
303
- message: input.message ?? "bridge error",
304
- error: input.error
305
- });
306
- emit({ type: "error", error: serialiseError(input.error) });
307
- };
308
- const installConsoleCapture = () => {
309
- if (consoleCaptureInstalled) return;
310
- consoleCaptureInstalled = true;
311
- const buffers = {
312
- stdout: "",
313
- stderr: ""
314
- };
315
- const patch = (stream, raw) => (chunk, encoding, cb) => {
316
- if (debugConfig?.enabled) {
317
- try {
318
- const enc = typeof encoding === "string" ? encoding : "utf8";
319
- const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(
320
- enc
321
- );
322
- const combined = buffers[stream] + text.replace(/\r\n/g, "\n");
323
- const parts = combined.split("\n");
324
- buffers[stream] = parts.pop() ?? "";
325
- for (const line of parts) {
326
- const trimmed = line.replace(/\s+$/, "");
327
- if (trimmed) {
328
- emit({
329
- type: "sandbox-log",
330
- source: bridgeType,
331
- stream,
332
- line: trimmed
333
- });
334
- }
335
- }
336
- } catch {
337
- }
338
- }
339
- return raw(
340
- chunk,
341
- encoding,
342
- cb
343
- );
344
- };
345
- process.stdout.write = patch(
346
- "stdout",
347
- rawStdoutWrite
348
- );
349
- process.stderr.write = patch(
350
- "stderr",
351
- rawStderrWrite
352
- );
353
- };
354
- const handleInbound = async (msg, ws) => {
355
- switch (msg.type) {
356
- case "start": {
357
- for (; ; ) {
358
- const pendingTurn = activeTurn;
359
- if (pendingTurn == null) break;
360
- turnAbort?.abort();
361
- currentUserMessages?.close(
362
- new Error("A new bridge turn replaced the active turn.")
363
- );
364
- let graceTimer;
365
- const settled = await Promise.race([
366
- pendingTurn.then(() => true),
367
- new Promise((resolve) => {
368
- graceTimer = setTimeout(() => resolve(false), teardownGraceMs);
369
- graceTimer.unref?.();
370
- })
371
- ]);
372
- clearTimeout(graceTimer);
373
- if (!settled) break;
374
- }
375
- let turnFinished;
376
- const thisTurn = new Promise((resolve) => turnFinished = resolve);
377
- activeTurn = thisTurn;
378
- activeSocket = ws;
379
- const firstTurn = isFirstTurn;
380
- isFirstTurn = false;
381
- eventLog = [];
382
- diskBuffer = "";
383
- void writeFile(eventLogPath, "").catch(() => {
384
- });
385
- turnAbort = new AbortController();
386
- currentTurnState = "running";
387
- void writeStartConfig(msg);
388
- void writeBridgeMeta("running");
389
- const startDebug = msg.debug;
390
- debugConfig = {
391
- enabled: startDebug?.enabled ?? envDebugEnabled,
392
- level: startDebug?.level ?? procEnv.HARNESS_DEBUG_LEVEL,
393
- subsystems: startDebug?.subsystems ?? parseEnvList(procEnv.HARNESS_DEBUG_SUBSYSTEMS)
394
- };
395
- if (debugConfig.enabled) {
396
- installConsoleCapture();
397
- }
398
- const userMessages = createBridgeUserMessageQueue({ respond: emit });
399
- const turn = {
400
- emit,
401
- requestToolResult: (requestInput) => {
402
- const request = typeof requestInput === "string" ? { toolCallId: requestInput } : requestInput;
403
- const bufferedIndex = bufferedToolResults.findIndex(
404
- (buffered) => buffered.toolCallId === request.toolCallId || request.matches?.(buffered.result) === true
405
- );
406
- if (bufferedIndex >= 0) {
407
- return Promise.resolve(
408
- bufferedToolResults.splice(bufferedIndex, 1)[0].result
409
- );
410
- }
411
- return new Promise((resolve) => {
412
- pendingToolResults.set(request.toolCallId, {
413
- resolve,
414
- matches: request.matches
415
- });
416
- });
417
- },
418
- requestToolApproval: (approvalId) => new Promise((resolve) => {
419
- pendingToolApprovals.set(approvalId, resolve);
420
- }),
421
- experimental_userMessages: userMessages,
422
- abortSignal: turnAbort.signal,
423
- firstTurn,
424
- bridgeLog: (input) => {
425
- const level = input.level ?? "debug";
426
- if (!shouldEmitDebugEvent(level, input.subsystem)) return;
427
- emit({
428
- type: "debug-event",
429
- level,
430
- subsystem: input.subsystem,
431
- message: input.message,
432
- ...input.attrs ? { attrs: input.attrs } : {},
433
- ...input.error !== void 0 ? { error: formatBridgeError(input.error) } : {}
434
- });
435
- },
436
- emitWarning,
437
- emitError
438
- };
439
- currentUserMessages = userMessages;
440
- try {
441
- await onStart(msg, turn);
442
- } catch (err) {
443
- emitError({ error: err, message: "bridge turn failed" });
444
- } finally {
445
- userMessages.close();
446
- if (currentUserMessages === userMessages) {
447
- currentUserMessages = void 0;
448
- }
449
- if (activeTurn === thisTurn) {
450
- activeTurn = void 0;
451
- currentTurnState = "waiting";
452
- void writeBridgeMeta("waiting");
453
- }
454
- turnFinished();
455
- }
456
- return;
457
- }
458
- case "tool-result": {
459
- const result = {
460
- output: msg.output,
461
- isError: msg.isError,
462
- toolResult: msg.toolResult
463
- };
464
- const exactPending = pendingToolResults.get(msg.toolCallId);
465
- const matchingPending = exactPending == null ? Array.from(pendingToolResults.entries()).find(
466
- ([, pending2]) => pending2.matches?.(result) === true
467
- ) : void 0;
468
- const pending = exactPending ?? matchingPending?.[1];
469
- const pendingId = exactPending != null ? msg.toolCallId : matchingPending?.[0];
470
- if (pending != null && pendingId != null) {
471
- pendingToolResults.delete(pendingId);
472
- pending.resolve(result);
473
- } else {
474
- bufferedToolResults.push({
475
- toolCallId: msg.toolCallId,
476
- result
477
- });
478
- }
479
- return;
480
- }
481
- case "tool-approval-response": {
482
- const resolver = pendingToolApprovals.get(msg.approvalId);
483
- if (resolver) {
484
- pendingToolApprovals.delete(msg.approvalId);
485
- resolver({ approved: msg.approved, reason: msg.reason });
486
- }
487
- return;
488
- }
489
- case "user-message": {
490
- const messageId = msg.messageId ?? randomUUID();
491
- if (currentUserMessages == null) {
492
- sendControl(ws, {
493
- type: "user-message-response",
494
- messageId,
495
- accepted: false,
496
- error: { message: "The bridge has no active turn to steer." }
497
- });
498
- return;
499
- }
500
- if (ws !== activeSocket) {
501
- sendControl(ws, {
502
- type: "user-message-response",
503
- messageId,
504
- accepted: false,
505
- error: {
506
- message: "The connection does not own the active bridge turn."
507
- }
508
- });
509
- return;
510
- }
511
- currentUserMessages.enqueue({
512
- messageId,
513
- text: msg.text
514
- });
515
- return;
516
- }
517
- case "abort":
518
- turnAbort?.abort();
519
- return;
520
- case "resume":
521
- activeSocket = ws;
522
- replay(ws, msg.lastSeenEventId);
523
- return;
524
- case "destroy":
525
- currentTurnState = "done";
526
- void writeBridgeMeta("done");
527
- await onDestroy?.();
528
- drainThenExit(ws, 1e3, "destroy");
529
- return;
530
- case "stop": {
531
- currentTurnState = "done";
532
- void writeBridgeMeta("done");
533
- const data = await onStop?.() ?? {};
534
- sendControl(ws, { type: "bridge-stop", data });
535
- drainThenExit(ws, 1e3, "stop");
536
- }
537
- }
538
- };
539
- void writeBridgeMeta("init");
540
- const wss = new WebSocketServer({ port: bridgeWsPort, host: "0.0.0.0" });
541
- const exit = () => {
542
- if (options.onExit) {
543
- options.onExit();
544
- return;
545
- }
546
- wss.close(() => process.exit(0));
547
- setTimeout(() => process.exit(0), 1e3).unref();
548
- };
549
- const drainThenExit = (ws, code, reason) => {
550
- const start = Date.now();
551
- const tick = () => {
552
- const drained = ws.bufferedAmount === 0 || ws.readyState !== WS_OPEN;
553
- if (drained || Date.now() - start >= 5e3) {
554
- void flushPendingEventsToDisk().finally(() => {
555
- try {
556
- ws.close(code, reason);
557
- } finally {
558
- exit();
559
- }
560
- });
561
- return;
562
- }
563
- setTimeout(tick, 10).unref();
564
- };
565
- tick();
566
- };
567
- wss.on("listening", () => {
568
- const addr = wss.address();
569
- currentBoundPort = typeof addr === "object" && addr ? addr.port : 0;
570
- currentTurnState = "waiting";
571
- void writeBridgeMeta("waiting");
572
- stdout.write(
573
- JSON.stringify({
574
- type: "bridge-ready",
575
- port: currentBoundPort
576
- }) + "\n"
577
- );
578
- options.onListening?.(currentBoundPort);
579
- });
580
- wss.on("connection", (ws, req) => {
581
- const url = new URL(req.url ?? "/", "http://localhost");
582
- if (url.searchParams.get("agent_bridge_token") !== expectedToken) {
583
- ws.close(1008, "unauthorized");
584
- return;
585
- }
586
- sendControl(ws, {
587
- type: "bridge-hello",
588
- state: currentTurnState,
589
- lastSeq: seqCounter,
590
- capabilities: { experimental_userMessageResponses: true }
591
- });
592
- ws.on("message", (raw) => {
593
- let parsed;
594
- try {
595
- const text = typeof raw === "string" ? raw : Buffer.from(raw).toString("utf8");
596
- parsed = JSON.parse(text);
597
- } catch (err) {
598
- sendControl(ws, {
599
- type: "error",
600
- error: `protocol parse error: ${err.message}`
601
- });
602
- return;
603
- }
604
- void handleInbound(parsed, ws);
605
- });
606
- ws.on("close", () => {
607
- if (activeSocket === ws) {
608
- activeSocket = void 0;
609
- }
610
- });
611
- ws.on("error", () => {
612
- });
613
- });
614
- process.on("uncaughtException", (err) => {
615
- emitError({ error: err, message: "uncaught exception" });
616
- });
617
- process.on("unhandledRejection", (err) => {
618
- emitError({ error: err, message: "unhandled rejection" });
619
- });
620
- await new Promise((resolve, reject) => {
621
- if (wss.address() != null) {
622
- resolve();
623
- return;
624
- }
625
- wss.once("listening", resolve);
626
- wss.once("error", reject);
627
- });
628
- return {
629
- port: currentBoundPort,
630
- close: () => new Promise((resolve) => {
631
- wss.close(() => resolve());
632
- })
633
- };
141
+ const { bridgeType, bridgeStateDir, onStart, onStop, onDestroy } = options;
142
+ const teardownGraceMs = options.turnTeardownGraceMs ?? 1e4;
143
+ const expectedToken = options.token ?? env.BRIDGE_CHANNEL_TOKEN ?? "";
144
+ const bridgeWsPort = options.port ?? parseInt(env.BRIDGE_WS_PORT ?? "0", 10);
145
+ const bridgeMetaPath = `${bridgeStateDir}/bridge-meta.json`;
146
+ const startConfigPath = `${bridgeStateDir}/start-config.json`;
147
+ const rerunStartConfigPath = `${bridgeStateDir}/rerun-start-config.json`;
148
+ const eventLogPath = `${bridgeStateDir}/event-log.ndjson`;
149
+ try {
150
+ await mkdir(bridgeStateDir, { recursive: true });
151
+ } catch {}
152
+ let currentBoundPort = 0;
153
+ let currentTurnState = "init";
154
+ let activeSocket;
155
+ let isFirstTurn = true;
156
+ let turnAbort;
157
+ let currentUserMessages;
158
+ /**
159
+ * Settles when the in-flight turn has fully wound down — `onStart`
160
+ * returned or threw AND its completion state was recorded. `undefined`
161
+ * between turns. A new `start` fences on this so turns never overlap.
162
+ */
163
+ let activeTurn;
164
+ let debugConfig;
165
+ let consoleCaptureInstalled = false;
166
+ const envDebugEnabled = ENV_TRUTHY.has((env.HARNESS_DEBUG ?? "").toLowerCase());
167
+ let seqCounter = 0;
168
+ let eventLog = [];
169
+ let diskBuffer = "";
170
+ let flushPromise = null;
171
+ const flushEventsToDisk = async () => {
172
+ while (diskBuffer.length > 0) {
173
+ const buf = diskBuffer;
174
+ diskBuffer = "";
175
+ await appendFile(eventLogPath, buf).catch(() => {});
176
+ }
177
+ };
178
+ const scheduleEventFlush = () => {
179
+ if (flushPromise) return;
180
+ flushPromise = new Promise((resolve) => {
181
+ setImmediate(() => {
182
+ flushEventsToDisk().finally(resolve);
183
+ });
184
+ }).finally(() => {
185
+ flushPromise = null;
186
+ if (diskBuffer.length > 0) scheduleEventFlush();
187
+ });
188
+ };
189
+ const flushPendingEventsToDisk = async () => {
190
+ if (diskBuffer.length > 0 && !flushPromise) scheduleEventFlush();
191
+ let inFlight = flushPromise;
192
+ while (inFlight) {
193
+ await inFlight;
194
+ inFlight = flushPromise;
195
+ }
196
+ };
197
+ if (env.BRIDGE_REPLAY_FROM_DISK === "1" && existsSync(eventLogPath)) try {
198
+ eventLog = readFileSync(eventLogPath, "utf8").split("\n").map((line) => line.trim()).filter(Boolean).map((line) => ({
199
+ seq: JSON.parse(line).seq,
200
+ line
201
+ }));
202
+ seqCounter = eventLog.at(-1)?.seq ?? 0;
203
+ } catch {
204
+ eventLog = [];
205
+ seqCounter = 0;
206
+ }
207
+ const pendingToolResults = /* @__PURE__ */ new Map();
208
+ const bufferedToolResults = [];
209
+ const pendingToolApprovals = /* @__PURE__ */ new Map();
210
+ const writeBridgeMeta = async (state) => {
211
+ try {
212
+ await writeFile(bridgeMetaPath, JSON.stringify({
213
+ type: bridgeType,
214
+ port: currentBoundPort,
215
+ state,
216
+ pid
217
+ }));
218
+ } catch {}
219
+ };
220
+ const writeStartConfig = async (start) => {
221
+ try {
222
+ const serialized = JSON.stringify(start);
223
+ await writeFile(startConfigPath, serialized);
224
+ if (!existsSync(rerunStartConfigPath)) await writeFile(rerunStartConfigPath, serialized);
225
+ } catch {}
226
+ };
227
+ const emit = (event) => {
228
+ const seq = ++seqCounter;
229
+ const line = JSON.stringify({
230
+ ...event,
231
+ seq
232
+ });
233
+ eventLog.push({
234
+ seq,
235
+ line
236
+ });
237
+ diskBuffer += `${line}\n`;
238
+ scheduleEventFlush();
239
+ if (activeSocket?.readyState === WS_OPEN) try {
240
+ activeSocket.send(line);
241
+ } catch {}
242
+ };
243
+ const replay = (ws, afterSeq) => {
244
+ for (const entry of eventLog) if (entry.seq > afterSeq && ws.readyState === WS_OPEN) ws.send(entry.line);
245
+ };
246
+ const shouldEmitDebugEvent = (level, subsystem) => {
247
+ if (!debugConfig?.enabled) return false;
248
+ const threshold = debugConfig.level ?? "debug";
249
+ if (DEBUG_LEVEL_WEIGHT[level] > DEBUG_LEVEL_WEIGHT[threshold]) return false;
250
+ return subsystemMatches(debugConfig.subsystems, subsystem);
251
+ };
252
+ const rawStdoutWrite = process.stdout.write.bind(process.stdout);
253
+ const rawStderrWrite = process.stderr.write.bind(process.stderr);
254
+ const writeErrorToStderr = (input) => {
255
+ try {
256
+ const formatted = formatBridgeError(input.error);
257
+ rawStderrWrite(`[harness:${bridgeType}:error] ${input.message}: ${formatted.message}\n`);
258
+ if (formatted.stack) rawStderrWrite(`${formatted.stack}\n`);
259
+ } catch {}
260
+ };
261
+ const emitWarning = (input) => {
262
+ try {
263
+ for (const line of input.message.split("\n")) if (line.trim().length > 0) rawStderrWrite(`[harness:${bridgeType}:warn] ${line}\n`);
264
+ } catch {}
265
+ };
266
+ const emitError = (input) => {
267
+ writeErrorToStderr({
268
+ message: input.message ?? "bridge error",
269
+ error: input.error
270
+ });
271
+ emit({
272
+ type: "error",
273
+ error: serialiseError(input.error)
274
+ });
275
+ };
276
+ const installConsoleCapture = () => {
277
+ if (consoleCaptureInstalled) return;
278
+ consoleCaptureInstalled = true;
279
+ const buffers = {
280
+ stdout: "",
281
+ stderr: ""
282
+ };
283
+ const patch = (stream, raw) => (chunk, encoding, cb) => {
284
+ if (debugConfig?.enabled) try {
285
+ const enc = typeof encoding === "string" ? encoding : "utf8";
286
+ const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(enc);
287
+ const parts = (buffers[stream] + text.replace(/\r\n/g, "\n")).split("\n");
288
+ buffers[stream] = parts.pop() ?? "";
289
+ for (const line of parts) {
290
+ const trimmed = line.replace(/\s+$/, "");
291
+ if (trimmed) emit({
292
+ type: "sandbox-log",
293
+ source: bridgeType,
294
+ stream,
295
+ line: trimmed
296
+ });
297
+ }
298
+ } catch {}
299
+ return raw(chunk, encoding, cb);
300
+ };
301
+ process.stdout.write = patch("stdout", rawStdoutWrite);
302
+ process.stderr.write = patch("stderr", rawStderrWrite);
303
+ };
304
+ const handleInbound = async (msg, ws) => {
305
+ switch (msg.type) {
306
+ case "start": {
307
+ for (;;) {
308
+ const pendingTurn = activeTurn;
309
+ if (pendingTurn == null) break;
310
+ turnAbort?.abort();
311
+ currentUserMessages?.close(/* @__PURE__ */ new Error("A new bridge turn replaced the active turn."));
312
+ let graceTimer;
313
+ const settled = await Promise.race([pendingTurn.then(() => true), new Promise((resolve) => {
314
+ graceTimer = setTimeout(() => resolve(false), teardownGraceMs);
315
+ graceTimer.unref?.();
316
+ })]);
317
+ clearTimeout(graceTimer);
318
+ if (!settled) break;
319
+ }
320
+ let turnFinished;
321
+ const thisTurn = new Promise((resolve) => turnFinished = resolve);
322
+ activeTurn = thisTurn;
323
+ activeSocket = ws;
324
+ const firstTurn = isFirstTurn;
325
+ isFirstTurn = false;
326
+ eventLog = [];
327
+ diskBuffer = "";
328
+ writeFile(eventLogPath, "").catch(() => {});
329
+ turnAbort = new AbortController();
330
+ currentTurnState = "running";
331
+ writeStartConfig(msg);
332
+ writeBridgeMeta("running");
333
+ const startDebug = msg.debug;
334
+ debugConfig = {
335
+ enabled: startDebug?.enabled ?? envDebugEnabled,
336
+ level: startDebug?.level ?? env.HARNESS_DEBUG_LEVEL,
337
+ subsystems: startDebug?.subsystems ?? parseEnvList(env.HARNESS_DEBUG_SUBSYSTEMS)
338
+ };
339
+ if (debugConfig.enabled) installConsoleCapture();
340
+ const userMessages = createBridgeUserMessageQueue({ respond: emit });
341
+ const turn = {
342
+ emit,
343
+ requestToolResult: (requestInput) => {
344
+ const request = typeof requestInput === "string" ? { toolCallId: requestInput } : requestInput;
345
+ const bufferedIndex = bufferedToolResults.findIndex((buffered) => buffered.toolCallId === request.toolCallId || request.matches?.(buffered.result) === true);
346
+ if (bufferedIndex >= 0) return Promise.resolve(bufferedToolResults.splice(bufferedIndex, 1)[0].result);
347
+ return new Promise((resolve) => {
348
+ pendingToolResults.set(request.toolCallId, {
349
+ resolve,
350
+ matches: request.matches
351
+ });
352
+ });
353
+ },
354
+ requestToolApproval: (approvalId) => new Promise((resolve) => {
355
+ pendingToolApprovals.set(approvalId, resolve);
356
+ }),
357
+ experimental_userMessages: userMessages,
358
+ abortSignal: turnAbort.signal,
359
+ firstTurn,
360
+ bridgeLog: (input) => {
361
+ const level = input.level ?? "debug";
362
+ if (!shouldEmitDebugEvent(level, input.subsystem)) return;
363
+ emit({
364
+ type: "debug-event",
365
+ level,
366
+ subsystem: input.subsystem,
367
+ message: input.message,
368
+ ...input.attrs ? { attrs: input.attrs } : {},
369
+ ...input.error !== void 0 ? { error: formatBridgeError(input.error) } : {}
370
+ });
371
+ },
372
+ emitWarning,
373
+ emitError
374
+ };
375
+ currentUserMessages = userMessages;
376
+ try {
377
+ await onStart(msg, turn);
378
+ } catch (err) {
379
+ emitError({
380
+ error: err,
381
+ message: "bridge turn failed"
382
+ });
383
+ } finally {
384
+ userMessages.close();
385
+ if (currentUserMessages === userMessages) currentUserMessages = void 0;
386
+ if (activeTurn === thisTurn) {
387
+ activeTurn = void 0;
388
+ currentTurnState = "waiting";
389
+ writeBridgeMeta("waiting");
390
+ }
391
+ turnFinished();
392
+ }
393
+ return;
394
+ }
395
+ case "tool-result": {
396
+ const result = {
397
+ output: msg.output,
398
+ isError: msg.isError,
399
+ toolResult: msg.toolResult
400
+ };
401
+ const exactPending = pendingToolResults.get(msg.toolCallId);
402
+ const matchingPending = exactPending == null ? Array.from(pendingToolResults.entries()).find(([, pending]) => pending.matches?.(result) === true) : void 0;
403
+ const pending = exactPending ?? matchingPending?.[1];
404
+ const pendingId = exactPending != null ? msg.toolCallId : matchingPending?.[0];
405
+ if (pending != null && pendingId != null) {
406
+ pendingToolResults.delete(pendingId);
407
+ pending.resolve(result);
408
+ } else bufferedToolResults.push({
409
+ toolCallId: msg.toolCallId,
410
+ result
411
+ });
412
+ return;
413
+ }
414
+ case "tool-approval-response": {
415
+ const resolver = pendingToolApprovals.get(msg.approvalId);
416
+ if (resolver) {
417
+ pendingToolApprovals.delete(msg.approvalId);
418
+ resolver({
419
+ approved: msg.approved,
420
+ reason: msg.reason
421
+ });
422
+ }
423
+ return;
424
+ }
425
+ case "user-message": {
426
+ const messageId = msg.messageId ?? randomUUID();
427
+ if (currentUserMessages == null) {
428
+ sendControl(ws, {
429
+ type: "user-message-response",
430
+ messageId,
431
+ accepted: false,
432
+ error: { message: "The bridge has no active turn to steer." }
433
+ });
434
+ return;
435
+ }
436
+ if (ws !== activeSocket) {
437
+ sendControl(ws, {
438
+ type: "user-message-response",
439
+ messageId,
440
+ accepted: false,
441
+ error: { message: "The connection does not own the active bridge turn." }
442
+ });
443
+ return;
444
+ }
445
+ currentUserMessages.enqueue({
446
+ messageId,
447
+ text: msg.text
448
+ });
449
+ return;
450
+ }
451
+ case "abort":
452
+ turnAbort?.abort();
453
+ return;
454
+ case "resume":
455
+ activeSocket = ws;
456
+ replay(ws, msg.lastSeenEventId);
457
+ return;
458
+ case "destroy":
459
+ currentTurnState = "done";
460
+ writeBridgeMeta("done");
461
+ await onDestroy?.();
462
+ drainThenExit(ws, 1e3, "destroy");
463
+ return;
464
+ case "stop":
465
+ currentTurnState = "done";
466
+ writeBridgeMeta("done");
467
+ sendControl(ws, {
468
+ type: "bridge-stop",
469
+ data: await onStop?.() ?? {}
470
+ });
471
+ drainThenExit(ws, 1e3, "stop");
472
+ }
473
+ };
474
+ writeBridgeMeta("init");
475
+ const wss = new WebSocketServer({
476
+ port: bridgeWsPort,
477
+ host: "0.0.0.0"
478
+ });
479
+ const exit = () => {
480
+ if (options.onExit) {
481
+ options.onExit();
482
+ return;
483
+ }
484
+ wss.close(() => process.exit(0));
485
+ setTimeout(() => process.exit(0), 1e3).unref();
486
+ };
487
+ const drainThenExit = (ws, code, reason) => {
488
+ const start = Date.now();
489
+ const tick = () => {
490
+ if (ws.bufferedAmount === 0 || ws.readyState !== WS_OPEN || Date.now() - start >= 5e3) {
491
+ flushPendingEventsToDisk().finally(() => {
492
+ try {
493
+ ws.close(code, reason);
494
+ } finally {
495
+ exit();
496
+ }
497
+ });
498
+ return;
499
+ }
500
+ setTimeout(tick, 10).unref();
501
+ };
502
+ tick();
503
+ };
504
+ wss.on("listening", () => {
505
+ const addr = wss.address();
506
+ currentBoundPort = typeof addr === "object" && addr ? addr.port : 0;
507
+ currentTurnState = "waiting";
508
+ writeBridgeMeta("waiting");
509
+ stdout.write(JSON.stringify({
510
+ type: "bridge-ready",
511
+ port: currentBoundPort
512
+ }) + "\n");
513
+ options.onListening?.(currentBoundPort);
514
+ });
515
+ wss.on("connection", (ws, req) => {
516
+ if (new URL(req.url ?? "/", "http://localhost").searchParams.get("agent_bridge_token") !== expectedToken) {
517
+ ws.close(1008, "unauthorized");
518
+ return;
519
+ }
520
+ sendControl(ws, {
521
+ type: "bridge-hello",
522
+ state: currentTurnState,
523
+ lastSeq: seqCounter,
524
+ capabilities: { experimental_userMessageResponses: true }
525
+ });
526
+ ws.on("message", (raw) => {
527
+ let parsed;
528
+ try {
529
+ const text = typeof raw === "string" ? raw : Buffer.from(raw).toString("utf8");
530
+ parsed = JSON.parse(text);
531
+ } catch (err) {
532
+ sendControl(ws, {
533
+ type: "error",
534
+ error: `protocol parse error: ${err.message}`
535
+ });
536
+ return;
537
+ }
538
+ handleInbound(parsed, ws);
539
+ });
540
+ ws.on("close", () => {
541
+ if (activeSocket === ws) activeSocket = void 0;
542
+ });
543
+ ws.on("error", () => {});
544
+ });
545
+ process.on("uncaughtException", (err) => {
546
+ emitError({
547
+ error: err,
548
+ message: "uncaught exception"
549
+ });
550
+ });
551
+ process.on("unhandledRejection", (err) => {
552
+ emitError({
553
+ error: err,
554
+ message: "unhandled rejection"
555
+ });
556
+ });
557
+ await new Promise((resolve, reject) => {
558
+ if (wss.address() != null) {
559
+ resolve();
560
+ return;
561
+ }
562
+ wss.once("listening", resolve);
563
+ wss.once("error", reject);
564
+ });
565
+ return {
566
+ port: currentBoundPort,
567
+ close: () => new Promise((resolve) => {
568
+ wss.close(() => resolve());
569
+ })
570
+ };
634
571
  }
635
572
  function sendControl(socket, message) {
636
- if (socket?.readyState === WS_OPEN) {
637
- try {
638
- socket.send(JSON.stringify(message));
639
- } catch {
640
- }
641
- }
573
+ if (socket?.readyState === WS_OPEN) try {
574
+ socket.send(JSON.stringify(message));
575
+ } catch {}
642
576
  }
643
577
  function serialiseError(err) {
644
- if (err instanceof Error) {
645
- return { name: err.name, message: err.message, stack: err.stack };
646
- }
647
- return err;
578
+ if (err instanceof Error) return {
579
+ name: err.name,
580
+ message: err.message,
581
+ stack: err.stack
582
+ };
583
+ return err;
648
584
  }
649
-
650
- // src/bridge/index.ts
651
- import { ChatAnthropic } from "@langchain/anthropic";
652
- import { tool as tool3 } from "@langchain/core/tools";
653
- import { Command as Command5, MemorySaver as MemorySaver2, Overwrite } from "@langchain/langgraph";
654
- import {
655
- MultiServerMCPClient
656
- } from "@langchain/mcp-adapters";
657
- import { createDeepAgent } from "deepagents";
658
-
659
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/chat_models/universal.js
660
- import { BaseChatModel } from "@langchain/core/language_models/chat_models";
661
- import { RunnableBinding, ensureConfig } from "@langchain/core/runnables";
662
- import { AsyncGeneratorWithSetup, IterableReadableStream } from "@langchain/core/utils/stream";
663
- import { ChatModelStream } from "@langchain/core/language_models/stream";
664
- import { DEFAULT_LANGSMITH_GATEWAY, resolveLangSmithGatewayConfig } from "@langchain/core/utils/gateway";
665
- import { getEnvironmentVariable } from "@langchain/core/utils/env";
666
- var MODEL_PROVIDER_CONFIG = {
667
- openai: {
668
- package: "@langchain/openai",
669
- className: "ChatOpenAI"
670
- },
671
- anthropic: {
672
- package: "@langchain/anthropic",
673
- className: "ChatAnthropic"
674
- },
675
- azure_openai: {
676
- package: "@langchain/openai",
677
- className: "AzureChatOpenAI"
678
- },
679
- langsmith: {
680
- package: "@langchain/openai",
681
- className: "ChatOpenAI"
682
- },
683
- cohere: {
684
- package: "@langchain/cohere",
685
- className: "ChatCohere"
686
- },
687
- google: {
688
- package: "@langchain/google",
689
- className: "ChatGoogle"
690
- },
691
- "google-vertexai": {
692
- package: "@langchain/google-vertexai",
693
- className: "ChatVertexAI"
694
- },
695
- "google-vertexai-web": {
696
- package: "@langchain/google-vertexai-web",
697
- className: "ChatVertexAI"
698
- },
699
- "google-genai": {
700
- package: "@langchain/google-genai",
701
- className: "ChatGoogleGenerativeAI"
702
- },
703
- ollama: {
704
- package: "@langchain/ollama",
705
- className: "ChatOllama"
706
- },
707
- mistralai: {
708
- package: "@langchain/mistralai",
709
- className: "ChatMistralAI"
710
- },
711
- mistral: {
712
- package: "@langchain/mistralai",
713
- className: "ChatMistralAI"
714
- },
715
- groq: {
716
- package: "@langchain/groq",
717
- className: "ChatGroq"
718
- },
719
- bedrock: {
720
- package: "@langchain/aws",
721
- className: "ChatBedrockConverse"
722
- },
723
- aws: {
724
- package: "@langchain/aws",
725
- className: "ChatBedrockConverse"
726
- },
727
- deepseek: {
728
- package: "@langchain/deepseek",
729
- className: "ChatDeepSeek"
730
- },
731
- xai: {
732
- package: "@langchain/xai",
733
- className: "ChatXAI"
734
- },
735
- cerebras: {
736
- package: "@langchain/cerebras",
737
- className: "ChatCerebras"
738
- },
739
- fireworks: {
740
- package: "@langchain/fireworks",
741
- className: "ChatFireworks"
742
- },
743
- together: {
744
- package: "@langchain/together-ai",
745
- className: "ChatTogetherAI",
746
- hasCircularDependency: true
747
- },
748
- perplexity: {
749
- package: "@langchain/perplexity",
750
- className: "ChatPerplexity"
751
- }
752
- };
753
- var SUPPORTED_PROVIDERS = Object.keys(MODEL_PROVIDER_CONFIG);
754
-
755
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/tools/headless.js
756
- import { tool } from "@langchain/core/tools";
757
-
758
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/errors.js
759
- import { isGraphBubbleUp } from "@langchain/langgraph";
760
- var StructuredOutputParsingError = class extends Error {
761
- toolName;
762
- errors;
763
- constructor(toolName, errors) {
764
- super(`Failed to parse structured output for tool '${toolName}':${errors.map((e) => `
765
- - ${e}`).join("")}.`);
766
- this.toolName = toolName;
767
- this.errors = errors;
768
- }
769
- };
770
-
771
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/model.js
772
- function isBaseChatModel(model) {
773
- return "invoke" in model && typeof model.invoke === "function" && "_streamResponseChunks" in model;
774
- }
775
-
776
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/responses.js
777
- import { isInteropZodObject, isInteropZodSchema } from "@langchain/core/utils/types";
778
- import { Validator, toJsonSchema } from "@langchain/core/utils/json_schema";
779
- import { isSerializableSchema } from "@langchain/core/utils/standard_schema";
780
- var PROVIDER_STRATEGY_DEFAULT_STRICT = true;
781
- var bindingIdentifier = 0;
782
- var ToolStrategy = class ToolStrategy2 {
783
- schema;
784
- tool;
785
- options;
786
- constructor(schema, tool4, options) {
787
- this.schema = schema;
788
- this.tool = tool4;
789
- this.options = options;
790
- }
791
- get name() {
792
- return this.tool.function.name;
793
- }
794
- static fromSchema(schema, outputOptions) {
795
- function getFunctionName(name) {
796
- return name ?? `extract-${++bindingIdentifier}`;
797
- }
798
- if (isSerializableSchema(schema) || isInteropZodSchema(schema)) {
799
- const asJsonSchema2 = toJsonSchema(schema);
800
- const tool4 = {
801
- type: "function",
802
- function: {
803
- name: getFunctionName(asJsonSchema2.title),
804
- strict: false,
805
- description: asJsonSchema2.description ?? "Tool for extracting structured output from the model's response.",
806
- parameters: asJsonSchema2
807
- }
808
- };
809
- return new ToolStrategy2(asJsonSchema2, tool4, outputOptions);
810
- }
811
- let functionDefinition;
812
- if (typeof schema.name === "string" && typeof schema.parameters === "object" && schema.parameters != null) functionDefinition = schema;
813
- else functionDefinition = {
814
- name: getFunctionName(schema.title),
815
- description: schema.description ?? "",
816
- parameters: schema.schema || schema
817
- };
818
- const asJsonSchema = toJsonSchema(schema);
819
- return new ToolStrategy2(asJsonSchema, {
820
- type: "function",
821
- function: functionDefinition
822
- }, outputOptions);
823
- }
824
- /**
825
- * Parse tool arguments according to the schema.
826
- *
827
- * @throws {StructuredOutputParsingError} if the response is not valid
828
- * @param toolArgs - The arguments from the tool call
829
- * @returns The parsed response according to the schema type
830
- */
831
- parse(toolArgs) {
832
- const result = new Validator(this.schema).validate(toolArgs);
833
- if (!result.valid) throw new StructuredOutputParsingError(this.name, result.errors.map((e) => e.error));
834
- return toolArgs;
835
- }
836
- };
837
- var ProviderStrategy = class ProviderStrategy2 {
838
- _schemaType;
839
- /**
840
- * The schema to use for the provider strategy
841
- */
842
- schema;
843
- /**
844
- * Whether to use strict mode for the provider strategy
845
- */
846
- strict;
847
- constructor(schemaOrOptions, strict) {
848
- if ("schema" in schemaOrOptions && typeof schemaOrOptions.schema === "object" && schemaOrOptions.schema !== null && !("type" in schemaOrOptions)) {
849
- const options = schemaOrOptions;
850
- this.schema = options.schema;
851
- this.strict = options.strict ?? PROVIDER_STRATEGY_DEFAULT_STRICT;
852
- } else {
853
- this.schema = schemaOrOptions;
854
- this.strict = strict ?? PROVIDER_STRATEGY_DEFAULT_STRICT;
855
- }
856
- }
857
- static fromSchema(schema, strict) {
858
- const asJsonSchema = toJsonSchema(schema);
859
- return new ProviderStrategy2(asJsonSchema, strict);
860
- }
861
- /**
862
- * Parse tool arguments according to the schema. If the response is not valid, return undefined.
863
- *
864
- * @param response - The AI message response to parse
865
- * @returns The parsed response according to the schema type
866
- */
867
- parse(response) {
868
- let textContent;
869
- if (typeof response.content === "string") textContent = response.content;
870
- else if (Array.isArray(response.content)) {
871
- for (const block of response.content) if (typeof block === "object" && block !== null && "type" in block && block.type === "text" && !("thought" in block && block.thought === true) && "text" in block && typeof block.text === "string") {
872
- textContent = block.text;
873
- break;
874
- }
875
- }
876
- if (!textContent || textContent === "") return;
877
- try {
878
- const content = JSON.parse(textContent);
879
- if (!new Validator(this.schema).validate(content).valid) return;
880
- return content;
881
- } catch {
882
- }
883
- }
884
- };
885
- function transformResponseFormat(responseFormat, options, model) {
886
- if (!responseFormat) return [];
887
- if (typeof responseFormat === "object" && responseFormat !== null && "__responseFormatUndefined" in responseFormat) return [];
888
- if (Array.isArray(responseFormat)) {
889
- if (responseFormat.every((item) => item instanceof ToolStrategy || item instanceof ProviderStrategy)) return responseFormat;
890
- if (responseFormat.every((item) => isSerializableSchema(item))) return responseFormat.map((item) => ToolStrategy.fromSchema(item, options));
891
- if (responseFormat.every((item) => isInteropZodObject(item))) return responseFormat.map((item) => ToolStrategy.fromSchema(item, options));
892
- if (responseFormat.every((item) => typeof item === "object" && item !== null && !isInteropZodObject(item) && !isSerializableSchema(item))) return responseFormat.map((item) => ToolStrategy.fromSchema(item, options));
893
- throw new Error("Invalid response format: list contains mixed types.\nAll items must be either InteropZodObject, Standard Schema, or plain JSON schema objects.");
894
- }
895
- if (responseFormat instanceof ToolStrategy || responseFormat instanceof ProviderStrategy) return [responseFormat];
896
- const useProviderStrategy = hasSupportForJsonSchemaOutput(model);
897
- if (isSerializableSchema(responseFormat)) return useProviderStrategy ? [ProviderStrategy.fromSchema(responseFormat)] : [ToolStrategy.fromSchema(responseFormat, options)];
898
- if (isInteropZodObject(responseFormat)) return useProviderStrategy ? [ProviderStrategy.fromSchema(responseFormat)] : [ToolStrategy.fromSchema(responseFormat, options)];
899
- if (typeof responseFormat === "object" && responseFormat !== null && "properties" in responseFormat) return useProviderStrategy ? [ProviderStrategy.fromSchema(responseFormat)] : [ToolStrategy.fromSchema(responseFormat, options)];
900
- throw new Error(`Invalid response format: ${String(responseFormat)}`);
901
- }
902
- function toolStrategy(responseFormat, options) {
903
- return transformResponseFormat(responseFormat, options);
904
- }
905
- function hasSupportForJsonSchemaOutput(model) {
906
- if (!model || !isBaseChatModel(model) || !("profile" in model) || typeof model.profile !== "object" || !model.profile) return false;
907
- return "structuredOutput" in model.profile && model.profile.structuredOutput === true;
908
- }
909
-
910
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/utils.js
911
- import { AIMessage, ToolMessage } from "@langchain/core/messages";
912
- import { isLangChainTool } from "@langchain/core/tools";
913
- import { convertToOpenAITool } from "@langchain/core/utils/function_calling";
914
-
915
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/transformers/tool-call.js
916
- import { ToolMessage as ToolMessage2 } from "@langchain/core/messages";
917
- import { StreamChannel } from "@langchain/langgraph";
918
-
919
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/transformers/subagent.js
920
- import { StreamChannel as StreamChannel2, createMessagesTransformer } from "@langchain/langgraph";
921
-
922
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/types.js
923
- var MIDDLEWARE_BRAND = /* @__PURE__ */ Symbol.for("AgentMiddleware");
924
-
925
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware.js
926
- function createMiddleware(config) {
927
- return {
928
- [MIDDLEWARE_BRAND]: true,
929
- name: config.name,
930
- stateSchema: config.stateSchema,
931
- contextSchema: config.contextSchema,
932
- wrapToolCall: config.wrapToolCall,
933
- wrapModelCall: config.wrapModelCall,
934
- beforeAgent: config.beforeAgent,
935
- beforeModel: config.beforeModel,
936
- afterModel: config.afterModel,
937
- afterAgent: config.afterAgent,
938
- tools: config.tools,
939
- streamTransformers: config.streamTransformers
940
- };
941
- }
942
-
943
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/tests/utils.js
944
- import { AIMessage as AIMessage2, HumanMessage } from "@langchain/core/messages";
945
- import { BaseChatModel as BaseChatModel2 } from "@langchain/core/language_models/chat_models";
946
- import { RunnableLambda } from "@langchain/core/runnables";
947
- import "@langchain/core/tools";
948
-
949
- // ../../node_modules/.pnpm/@langchain+langgraph-checkpoint@1.1.5_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@_ff898d037cda6bb5f88aa9c9d1caaf93/node_modules/@langchain/langgraph-checkpoint/dist/id.js
950
- import { v5, v6 } from "@langchain/core/utils/uuid";
951
-
952
- // ../../node_modules/.pnpm/@langchain+langgraph-checkpoint@1.1.5_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@_ff898d037cda6bb5f88aa9c9d1caaf93/node_modules/@langchain/langgraph-checkpoint/dist/serde/types.js
953
- var ERROR = "__error__";
954
- var SCHEDULED = "__scheduled__";
955
- var INTERRUPT = "__interrupt__";
956
- var RESUME = "__resume__";
957
-
958
- // ../../node_modules/.pnpm/@langchain+langgraph-checkpoint@1.1.5_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@_ff898d037cda6bb5f88aa9c9d1caaf93/node_modules/@langchain/langgraph-checkpoint/dist/serde/jsonplus.js
959
- import { load } from "@langchain/core/load";
960
-
961
- // ../../node_modules/.pnpm/@langchain+langgraph-checkpoint@1.1.5_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@_ff898d037cda6bb5f88aa9c9d1caaf93/node_modules/@langchain/langgraph-checkpoint/dist/base.js
962
- var WRITES_IDX_MAP = {
963
- [ERROR]: -1,
964
- [SCHEDULED]: -2,
965
- [INTERRUPT]: -3,
966
- [RESUME]: -4
967
- };
968
-
969
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/tests/utils.js
970
- import "zod/v3";
971
-
972
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/annotation.js
973
- import { MessagesValue, ReducedValue, StateSchema, UntrackedValue } from "@langchain/langgraph";
974
- import { schemaMetaRegistry } from "@langchain/langgraph/zod";
975
- import { getInteropZodObjectShape, isInteropZodObject as isInteropZodObject2, isZodSchemaV4 } from "@langchain/core/utils/types";
976
-
977
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/utils.js
978
- import { AIMessage as AIMessage3, AIMessageChunk, SystemMessage, ToolMessage as ToolMessage3 } from "@langchain/core/messages";
979
- import { Runnable, RunnableBinding as RunnableBinding2, RunnableSequence } from "@langchain/core/runnables";
980
- import { StateSchema as StateSchema2, isCommand } from "@langchain/langgraph";
981
- import { interopParse, isInteropZodSchema as isInteropZodSchema2 } from "@langchain/core/utils/types";
982
-
983
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/nodes/utils.js
984
- import { END, ReducedValue as ReducedValue2, StateSchema as StateSchema3 } from "@langchain/langgraph";
985
- import { getInteropZodObjectShape as getInteropZodObjectShape2, interopSafeParseAsync, interopZodObjectMakeFieldsOptional, interopZodObjectPartial, isInteropZodObject as isInteropZodObject3, isZodSchemaV4 as isZodSchemaV42 } from "@langchain/core/utils/types";
986
- import { z } from "zod/v4";
987
-
988
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/RunnableCallable.js
989
- import { Runnable as Runnable2, mergeConfigs } from "@langchain/core/runnables";
990
- import { AsyncLocalStorageProviderSingleton } from "@langchain/core/singletons";
991
-
992
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/withAgentName.js
993
- import { RunnableLambda as RunnableLambda2, RunnableSequence as RunnableSequence2 } from "@langchain/core/runnables";
994
-
995
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/nodes/AgentNode.js
996
- import { AIMessage as AIMessage4, SystemMessage as SystemMessage2, ToolMessage as ToolMessage4 } from "@langchain/core/messages";
997
- import { raceWithSignal } from "@langchain/core/runnables";
998
- import { Command, isCommand as isCommand2 } from "@langchain/langgraph";
999
- import { getSchemaDescription, interopParse as interopParse2 } from "@langchain/core/utils/types";
1000
-
1001
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/nodes/ToolNode.js
1002
- import { AIMessage as AIMessage5, BaseMessage, ToolMessage as ToolMessage5 } from "@langchain/core/messages";
1003
- import { ToolInputParsingException } from "@langchain/core/tools";
1004
- import { Command as Command2, Send, isCommand as isCommand3, isGraphInterrupt } from "@langchain/langgraph";
1005
-
1006
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/nodes/middleware.js
1007
- import { getInteropZodObjectShape as getInteropZodObjectShape3, interopParse as interopParse3, isInteropZodObject as isInteropZodObject4 } from "@langchain/core/utils/types";
1008
-
1009
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/ReactAgent.js
1010
- import { AIMessage as AIMessage6, ToolMessage as ToolMessage6 } from "@langchain/core/messages";
1011
- import { mergeConfigs as mergeConfigs2 } from "@langchain/core/runnables";
1012
- import { Command as Command3, END as END2, START, Send as Send2, StateGraph } from "@langchain/langgraph";
1013
-
1014
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/hitl.js
1015
- import { AIMessage as AIMessage7, ToolMessage as ToolMessage7 } from "@langchain/core/messages";
1016
- import { interrupt } from "@langchain/langgraph";
1017
- import { interopParse as interopParse4 } from "@langchain/core/utils/types";
1018
- import { z as z2 } from "zod/v3";
1019
- var WhenFunctionSchema = z2.function().args(z2.custom()).returns(z2.union([z2.boolean(), z2.promise(z2.boolean())]));
1020
- var DescriptionFunctionSchema = z2.function().args(z2.custom(), z2.custom(), z2.custom()).returns(z2.union([z2.string(), z2.promise(z2.string())]));
1021
- var ALLOWED_DECISIONS = [
1022
- "approve",
1023
- "edit",
1024
- "reject"
1025
- ];
1026
- var DecisionType = z2.enum(ALLOWED_DECISIONS);
1027
- var InterruptOnConfigSchema = z2.object({
1028
- /**
1029
- * The decisions that are allowed for this action.
1030
- */
1031
- allowedDecisions: z2.array(DecisionType),
1032
- /**
1033
- * The description attached to the request for human input.
1034
- * Can be either:
1035
- * - A static string describing the approval request
1036
- * - A callable that dynamically generates the description based on agent state,
1037
- * runtime, and tool call information
1038
- *
1039
- * @example
1040
- * Static string description
1041
- * ```typescript
1042
- * import type { InterruptOnConfig } from "langchain";
1043
- *
1044
- * const config: InterruptOnConfig = {
1045
- * allowedDecisions: ["approve", "reject"],
1046
- * description: "Please review this tool execution"
1047
- * };
1048
- * ```
1049
- *
1050
- * @example
1051
- * Dynamic callable description
1052
- * ```typescript
1053
- * import type {
1054
- * AgentBuiltInState,
1055
- * Runtime,
1056
- * DescriptionFactory,
1057
- * ToolCall,
1058
- * InterruptOnConfig
1059
- * } from "langchain";
1060
- *
1061
- * const formatToolDescription: DescriptionFactory = (
1062
- * toolCall: ToolCall,
1063
- * state: AgentBuiltInState,
1064
- * runtime: Runtime<unknown>
1065
- * ) => {
1066
- * return `Tool: ${toolCall.name}\nArguments:\n${JSON.stringify(toolCall.args, null, 2)}`;
1067
- * };
1068
- *
1069
- * const config: InterruptOnConfig = {
1070
- * allowedDecisions: ["approve", "edit"],
1071
- * description: formatToolDescription
1072
- * };
1073
- * ```
1074
- */
1075
- description: z2.union([z2.string(), DescriptionFunctionSchema]).optional(),
1076
- /**
1077
- * JSON schema for the arguments associated with the action, if edits are allowed.
1078
- */
1079
- argsSchema: z2.record(z2.any()).optional(),
1080
- /**
1081
- * Optional predicate controlling whether to interrupt for a given tool call.
1082
- *
1083
- * Receives a {@link ToolCallRequest} and returns `true` to interrupt or
1084
- * `false` to auto-approve the tool call.
1085
- *
1086
- * The request is constructed with `tool` set to `undefined` and `runtime` set
1087
- * to the node-level {@link Runtime}, so `request.tool` is not available.
1088
- *
1089
- * @example
1090
- * ```typescript
1091
- * import type { InterruptOnConfig } from "langchain";
1092
- *
1093
- * // Only interrupt delete_file calls targeting /etc
1094
- * const config: InterruptOnConfig = {
1095
- * allowedDecisions: ["approve", "reject"],
1096
- * when: (request) =>
1097
- * String(request.toolCall.args.path ?? "").startsWith("/etc"),
1098
- * };
1099
- * ```
1100
- */
1101
- when: WhenFunctionSchema.optional()
1102
- });
1103
- var contextSchema = z2.object({
1104
- /**
1105
- * Mapping of tool name to allowed reviewer responses.
1106
- * If a tool doesn't have an entry, it's auto-approved by default.
1107
- *
1108
- * - `true` -> pause for approval and allow approve/edit/reject decisions
1109
- * - `false` -> auto-approve (no human review)
1110
- * - `InterruptOnConfig` -> explicitly specify which decisions are allowed for this tool
1111
- */
1112
- interruptOn: z2.record(z2.union([z2.boolean(), InterruptOnConfigSchema])).optional(),
1113
- /**
1114
- * Prefix used when constructing human-facing approval messages.
1115
- * Provides context about the tool call being reviewed; does not change the underlying action.
1116
- *
1117
- * Note: This prefix is only applied for tools that do not provide a custom
1118
- * `description` via their {@link InterruptOnConfig}. If a tool specifies a custom
1119
- * `description`, that per-tool text is used and this prefix is ignored.
1120
- */
1121
- descriptionPrefix: z2.string().default("Tool execution requires approval")
1122
- });
1123
-
1124
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/constants.js
1125
- import { z as z3 } from "zod/v3";
1126
- import { getRetryable } from "@langchain/core/errors";
1127
- var RetrySchema = z3.object({
1128
- /**
1129
- * Maximum number of retry attempts after the initial call.
1130
- * Default is 2 retries (3 total attempts). Must be >= 0.
1131
- */
1132
- maxRetries: z3.number().min(0).default(2),
1133
- /**
1134
- * Either an array of error constructors to retry on, or a function
1135
- * that takes an error and returns `true` if it should be retried.
1136
- * Default is to retry unless the error is marked non-retryable.
1137
- */
1138
- retryOn: z3.union([z3.function().args(z3.instanceof(Error)).returns(z3.boolean()), z3.array(z3.custom())]).default(() => (error) => getRetryable(error) ?? true),
1139
- /**
1140
- * Multiplier for exponential backoff. Each retry waits
1141
- * `initialDelayMs * (backoffFactor ** retryNumber)` milliseconds.
1142
- * Set to 0.0 for constant delay. Default is 2.0.
1143
- */
1144
- backoffFactor: z3.number().min(0).default(2),
1145
- /**
1146
- * Initial delay in milliseconds before first retry. Default is 1000 (1 second).
1147
- */
1148
- initialDelayMs: z3.number().min(0).default(1e3),
1149
- /**
1150
- * Maximum delay in milliseconds between retries. Caps exponential
1151
- * backoff growth. Default is 60000 (60 seconds).
1152
- */
1153
- maxDelayMs: z3.number().min(0).default(6e4),
1154
- /**
1155
- * Whether to add random jitter (±25%) to delay to avoid thundering herd.
1156
- * Default is `true`.
1157
- */
1158
- jitter: z3.boolean().default(true)
1159
- });
1160
-
1161
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/summarization.js
1162
- import { AIMessage as AIMessage8, HumanMessage as HumanMessage2, RemoveMessage, SystemMessage as SystemMessage3, ToolMessage as ToolMessage8, getBufferString, trimMessages } from "@langchain/core/messages";
1163
- import { mergeConfigs as mergeConfigs3, pickRunnableConfigKeys } from "@langchain/core/runnables";
1164
- import { REMOVE_ALL_MESSAGES } from "@langchain/langgraph";
1165
- import { interopSafeParse } from "@langchain/core/utils/types";
1166
- import { z as z4 } from "zod/v4";
1167
- import { z as z$1 } from "zod/v3";
1168
- import { v4 } from "@langchain/core/utils/uuid";
1169
- import { getModelContextSize } from "@langchain/core/language_models/base";
1170
- var DEFAULT_SUMMARY_PROMPT = `<role>
1171
- Context Extraction Assistant
1172
- </role>
1173
-
1174
- <primary_objective>
1175
- Your sole objective in this task is to extract the highest quality/most relevant context from the conversation history below.
1176
- </primary_objective>
1177
-
1178
- <objective_information>
1179
- You're nearing the total number of input tokens you can accept, so you must extract the highest quality/most relevant pieces of information from your conversation history.
1180
- This context will then overwrite the conversation history presented below. Because of this, ensure the context you extract is only the most important information to your overall goal.
1181
- </objective_information>
1182
-
1183
- <instructions>
1184
- The conversation history below will be replaced with the context you extract in this step. Because of this, you must do your very best to extract and record all of the most important context from the conversation history.
1185
- You want to ensure that you don't repeat any actions you've already completed, so the context you extract from the conversation history should be focused on the most important information to your overall goal.
1186
- </instructions>
1187
-
1188
- The user will message you with the full message history you'll be extracting context from, to then replace. Carefully read over it all, and think deeply about what information is most important to your overall goal that should be saved:
1189
-
1190
- With all of this in mind, please carefully read over the entire conversation history, and extract the most important and relevant context to replace it so that you can free up space in the conversation history.
1191
- Respond ONLY with the extracted context. Do not include any additional information, or text before or after the extracted context.
1192
-
1193
- <messages>
1194
- Messages to summarize:
1195
- {messages}
1196
- </messages>`;
1197
- var tokenCounterSchema = z$1.function().args(z$1.array(z$1.custom())).returns(z$1.union([z$1.number(), z$1.promise(z$1.number())]));
1198
- var contextSizeSchema = z$1.object({
1199
- /**
1200
- * Fraction of the model's context size to use as the trigger
1201
- */
1202
- fraction: z$1.number().gt(0, "Fraction must be greater than 0").max(1, "Fraction must be less than or equal to 1").optional(),
1203
- /**
1204
- * Number of tokens to use as the trigger
1205
- */
1206
- tokens: z$1.number().positive("Tokens must be greater than 0").optional(),
1207
- /**
1208
- * Number of messages to use as the trigger
1209
- */
1210
- messages: z$1.number().int("Messages must be an integer").positive("Messages must be greater than 0").optional()
1211
- }).refine((data) => {
1212
- return [
1213
- data.fraction,
1214
- data.tokens,
1215
- data.messages
1216
- ].filter((v) => v !== void 0).length >= 1;
1217
- }, { message: "At least one of fraction, tokens, or messages must be provided" });
1218
- var keepSchema = z$1.object({
1219
- /**
1220
- * Fraction of the model's context size to keep
1221
- */
1222
- fraction: z$1.number().min(0, "Messages must be non-negative").max(1, "Fraction must be less than or equal to 1").optional(),
1223
- /**
1224
- * Number of tokens to keep
1225
- */
1226
- tokens: z$1.number().min(0, "Tokens must be greater than or equal to 0").optional(),
1227
- messages: z$1.number().int("Messages must be an integer").min(0, "Messages must be non-negative").optional()
1228
- }).refine((data) => {
1229
- return [
1230
- data.fraction,
1231
- data.tokens,
1232
- data.messages
1233
- ].filter((v) => v !== void 0).length === 1;
1234
- }, { message: "Exactly one of fraction, tokens, or messages must be provided" });
1235
- var contextSchema2 = z$1.object({
1236
- /**
1237
- * Model to use for summarization
1238
- */
1239
- model: z$1.custom(),
1240
- /**
1241
- * Trigger conditions for summarization.
1242
- * Can be a single condition object (all properties must be met) or an array of conditions (any condition must be met).
1243
- *
1244
- * @example
1245
- * ```ts
1246
- * // Single condition: trigger if tokens >= 5000 AND messages >= 3
1247
- * trigger: { tokens: 5000, messages: 3 }
1248
- *
1249
- * // Multiple conditions: trigger if (tokens >= 5000 AND messages >= 3) OR (tokens >= 3000 AND messages >= 6)
1250
- * trigger: [
1251
- * { tokens: 5000, messages: 3 },
1252
- * { tokens: 3000, messages: 6 }
1253
- * ]
1254
- * ```
1255
- */
1256
- trigger: z$1.union([contextSizeSchema, z$1.array(contextSizeSchema)]).optional(),
1257
- /**
1258
- * Keep conditions for summarization
1259
- */
1260
- keep: keepSchema.optional(),
1261
- /**
1262
- * Token counter function to use for summarization
1263
- */
1264
- tokenCounter: tokenCounterSchema.optional(),
1265
- /**
1266
- * Summary prompt to use for summarization
1267
- * @default {@link DEFAULT_SUMMARY_PROMPT}
1268
- */
1269
- summaryPrompt: z$1.string().default(DEFAULT_SUMMARY_PROMPT),
1270
- /**
1271
- * Number of tokens to trim to before summarizing
1272
- */
1273
- trimTokensToSummarize: z$1.number().optional(),
1274
- /**
1275
- * Prefix to add to the summary
1276
- */
1277
- summaryPrefix: z$1.string().optional(),
1278
- /**
1279
- * @deprecated Use `trigger: { tokens: value }` instead.
1280
- */
1281
- maxTokensBeforeSummary: z$1.number().optional(),
1282
- /**
1283
- * @deprecated Use `keep: { messages: value }` instead.
1284
- */
1285
- messagesToKeep: z$1.number().optional()
1286
- });
1287
-
1288
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/dynamicSystemPrompt.js
1289
- import { SystemMessage as SystemMessage4 } from "@langchain/core/messages";
1290
-
1291
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/llmToolSelector.js
1292
- import { HumanMessage as HumanMessage3 } from "@langchain/core/messages";
1293
- import { mergeConfigs as mergeConfigs4, pickRunnableConfigKeys as pickRunnableConfigKeys2 } from "@langchain/core/runnables";
1294
- import { z as z5 } from "zod/v3";
1295
- import { BaseLanguageModel } from "@langchain/core/language_models/base";
1296
- var LLMToolSelectorOptionsSchema = z5.object({
1297
- /**
1298
- * The language model to use for tool selection (default: the provided model from the agent options).
1299
- */
1300
- model: z5.string().or(z5.instanceof(BaseLanguageModel)).optional(),
1301
- /**
1302
- * System prompt for the tool selection model.
1303
- */
1304
- systemPrompt: z5.string().optional(),
1305
- /**
1306
- * Maximum number of tools to select. If the model selects more,
1307
- * only the first maxTools will be used. No limit if not specified.
1308
- */
1309
- maxTools: z5.number().optional(),
1310
- /**
1311
- * Tool names to always include regardless of selection.
1312
- * These do not count against the maxTools limit.
1313
- */
1314
- alwaysInclude: z5.array(z5.string()).optional()
1315
- });
1316
-
1317
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/pii.js
1318
- import { AIMessage as AIMessage9, HumanMessage as HumanMessage4, ToolMessage as ToolMessage9 } from "@langchain/core/messages";
1319
- import { z as z6 } from "zod/v3";
1320
- import { sha256 } from "@langchain/core/utils/hash";
1321
- var contextSchema3 = z6.object({
1322
- /**
1323
- * Whether to check user messages before model call
1324
- */
1325
- applyToInput: z6.boolean().optional(),
1326
- /**
1327
- * Whether to check AI messages after model call
1328
- */
1329
- applyToOutput: z6.boolean().optional(),
1330
- /**
1331
- * Whether to check tool result messages after tool execution
1332
- */
1333
- applyToToolResults: z6.boolean().optional()
1334
- });
1335
-
1336
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/piiRedaction.js
1337
- import { AIMessage as AIMessage10, HumanMessage as HumanMessage5, RemoveMessage as RemoveMessage2, SystemMessage as SystemMessage5, ToolMessage as ToolMessage10 } from "@langchain/core/messages";
1338
- import { z as z7 } from "zod/v3";
1339
- var contextSchema4 = z7.object({
1340
- /**
1341
- * A record of PII detection rules to apply
1342
- * @default DEFAULT_PII_RULES (with enabled rules only)
1343
- */
1344
- rules: z7.record(z7.string(), z7.instanceof(RegExp).describe("Regular expression pattern to match PII")).optional()
1345
- });
1346
-
1347
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/contextEditing.js
1348
- import { AIMessage as AIMessage11, SystemMessage as SystemMessage6, ToolMessage as ToolMessage11 } from "@langchain/core/messages";
1349
-
1350
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/toolCallLimit.js
1351
- import { AIMessage as AIMessage12, ToolMessage as ToolMessage12 } from "@langchain/core/messages";
1352
- import { z as z8 } from "zod/v4";
1353
- import { z as z$12 } from "zod/v3";
1354
- var VALID_EXIT_BEHAVIORS = [
1355
- "continue",
1356
- "error",
1357
- "end"
1358
- ];
1359
- var DEFAULT_EXIT_BEHAVIOR = "continue";
1360
- var exitBehaviorSchema = z$12.enum(VALID_EXIT_BEHAVIORS).default(DEFAULT_EXIT_BEHAVIOR);
1361
- z$12.object({
1362
- /**
1363
- * Name of the specific tool to limit. If undefined, limits apply to all tools.
1364
- */
1365
- toolName: z$12.string().optional(),
1366
- /**
1367
- * Maximum number of tool calls allowed per thread.
1368
- * undefined means no limit.
1369
- */
1370
- threadLimit: z$12.number().optional(),
1371
- /**
1372
- * Maximum number of tool calls allowed per run.
1373
- * undefined means no limit.
1374
- */
1375
- runLimit: z$12.number().optional(),
1376
- /**
1377
- * What to do when limits are exceeded.
1378
- * - "continue": Block exceeded tools with error messages, let other tools continue (default)
1379
- * - "error": Raise a ToolCallLimitExceededError exception
1380
- * - "end": Stop execution immediately, injecting a ToolMessage and an AI message
1381
- * for the single tool call that exceeded the limit. Raises NotImplementedError
1382
- * if there are multiple tool calls.
1383
- *
1384
- * @default "continue"
1385
- */
1386
- exitBehavior: exitBehaviorSchema
1387
- });
1388
- var stateSchema = z$12.object({
1389
- threadToolCallCount: z$12.record(z$12.string(), z$12.number()).default({}),
1390
- runToolCallCount: z$12.record(z$12.string(), z$12.number()).default({})
1391
- });
1392
-
1393
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/todoListMiddleware.js
1394
- import { AIMessage as AIMessage13, ToolMessage as ToolMessage13 } from "@langchain/core/messages";
1395
- import { tool as tool2 } from "@langchain/core/tools";
1396
- import { Command as Command4 } from "@langchain/langgraph";
1397
- import { z as z9 } from "zod/v3";
1398
- var TodoStatus = z9.enum([
1399
- "pending",
1400
- "in_progress",
1401
- "completed"
1402
- ]).describe("Status of the todo");
1403
- var TodoSchema = z9.object({
1404
- content: z9.string().describe("Content of the todo item"),
1405
- status: TodoStatus
1406
- });
1407
- var stateSchema2 = z9.object({ todos: z9.array(TodoSchema).default([]) });
1408
-
1409
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/modelCallLimit.js
1410
- import { AIMessage as AIMessage14 } from "@langchain/core/messages";
1411
- import { z as z10 } from "zod/v3";
1412
- var contextSchema5 = z10.object({
1413
- /**
1414
- * The maximum number of model calls allowed per thread.
1415
- */
1416
- threadLimit: z10.number().optional(),
1417
- /**
1418
- * The maximum number of model calls allowed per run.
1419
- */
1420
- runLimit: z10.number().optional(),
1421
- /**
1422
- * The behavior to take when the limit is exceeded.
1423
- * - "error" will throw an error and stop the agent.
1424
- * - "end" will end the agent.
1425
- * @default "end"
1426
- */
1427
- exitBehavior: z10.enum(["error", "end"]).optional()
1428
- });
1429
- var stateSchema3 = z10.object({
1430
- threadModelCallCount: z10.number().default(0),
1431
- runModelCallCount: z10.number().default(0)
1432
- });
1433
-
1434
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/error.js
1435
- import { z as z11 } from "zod/v4";
1436
-
1437
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/modelRetry.js
1438
- import { AIMessage as AIMessage15 } from "@langchain/core/messages";
1439
- import { z as z12 } from "zod/v3";
1440
- var ModelRetryMiddlewareOptionsSchema = z12.object({
1441
- /**
1442
- * Behavior when all retries are exhausted. Options:
1443
- * - `"continue"` (default): Return an AIMessage with error details, allowing
1444
- * the agent to potentially handle the failure gracefully.
1445
- * - `"error"`: Re-raise the exception, stopping agent execution.
1446
- * - Custom function: Function that takes the exception and returns a string
1447
- * for the AIMessage content, allowing custom error formatting.
1448
- */
1449
- onFailure: z12.union([
1450
- z12.literal("error"),
1451
- z12.literal("continue"),
1452
- z12.function().args(z12.instanceof(Error)).returns(z12.string())
1453
- ]).default("continue")
1454
- }).merge(RetrySchema);
1455
-
1456
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/toolRetry.js
1457
- import { ToolMessage as ToolMessage14 } from "@langchain/core/messages";
1458
- import { z as z13 } from "zod/v3";
1459
- var ToolRetryMiddlewareOptionsSchema = z13.object({
1460
- /**
1461
- * Optional list of tools or tool names to apply retry logic to.
1462
- * Can be a list of `BaseTool` instances or tool name strings.
1463
- * If `undefined`, applies to all tools. Default is `undefined`.
1464
- */
1465
- tools: z13.array(z13.union([
1466
- z13.custom(),
1467
- z13.custom(),
1468
- z13.string()
1469
- ])).optional(),
1470
- /**
1471
- * Behavior when all retries are exhausted. Options:
1472
- * - `"continue"` (default): Return an AIMessage with error details, allowing
1473
- * the agent to potentially handle the failure gracefully.
1474
- * - `"error"`: Re-raise the exception, stopping agent execution.
1475
- * - Custom function: Function that takes the exception and returns a string
1476
- * for the AIMessage content, allowing custom error formatting.
1477
- *
1478
- * Deprecated values:
1479
- * - `"raise"`: use `"error"` instead.
1480
- * - `"return_message"`: use `"continue"` instead.
1481
- */
1482
- onFailure: z13.union([
1483
- z13.literal("error"),
1484
- z13.literal("continue"),
1485
- z13.literal("raise"),
1486
- z13.literal("return_message"),
1487
- z13.function().args(z13.instanceof(Error)).returns(z13.string())
1488
- ]).default("continue")
1489
- }).merge(RetrySchema);
1490
-
1491
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/toolError.js
1492
- import { ToolMessage as ToolMessage15 } from "@langchain/core/messages";
1493
- import { isGraphBubbleUp as isGraphBubbleUp2 } from "@langchain/langgraph";
1494
-
1495
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/toolEmulator.js
1496
- import { HumanMessage as HumanMessage6, ToolMessage as ToolMessage16 } from "@langchain/core/messages";
1497
- import { mergeConfigs as mergeConfigs5, pickRunnableConfigKeys as pickRunnableConfigKeys3 } from "@langchain/core/runnables";
1498
-
1499
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/providerToolSearch.js
1500
- import { isLangChainTool as isLangChainTool2 } from "@langchain/core/utils/function_calling";
1501
-
1502
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/provider/openai/moderation.js
1503
- import { AIMessage as AIMessage16, HumanMessage as HumanMessage7, ToolMessage as ToolMessage17 } from "@langchain/core/messages";
1504
-
1505
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/provider/anthropic/promptCaching.js
1506
- import { z as z14 } from "zod/v3";
1507
- var contextSchema6 = z14.object({
1508
- /**
1509
- * Whether to enable prompt caching.
1510
- * @default true
1511
- */
1512
- enableCaching: z14.boolean().optional(),
1513
- /**
1514
- * The time-to-live for the cached prompt.
1515
- * @default "5m"
1516
- */
1517
- ttl: z14.enum(["5m", "1h"]).optional(),
1518
- /**
1519
- * The minimum number of messages required before caching is applied.
1520
- * @default 3
1521
- */
1522
- minMessagesToCache: z14.number().optional(),
1523
- /**
1524
- * The behavior to take when an unsupported model is used.
1525
- * - "ignore" will ignore the unsupported model and continue without caching.
1526
- * - "warn" will warn the user and continue without caching.
1527
- * - "raise" will raise an error and stop the agent.
1528
- * @default "warn"
1529
- */
1530
- unsupportedModelBehavior: z14.enum([
1531
- "ignore",
1532
- "warn",
1533
- "raise"
1534
- ]).optional()
1535
- });
1536
-
1537
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/agents/middleware/provider/aws/promptCaching.js
1538
- import { z as z15 } from "zod/v3";
1539
- var contextSchema7 = z15.object({
1540
- /**
1541
- * Whether to enable prompt caching.
1542
- * @default true
1543
- */
1544
- enableCaching: z15.boolean().optional(),
1545
- /**
1546
- * The time-to-live for the cached prompt.
1547
- * @default "5m"
1548
- */
1549
- ttl: z15.enum(["5m", "1h"]).optional(),
1550
- /**
1551
- * The minimum number of messages required before caching is applied.
1552
- * @default 1
1553
- */
1554
- minMessagesToCache: z15.number().optional(),
1555
- /**
1556
- * The behavior to take when an unsupported model is used.
1557
- * - "ignore" will ignore the unsupported model and continue without caching.
1558
- * - "warn" will warn the user and continue without caching.
1559
- * - "raise" will raise an error and stop the agent.
1560
- * @default "warn"
1561
- */
1562
- unsupportedModelBehavior: z15.enum([
1563
- "ignore",
1564
- "warn",
1565
- "raise"
1566
- ]).optional()
1567
- });
1568
-
1569
- // ../../node_modules/.pnpm/langchain@1.5.11_@langchain+core@1.2.11_@opentelemetry+api@1.9.1_@opentelemetry+exporte_f5289af23b1dceae16b2f90e7460a344/node_modules/langchain/dist/index.js
1570
- import { AIMessage as AIMessage17, AIMessageChunk as AIMessageChunk2, BaseMessage as BaseMessage2, BaseMessageChunk, HumanMessage as HumanMessage8, HumanMessageChunk, SystemMessage as SystemMessage7, SystemMessageChunk, ToolMessage as ToolMessage18, ToolMessageChunk, filterMessages, trimMessages as trimMessages2 } from "@langchain/core/messages";
1571
- import { DynamicStructuredTool, DynamicTool, StructuredTool, Tool } from "@langchain/core/tools";
1572
- import { context } from "@langchain/core/utils/context";
1573
- import { InMemoryStore as InMemoryStore2 } from "@langchain/core/stores";
1574
- import { Document } from "@langchain/core/documents";
1575
- import { fakeModel, langchainMatchers } from "@langchain/core/testing";
1576
-
1577
- // src/bridge/approvals.ts
1578
- var NATIVE_TOOL_KIND = {
1579
- read_file: "readonly",
1580
- write_file: "edit",
1581
- edit_file: "edit",
1582
- execute: "bash",
1583
- grep: "readonly",
1584
- glob: "readonly",
1585
- ls: "readonly",
1586
- task: "edit",
1587
- write_todos: "edit"
585
+ //#endregion
586
+ //#region src/bridge/approvals.ts
587
+ const NATIVE_TOOL_KIND = {
588
+ read_file: "readonly",
589
+ write_file: "edit",
590
+ edit_file: "edit",
591
+ execute: "bash",
592
+ grep: "readonly",
593
+ glob: "readonly",
594
+ ls: "readonly",
595
+ task: "edit",
596
+ write_todos: "edit"
1588
597
  };
1589
- var NATIVE_TO_COMMON = {
1590
- read_file: "read",
1591
- write_file: "write",
1592
- edit_file: "edit",
1593
- execute: "bash"
598
+ const NATIVE_TO_COMMON$1 = {
599
+ read_file: "read",
600
+ write_file: "write",
601
+ edit_file: "edit",
602
+ execute: "bash"
1594
603
  };
1595
- function toCommonName(nativeName) {
1596
- return NATIVE_TO_COMMON[nativeName] ?? nativeName;
604
+ function toCommonName$1(nativeName) {
605
+ return NATIVE_TO_COMMON$1[nativeName] ?? nativeName;
1597
606
  }
1598
607
  function isBuiltinToolIncluded(input) {
1599
- if (input.toolFiltering == null) return true;
1600
- const toolName = toCommonName(input.nativeName);
1601
- return input.toolFiltering.mode === "allow" ? input.toolFiltering.toolNames.includes(toolName) : !input.toolFiltering.toolNames.includes(toolName);
608
+ if (input.toolFiltering == null) return true;
609
+ const toolName = toCommonName$1(input.nativeName);
610
+ return input.toolFiltering.mode === "allow" ? input.toolFiltering.toolNames.includes(toolName) : !input.toolFiltering.toolNames.includes(toolName);
1602
611
  }
1603
612
  function builtinToolRequiresApproval(kind, permissionMode) {
1604
- if (permissionMode === "allow-all") return false;
1605
- if (permissionMode === "allow-edits") return kind === "bash";
1606
- return kind === "edit" || kind === "bash";
613
+ if (permissionMode === "allow-all") return false;
614
+ if (permissionMode === "allow-edits") return kind === "bash";
615
+ return kind === "edit" || kind === "bash";
1607
616
  }
1608
617
  function buildInterruptOn(permissionMode, builtinToolFiltering) {
1609
- const config = {};
1610
- for (const [nativeName, kind] of Object.entries(NATIVE_TOOL_KIND)) {
1611
- if (permissionMode != null && isBuiltinToolIncluded({
1612
- nativeName,
1613
- toolFiltering: builtinToolFiltering
1614
- }) && builtinToolRequiresApproval(kind, permissionMode)) {
1615
- config[nativeName] = { allowedDecisions: ["approve", "reject"] };
1616
- }
1617
- }
1618
- return Object.keys(config).length > 0 ? config : void 0;
618
+ const config = {};
619
+ for (const [nativeName, kind] of Object.entries(NATIVE_TOOL_KIND)) if (permissionMode != null && isBuiltinToolIncluded({
620
+ nativeName,
621
+ toolFiltering: builtinToolFiltering
622
+ }) && builtinToolRequiresApproval(kind, permissionMode)) config[nativeName] = { allowedDecisions: ["approve", "reject"] };
623
+ return Object.keys(config).length > 0 ? config : void 0;
1619
624
  }
1620
625
  function collectActionRequests(interrupts) {
1621
- const out = [];
1622
- for (const interrupt2 of interrupts) {
1623
- const value = interrupt2.value;
1624
- for (const action of value?.actionRequests ?? []) {
1625
- out.push({ name: action.name, args: action.args ?? {} });
1626
- }
1627
- }
1628
- return out;
626
+ const out = [];
627
+ for (const interrupt of interrupts) {
628
+ const value = interrupt.value;
629
+ for (const action of value?.actionRequests ?? []) out.push({
630
+ name: action.name,
631
+ args: action.args ?? {}
632
+ });
633
+ }
634
+ return out;
1629
635
  }
1630
-
1631
- // src/bridge/create-emit-stream-event.ts
1632
- import { randomUUID as randomUUID2 } from "crypto";
636
+ //#endregion
637
+ //#region src/bridge/create-emit-stream-event.ts
1633
638
  function createDeepAgentsStreamEventState() {
1634
- return {
1635
- streamStarted: false,
1636
- textBlockId: void 0,
1637
- reasoningBlockId: void 0,
1638
- inputTokens: 0,
1639
- outputTokens: 0,
1640
- streamedStepInput: 0,
1641
- streamedStepOutput: 0,
1642
- pendingStep: void 0,
1643
- approvedToolQueue: /* @__PURE__ */ new Map(),
1644
- approvedRunIds: /* @__PURE__ */ new Map(),
1645
- dynamicToolRunIds: /* @__PURE__ */ new Set()
1646
- };
639
+ return {
640
+ streamStarted: false,
641
+ textBlockId: void 0,
642
+ reasoningBlockId: void 0,
643
+ inputTokens: 0,
644
+ outputTokens: 0,
645
+ streamedStepInput: 0,
646
+ streamedStepOutput: 0,
647
+ pendingStep: void 0,
648
+ approvedToolQueue: /* @__PURE__ */ new Map(),
649
+ approvedRunIds: /* @__PURE__ */ new Map(),
650
+ dynamicToolRunIds: /* @__PURE__ */ new Set()
651
+ };
1647
652
  }
1648
- var NATIVE_TO_COMMON2 = {
1649
- read_file: "read",
1650
- write_file: "write",
1651
- edit_file: "edit",
1652
- execute: "bash"
653
+ const NATIVE_TO_COMMON = {
654
+ read_file: "read",
655
+ write_file: "write",
656
+ edit_file: "edit",
657
+ execute: "bash"
1653
658
  };
1654
- function toCommonName2(nativeName) {
1655
- return NATIVE_TO_COMMON2[nativeName] ?? nativeName;
659
+ function toCommonName(nativeName) {
660
+ return NATIVE_TO_COMMON[nativeName] ?? nativeName;
1656
661
  }
1657
- function createEmitStreamEvent({
1658
- state,
1659
- configuredModel,
1660
- hostToolNames,
1661
- mcpToolNames: mcpToolNames2,
1662
- structuredOutputToolNames = /* @__PURE__ */ new Set(),
1663
- emit
1664
- }) {
1665
- return (event) => {
1666
- const kind = event.event;
1667
- const data = event.data ?? {};
1668
- const ns = event.metadata?.langgraph_checkpoint_ns ?? "";
1669
- const nested = ns.includes("|");
1670
- if (kind === "on_chat_model_start") {
1671
- if (!nested) {
1672
- if (!state.streamStarted) {
1673
- state.streamStarted = true;
1674
- const modelId = resolveDeepAgentsModelId({
1675
- configuredModel,
1676
- metadata: event.metadata
1677
- });
1678
- emit({
1679
- type: "stream-start",
1680
- ...modelId ? { modelId } : {}
1681
- });
1682
- }
1683
- flushStep({ state, emit });
1684
- }
1685
- } else if (kind === "on_chat_model_stream") {
1686
- if (nested) return;
1687
- const chunk = data.chunk;
1688
- if (!chunk) return;
1689
- const content = chunk.content;
1690
- if (typeof content === "string" && content) {
1691
- emitText({ state, emit, delta: content });
1692
- } else if (Array.isArray(content)) {
1693
- for (const block of content) {
1694
- if (block && typeof block === "object") {
1695
- const value = block;
1696
- if ((value.type === "text" || value.type === "text-delta") && value.text) {
1697
- emitText({ state, emit, delta: value.text });
1698
- } else if (value.type === "thinking" && value.thinking) {
1699
- emitReasoning({ state, emit, delta: value.thinking });
1700
- } else if ((value.type === "reasoning" || value.type === "reasoning-delta") && value.reasoning) {
1701
- emitReasoning({ state, emit, delta: value.reasoning });
1702
- }
1703
- }
1704
- }
1705
- }
1706
- const usage = chunk.usage_metadata;
1707
- if (usage) {
1708
- state.streamedStepInput = Math.max(
1709
- state.streamedStepInput,
1710
- usage.input_tokens ?? 0
1711
- );
1712
- state.streamedStepOutput = Math.max(
1713
- state.streamedStepOutput,
1714
- usage.output_tokens ?? 0
1715
- );
1716
- }
1717
- } else if (kind === "on_chat_model_end") {
1718
- const output = data.output;
1719
- const usage = output?.usage_metadata;
1720
- const stepInput = usage?.input_tokens ?? state.streamedStepInput;
1721
- const stepOutput = usage?.output_tokens ?? state.streamedStepOutput;
1722
- state.inputTokens += stepInput;
1723
- state.outputTokens += stepOutput;
1724
- state.streamedStepInput = 0;
1725
- state.streamedStepOutput = 0;
1726
- if (!nested) {
1727
- endTextBlock({ state, emit });
1728
- endReasoningBlock({ state, emit });
1729
- state.pendingStep = { input: stepInput, output: stepOutput };
1730
- }
1731
- } else if (kind === "on_tool_start") {
1732
- const toolName = event.name ?? "unknown";
1733
- if (structuredOutputToolNames.has(toolName)) return;
1734
- const runId = event.run_id ?? "";
1735
- if (!nested && !hostToolNames.has(toolName)) {
1736
- const isMcpTool = mcpToolNames2.has(toolName);
1737
- if (isMcpTool && runId) state.dynamicToolRunIds.add(runId);
1738
- const queued = state.approvedToolQueue.get(toolName);
1739
- if (queued && queued.length > 0) {
1740
- const approvalId = queued.shift();
1741
- if (runId) state.approvedRunIds.set(runId, approvalId);
1742
- } else {
1743
- endTextBlock({ state, emit });
1744
- endReasoningBlock({ state, emit });
1745
- emit({
1746
- type: "tool-call",
1747
- toolCallId: runId,
1748
- toolName: toCommonName2(toolName),
1749
- input: toToolCallInput(data.input),
1750
- providerExecuted: true,
1751
- nativeName: toolName,
1752
- ...isMcpTool ? { dynamic: true } : {}
1753
- });
1754
- }
1755
- }
1756
- } else if (kind === "on_tool_end") {
1757
- const toolName = event.name ?? "unknown";
1758
- if (structuredOutputToolNames.has(toolName)) return;
1759
- const runId = event.run_id ?? "";
1760
- if (!nested && !hostToolNames.has(toolName)) {
1761
- const dynamic = state.dynamicToolRunIds.delete(runId);
1762
- let output = data.output ?? "";
1763
- if (output && typeof output === "object" && "content" in output) {
1764
- output = output.content;
1765
- }
1766
- emit({
1767
- type: "tool-result",
1768
- toolCallId: state.approvedRunIds.get(runId) ?? runId,
1769
- toolName: toCommonName2(toolName),
1770
- result: output ?? null,
1771
- ...dynamic ? { dynamic: true } : {}
1772
- });
1773
- state.approvedRunIds.delete(runId);
1774
- }
1775
- }
1776
- };
662
+ function createEmitStreamEvent({ state, configuredModel, hostToolNames, mcpToolNames, structuredOutputToolNames = /* @__PURE__ */ new Set(), emit }) {
663
+ return (event) => {
664
+ const kind = event.event;
665
+ const data = event.data ?? {};
666
+ const nested = (event.metadata?.langgraph_checkpoint_ns ?? "").includes("|");
667
+ if (kind === "on_chat_model_start") {
668
+ if (!nested) {
669
+ if (!state.streamStarted) {
670
+ state.streamStarted = true;
671
+ const modelId = resolveDeepAgentsModelId({
672
+ configuredModel,
673
+ metadata: event.metadata
674
+ });
675
+ emit({
676
+ type: "stream-start",
677
+ ...modelId ? { modelId } : {}
678
+ });
679
+ }
680
+ flushStep({
681
+ state,
682
+ emit
683
+ });
684
+ }
685
+ } else if (kind === "on_chat_model_stream") {
686
+ if (nested) return;
687
+ const chunk = data.chunk;
688
+ if (!chunk) return;
689
+ const content = chunk.content;
690
+ if (typeof content === "string" && content) emitText({
691
+ state,
692
+ emit,
693
+ delta: content
694
+ });
695
+ else if (Array.isArray(content)) {
696
+ for (const block of content) if (block && typeof block === "object") {
697
+ const value = block;
698
+ if ((value.type === "text" || value.type === "text-delta") && value.text) emitText({
699
+ state,
700
+ emit,
701
+ delta: value.text
702
+ });
703
+ else if (value.type === "thinking" && value.thinking) emitReasoning({
704
+ state,
705
+ emit,
706
+ delta: value.thinking
707
+ });
708
+ else if ((value.type === "reasoning" || value.type === "reasoning-delta") && value.reasoning) emitReasoning({
709
+ state,
710
+ emit,
711
+ delta: value.reasoning
712
+ });
713
+ }
714
+ }
715
+ const usage = chunk.usage_metadata;
716
+ if (usage) {
717
+ state.streamedStepInput = Math.max(state.streamedStepInput, usage.input_tokens ?? 0);
718
+ state.streamedStepOutput = Math.max(state.streamedStepOutput, usage.output_tokens ?? 0);
719
+ }
720
+ } else if (kind === "on_chat_model_end") {
721
+ const usage = data.output?.usage_metadata;
722
+ const stepInput = usage?.input_tokens ?? state.streamedStepInput;
723
+ const stepOutput = usage?.output_tokens ?? state.streamedStepOutput;
724
+ state.inputTokens += stepInput;
725
+ state.outputTokens += stepOutput;
726
+ state.streamedStepInput = 0;
727
+ state.streamedStepOutput = 0;
728
+ if (!nested) {
729
+ endTextBlock({
730
+ state,
731
+ emit
732
+ });
733
+ endReasoningBlock({
734
+ state,
735
+ emit
736
+ });
737
+ state.pendingStep = {
738
+ input: stepInput,
739
+ output: stepOutput
740
+ };
741
+ }
742
+ } else if (kind === "on_tool_start") {
743
+ const toolName = event.name ?? "unknown";
744
+ if (structuredOutputToolNames.has(toolName)) return;
745
+ const runId = event.run_id ?? "";
746
+ if (!nested && !hostToolNames.has(toolName)) {
747
+ const isMcpTool = mcpToolNames.has(toolName);
748
+ if (isMcpTool && runId) state.dynamicToolRunIds.add(runId);
749
+ const queued = state.approvedToolQueue.get(toolName);
750
+ if (queued && queued.length > 0) {
751
+ const approvalId = queued.shift();
752
+ if (runId) state.approvedRunIds.set(runId, approvalId);
753
+ } else {
754
+ endTextBlock({
755
+ state,
756
+ emit
757
+ });
758
+ endReasoningBlock({
759
+ state,
760
+ emit
761
+ });
762
+ emit({
763
+ type: "tool-call",
764
+ toolCallId: runId,
765
+ toolName: toCommonName(toolName),
766
+ input: toToolCallInput(data.input),
767
+ providerExecuted: true,
768
+ nativeName: toolName,
769
+ ...isMcpTool ? { dynamic: true } : {}
770
+ });
771
+ }
772
+ }
773
+ } else if (kind === "on_tool_end") {
774
+ const toolName = event.name ?? "unknown";
775
+ if (structuredOutputToolNames.has(toolName)) return;
776
+ const runId = event.run_id ?? "";
777
+ if (!nested && !hostToolNames.has(toolName)) {
778
+ const dynamic = state.dynamicToolRunIds.delete(runId);
779
+ let output = data.output ?? "";
780
+ if (output && typeof output === "object" && "content" in output) output = output.content;
781
+ emit({
782
+ type: "tool-result",
783
+ toolCallId: state.approvedRunIds.get(runId) ?? runId,
784
+ toolName: toCommonName(toolName),
785
+ result: output ?? null,
786
+ ...dynamic ? { dynamic: true } : {}
787
+ });
788
+ state.approvedRunIds.delete(runId);
789
+ }
790
+ }
791
+ };
1777
792
  }
1778
- function endTextBlock({
1779
- state,
1780
- emit
1781
- }) {
1782
- if (state.textBlockId) {
1783
- emit({ type: "text-end", id: state.textBlockId });
1784
- state.textBlockId = void 0;
1785
- }
793
+ function endTextBlock({ state, emit }) {
794
+ if (state.textBlockId) {
795
+ emit({
796
+ type: "text-end",
797
+ id: state.textBlockId
798
+ });
799
+ state.textBlockId = void 0;
800
+ }
1786
801
  }
1787
- function endReasoningBlock({
1788
- state,
1789
- emit
1790
- }) {
1791
- if (state.reasoningBlockId) {
1792
- emit({ type: "reasoning-end", id: state.reasoningBlockId });
1793
- state.reasoningBlockId = void 0;
1794
- }
802
+ function endReasoningBlock({ state, emit }) {
803
+ if (state.reasoningBlockId) {
804
+ emit({
805
+ type: "reasoning-end",
806
+ id: state.reasoningBlockId
807
+ });
808
+ state.reasoningBlockId = void 0;
809
+ }
1795
810
  }
1796
- function flushStep({
1797
- state,
1798
- emit
1799
- }) {
1800
- if (!state.pendingStep) return;
1801
- emit({
1802
- type: "finish-step",
1803
- finishReason: { unified: "stop" },
1804
- usage: {
1805
- inputTokens: { total: state.pendingStep.input },
1806
- outputTokens: { total: state.pendingStep.output }
1807
- }
1808
- });
1809
- state.pendingStep = void 0;
811
+ function flushStep({ state, emit }) {
812
+ if (!state.pendingStep) return;
813
+ emit({
814
+ type: "finish-step",
815
+ finishReason: { unified: "stop" },
816
+ usage: {
817
+ inputTokens: { total: state.pendingStep.input },
818
+ outputTokens: { total: state.pendingStep.output }
819
+ }
820
+ });
821
+ state.pendingStep = void 0;
1810
822
  }
1811
- function ensureTextBlock({
1812
- state,
1813
- emit
1814
- }) {
1815
- if (!state.textBlockId) {
1816
- state.textBlockId = `text-${randomUUID2()}`;
1817
- emit({ type: "text-start", id: state.textBlockId });
1818
- }
1819
- return state.textBlockId;
823
+ function ensureTextBlock({ state, emit }) {
824
+ if (!state.textBlockId) {
825
+ state.textBlockId = `text-${randomUUID()}`;
826
+ emit({
827
+ type: "text-start",
828
+ id: state.textBlockId
829
+ });
830
+ }
831
+ return state.textBlockId;
1820
832
  }
1821
- function emitText({
1822
- state,
1823
- emit,
1824
- delta
1825
- }) {
1826
- endReasoningBlock({ state, emit });
1827
- emit({ type: "text-delta", id: ensureTextBlock({ state, emit }), delta });
833
+ function emitText({ state, emit, delta }) {
834
+ endReasoningBlock({
835
+ state,
836
+ emit
837
+ });
838
+ emit({
839
+ type: "text-delta",
840
+ id: ensureTextBlock({
841
+ state,
842
+ emit
843
+ }),
844
+ delta
845
+ });
1828
846
  }
1829
- function emitReasoning({
1830
- state,
1831
- emit,
1832
- delta
1833
- }) {
1834
- endTextBlock({ state, emit });
1835
- if (!state.reasoningBlockId) {
1836
- state.reasoningBlockId = `reasoning-${randomUUID2()}`;
1837
- emit({ type: "reasoning-start", id: state.reasoningBlockId });
1838
- }
1839
- emit({ type: "reasoning-delta", id: state.reasoningBlockId, delta });
847
+ function emitReasoning({ state, emit, delta }) {
848
+ endTextBlock({
849
+ state,
850
+ emit
851
+ });
852
+ if (!state.reasoningBlockId) {
853
+ state.reasoningBlockId = `reasoning-${randomUUID()}`;
854
+ emit({
855
+ type: "reasoning-start",
856
+ id: state.reasoningBlockId
857
+ });
858
+ }
859
+ emit({
860
+ type: "reasoning-delta",
861
+ id: state.reasoningBlockId,
862
+ delta
863
+ });
1840
864
  }
1841
- function resolveDeepAgentsModelId({
1842
- configuredModel,
1843
- metadata
1844
- }) {
1845
- if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
1846
- const modelId = metadata.ls_model_name;
1847
- if (typeof modelId === "string" && modelId.length > 0) return modelId;
1848
- }
1849
- return configuredModel;
865
+ function resolveDeepAgentsModelId({ configuredModel, metadata }) {
866
+ if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
867
+ const modelId = metadata.ls_model_name;
868
+ if (typeof modelId === "string" && modelId.length > 0) return modelId;
869
+ }
870
+ return configuredModel;
1850
871
  }
1851
872
  function toToolCallInput(raw) {
1852
- if (raw && typeof raw === "object" && !Array.isArray(raw) && Object.keys(raw).length === 1 && typeof raw.input === "string") {
1853
- const inner = raw.input;
1854
- if (/^\s*[[{]/.test(inner)) return inner;
1855
- }
1856
- return JSON.stringify(raw ?? {});
873
+ if (raw && typeof raw === "object" && !Array.isArray(raw) && Object.keys(raw).length === 1 && typeof raw.input === "string") {
874
+ const inner = raw.input;
875
+ if (/^\s*[[{]/.test(inner)) return inner;
876
+ }
877
+ return JSON.stringify(raw ?? {});
1857
878
  }
1858
-
1859
- // src/bridge/json-schema-to-zod.ts
1860
- import { z as z16 } from "zod/v4";
879
+ //#endregion
880
+ //#region src/bridge/json-schema-to-zod.ts
1861
881
  function jsonSchemaToZodObject(input) {
1862
- const schema = input && typeof input === "object" ? input : {};
1863
- return z16.object(toZodShape(schema));
882
+ const schema = input && typeof input === "object" ? input : {};
883
+ return z.object(toZodShape(schema));
1864
884
  }
1865
885
  function toZodShape(schema) {
1866
- if (!schema.properties) return {};
1867
- const required = new Set(schema.required);
1868
- const shape = {};
1869
- for (const [key, propSchema] of Object.entries(schema.properties)) {
1870
- const propType = toZodType(propSchema);
1871
- shape[key] = required.has(key) ? propType : propType.optional();
1872
- }
1873
- return shape;
886
+ if (!schema.properties) return {};
887
+ const required = new Set(schema.required);
888
+ const shape = {};
889
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
890
+ const propType = toZodType(propSchema);
891
+ shape[key] = required.has(key) ? propType : propType.optional();
892
+ }
893
+ return shape;
1874
894
  }
1875
895
  function toZodType(schema) {
1876
- if (!schema) return z16.any();
1877
- const types = Array.isArray(schema.type) ? schema.type.filter((t) => t !== "null") : [schema.type].filter(Boolean);
1878
- let zType;
1879
- switch (types[0]) {
1880
- case "string":
1881
- zType = z16.string();
1882
- break;
1883
- case "number":
1884
- zType = z16.number();
1885
- break;
1886
- case "integer":
1887
- zType = z16.number().int();
1888
- break;
1889
- case "boolean":
1890
- zType = z16.boolean();
1891
- break;
1892
- case "array":
1893
- zType = z16.array(toZodType(schema.items));
1894
- break;
1895
- case "object":
1896
- zType = z16.object(toZodShape(schema));
1897
- break;
1898
- case "null":
1899
- zType = z16.null();
1900
- break;
1901
- default:
1902
- zType = z16.any();
1903
- }
1904
- if (schema.description) zType = zType.describe(schema.description);
1905
- if (schema.nullable) zType = zType.nullable();
1906
- return zType;
896
+ if (!schema) return z.any();
897
+ const types = Array.isArray(schema.type) ? schema.type.filter((t) => t !== "null") : [schema.type].filter(Boolean);
898
+ let zType;
899
+ switch (types[0]) {
900
+ case "string":
901
+ zType = z.string();
902
+ break;
903
+ case "number":
904
+ zType = z.number();
905
+ break;
906
+ case "integer":
907
+ zType = z.number().int();
908
+ break;
909
+ case "boolean":
910
+ zType = z.boolean();
911
+ break;
912
+ case "array":
913
+ zType = z.array(toZodType(schema.items));
914
+ break;
915
+ case "object":
916
+ zType = z.object(toZodShape(schema));
917
+ break;
918
+ case "null":
919
+ zType = z.null();
920
+ break;
921
+ default: zType = z.any();
922
+ }
923
+ if (schema.description) zType = zType.describe(schema.description);
924
+ if (schema.nullable) zType = zType.nullable();
925
+ return zType;
1907
926
  }
1908
-
1909
- // src/bridge/local-shell-backend.ts
1910
- import { LocalShellBackend } from "deepagents";
1911
- var SANDBOX_PATH_FALLBACK = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1912
- function createLocalShellBackend({
1913
- rootDir,
1914
- env = process.env
1915
- }) {
1916
- return new LocalShellBackend({
1917
- rootDir,
1918
- env: {
1919
- PATH: env.PATH ?? SANDBOX_PATH_FALLBACK
1920
- }
1921
- });
927
+ function createLocalShellBackend({ rootDir, env = process.env }) {
928
+ return new LocalShellBackend({
929
+ rootDir,
930
+ env: { PATH: env.PATH ?? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }
931
+ });
1922
932
  }
1923
-
1924
- // src/bridge/persistent-memory-saver.ts
1925
- import { mkdir as mkdir2, readFile, rename, rm, writeFile as writeFile2 } from "fs/promises";
1926
- import { dirname } from "path";
1927
- var SNAPSHOT_HEADER = "deepagents-memory-saver-v1";
933
+ //#endregion
934
+ //#region src/bridge/persistent-memory-saver.ts
935
+ const SNAPSHOT_HEADER = "deepagents-memory-saver-v1";
1928
936
  function encodeString(value) {
1929
- return Buffer.from(value, "utf8").toString("base64");
937
+ return Buffer.from(value, "utf8").toString("base64");
1930
938
  }
1931
939
  function decodeString(value) {
1932
- return Buffer.from(value, "base64").toString("utf8");
940
+ return Buffer.from(value, "base64").toString("utf8");
1933
941
  }
1934
942
  function encodeBytes(value) {
1935
- return Buffer.from(value).toString("base64");
943
+ return Buffer.from(value).toString("base64");
1936
944
  }
1937
945
  function decodeBytes(value) {
1938
- return Buffer.from(value, "base64");
946
+ return Buffer.from(value, "base64");
1939
947
  }
1940
- async function loadMemorySaver({
1941
- path,
1942
- saver
1943
- }) {
1944
- let snapshot;
1945
- try {
1946
- snapshot = await readFile(path, "utf8");
1947
- } catch (error) {
1948
- if (error.code === "ENOENT") return;
1949
- throw error;
1950
- }
1951
- const [header, ...lines] = snapshot.split("\n");
1952
- if (header !== SNAPSHOT_HEADER) {
1953
- throw new Error("Unsupported Deep Agents conversation checkpoint format");
1954
- }
1955
- const storage = /* @__PURE__ */ Object.create(null);
1956
- const writes = /* @__PURE__ */ Object.create(null);
1957
- for (const line of lines) {
1958
- if (line === "") continue;
1959
- const fields = line.split(" ");
1960
- if (fields[0] === "S" && fields.length === 7) {
1961
- const [, threadIdValue, namespaceValue, checkpointIdValue] = fields;
1962
- const threadId = decodeString(threadIdValue);
1963
- const namespace = decodeString(namespaceValue);
1964
- const checkpointId = decodeString(checkpointIdValue);
1965
- storage[threadId] ??= /* @__PURE__ */ Object.create(null);
1966
- storage[threadId][namespace] ??= /* @__PURE__ */ Object.create(null);
1967
- storage[threadId][namespace][checkpointId] = [
1968
- decodeBytes(fields[4]),
1969
- decodeBytes(fields[5]),
1970
- fields[6] === "" ? void 0 : decodeString(fields[6])
1971
- ];
1972
- continue;
1973
- }
1974
- if (fields[0] === "W" && fields.length === 6) {
1975
- const [, keyValue, indexValue, taskIdValue, channelValue, value] = fields;
1976
- const key = decodeString(keyValue);
1977
- const index = decodeString(indexValue);
1978
- writes[key] ??= /* @__PURE__ */ Object.create(null);
1979
- writes[key][index] = [
1980
- decodeString(taskIdValue),
1981
- decodeString(channelValue),
1982
- decodeBytes(value)
1983
- ];
1984
- continue;
1985
- }
1986
- throw new Error("Invalid Deep Agents conversation checkpoint");
1987
- }
1988
- saver.storage = storage;
1989
- saver.writes = writes;
948
+ async function loadMemorySaver({ path, saver }) {
949
+ let snapshot;
950
+ try {
951
+ snapshot = await readFile(path, "utf8");
952
+ } catch (error) {
953
+ if (error.code === "ENOENT") return;
954
+ throw error;
955
+ }
956
+ const [header, ...lines] = snapshot.split("\n");
957
+ if (header !== SNAPSHOT_HEADER) throw new Error("Unsupported Deep Agents conversation checkpoint format");
958
+ const storage = Object.create(null);
959
+ const writes = Object.create(null);
960
+ for (const line of lines) {
961
+ if (line === "") continue;
962
+ const fields = line.split(" ");
963
+ if (fields[0] === "S" && fields.length === 7) {
964
+ const [, threadIdValue, namespaceValue, checkpointIdValue] = fields;
965
+ const threadId = decodeString(threadIdValue);
966
+ const namespace = decodeString(namespaceValue);
967
+ const checkpointId = decodeString(checkpointIdValue);
968
+ storage[threadId] ??= Object.create(null);
969
+ storage[threadId][namespace] ??= Object.create(null);
970
+ storage[threadId][namespace][checkpointId] = [
971
+ decodeBytes(fields[4]),
972
+ decodeBytes(fields[5]),
973
+ fields[6] === "" ? void 0 : decodeString(fields[6])
974
+ ];
975
+ continue;
976
+ }
977
+ if (fields[0] === "W" && fields.length === 6) {
978
+ const [, keyValue, indexValue, taskIdValue, channelValue, value] = fields;
979
+ const key = decodeString(keyValue);
980
+ const index = decodeString(indexValue);
981
+ writes[key] ??= Object.create(null);
982
+ writes[key][index] = [
983
+ decodeString(taskIdValue),
984
+ decodeString(channelValue),
985
+ decodeBytes(value)
986
+ ];
987
+ continue;
988
+ }
989
+ throw new Error("Invalid Deep Agents conversation checkpoint");
990
+ }
991
+ saver.storage = storage;
992
+ saver.writes = writes;
1990
993
  }
1991
- async function saveMemorySaver({
1992
- path,
1993
- saver
1994
- }) {
1995
- const lines = [SNAPSHOT_HEADER];
1996
- for (const [threadId, namespaces] of Object.entries(saver.storage)) {
1997
- for (const [namespace, checkpoints] of Object.entries(namespaces)) {
1998
- for (const [
1999
- checkpointId,
2000
- [checkpoint, metadata, parentCheckpointId]
2001
- ] of Object.entries(checkpoints)) {
2002
- lines.push(
2003
- [
2004
- "S",
2005
- encodeString(threadId),
2006
- encodeString(namespace),
2007
- encodeString(checkpointId),
2008
- encodeBytes(checkpoint),
2009
- encodeBytes(metadata),
2010
- parentCheckpointId == null ? "" : encodeString(parentCheckpointId)
2011
- ].join(" ")
2012
- );
2013
- }
2014
- }
2015
- }
2016
- for (const [key, indexedWrites] of Object.entries(saver.writes)) {
2017
- for (const [index, [taskId, channel, value]] of Object.entries(
2018
- indexedWrites
2019
- )) {
2020
- lines.push(
2021
- [
2022
- "W",
2023
- encodeString(key),
2024
- encodeString(index),
2025
- encodeString(taskId),
2026
- encodeString(channel),
2027
- encodeBytes(value)
2028
- ].join(" ")
2029
- );
2030
- }
2031
- }
2032
- await mkdir2(dirname(path), { recursive: true });
2033
- const temporaryPath = `${path}.${process.pid}.tmp`;
2034
- await writeFile2(temporaryPath, `${lines.join("\n")}
2035
- `, "utf8");
2036
- await rename(temporaryPath, path);
994
+ async function saveMemorySaver({ path, saver }) {
995
+ const lines = [SNAPSHOT_HEADER];
996
+ for (const [threadId, namespaces] of Object.entries(saver.storage)) for (const [namespace, checkpoints] of Object.entries(namespaces)) for (const [checkpointId, [checkpoint, metadata, parentCheckpointId]] of Object.entries(checkpoints)) lines.push([
997
+ "S",
998
+ encodeString(threadId),
999
+ encodeString(namespace),
1000
+ encodeString(checkpointId),
1001
+ encodeBytes(checkpoint),
1002
+ encodeBytes(metadata),
1003
+ parentCheckpointId == null ? "" : encodeString(parentCheckpointId)
1004
+ ].join(" "));
1005
+ for (const [key, indexedWrites] of Object.entries(saver.writes)) for (const [index, [taskId, channel, value]] of Object.entries(indexedWrites)) lines.push([
1006
+ "W",
1007
+ encodeString(key),
1008
+ encodeString(index),
1009
+ encodeString(taskId),
1010
+ encodeString(channel),
1011
+ encodeBytes(value)
1012
+ ].join(" "));
1013
+ await mkdir(dirname(path), { recursive: true });
1014
+ const temporaryPath = `${path}.${process.pid}.tmp`;
1015
+ await writeFile(temporaryPath, `${lines.join("\n")}\n`, "utf8");
1016
+ await rename(temporaryPath, path);
2037
1017
  }
2038
1018
  async function removeMemorySaverSnapshot(path) {
2039
- await rm(path, { force: true });
1019
+ await rm(path, { force: true });
2040
1020
  }
2041
-
2042
- // src/bridge/tool-filtering.ts
2043
- import {
2044
- AIMessage as AIMessage18,
2045
- ToolMessage as ToolMessage19
2046
- } from "@langchain/core/messages";
2047
- var MIDDLEWARE_BRAND2 = /* @__PURE__ */ Symbol.for("AgentMiddleware");
1021
+ //#endregion
1022
+ //#region src/bridge/tool-filtering.ts
1023
+ const MIDDLEWARE_BRAND = Symbol.for("AgentMiddleware");
2048
1024
  function getBuiltinToolFilteringDenialReason(input) {
2049
- return `Tool '${input.toolName}' is inactive due to the HarnessAgent tool filtering policy.`;
1025
+ return `Tool '${input.toolName}' is inactive due to the HarnessAgent tool filtering policy.`;
2050
1026
  }
2051
1027
  function stringifyToolInput(input) {
2052
- return JSON.stringify(input ?? {});
1028
+ return JSON.stringify(input ?? {});
2053
1029
  }
2054
1030
  function isNativeBuiltinToolCall(input) {
2055
- return Object.keys(NATIVE_TOOL_KIND).includes(input.toolCall.name);
1031
+ return Object.keys(NATIVE_TOOL_KIND).includes(input.toolCall.name);
2056
1032
  }
2057
1033
  function isInactiveBuiltinToolCall(input) {
2058
- return isNativeBuiltinToolCall({ toolCall: input.toolCall }) && !isBuiltinToolIncluded({
2059
- nativeName: input.toolCall.name,
2060
- toolFiltering: input.builtinToolFiltering
2061
- });
1034
+ return isNativeBuiltinToolCall({ toolCall: input.toolCall }) && !isBuiltinToolIncluded({
1035
+ nativeName: input.toolCall.name,
1036
+ toolFiltering: input.builtinToolFiltering
1037
+ });
2062
1038
  }
2063
1039
  function createBuiltinToolFilteringMiddleware(input) {
2064
- if (input.builtinToolFiltering == null) return void 0;
2065
- return {
2066
- [MIDDLEWARE_BRAND2]: true,
2067
- name: "HarnessBuiltinToolFilteringMiddleware",
2068
- afterModel: {
2069
- canJumpTo: ["model"],
2070
- hook: (state) => {
2071
- const lastMessage = [...state.messages].reverse().find((message) => AIMessage18.isInstance(message));
2072
- if (!lastMessage?.tool_calls?.length) return void 0;
2073
- let hasActiveToolCalls = false;
2074
- const deniedToolMessages = [];
2075
- for (const toolCall of lastMessage.tool_calls) {
2076
- if (!isInactiveBuiltinToolCall({
2077
- toolCall,
2078
- builtinToolFiltering: input.builtinToolFiltering
2079
- })) {
2080
- hasActiveToolCalls = true;
2081
- continue;
2082
- }
2083
- const nativeName = toolCall.name;
2084
- toolCall.id ??= `${nativeName}-filtered-${deniedToolMessages.length}`;
2085
- const toolName = toCommonName(nativeName);
2086
- const reason = getBuiltinToolFilteringDenialReason({ toolName });
2087
- input.emit({
2088
- type: "tool-call",
2089
- toolCallId: toolCall.id,
2090
- toolName,
2091
- input: stringifyToolInput(toolCall.args),
2092
- providerExecuted: true,
2093
- nativeName
2094
- });
2095
- input.emit({
2096
- type: "tool-result",
2097
- toolCallId: toolCall.id,
2098
- toolName,
2099
- result: reason
2100
- });
2101
- deniedToolMessages.push(
2102
- new ToolMessage19({
2103
- content: reason,
2104
- name: nativeName,
2105
- tool_call_id: toolCall.id,
2106
- status: "error"
2107
- })
2108
- );
2109
- }
2110
- if (deniedToolMessages.length === 0) return void 0;
2111
- return {
2112
- messages: [lastMessage, ...deniedToolMessages],
2113
- ...hasActiveToolCalls ? {} : { jumpTo: "model" }
2114
- };
2115
- }
2116
- }
2117
- };
1040
+ if (input.builtinToolFiltering == null) return void 0;
1041
+ return {
1042
+ [MIDDLEWARE_BRAND]: true,
1043
+ name: "HarnessBuiltinToolFilteringMiddleware",
1044
+ afterModel: {
1045
+ canJumpTo: ["model"],
1046
+ hook: (state) => {
1047
+ const lastMessage = [...state.messages].reverse().find((message) => AIMessage.isInstance(message));
1048
+ if (!lastMessage?.tool_calls?.length) return void 0;
1049
+ let hasActiveToolCalls = false;
1050
+ const deniedToolMessages = [];
1051
+ for (const toolCall of lastMessage.tool_calls) {
1052
+ if (!isInactiveBuiltinToolCall({
1053
+ toolCall,
1054
+ builtinToolFiltering: input.builtinToolFiltering
1055
+ })) {
1056
+ hasActiveToolCalls = true;
1057
+ continue;
1058
+ }
1059
+ const nativeName = toolCall.name;
1060
+ toolCall.id ??= `${nativeName}-filtered-${deniedToolMessages.length}`;
1061
+ const toolName = toCommonName$1(nativeName);
1062
+ const reason = getBuiltinToolFilteringDenialReason({ toolName });
1063
+ input.emit({
1064
+ type: "tool-call",
1065
+ toolCallId: toolCall.id,
1066
+ toolName,
1067
+ input: stringifyToolInput(toolCall.args),
1068
+ providerExecuted: true,
1069
+ nativeName
1070
+ });
1071
+ input.emit({
1072
+ type: "tool-result",
1073
+ toolCallId: toolCall.id,
1074
+ toolName,
1075
+ result: reason
1076
+ });
1077
+ deniedToolMessages.push(new ToolMessage({
1078
+ content: reason,
1079
+ name: nativeName,
1080
+ tool_call_id: toolCall.id,
1081
+ status: "error"
1082
+ }));
1083
+ }
1084
+ if (deniedToolMessages.length === 0) return void 0;
1085
+ return {
1086
+ messages: [lastMessage, ...deniedToolMessages],
1087
+ ...hasActiveToolCalls ? {} : { jumpTo: "model" }
1088
+ };
1089
+ }
1090
+ }
1091
+ };
2118
1092
  }
2119
-
2120
- // src/bridge/index.ts
2121
- var HARNESS_CLIENT_APP = procEnv2.AI_SDK_HARNESS_CLIENT_APP;
1093
+ //#endregion
1094
+ //#region src/bridge/index.ts
1095
+ const HARNESS_CLIENT_APP = env.AI_SDK_HARNESS_CLIENT_APP;
2122
1096
  function parseArgs(rawArgs) {
2123
- const out = {};
2124
- for (let i = 0; i < rawArgs.length; i++) {
2125
- const arg = rawArgs[i];
2126
- if (arg.startsWith("--")) {
2127
- const key = arg.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
2128
- out[key] = rawArgs[i + 1];
2129
- i++;
2130
- }
2131
- }
2132
- return out;
1097
+ const out = {};
1098
+ for (let i = 0; i < rawArgs.length; i++) {
1099
+ const arg = rawArgs[i];
1100
+ if (arg.startsWith("--")) {
1101
+ const key = arg.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1102
+ out[key] = rawArgs[i + 1];
1103
+ i++;
1104
+ }
1105
+ }
1106
+ return out;
2133
1107
  }
2134
- function buildModel({
2135
- rawModel,
2136
- thinking,
2137
- effort,
2138
- headers
2139
- }) {
2140
- if (!rawModel) return void 0;
2141
- const baseUrl = procEnv2.ANTHROPIC_BASE_URL;
2142
- const model = baseUrl ? rawModel : rawModel.replace(/^anthropic[/:]/, "");
2143
- return new ChatAnthropic({
2144
- model,
2145
- ...thinking ? { thinking } : {},
2146
- ...effort ? { outputConfig: { effort } } : {},
2147
- ...procEnv2.ANTHROPIC_API_KEY ? { apiKey: procEnv2.ANTHROPIC_API_KEY } : {},
2148
- ...baseUrl ? { anthropicApiUrl: baseUrl } : {},
2149
- ...headers != null || procEnv2.AI_GATEWAY_API_KEY ? {
2150
- clientOptions: {
2151
- defaultHeaders: {
2152
- ...headers,
2153
- ...procEnv2.AI_GATEWAY_API_KEY && HARNESS_CLIENT_APP ? {
2154
- "User-Agent": HARNESS_CLIENT_APP,
2155
- "x-client-app": HARNESS_CLIENT_APP
2156
- } : {}
2157
- }
2158
- }
2159
- } : {}
2160
- });
1108
+ function buildModel({ rawModel, thinking, effort, headers }) {
1109
+ if (!rawModel) return void 0;
1110
+ const baseUrl = env.ANTHROPIC_BASE_URL;
1111
+ const model = baseUrl ? rawModel : rawModel.replace(/^anthropic[/:]/, "");
1112
+ return new ChatAnthropic({
1113
+ model,
1114
+ ...thinking ? { thinking } : {},
1115
+ ...effort ? { outputConfig: { effort } } : {},
1116
+ ...env.ANTHROPIC_API_KEY ? { apiKey: env.ANTHROPIC_API_KEY } : {},
1117
+ ...baseUrl ? { anthropicApiUrl: baseUrl } : {},
1118
+ ...headers != null || env.AI_GATEWAY_API_KEY ? { clientOptions: { defaultHeaders: {
1119
+ ...headers,
1120
+ ...env.AI_GATEWAY_API_KEY && HARNESS_CLIENT_APP ? {
1121
+ "User-Agent": HARNESS_CLIENT_APP,
1122
+ "x-client-app": HARNESS_CLIENT_APP
1123
+ } : {}
1124
+ } } } : {}
1125
+ });
2161
1126
  }
2162
1127
  function createModelMiddleware() {
2163
- return createMiddleware({
2164
- name: "harnessModel",
2165
- wrapModelCall: async (request, handler) => {
2166
- if (!activeModel && !activeThinking && !activeEffort && !activeHeaders) {
2167
- return handler(request);
2168
- }
2169
- if (activeModel) {
2170
- const configuredModel2 = buildModel({
2171
- rawModel: activeModel,
2172
- thinking: activeThinking,
2173
- effort: activeEffort,
2174
- headers: activeHeaders
2175
- });
2176
- if (!configuredModel2) throw new Error("Deep Agents model is missing");
2177
- return handler({ ...request, model: configuredModel2 });
2178
- }
2179
- let model = request.model;
2180
- if ("_getModelInstance" in model && typeof model._getModelInstance === "function") {
2181
- model = await model._getModelInstance();
2182
- }
2183
- if (!(model instanceof ChatAnthropic)) {
2184
- throw new Error("Deep Agents reasoning requires ChatAnthropic");
2185
- }
2186
- const configuredModel = buildModel({
2187
- rawModel: model.model,
2188
- thinking: activeThinking,
2189
- effort: activeEffort,
2190
- headers: activeHeaders
2191
- });
2192
- if (!configuredModel) throw new Error("Deep Agents model is missing");
2193
- return handler({ ...request, model: configuredModel });
2194
- }
2195
- });
1128
+ return createMiddleware({
1129
+ name: "harnessModel",
1130
+ wrapModelCall: async (request, handler) => {
1131
+ if (!activeModel && !activeThinking && !activeEffort && !activeHeaders) return handler(request);
1132
+ if (activeModel) {
1133
+ const configuredModel = buildModel({
1134
+ rawModel: activeModel,
1135
+ thinking: activeThinking,
1136
+ effort: activeEffort,
1137
+ headers: activeHeaders
1138
+ });
1139
+ if (!configuredModel) throw new Error("Deep Agents model is missing");
1140
+ return handler({
1141
+ ...request,
1142
+ model: configuredModel
1143
+ });
1144
+ }
1145
+ let model = request.model;
1146
+ if ("_getModelInstance" in model && typeof model._getModelInstance === "function") model = await model._getModelInstance();
1147
+ if (!(model instanceof ChatAnthropic)) throw new Error("Deep Agents reasoning requires ChatAnthropic");
1148
+ const configuredModel = buildModel({
1149
+ rawModel: model.model,
1150
+ thinking: activeThinking,
1151
+ effort: activeEffort,
1152
+ headers: activeHeaders
1153
+ });
1154
+ if (!configuredModel) throw new Error("Deep Agents model is missing");
1155
+ return handler({
1156
+ ...request,
1157
+ model: configuredModel
1158
+ });
1159
+ }
1160
+ });
2196
1161
  }
2197
- var args = parseArgs(argv.slice(2));
2198
- var workdir = args.workdir;
2199
- var bridgeStateDir = args.bridgeStateDir;
1162
+ const args = parseArgs(argv.slice(2));
1163
+ const workdir = args.workdir;
1164
+ const bridgeStateDir = args.bridgeStateDir;
2200
1165
  if (!workdir || !bridgeStateDir) {
2201
- console.error("deepagents bridge: missing --workdir / --bridge-state-dir");
2202
- process.exit(1);
1166
+ console.error("deepagents bridge: missing --workdir / --bridge-state-dir");
1167
+ process.exit(1);
2203
1168
  }
2204
- var conversationCheckpointPath = `${bridgeStateDir}/conversation.checkpoint`;
2205
- var agent;
2206
- var currentTurn;
2207
- var mcpClient;
2208
- var mcpToolNames = /* @__PURE__ */ new Set();
2209
- var currentResponseFormat;
2210
- var checkpointer = new MemorySaver2();
2211
- if (args.resume === "true") {
2212
- await loadMemorySaver({
2213
- path: conversationCheckpointPath,
2214
- saver: checkpointer
2215
- });
2216
- } else {
2217
- await removeMemorySaverSnapshot(conversationCheckpointPath);
2218
- }
2219
- var agentConfigurationSignature;
2220
- var activeModel;
2221
- var activeThinking;
2222
- var activeEffort;
2223
- var activeHeaders;
2224
- var modelMiddleware = createModelMiddleware();
2225
- var responseFormatMiddleware = createMiddleware({
2226
- name: "HarnessResponseFormat",
2227
- wrapModelCall(request, handler) {
2228
- return handler({
2229
- ...request,
2230
- ...currentResponseFormat == null ? {} : { responseFormat: currentResponseFormat }
2231
- });
2232
- }
1169
+ const conversationCheckpointPath = `${bridgeStateDir}/conversation.checkpoint`;
1170
+ let agent;
1171
+ let currentTurn;
1172
+ let mcpClient;
1173
+ let mcpToolNames = /* @__PURE__ */ new Set();
1174
+ let currentResponseFormat;
1175
+ const checkpointer = new MemorySaver();
1176
+ if (args.resume === "true") await loadMemorySaver({
1177
+ path: conversationCheckpointPath,
1178
+ saver: checkpointer
1179
+ });
1180
+ else await removeMemorySaverSnapshot(conversationCheckpointPath);
1181
+ let agentConfigurationSignature;
1182
+ let activeModel;
1183
+ let activeThinking;
1184
+ let activeEffort;
1185
+ let activeHeaders;
1186
+ const modelMiddleware = createModelMiddleware();
1187
+ const responseFormatMiddleware = createMiddleware({
1188
+ name: "HarnessResponseFormat",
1189
+ wrapModelCall(request, handler) {
1190
+ return handler({
1191
+ ...request,
1192
+ ...currentResponseFormat == null ? {} : { responseFormat: currentResponseFormat }
1193
+ });
1194
+ }
2233
1195
  });
2234
1196
  function buildHostTools(toolSchemas) {
2235
- return (toolSchemas ?? []).map(
2236
- (schema) => tool3(
2237
- async (input) => {
2238
- const turn = currentTurn;
2239
- if (!turn) throw new Error("no active turn");
2240
- const toolCallId = `${schema.name}-${randomUUID3()}`;
2241
- turn.emit({
2242
- type: "tool-call",
2243
- toolCallId,
2244
- toolName: schema.name,
2245
- input: JSON.stringify(input),
2246
- providerExecuted: false
2247
- });
2248
- const { output, isError } = await turn.requestToolResult(toolCallId);
2249
- turn.emit({
2250
- type: "tool-result",
2251
- toolCallId,
2252
- toolName: schema.name,
2253
- result: output ?? null,
2254
- ...isError !== void 0 ? { isError } : {}
2255
- });
2256
- return typeof output === "string" ? output : JSON.stringify(output);
2257
- },
2258
- {
2259
- name: schema.name,
2260
- description: schema.description ?? "",
2261
- schema: jsonSchemaToZodObject(schema.inputSchema)
2262
- }
2263
- )
2264
- );
1197
+ return (toolSchemas ?? []).map((schema) => tool(async (input) => {
1198
+ const turn = currentTurn;
1199
+ if (!turn) throw new Error("no active turn");
1200
+ const toolCallId = `${schema.name}-${randomUUID()}`;
1201
+ turn.emit({
1202
+ type: "tool-call",
1203
+ toolCallId,
1204
+ toolName: schema.name,
1205
+ input: JSON.stringify(input),
1206
+ providerExecuted: false
1207
+ });
1208
+ const { output, isError } = await turn.requestToolResult(toolCallId);
1209
+ turn.emit({
1210
+ type: "tool-result",
1211
+ toolCallId,
1212
+ toolName: schema.name,
1213
+ result: output ?? null,
1214
+ ...isError !== void 0 ? { isError } : {}
1215
+ });
1216
+ return typeof output === "string" ? output : JSON.stringify(output);
1217
+ }, {
1218
+ name: schema.name,
1219
+ description: schema.description ?? "",
1220
+ schema: jsonSchemaToZodObject(schema.inputSchema)
1221
+ }));
2265
1222
  }
2266
1223
  async function runTurn(start, turn) {
2267
- currentTurn = turn;
2268
- if (start.model) activeModel = start.model;
2269
- activeThinking = start.thinking;
2270
- activeEffort = start.effort;
2271
- activeHeaders = start.headers;
2272
- currentResponseFormat = start.responseFormat?.type === "json" && start.responseFormat.schema != null ? toolStrategy(start.responseFormat.schema) : void 0;
2273
- const emit = (event) => turn.emit(event);
2274
- const interruptOn = buildInterruptOn(
2275
- start.permissionMode,
2276
- start.builtinToolFiltering
2277
- );
2278
- const config = {
2279
- version: "v2",
2280
- configurable: { thread_id: "bridge-session" },
2281
- ...start.recursionLimit != null ? { recursionLimit: start.recursionLimit } : {},
2282
- signal: turn.abortSignal
2283
- };
2284
- const nextAgentConfigurationSignature = JSON.stringify({
2285
- instructions: start.instructions,
2286
- tools: start.tools,
2287
- skillsPaths: start.skillsPaths
2288
- });
2289
- const rebuildAgent = agent == null || agentConfigurationSignature !== nextAgentConfigurationSignature || start.skillsChanged === true;
2290
- if (rebuildAgent) {
2291
- if (agent != null && start.skillsChanged === true) {
2292
- await agent.updateState(config, {
2293
- skillsMetadata: new Overwrite([])
2294
- });
2295
- }
2296
- await closeMcpClient();
2297
- const builtinToolFilteringMiddleware = createBuiltinToolFilteringMiddleware(
2298
- {
2299
- builtinToolFiltering: start.builtinToolFiltering,
2300
- emit: (event) => {
2301
- const turn2 = currentTurn;
2302
- if (!turn2) throw new Error("no active turn");
2303
- turn2.emit(event);
2304
- }
2305
- }
2306
- );
2307
- const middleware = [
2308
- responseFormatMiddleware,
2309
- modelMiddleware,
2310
- ...builtinToolFilteringMiddleware ? [builtinToolFilteringMiddleware] : []
2311
- ];
2312
- const hostTools = buildHostTools(start.tools);
2313
- const hostToolNames2 = new Set(hostTools.map((hostTool) => hostTool.name));
2314
- const externalTools = await loadMcpTools({
2315
- mcpServers: start.mcpServers
2316
- });
2317
- const mcpTools = externalTools.filter(
2318
- (externalTool) => !hostToolNames2.has(externalTool.name)
2319
- );
2320
- mcpToolNames = new Set(mcpTools.map((mcpTool) => mcpTool.name));
2321
- agent = createDeepAgent({
2322
- tools: [...mcpTools, ...hostTools],
2323
- backend: createLocalShellBackend({ rootDir: workdir }),
2324
- systemPrompt: start.instructions ? { suffix: start.instructions } : void 0,
2325
- // Native skills loaded from the source dirs ($HOME-materialized + <workDir> for repo-provided skills).
2326
- ...start.skillsPaths?.length ? { skills: start.skillsPaths } : {},
2327
- ...middleware.length > 0 ? { middleware } : {},
2328
- // Gate built-in tools behind HITL approval when the permission mode requires it.
2329
- ...interruptOn ? { interruptOn } : {},
2330
- // Real instance (LangGraph rejects `true` for root graphs); gives multi-turn memory.
2331
- checkpointer
2332
- });
2333
- agentConfigurationSignature = nextAgentConfigurationSignature;
2334
- }
2335
- const activeAgent = agent;
2336
- if (activeAgent == null) {
2337
- throw new Error("Deep Agents runtime was not initialized");
2338
- }
2339
- const hostToolNames = new Set((start.tools ?? []).map((t) => t.name));
2340
- const streamEventState = createDeepAgentsStreamEventState();
2341
- const emitStreamEvent = createEmitStreamEvent({
2342
- state: streamEventState,
2343
- configuredModel: activeModel,
2344
- hostToolNames,
2345
- mcpToolNames,
2346
- structuredOutputToolNames: new Set(
2347
- currentResponseFormat?.map((format) => format.name)
2348
- ),
2349
- emit
2350
- });
2351
- const readPendingApprovals = async () => {
2352
- try {
2353
- const state = await activeAgent.getState({
2354
- configurable: { thread_id: "bridge-session" }
2355
- });
2356
- return collectActionRequests(
2357
- (state.tasks ?? []).flatMap((t) => t.interrupts ?? [])
2358
- );
2359
- } catch {
2360
- return [];
2361
- }
2362
- };
2363
- let resumeInput = {
2364
- messages: [{ role: "user", content: start.prompt }]
2365
- };
2366
- let emittedStructuredOutput = false;
2367
- while (true) {
2368
- const stream = await activeAgent.streamEvents(resumeInput, config);
2369
- for await (const event of stream) {
2370
- emitStreamEvent(event);
2371
- const streamEvent = event;
2372
- const namespace = streamEvent.metadata?.langgraph_checkpoint_ns ?? "";
2373
- const output = streamEvent.data?.output;
2374
- if (!emittedStructuredOutput && streamEvent.event === "on_chain_end" && !namespace.includes("|") && output?.structuredResponse !== void 0) {
2375
- const id = `structured-output-${randomUUID3()}`;
2376
- emit({ type: "text-start", id });
2377
- emit({
2378
- type: "text-delta",
2379
- id,
2380
- delta: JSON.stringify(output.structuredResponse)
2381
- });
2382
- emit({ type: "text-end", id });
2383
- emittedStructuredOutput = true;
2384
- }
2385
- }
2386
- const actionRequests = await readPendingApprovals();
2387
- if (actionRequests.length === 0) break;
2388
- const decisions = [];
2389
- for (const action of actionRequests) {
2390
- const approvalId = `approval-${randomUUID3()}`;
2391
- endTextBlock({ state: streamEventState, emit });
2392
- endReasoningBlock({ state: streamEventState, emit });
2393
- emit({
2394
- type: "tool-call",
2395
- toolCallId: approvalId,
2396
- toolName: toCommonName2(action.name),
2397
- input: JSON.stringify(action.args ?? {}),
2398
- providerExecuted: true,
2399
- nativeName: action.name
2400
- });
2401
- emit({
2402
- type: "tool-approval-request",
2403
- approvalId,
2404
- toolCallId: approvalId
2405
- });
2406
- flushStep({ state: streamEventState, emit });
2407
- const decision = await turn.requestToolApproval(approvalId);
2408
- if (decision.approved) {
2409
- const queue = streamEventState.approvedToolQueue.get(action.name) ?? [];
2410
- queue.push(approvalId);
2411
- streamEventState.approvedToolQueue.set(action.name, queue);
2412
- decisions.push({ type: "approve" });
2413
- } else {
2414
- emit({
2415
- type: "tool-result",
2416
- toolCallId: approvalId,
2417
- toolName: toCommonName2(action.name),
2418
- result: decision.reason ?? "Rejected by user."
2419
- });
2420
- decisions.push({
2421
- type: "reject",
2422
- ...decision.reason ? { message: decision.reason } : {}
2423
- });
2424
- }
2425
- }
2426
- resumeInput = new Command5({ resume: { decisions } });
2427
- }
2428
- endTextBlock({ state: streamEventState, emit });
2429
- endReasoningBlock({ state: streamEventState, emit });
2430
- flushStep({ state: streamEventState, emit });
2431
- emit({
2432
- type: "finish",
2433
- finishReason: { unified: "stop" },
2434
- totalUsage: {
2435
- inputTokens: { total: streamEventState.inputTokens },
2436
- outputTokens: { total: streamEventState.outputTokens }
2437
- }
2438
- });
1224
+ currentTurn = turn;
1225
+ if (start.model) activeModel = start.model;
1226
+ activeThinking = start.thinking;
1227
+ activeEffort = start.effort;
1228
+ activeHeaders = start.headers;
1229
+ currentResponseFormat = start.responseFormat?.type === "json" && start.responseFormat.schema != null ? toolStrategy(start.responseFormat.schema) : void 0;
1230
+ const emit = (event) => turn.emit(event);
1231
+ const interruptOn = buildInterruptOn(start.permissionMode, start.builtinToolFiltering);
1232
+ const config = {
1233
+ version: "v2",
1234
+ configurable: { thread_id: "bridge-session" },
1235
+ ...start.recursionLimit != null ? { recursionLimit: start.recursionLimit } : {},
1236
+ signal: turn.abortSignal
1237
+ };
1238
+ const nextAgentConfigurationSignature = JSON.stringify({
1239
+ instructions: start.instructions,
1240
+ tools: start.tools,
1241
+ skillsPaths: start.skillsPaths
1242
+ });
1243
+ if (agent == null || agentConfigurationSignature !== nextAgentConfigurationSignature || start.skillsChanged === true) {
1244
+ if (agent != null && start.skillsChanged === true) await agent.updateState(config, { skillsMetadata: new Overwrite([]) });
1245
+ await closeMcpClient();
1246
+ const builtinToolFilteringMiddleware = createBuiltinToolFilteringMiddleware({
1247
+ builtinToolFiltering: start.builtinToolFiltering,
1248
+ emit: (event) => {
1249
+ const turn = currentTurn;
1250
+ if (!turn) throw new Error("no active turn");
1251
+ turn.emit(event);
1252
+ }
1253
+ });
1254
+ const middleware = [
1255
+ responseFormatMiddleware,
1256
+ modelMiddleware,
1257
+ ...builtinToolFilteringMiddleware ? [builtinToolFilteringMiddleware] : []
1258
+ ];
1259
+ const hostTools = buildHostTools(start.tools);
1260
+ const hostToolNames = new Set(hostTools.map((hostTool) => hostTool.name));
1261
+ const mcpTools = (await loadMcpTools({ mcpServers: start.mcpServers })).filter((externalTool) => !hostToolNames.has(externalTool.name));
1262
+ mcpToolNames = new Set(mcpTools.map((mcpTool) => mcpTool.name));
1263
+ agent = createDeepAgent({
1264
+ tools: [...mcpTools, ...hostTools],
1265
+ backend: createLocalShellBackend({ rootDir: workdir }),
1266
+ systemPrompt: start.instructions ? { suffix: start.instructions } : void 0,
1267
+ ...start.skillsPaths?.length ? { skills: start.skillsPaths } : {},
1268
+ ...middleware.length > 0 ? { middleware } : {},
1269
+ ...interruptOn ? { interruptOn } : {},
1270
+ checkpointer
1271
+ });
1272
+ agentConfigurationSignature = nextAgentConfigurationSignature;
1273
+ }
1274
+ const activeAgent = agent;
1275
+ if (activeAgent == null) throw new Error("Deep Agents runtime was not initialized");
1276
+ const hostToolNames = new Set((start.tools ?? []).map((t) => t.name));
1277
+ const streamEventState = createDeepAgentsStreamEventState();
1278
+ const emitStreamEvent = createEmitStreamEvent({
1279
+ state: streamEventState,
1280
+ configuredModel: activeModel,
1281
+ hostToolNames,
1282
+ mcpToolNames,
1283
+ structuredOutputToolNames: new Set(currentResponseFormat?.map((format) => format.name)),
1284
+ emit
1285
+ });
1286
+ const readPendingApprovals = async () => {
1287
+ try {
1288
+ return collectActionRequests(((await activeAgent.getState({ configurable: { thread_id: "bridge-session" } })).tasks ?? []).flatMap((t) => t.interrupts ?? []));
1289
+ } catch {
1290
+ return [];
1291
+ }
1292
+ };
1293
+ let resumeInput = { messages: [{
1294
+ role: "user",
1295
+ content: start.prompt
1296
+ }] };
1297
+ let emittedStructuredOutput = false;
1298
+ while (true) {
1299
+ const stream = await activeAgent.streamEvents(resumeInput, config);
1300
+ for await (const event of stream) {
1301
+ emitStreamEvent(event);
1302
+ const streamEvent = event;
1303
+ const namespace = streamEvent.metadata?.langgraph_checkpoint_ns ?? "";
1304
+ const output = streamEvent.data?.output;
1305
+ if (!emittedStructuredOutput && streamEvent.event === "on_chain_end" && !namespace.includes("|") && output?.structuredResponse !== void 0) {
1306
+ const id = `structured-output-${randomUUID()}`;
1307
+ emit({
1308
+ type: "text-start",
1309
+ id
1310
+ });
1311
+ emit({
1312
+ type: "text-delta",
1313
+ id,
1314
+ delta: JSON.stringify(output.structuredResponse)
1315
+ });
1316
+ emit({
1317
+ type: "text-end",
1318
+ id
1319
+ });
1320
+ emittedStructuredOutput = true;
1321
+ }
1322
+ }
1323
+ const actionRequests = await readPendingApprovals();
1324
+ if (actionRequests.length === 0) break;
1325
+ const decisions = [];
1326
+ for (const action of actionRequests) {
1327
+ const approvalId = `approval-${randomUUID()}`;
1328
+ endTextBlock({
1329
+ state: streamEventState,
1330
+ emit
1331
+ });
1332
+ endReasoningBlock({
1333
+ state: streamEventState,
1334
+ emit
1335
+ });
1336
+ emit({
1337
+ type: "tool-call",
1338
+ toolCallId: approvalId,
1339
+ toolName: toCommonName(action.name),
1340
+ input: JSON.stringify(action.args ?? {}),
1341
+ providerExecuted: true,
1342
+ nativeName: action.name
1343
+ });
1344
+ emit({
1345
+ type: "tool-approval-request",
1346
+ approvalId,
1347
+ toolCallId: approvalId
1348
+ });
1349
+ flushStep({
1350
+ state: streamEventState,
1351
+ emit
1352
+ });
1353
+ const decision = await turn.requestToolApproval(approvalId);
1354
+ if (decision.approved) {
1355
+ const queue = streamEventState.approvedToolQueue.get(action.name) ?? [];
1356
+ queue.push(approvalId);
1357
+ streamEventState.approvedToolQueue.set(action.name, queue);
1358
+ decisions.push({ type: "approve" });
1359
+ } else {
1360
+ emit({
1361
+ type: "tool-result",
1362
+ toolCallId: approvalId,
1363
+ toolName: toCommonName(action.name),
1364
+ result: decision.reason ?? "Rejected by user."
1365
+ });
1366
+ decisions.push({
1367
+ type: "reject",
1368
+ ...decision.reason ? { message: decision.reason } : {}
1369
+ });
1370
+ }
1371
+ }
1372
+ resumeInput = new Command({ resume: { decisions } });
1373
+ }
1374
+ endTextBlock({
1375
+ state: streamEventState,
1376
+ emit
1377
+ });
1378
+ endReasoningBlock({
1379
+ state: streamEventState,
1380
+ emit
1381
+ });
1382
+ flushStep({
1383
+ state: streamEventState,
1384
+ emit
1385
+ });
1386
+ emit({
1387
+ type: "finish",
1388
+ finishReason: { unified: "stop" },
1389
+ totalUsage: {
1390
+ inputTokens: { total: streamEventState.inputTokens },
1391
+ outputTokens: { total: streamEventState.outputTokens }
1392
+ }
1393
+ });
2439
1394
  }
2440
1395
  await runBridge({
2441
- bridgeType: "deepagents",
2442
- bridgeStateDir,
2443
- onStart: runTurn,
2444
- onStop: async () => {
2445
- await closeMcpClient();
2446
- await saveMemorySaver({
2447
- path: conversationCheckpointPath,
2448
- saver: checkpointer
2449
- });
2450
- return {};
2451
- },
2452
- onDestroy: async () => {
2453
- await closeMcpClient();
2454
- await removeMemorySaverSnapshot(conversationCheckpointPath);
2455
- }
1396
+ bridgeType: "deepagents",
1397
+ bridgeStateDir,
1398
+ onStart: runTurn,
1399
+ onStop: async () => {
1400
+ await closeMcpClient();
1401
+ await saveMemorySaver({
1402
+ path: conversationCheckpointPath,
1403
+ saver: checkpointer
1404
+ });
1405
+ return {};
1406
+ },
1407
+ onDestroy: async () => {
1408
+ await closeMcpClient();
1409
+ await removeMemorySaverSnapshot(conversationCheckpointPath);
1410
+ }
2456
1411
  });
2457
- async function loadMcpTools({
2458
- mcpServers
2459
- }) {
2460
- if (mcpServers == null || Object.keys(mcpServers).length === 0) return [];
2461
- for (const [name, value] of Object.entries(mcpServers)) {
2462
- if (value == null || typeof value !== "object" || Array.isArray(value)) {
2463
- throw new Error(
2464
- `DeepAgents MCP server ${JSON.stringify(name)} must be configured with an object value.`
2465
- );
2466
- }
2467
- }
2468
- mcpClient = new MultiServerMCPClient({
2469
- mcpServers,
2470
- prefixToolNameWithServerName: true,
2471
- additionalToolNamePrefix: "mcp"
2472
- });
2473
- return mcpClient.getTools();
1412
+ async function loadMcpTools({ mcpServers }) {
1413
+ if (mcpServers == null || Object.keys(mcpServers).length === 0) return [];
1414
+ for (const [name, value] of Object.entries(mcpServers)) if (value == null || typeof value !== "object" || Array.isArray(value)) throw new Error(`DeepAgents MCP server ${JSON.stringify(name)} must be configured with an object value.`);
1415
+ mcpClient = new MultiServerMCPClient({
1416
+ mcpServers,
1417
+ prefixToolNameWithServerName: true,
1418
+ additionalToolNamePrefix: "mcp"
1419
+ });
1420
+ return mcpClient.getTools();
2474
1421
  }
2475
1422
  async function closeMcpClient() {
2476
- const client = mcpClient;
2477
- mcpClient = void 0;
2478
- mcpToolNames = /* @__PURE__ */ new Set();
2479
- await client?.close();
1423
+ const client = mcpClient;
1424
+ mcpClient = void 0;
1425
+ mcpToolNames = /* @__PURE__ */ new Set();
1426
+ await client?.close();
2480
1427
  }
1428
+ //#endregion
1429
+ export {};
1430
+
2481
1431
  //# sourceMappingURL=index.mjs.map