@botbotgo/agent-harness 0.0.30 → 0.0.31

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 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.29";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.30";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.29";
1
+ export const AGENT_HARNESS_VERSION = "0.0.30";
@@ -7,13 +7,16 @@ type RunnableLike = {
7
7
  };
8
8
  declare const AGENT_INTERRUPT_SENTINEL_PREFIX = "__agent_harness_interrupt__:";
9
9
  declare class RuntimeOperationTimeoutError extends Error {
10
+ readonly operation: string;
10
11
  readonly timeoutMs: number;
11
- constructor(operation: string, timeoutMs: number);
12
+ readonly stage: "stream" | "invoke";
13
+ constructor(operation: string, timeoutMs: number, stage?: "stream" | "invoke");
12
14
  }
13
15
  export declare class AgentRuntimeAdapter {
14
16
  private readonly options;
15
17
  constructor(options?: RuntimeAdapterOptions);
16
18
  private resolveBindingTimeout;
19
+ private resolveStreamIdleTimeout;
17
20
  private withTimeout;
18
21
  private iterateWithTimeout;
19
22
  private materializeModelStream;
@@ -13,10 +13,14 @@ import { extractMessageText, normalizeMessageContent } from "../utils/message-co
13
13
  const AGENT_INTERRUPT_SENTINEL_PREFIX = "__agent_harness_interrupt__:";
14
14
  const MODEL_SAFE_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
15
15
  class RuntimeOperationTimeoutError extends Error {
16
+ operation;
16
17
  timeoutMs;
17
- constructor(operation, timeoutMs) {
18
+ stage;
19
+ constructor(operation, timeoutMs, stage = operation.includes("stream") ? "stream" : "invoke") {
18
20
  super(`${operation} timed out after ${timeoutMs}ms`);
21
+ this.operation = operation;
19
22
  this.timeoutMs = timeoutMs;
23
+ this.stage = stage;
20
24
  this.name = "RuntimeOperationTimeoutError";
21
25
  }
22
26
  }
@@ -127,12 +131,23 @@ export class AgentRuntimeAdapter {
127
131
  resolveBindingTimeout(binding) {
128
132
  return resolveTimeoutMs(binding.langchainAgentParams?.model.init.timeout ?? binding.deepAgentParams?.model.init.timeout);
129
133
  }
130
- async withTimeout(producer, timeoutMs, operation) {
134
+ resolveStreamIdleTimeout(binding) {
135
+ const configuredIdleTimeout = resolveTimeoutMs(binding.langchainAgentParams?.model.init.streamIdleTimeout ?? binding.deepAgentParams?.model.init.streamIdleTimeout);
136
+ if (configuredIdleTimeout) {
137
+ return configuredIdleTimeout;
138
+ }
139
+ const invokeTimeout = this.resolveBindingTimeout(binding);
140
+ if (invokeTimeout) {
141
+ return Math.min(invokeTimeout, 15_000);
142
+ }
143
+ return 15_000;
144
+ }
145
+ async withTimeout(producer, timeoutMs, operation, stage = operation.includes("stream") ? "stream" : "invoke") {
131
146
  if (!timeoutMs) {
132
147
  return Promise.resolve(producer());
133
148
  }
134
149
  return new Promise((resolve, reject) => {
135
- const timer = setTimeout(() => reject(new RuntimeOperationTimeoutError(operation, timeoutMs)), timeoutMs);
150
+ const timer = setTimeout(() => reject(new RuntimeOperationTimeoutError(operation, timeoutMs, stage)), timeoutMs);
136
151
  Promise.resolve(producer()).then((value) => {
137
152
  clearTimeout(timer);
138
153
  resolve(value);
@@ -146,7 +161,7 @@ export class AgentRuntimeAdapter {
146
161
  const iterator = iterable[Symbol.asyncIterator]();
147
162
  try {
148
163
  for (;;) {
149
- const next = await this.withTimeout(() => iterator.next(), timeoutMs, operation);
164
+ const next = await this.withTimeout(() => iterator.next(), timeoutMs, operation, "stream");
150
165
  if (next.done) {
151
166
  return;
152
167
  }
@@ -251,7 +266,7 @@ export class AgentRuntimeAdapter {
251
266
  role: "user",
252
267
  content: `Original user request:\n${extractMessageText(input)}\n\nTool results:\n${toolContext}`,
253
268
  },
254
- ]), this.resolveBindingTimeout(binding), "deepagent synthesis invoke");
269
+ ]), this.resolveBindingTimeout(binding), "deepagent synthesis invoke", "invoke");
255
270
  return sanitizeVisibleText(extractVisibleOutput(synthesized));
256
271
  }
257
272
  async resolveModel(model) {
@@ -470,7 +485,7 @@ export class AgentRuntimeAdapter {
470
485
  let result;
471
486
  try {
472
487
  const runnable = await this.create(binding);
473
- result = (await this.withTimeout(() => runnable.invoke(request, { configurable: { thread_id: threadId } }), this.resolveBindingTimeout(binding), "agent invoke"));
488
+ result = (await this.withTimeout(() => runnable.invoke(request, { configurable: { thread_id: threadId } }), this.resolveBindingTimeout(binding), "agent invoke", "invoke"));
474
489
  }
475
490
  catch (error) {
476
491
  if (resumePayload !== undefined || !isToolCallParseFailure(error)) {
@@ -478,7 +493,7 @@ export class AgentRuntimeAdapter {
478
493
  }
479
494
  const retriedBinding = this.applyStrictToolJsonInstruction(binding);
480
495
  const runnable = await this.create(retriedBinding);
481
- result = (await this.withTimeout(() => runnable.invoke({ messages: this.buildAgentMessages(history, input) }, { configurable: { thread_id: threadId } }), this.resolveBindingTimeout(retriedBinding), "agent invoke"));
496
+ result = (await this.withTimeout(() => runnable.invoke({ messages: this.buildAgentMessages(history, input) }, { configurable: { thread_id: threadId } }), this.resolveBindingTimeout(retriedBinding), "agent invoke", "invoke"));
482
497
  }
483
498
  const interruptContent = Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? JSON.stringify(result.__interrupt__) : undefined;
484
499
  const extractedOutput = extractVisibleOutput(result);
@@ -501,7 +516,8 @@ export class AgentRuntimeAdapter {
501
516
  }
502
517
  async *stream(binding, input, threadId, history = []) {
503
518
  try {
504
- const timeoutMs = this.resolveBindingTimeout(binding);
519
+ const invokeTimeoutMs = this.resolveBindingTimeout(binding);
520
+ const streamIdleTimeoutMs = this.resolveStreamIdleTimeout(binding);
505
521
  if (binding.langchainAgentParams) {
506
522
  const langchainParams = binding.langchainAgentParams;
507
523
  const resolvedModel = (await this.resolveModel(binding.langchainAgentParams.model));
@@ -516,8 +532,8 @@ export class AgentRuntimeAdapter {
516
532
  // agent loop and only adds an extra model round-trip before the runnable path.
517
533
  if (canUseDirectModelStream && typeof model.stream === "function") {
518
534
  let emitted = false;
519
- const stream = await this.withTimeout(() => model.stream(this.buildRawModelMessages(langchainParams.systemPrompt, history, input)), timeoutMs, "model stream start");
520
- for await (const chunk of this.iterateWithTimeout(stream, timeoutMs, "model stream")) {
535
+ const stream = await this.withTimeout(() => model.stream(this.buildRawModelMessages(langchainParams.systemPrompt, history, input)), invokeTimeoutMs, "model stream start", "stream");
536
+ for await (const chunk of this.iterateWithTimeout(stream, streamIdleTimeoutMs, "model stream")) {
521
537
  const delta = readStreamDelta(chunk);
522
538
  if (delta) {
523
539
  emitted = true;
@@ -537,11 +553,11 @@ export class AgentRuntimeAdapter {
537
553
  const runnable = await this.create(binding);
538
554
  const request = { messages: this.buildAgentMessages(history, input) };
539
555
  if (typeof runnable.streamEvents === "function") {
540
- const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId }, version: "v2" }), timeoutMs, "agent streamEvents start");
556
+ const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId }, version: "v2" }), invokeTimeoutMs, "agent streamEvents start", "stream");
541
557
  let terminalOutput = "";
542
558
  const seenTerminalOutputs = new Set();
543
559
  let lastStep = "";
544
- for await (const event of this.iterateWithTimeout(events, timeoutMs, "agent streamEvents")) {
560
+ for await (const event of this.iterateWithTimeout(events, streamIdleTimeoutMs, "agent streamEvents")) {
545
561
  const interruptPayload = extractInterruptPayload(event);
546
562
  if (interruptPayload) {
547
563
  yield { kind: "interrupt", content: interruptPayload };
@@ -578,9 +594,9 @@ export class AgentRuntimeAdapter {
578
594
  }
579
595
  }
580
596
  if (binding.langchainAgentParams && typeof runnable.stream === "function") {
581
- const stream = await this.withTimeout(() => runnable.stream(request, { configurable: { thread_id: threadId } }), timeoutMs, "agent stream start");
597
+ const stream = await this.withTimeout(() => runnable.stream(request, { configurable: { thread_id: threadId } }), invokeTimeoutMs, "agent stream start", "stream");
582
598
  let emitted = false;
583
- for await (const chunk of this.iterateWithTimeout(stream, timeoutMs, "agent stream")) {
599
+ for await (const chunk of this.iterateWithTimeout(stream, streamIdleTimeoutMs, "agent stream")) {
584
600
  const delta = readStreamDelta(chunk);
585
601
  if (delta) {
586
602
  emitted = true;
@@ -628,7 +628,7 @@ export class AgentHarness {
628
628
  }) };
629
629
  return;
630
630
  }
631
- if (error instanceof RuntimeOperationTimeoutError) {
631
+ if (error instanceof RuntimeOperationTimeoutError && error.stage === "invoke") {
632
632
  yield { type: "event", event: await this.setRunStateAndEmit(threadId, runId, 4, "failed", {
633
633
  previousState: null,
634
634
  error: error.message,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.30",
3
+ "version": "0.0.31",
4
4
  "description": "Agent Harness framework package",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",