@botbotgo/agent-harness 0.0.5 → 0.0.6
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.
|
@@ -5,7 +5,7 @@ import { ChatGoogle } from "@langchain/google";
|
|
|
5
5
|
import { ChatOllama } from "@langchain/ollama";
|
|
6
6
|
import { ChatOpenAI } from "@langchain/openai";
|
|
7
7
|
import { createAgent, humanInTheLoopMiddleware, initChatModel } from "langchain";
|
|
8
|
-
import { extractReasoningText, extractToolFallbackContext, extractVisibleOutput, isLikelyToolArgsObject, isToolCallParseFailure, STRICT_TOOL_JSON_INSTRUCTION, sanitizeVisibleText, tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
|
|
8
|
+
import { extractEmptyAssistantMessageFailure, extractReasoningText, extractToolFallbackContext, extractVisibleOutput, isLikelyToolArgsObject, isToolCallParseFailure, STRICT_TOOL_JSON_INSTRUCTION, sanitizeVisibleText, tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
|
|
9
9
|
import { extractAgentStep, extractInterruptPayload, extractReasoningStreamOutput, extractTerminalStreamOutput, extractToolResult, normalizeTerminalOutputKey, readStreamDelta, } from "./parsing/stream-event-parsing.js";
|
|
10
10
|
import { wrapToolForExecution } from "./tool-hitl.js";
|
|
11
11
|
const AGENT_INTERRUPT_SENTINEL_PREFIX = "__agent_harness_interrupt__:";
|
|
@@ -382,8 +382,13 @@ export class AgentRuntimeAdapter {
|
|
|
382
382
|
const interruptContent = Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? JSON.stringify(result.__interrupt__) : undefined;
|
|
383
383
|
const extractedOutput = extractVisibleOutput(result);
|
|
384
384
|
const visibleOutput = extractedOutput && !isLikelyToolArgsObject(tryParseJson(extractedOutput)) ? extractedOutput : "";
|
|
385
|
+
const emptyAssistantMessageFailure = extractEmptyAssistantMessageFailure(result);
|
|
385
386
|
const toolFallback = extractToolFallbackContext(result);
|
|
386
|
-
const
|
|
387
|
+
const synthesizedOutput = await this.synthesizeDeepAgentAnswer(binding, input, result);
|
|
388
|
+
if (!visibleOutput && !synthesizedOutput && !toolFallback && emptyAssistantMessageFailure) {
|
|
389
|
+
throw new Error(emptyAssistantMessageFailure);
|
|
390
|
+
}
|
|
391
|
+
const output = visibleOutput || synthesizedOutput || toolFallback || JSON.stringify(result, null, 2);
|
|
387
392
|
return {
|
|
388
393
|
threadId,
|
|
389
394
|
runId,
|
|
@@ -6,6 +6,7 @@ export declare function readTextContent(value: unknown): string;
|
|
|
6
6
|
export declare function hasToolCalls(value: unknown): boolean;
|
|
7
7
|
export declare function extractToolFallbackContext(value: unknown): string;
|
|
8
8
|
export declare function extractVisibleOutput(value: unknown): string;
|
|
9
|
+
export declare function extractEmptyAssistantMessageFailure(value: unknown): string;
|
|
9
10
|
export declare function isToolCallParseFailure(error: unknown): boolean;
|
|
10
11
|
export declare const STRICT_TOOL_JSON_INSTRUCTION = "When calling tools, return only the tool call itself. The arguments must be a pure JSON object with no explanatory text before or after it.";
|
|
11
12
|
export declare function wrapResolvedModel<T>(value: T): T;
|
|
@@ -225,19 +225,56 @@ function extractAssistantTextFromMessages(messages) {
|
|
|
225
225
|
: typeof message.getType === "function"
|
|
226
226
|
? message.getType()
|
|
227
227
|
: undefined;
|
|
228
|
+
if (!(typeName === "AIMessage" || runtimeType === "ai"))
|
|
229
|
+
continue;
|
|
228
230
|
const kwargs = typeof typed.kwargs === "object" && typed.kwargs ? typed.kwargs : undefined;
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return content;
|
|
237
|
-
}
|
|
231
|
+
if (hasToolCalls(message))
|
|
232
|
+
continue;
|
|
233
|
+
if (Array.isArray(kwargs?.tool_calls) && kwargs.tool_calls.length > 0)
|
|
234
|
+
continue;
|
|
235
|
+
const content = extractMessageContent(message);
|
|
236
|
+
if (content)
|
|
237
|
+
return content;
|
|
238
238
|
}
|
|
239
239
|
return "";
|
|
240
240
|
}
|
|
241
|
+
function extractEmptyAssistantMessageReason(messages) {
|
|
242
|
+
if (!Array.isArray(messages))
|
|
243
|
+
return null;
|
|
244
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
245
|
+
const message = messages[index];
|
|
246
|
+
if (typeof message !== "object" || !message)
|
|
247
|
+
continue;
|
|
248
|
+
const typed = message;
|
|
249
|
+
const ids = Array.isArray(typed.id) ? typed.id.filter((item) => typeof item === "string") : [];
|
|
250
|
+
const typeName = ids.at(-1);
|
|
251
|
+
const runtimeType = typeof message._getType === "function"
|
|
252
|
+
? message._getType()
|
|
253
|
+
: typeof message.getType === "function"
|
|
254
|
+
? message.getType()
|
|
255
|
+
: undefined;
|
|
256
|
+
const kwargs = typeof typed.kwargs === "object" && typed.kwargs ? typed.kwargs : undefined;
|
|
257
|
+
if (!(typeName === "AIMessage" || runtimeType === "ai")) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (hasToolCalls(message)) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
const content = extractMessageContent(message).trim();
|
|
264
|
+
if (content) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
const responseMetadata = typeof kwargs?.response_metadata === "object" && kwargs.response_metadata
|
|
268
|
+
? kwargs.response_metadata
|
|
269
|
+
: {};
|
|
270
|
+
return {
|
|
271
|
+
finishReason: typeof responseMetadata.finish_reason === "string" ? responseMetadata.finish_reason : undefined,
|
|
272
|
+
modelProvider: typeof responseMetadata.model_provider === "string" ? responseMetadata.model_provider : undefined,
|
|
273
|
+
modelName: typeof responseMetadata.model_name === "string" ? responseMetadata.model_name : undefined,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
241
278
|
function extractStructuredOutputText(value) {
|
|
242
279
|
if (typeof value !== "object" || !value)
|
|
243
280
|
return "";
|
|
@@ -304,6 +341,27 @@ export function extractVisibleOutput(value) {
|
|
|
304
341
|
}
|
|
305
342
|
return "";
|
|
306
343
|
}
|
|
344
|
+
export function extractEmptyAssistantMessageFailure(value) {
|
|
345
|
+
if (typeof value !== "object" || !value)
|
|
346
|
+
return "";
|
|
347
|
+
const typed = value;
|
|
348
|
+
const reason = extractEmptyAssistantMessageReason(typed.messages)
|
|
349
|
+
?? (typeof typed.output === "object" && typed.output
|
|
350
|
+
? extractEmptyAssistantMessageReason(typed.output.messages)
|
|
351
|
+
: null);
|
|
352
|
+
if (!reason) {
|
|
353
|
+
return "";
|
|
354
|
+
}
|
|
355
|
+
const detailParts = [
|
|
356
|
+
reason.finishReason ? `finish_reason=${reason.finishReason}` : "",
|
|
357
|
+
reason.modelProvider ? `model_provider=${reason.modelProvider}` : "",
|
|
358
|
+
reason.modelName ? `model_name=${reason.modelName}` : "",
|
|
359
|
+
].filter(Boolean);
|
|
360
|
+
return [
|
|
361
|
+
"empty_final_ai_message: model returned no visible assistant content and no tool calls",
|
|
362
|
+
detailParts.length > 0 ? `(${detailParts.join(", ")})` : "",
|
|
363
|
+
].filter(Boolean).join(" ");
|
|
364
|
+
}
|
|
307
365
|
function isAiMessageLike(value) {
|
|
308
366
|
if (typeof value !== "object" || !value)
|
|
309
367
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Agent Harness framework package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@botbotgo/agent-harness-builtin": "0.0.
|
|
28
|
+
"@botbotgo/agent-harness-builtin": "0.0.6"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -p tsconfig.json && cp -R config dist/",
|