@botbotgo/agent-harness 0.0.32 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/agent-runtime-adapter.d.ts +1 -0
- package/dist/runtime/agent-runtime-adapter.js +65 -5
- package/dist/runtime/parsing/stream-event-parsing.d.ts +6 -0
- package/dist/runtime/parsing/stream-event-parsing.js +53 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.32";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.32";
|
|
@@ -15,6 +15,7 @@ declare class RuntimeOperationTimeoutError extends Error {
|
|
|
15
15
|
export declare class AgentRuntimeAdapter {
|
|
16
16
|
private readonly options;
|
|
17
17
|
constructor(options?: RuntimeAdapterOptions);
|
|
18
|
+
private canUseSimpleDeepAgentFastPath;
|
|
18
19
|
private resolveBindingTimeout;
|
|
19
20
|
private resolveStreamIdleTimeout;
|
|
20
21
|
private withTimeout;
|
|
@@ -8,7 +8,7 @@ import { ChatOpenAI } from "@langchain/openai";
|
|
|
8
8
|
import { createAgent, humanInTheLoopMiddleware, initChatModel } from "langchain";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
import { extractEmptyAssistantMessageFailure, extractReasoningText, extractToolFallbackContext, extractVisibleOutput, isLikelyToolArgsObject, isToolCallParseFailure, STRICT_TOOL_JSON_INSTRUCTION, sanitizeVisibleText, tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
|
|
11
|
-
import { extractAgentStep, extractInterruptPayload, extractReasoningStreamOutput, extractTerminalStreamOutput, extractToolResult, normalizeTerminalOutputKey, readStreamDelta, } from "./parsing/stream-event-parsing.js";
|
|
11
|
+
import { computeIncrementalOutput, extractAgentStep, extractInterruptPayload, extractReasoningStreamOutput, extractStateStreamOutput, extractVisibleStreamOutput, extractTerminalStreamOutput, extractToolResult, normalizeTerminalOutputKey, readStreamDelta, } from "./parsing/stream-event-parsing.js";
|
|
12
12
|
import { wrapToolForExecution } from "./tool-hitl.js";
|
|
13
13
|
import { resolveDeclaredMiddleware } from "./declared-middleware.js";
|
|
14
14
|
import { extractMessageText, normalizeMessageContent } from "../utils/message-content.js";
|
|
@@ -161,6 +161,25 @@ export class AgentRuntimeAdapter {
|
|
|
161
161
|
constructor(options = {}) {
|
|
162
162
|
this.options = options;
|
|
163
163
|
}
|
|
164
|
+
canUseSimpleDeepAgentFastPath(binding) {
|
|
165
|
+
const params = binding.deepAgentParams;
|
|
166
|
+
if (!params) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if ((params.subagents?.length ?? 0) > 0) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if ((params.memory?.length ?? 0) > 0) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
if ((params.skills?.length ?? 0) > 0) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
if (params.backend || params.store) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
164
183
|
resolveBindingTimeout(binding) {
|
|
165
184
|
return resolveTimeoutMs(binding.langchainAgentParams?.model.init.timeout ?? binding.deepAgentParams?.model.init.timeout);
|
|
166
185
|
}
|
|
@@ -468,6 +487,23 @@ export class AgentRuntimeAdapter {
|
|
|
468
487
|
if (!params) {
|
|
469
488
|
throw new Error(`Agent ${binding.agent.id} has no runnable params`);
|
|
470
489
|
}
|
|
490
|
+
if (this.canUseSimpleDeepAgentFastPath(binding)) {
|
|
491
|
+
const interruptOn = this.resolveInterruptOn(binding);
|
|
492
|
+
const model = (await this.resolveModel(params.model));
|
|
493
|
+
const tools = this.resolveTools(params.tools, binding);
|
|
494
|
+
if (tools.length > 0 && typeof model.bindTools !== "function") {
|
|
495
|
+
throw new Error(`Agent ${binding.agent.id} configures ${tools.length} tool(s), but resolved model ${params.model.id} does not support tool binding.`);
|
|
496
|
+
}
|
|
497
|
+
return createAgent({
|
|
498
|
+
model: model,
|
|
499
|
+
tools: tools,
|
|
500
|
+
systemPrompt: params.systemPrompt,
|
|
501
|
+
responseFormat: params.responseFormat,
|
|
502
|
+
contextSchema: params.contextSchema,
|
|
503
|
+
middleware: (await this.resolveMiddleware(binding, interruptOn)),
|
|
504
|
+
checkpointer: this.resolveCheckpointer(binding),
|
|
505
|
+
});
|
|
506
|
+
}
|
|
471
507
|
const deepAgentConfig = {
|
|
472
508
|
model: (await this.resolveModel(params.model)),
|
|
473
509
|
tools: this.resolveTools(params.tools, binding),
|
|
@@ -591,7 +627,8 @@ export class AgentRuntimeAdapter {
|
|
|
591
627
|
const request = { messages: this.buildAgentMessages(history, input) };
|
|
592
628
|
if (typeof runnable.streamEvents === "function") {
|
|
593
629
|
const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId }, version: "v2" }), invokeTimeoutMs, "agent streamEvents start", "stream");
|
|
594
|
-
|
|
630
|
+
const allowVisibleStreamDeltas = Boolean(binding.langchainAgentParams);
|
|
631
|
+
let emittedOutput = "";
|
|
595
632
|
const seenTerminalOutputs = new Set();
|
|
596
633
|
let lastStep = "";
|
|
597
634
|
for await (const event of this.iterateWithTimeout(events, streamIdleTimeoutMs, "agent streamEvents")) {
|
|
@@ -604,6 +641,26 @@ export class AgentRuntimeAdapter {
|
|
|
604
641
|
if (reasoning) {
|
|
605
642
|
yield { kind: "reasoning", content: reasoning };
|
|
606
643
|
}
|
|
644
|
+
if (allowVisibleStreamDeltas) {
|
|
645
|
+
const visibleStreamOutput = extractVisibleStreamOutput(event);
|
|
646
|
+
if (visibleStreamOutput) {
|
|
647
|
+
const nextOutput = computeIncrementalOutput(emittedOutput, visibleStreamOutput);
|
|
648
|
+
emittedOutput = nextOutput.accumulated;
|
|
649
|
+
if (nextOutput.delta) {
|
|
650
|
+
yield { kind: "content", content: nextOutput.delta };
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (binding.deepAgentParams) {
|
|
655
|
+
const stateStreamOutput = extractStateStreamOutput(event);
|
|
656
|
+
if (stateStreamOutput) {
|
|
657
|
+
const nextOutput = computeIncrementalOutput(emittedOutput, sanitizeVisibleText(stateStreamOutput));
|
|
658
|
+
emittedOutput = nextOutput.accumulated;
|
|
659
|
+
if (nextOutput.delta) {
|
|
660
|
+
yield { kind: "content", content: nextOutput.delta };
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
607
664
|
const agentStep = extractAgentStep(event);
|
|
608
665
|
if (agentStep && agentStep !== lastStep) {
|
|
609
666
|
lastStep = agentStep;
|
|
@@ -622,11 +679,14 @@ export class AgentRuntimeAdapter {
|
|
|
622
679
|
if (outputKey) {
|
|
623
680
|
seenTerminalOutputs.add(outputKey);
|
|
624
681
|
}
|
|
625
|
-
|
|
682
|
+
const nextOutput = computeIncrementalOutput(emittedOutput, sanitizeVisibleText(output));
|
|
683
|
+
emittedOutput = nextOutput.accumulated;
|
|
684
|
+
if (nextOutput.delta) {
|
|
685
|
+
yield { kind: "content", content: nextOutput.delta };
|
|
686
|
+
}
|
|
626
687
|
}
|
|
627
688
|
}
|
|
628
|
-
if (
|
|
629
|
-
yield { kind: "content", content: sanitizeVisibleText(terminalOutput) };
|
|
689
|
+
if (emittedOutput) {
|
|
630
690
|
return;
|
|
631
691
|
}
|
|
632
692
|
}
|
|
@@ -17,6 +17,8 @@ export type RuntimeStreamChunk = {
|
|
|
17
17
|
};
|
|
18
18
|
export declare function extractTerminalStreamOutput(event: unknown): string;
|
|
19
19
|
export declare function extractReasoningStreamOutput(event: unknown): string;
|
|
20
|
+
export declare function extractVisibleStreamOutput(event: unknown): string;
|
|
21
|
+
export declare function extractStateStreamOutput(event: unknown): string;
|
|
20
22
|
export declare function extractAgentStep(event: unknown): string | null;
|
|
21
23
|
export declare function extractToolResult(event: unknown): {
|
|
22
24
|
toolName: string;
|
|
@@ -24,4 +26,8 @@ export declare function extractToolResult(event: unknown): {
|
|
|
24
26
|
} | null;
|
|
25
27
|
export declare function extractInterruptPayload(event: unknown): string | null;
|
|
26
28
|
export declare function normalizeTerminalOutputKey(value: string): string;
|
|
29
|
+
export declare function computeIncrementalOutput(accumulated: string, next: string): {
|
|
30
|
+
accumulated: string;
|
|
31
|
+
delta: string;
|
|
32
|
+
};
|
|
27
33
|
export declare function readStreamDelta(chunk: unknown): string;
|
|
@@ -73,6 +73,29 @@ export function extractReasoningStreamOutput(event) {
|
|
|
73
73
|
const typed = event;
|
|
74
74
|
return typed.event === "on_chat_model_stream" ? extractReasoningText(typed.data?.chunk) : "";
|
|
75
75
|
}
|
|
76
|
+
export function extractVisibleStreamOutput(event) {
|
|
77
|
+
if (typeof event !== "object" || !event)
|
|
78
|
+
return "";
|
|
79
|
+
const typed = event;
|
|
80
|
+
return typed.event === "on_chat_model_stream" ? readTextContent(typed.data?.chunk) : "";
|
|
81
|
+
}
|
|
82
|
+
export function extractStateStreamOutput(event) {
|
|
83
|
+
if (typeof event !== "object" || !event)
|
|
84
|
+
return "";
|
|
85
|
+
const typed = event;
|
|
86
|
+
if (typed.event !== "on_chain_stream") {
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
const chunk = typed.data?.chunk;
|
|
90
|
+
if (typeof chunk !== "object" || !chunk) {
|
|
91
|
+
return "";
|
|
92
|
+
}
|
|
93
|
+
const record = chunk;
|
|
94
|
+
if (!("messages" in record) && !("output" in record)) {
|
|
95
|
+
return "";
|
|
96
|
+
}
|
|
97
|
+
return extractVisibleOutput(chunk);
|
|
98
|
+
}
|
|
76
99
|
export function extractAgentStep(event) {
|
|
77
100
|
if (typeof event !== "object" || !event)
|
|
78
101
|
return null;
|
|
@@ -156,6 +179,36 @@ export function extractInterruptPayload(event) {
|
|
|
156
179
|
export function normalizeTerminalOutputKey(value) {
|
|
157
180
|
return value.trim();
|
|
158
181
|
}
|
|
182
|
+
export function computeIncrementalOutput(accumulated, next) {
|
|
183
|
+
if (!next) {
|
|
184
|
+
return { accumulated, delta: "" };
|
|
185
|
+
}
|
|
186
|
+
if (!accumulated) {
|
|
187
|
+
return { accumulated: next, delta: next };
|
|
188
|
+
}
|
|
189
|
+
if (next === accumulated || accumulated.endsWith(next)) {
|
|
190
|
+
return { accumulated, delta: "" };
|
|
191
|
+
}
|
|
192
|
+
if (next.startsWith(accumulated)) {
|
|
193
|
+
return {
|
|
194
|
+
accumulated: next,
|
|
195
|
+
delta: next.slice(accumulated.length),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const overlapLength = Math.min(accumulated.length, next.length);
|
|
199
|
+
for (let size = overlapLength; size > 0; size -= 1) {
|
|
200
|
+
if (accumulated.slice(-size) === next.slice(0, size)) {
|
|
201
|
+
return {
|
|
202
|
+
accumulated: accumulated + next.slice(size),
|
|
203
|
+
delta: next.slice(size),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
accumulated: accumulated + next,
|
|
209
|
+
delta: next,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
159
212
|
export function readStreamDelta(chunk) {
|
|
160
213
|
return readTextContent(chunk);
|
|
161
214
|
}
|