@botbotgo/agent-harness 0.0.37 → 0.0.38
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/contracts/types.d.ts +2 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/agent-runtime-adapter.js +4 -2
- package/dist/runtime/harness.js +12 -1
- package/dist/runtime/parsing/stream-event-parsing.d.ts +2 -0
- package/dist/runtime/parsing/stream-event-parsing.js +35 -3
- package/dist/runtime/support/harness-support.d.ts +1 -0
- package/dist/runtime/support/harness-support.js +27 -0
- package/package.json +1 -1
|
@@ -236,6 +236,7 @@ export type RunListeners = {
|
|
|
236
236
|
onToolResult?: (item: {
|
|
237
237
|
toolName: string;
|
|
238
238
|
output: unknown;
|
|
239
|
+
isError?: boolean;
|
|
239
240
|
}) => void | Promise<void>;
|
|
240
241
|
};
|
|
241
242
|
export type MessageContentPart = {
|
|
@@ -289,6 +290,7 @@ export type HarnessStreamItem = {
|
|
|
289
290
|
agentId: string;
|
|
290
291
|
toolName: string;
|
|
291
292
|
output: unknown;
|
|
293
|
+
isError?: boolean;
|
|
292
294
|
};
|
|
293
295
|
export type TranscriptMessage = {
|
|
294
296
|
role: "user" | "assistant";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.37";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.37";
|
|
@@ -656,6 +656,7 @@ export class AgentRuntimeAdapter {
|
|
|
656
656
|
const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId }, version: "v2" }), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "agent streamEvents start", "stream");
|
|
657
657
|
const allowVisibleStreamDeltas = Boolean(binding.langchainAgentParams);
|
|
658
658
|
let emittedOutput = "";
|
|
659
|
+
let emittedToolError = false;
|
|
659
660
|
const seenTerminalOutputs = new Set();
|
|
660
661
|
let lastStep = "";
|
|
661
662
|
for await (const event of this.iterateWithTimeout(events, streamIdleTimeoutMs, "agent streamEvents", streamDeadlineAt, invokeTimeoutMs)) {
|
|
@@ -695,7 +696,8 @@ export class AgentRuntimeAdapter {
|
|
|
695
696
|
}
|
|
696
697
|
const toolResult = extractToolResult(event);
|
|
697
698
|
if (toolResult) {
|
|
698
|
-
|
|
699
|
+
emittedToolError = emittedToolError || toolResult.isError === true;
|
|
700
|
+
yield { kind: "tool-result", toolName: toolResult.toolName, output: toolResult.output, isError: toolResult.isError };
|
|
699
701
|
}
|
|
700
702
|
const output = extractTerminalStreamOutput(event);
|
|
701
703
|
if (output) {
|
|
@@ -713,7 +715,7 @@ export class AgentRuntimeAdapter {
|
|
|
713
715
|
}
|
|
714
716
|
}
|
|
715
717
|
}
|
|
716
|
-
if (emittedOutput) {
|
|
718
|
+
if (emittedOutput || emittedToolError) {
|
|
717
719
|
return;
|
|
718
720
|
}
|
|
719
721
|
}
|
package/dist/runtime/harness.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createResourceBackendResolver, createResourceToolResolver } from "../re
|
|
|
6
6
|
import { EventBus } from "./event-bus.js";
|
|
7
7
|
import { PolicyEngine } from "./policy-engine.js";
|
|
8
8
|
import { getRoutingSystemPrompt } from "../workspace/support/workspace-ref-utils.js";
|
|
9
|
-
import { createHarnessEvent, createPendingApproval, heuristicRoute, inferRoutingBindings, resolveDeterministicRouteIntent, renderRuntimeFailure, requiresResearchRoute, } from "./support/harness-support.js";
|
|
9
|
+
import { createHarnessEvent, createPendingApproval, heuristicRoute, inferRoutingBindings, resolveDeterministicRouteIntent, renderRuntimeFailure, renderToolFailure, requiresResearchRoute, } from "./support/harness-support.js";
|
|
10
10
|
import { createCheckpointerForConfig, createStoreForConfig } from "./support/runtime-factories.js";
|
|
11
11
|
import { resolveCompiledEmbeddingModel, resolveCompiledEmbeddingModelRef } from "./support/embedding-models.js";
|
|
12
12
|
import { resolveCompiledVectorStore, resolveCompiledVectorStoreRef } from "./support/vector-stores.js";
|
|
@@ -429,6 +429,7 @@ export class AgentHarness {
|
|
|
429
429
|
await this.notifyListener(listeners.onToolResult, {
|
|
430
430
|
toolName: item.toolName,
|
|
431
431
|
output: item.output,
|
|
432
|
+
isError: item.isError,
|
|
432
433
|
});
|
|
433
434
|
}
|
|
434
435
|
}
|
|
@@ -543,6 +544,7 @@ export class AgentHarness {
|
|
|
543
544
|
try {
|
|
544
545
|
const priorHistory = await this.loadPriorHistory(threadId, runId);
|
|
545
546
|
let assistantOutput = "";
|
|
547
|
+
const toolErrors = [];
|
|
546
548
|
for await (const chunk of this.runtimeAdapter.stream(binding, options.input, threadId, priorHistory)) {
|
|
547
549
|
if (chunk) {
|
|
548
550
|
const normalizedChunk = typeof chunk === "string"
|
|
@@ -591,6 +593,9 @@ export class AgentHarness {
|
|
|
591
593
|
continue;
|
|
592
594
|
}
|
|
593
595
|
if (normalizedChunk.kind === "tool-result") {
|
|
596
|
+
if (normalizedChunk.isError) {
|
|
597
|
+
toolErrors.push(renderToolFailure(normalizedChunk.toolName, normalizedChunk.output));
|
|
598
|
+
}
|
|
594
599
|
yield {
|
|
595
600
|
type: "tool-result",
|
|
596
601
|
threadId,
|
|
@@ -598,6 +603,7 @@ export class AgentHarness {
|
|
|
598
603
|
agentId: selectedAgentId,
|
|
599
604
|
toolName: normalizedChunk.toolName,
|
|
600
605
|
output: normalizedChunk.output,
|
|
606
|
+
isError: normalizedChunk.isError,
|
|
601
607
|
};
|
|
602
608
|
continue;
|
|
603
609
|
}
|
|
@@ -606,6 +612,11 @@ export class AgentHarness {
|
|
|
606
612
|
yield await this.emitOutputDeltaAndCreateItem(threadId, runId, selectedAgentId, normalizedChunk.content);
|
|
607
613
|
}
|
|
608
614
|
}
|
|
615
|
+
if (!assistantOutput && toolErrors.length > 0) {
|
|
616
|
+
assistantOutput = toolErrors.join("\n\n");
|
|
617
|
+
emitted = true;
|
|
618
|
+
yield await this.emitOutputDeltaAndCreateItem(threadId, runId, selectedAgentId, assistantOutput);
|
|
619
|
+
}
|
|
609
620
|
if (!assistantOutput) {
|
|
610
621
|
const actual = await this.invokeWithHistory(binding, options.input, threadId, runId);
|
|
611
622
|
if (actual.output) {
|
|
@@ -14,6 +14,7 @@ export type RuntimeStreamChunk = {
|
|
|
14
14
|
kind: "tool-result";
|
|
15
15
|
toolName: string;
|
|
16
16
|
output: unknown;
|
|
17
|
+
isError?: boolean;
|
|
17
18
|
};
|
|
18
19
|
export declare function extractTerminalStreamOutput(event: unknown): string;
|
|
19
20
|
export declare function extractReasoningStreamOutput(event: unknown): string;
|
|
@@ -23,6 +24,7 @@ export declare function extractAgentStep(event: unknown): string | null;
|
|
|
23
24
|
export declare function extractToolResult(event: unknown): {
|
|
24
25
|
toolName: string;
|
|
25
26
|
output: unknown;
|
|
27
|
+
isError?: boolean;
|
|
26
28
|
} | null;
|
|
27
29
|
export declare function extractInterruptPayload(event: unknown): string | null;
|
|
28
30
|
export declare function normalizeTerminalOutputKey(value: string): string;
|
|
@@ -50,6 +50,31 @@ function summarizeStepValue(value) {
|
|
|
50
50
|
function humanizeEventName(name) {
|
|
51
51
|
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[._-]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase();
|
|
52
52
|
}
|
|
53
|
+
function readToolErrorText(value) {
|
|
54
|
+
if (typeof value === "string") {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
if (value instanceof Error) {
|
|
58
|
+
return value.message;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value !== "object" || !value) {
|
|
61
|
+
return "";
|
|
62
|
+
}
|
|
63
|
+
const record = value;
|
|
64
|
+
for (const candidate of [record.error, record.message, record.detail, record.details]) {
|
|
65
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
66
|
+
return candidate;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
function isErrorLikeToolOutput(value) {
|
|
72
|
+
const message = readToolErrorText(value).trim();
|
|
73
|
+
if (!message) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return /(^|\b)(error|exception|failed|failure|denied|timed out|timeout|not permitted|eperm|eacces)(\b|:)/i.test(message);
|
|
77
|
+
}
|
|
53
78
|
export function extractTerminalStreamOutput(event) {
|
|
54
79
|
if (typeof event !== "object" || !event)
|
|
55
80
|
return "";
|
|
@@ -109,6 +134,10 @@ export function extractAgentStep(event) {
|
|
|
109
134
|
const outputSummary = formatStepValue(typed.data?.output, 80);
|
|
110
135
|
return outputSummary ? `tool ${name || "tool"} done ${outputSummary}` : `tool ${name || "tool"} done`;
|
|
111
136
|
}
|
|
137
|
+
if (typed.event === "on_tool_error" || (typed.event === "on_chain_error" && typed.run_type === "tool")) {
|
|
138
|
+
const errorSummary = formatStepValue(typed.data?.error ?? typed.data?.output, 80);
|
|
139
|
+
return errorSummary ? `tool ${name || "tool"} error ${errorSummary}` : `tool ${name || "tool"} error`;
|
|
140
|
+
}
|
|
112
141
|
if (typed.event === "on_chat_model_start") {
|
|
113
142
|
const inputTools = typed.data?.input?.tools;
|
|
114
143
|
const tools = typed.invocation_params?.tools ?? inputTools ?? [];
|
|
@@ -148,14 +177,17 @@ export function extractToolResult(event) {
|
|
|
148
177
|
return null;
|
|
149
178
|
const typed = event;
|
|
150
179
|
const isToolEnd = typed.event === "on_tool_end" || (typed.event === "on_chain_end" && typed.run_type === "tool");
|
|
180
|
+
const isToolError = typed.event === "on_tool_error" || (typed.event === "on_chain_error" && typed.run_type === "tool");
|
|
151
181
|
const toolName = typeof typed.name === "string" ? typed.name : "";
|
|
152
|
-
if (!isToolEnd || !toolName) {
|
|
182
|
+
if ((!isToolEnd && !isToolError) || !toolName) {
|
|
153
183
|
return null;
|
|
154
184
|
}
|
|
155
|
-
const rawOutput = typed.data?.output;
|
|
185
|
+
const rawOutput = isToolError ? typed.data?.error ?? typed.data?.output : typed.data?.output;
|
|
186
|
+
const normalizedOutput = typeof rawOutput === "string" ? parseMaybeJson(rawOutput) : rawOutput;
|
|
156
187
|
return {
|
|
157
188
|
toolName,
|
|
158
|
-
output:
|
|
189
|
+
output: normalizedOutput,
|
|
190
|
+
isError: isToolError || isErrorLikeToolOutput(normalizedOutput),
|
|
159
191
|
};
|
|
160
192
|
}
|
|
161
193
|
export function extractInterruptPayload(event) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ApprovalRecord, HarnessEvent, WorkspaceBundle } from "../../contracts/types.js";
|
|
2
2
|
export declare function renderRuntimeFailure(error: unknown): string;
|
|
3
|
+
export declare function renderToolFailure(toolName: string, output: unknown): string;
|
|
3
4
|
export declare function parseInterruptContent(content: string): {
|
|
4
5
|
toolName?: string;
|
|
5
6
|
toolId?: string;
|
|
@@ -3,6 +3,33 @@ export function renderRuntimeFailure(error) {
|
|
|
3
3
|
const message = error instanceof Error ? error.message : String(error);
|
|
4
4
|
return `runtime_error=${message}`.trim();
|
|
5
5
|
}
|
|
6
|
+
function readToolErrorMessage(output) {
|
|
7
|
+
if (typeof output === "string" && output.trim()) {
|
|
8
|
+
return output.trim();
|
|
9
|
+
}
|
|
10
|
+
if (output instanceof Error) {
|
|
11
|
+
return output.message;
|
|
12
|
+
}
|
|
13
|
+
if (typeof output !== "object" || !output) {
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
const record = output;
|
|
17
|
+
for (const candidate of [record.error, record.message, record.detail, record.details]) {
|
|
18
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
19
|
+
return candidate.trim();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
return JSON.stringify(output);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return String(output);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function renderToolFailure(toolName, output) {
|
|
30
|
+
const detail = readToolErrorMessage(output);
|
|
31
|
+
return detail ? `Tool ${toolName} failed: ${detail}` : `Tool ${toolName} failed.`;
|
|
32
|
+
}
|
|
6
33
|
export function parseInterruptContent(content) {
|
|
7
34
|
try {
|
|
8
35
|
const raw = JSON.parse(content);
|