@botbotgo/agent-harness 0.0.320 → 0.0.322
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/cli/chat-rendering.js +2 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/projections/presentation.js +14 -8
- package/dist/resources/prompts/runtime/autonomous-investigation-recovery.md +1 -0
- package/dist/runtime/parsing/output-recovery.d.ts +1 -1
- package/dist/runtime/parsing/output-recovery.js +95 -5
- package/dist/runtime/prompts/runtime-prompts.d.ts +1 -0
- package/dist/runtime/prompts/runtime-prompts.js +1 -0
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { markdownToConsole } from "../projections/presentation.js";
|
|
1
2
|
import { renderChatRuntimeFailure } from "./chat-workspace.js";
|
|
2
3
|
export function countRenderedLines(text) {
|
|
3
4
|
return text.replace(/\n$/, "").split("\n").length;
|
|
4
5
|
}
|
|
5
6
|
export function renderChatTextChunk(text, modelInfo) {
|
|
6
|
-
return renderChatRuntimeFailure(text, modelInfo);
|
|
7
|
+
return markdownToConsole(renderChatRuntimeFailure(text, modelInfo));
|
|
7
8
|
}
|
|
8
9
|
export function renderChatRequestRunning(input) {
|
|
9
10
|
const parts = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.321";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.321";
|
|
@@ -94,7 +94,7 @@ export function markdownToHtml(markdown) {
|
|
|
94
94
|
}
|
|
95
95
|
export function markdownToConsole(markdown) {
|
|
96
96
|
if (!markdown.includes("\n")) {
|
|
97
|
-
return renderInlineConsoleMarkdown(markdown);
|
|
97
|
+
return renderInlineConsoleMarkdown(markdown.trim());
|
|
98
98
|
}
|
|
99
99
|
const normalized = markdown.replace(/\r\n/g, "\n");
|
|
100
100
|
const blocks = normalized.split(/\n\n+/);
|
|
@@ -114,11 +114,12 @@ export function markdownToConsole(markdown) {
|
|
|
114
114
|
const language = lines[0]?.slice(3).trim();
|
|
115
115
|
const code = lines.slice(1, -1);
|
|
116
116
|
const label = language ? ` ${language} ` : " code ";
|
|
117
|
+
const borderWidth = Math.max(label.length, 6);
|
|
117
118
|
rendered.push([
|
|
118
|
-
`\u001b[2m┌${"─".repeat(
|
|
119
|
+
`\u001b[2m┌${"─".repeat(borderWidth)}\u001b[0m`,
|
|
119
120
|
`\u001b[2m│\u001b[0m${label}`,
|
|
120
121
|
...code.map((line) => ` ${line}`),
|
|
121
|
-
|
|
122
|
+
`\u001b[2m└${"─".repeat(borderWidth)}\u001b[0m`,
|
|
122
123
|
].join("\n"));
|
|
123
124
|
continue;
|
|
124
125
|
}
|
|
@@ -130,25 +131,30 @@ export function markdownToConsole(markdown) {
|
|
|
130
131
|
rendered.push(`\u001b[1m${title}\u001b[0m\n\u001b[2m${underline.repeat(Math.max(3, title.replace(/\u001b\[[0-9;]*m/g, "").length))}\u001b[0m`);
|
|
131
132
|
continue;
|
|
132
133
|
}
|
|
133
|
-
if (trimmed.split("\n").every((line) =>
|
|
134
|
+
if (trimmed.split("\n").every((line) => /^\s*[-*]\s+/.test(line))) {
|
|
134
135
|
rendered.push(trimmed
|
|
135
136
|
.split("\n")
|
|
136
|
-
.map((line) =>
|
|
137
|
+
.map((line) => {
|
|
138
|
+
const match = line.match(/^(\s*)[-*]\s+(.*)$/);
|
|
139
|
+
const indent = match?.[1] ?? "";
|
|
140
|
+
const content = match?.[2] ?? line;
|
|
141
|
+
return `${indent}• ${content}`;
|
|
142
|
+
})
|
|
137
143
|
.map((line) => renderInlineConsoleMarkdown(line))
|
|
138
144
|
.join("\n"));
|
|
139
145
|
continue;
|
|
140
146
|
}
|
|
141
|
-
if (trimmed.split("\n").every((line) => /^\d+\.\s+/.test(line))) {
|
|
147
|
+
if (trimmed.split("\n").every((line) => /^\s*\d+\.\s+/.test(line))) {
|
|
142
148
|
rendered.push(trimmed
|
|
143
149
|
.split("\n")
|
|
144
150
|
.map((line) => renderInlineConsoleMarkdown(line))
|
|
145
151
|
.join("\n"));
|
|
146
152
|
continue;
|
|
147
153
|
}
|
|
148
|
-
if (trimmed.split("\n").every((line) =>
|
|
154
|
+
if (trimmed.split("\n").every((line) => /^\s*>\s?/.test(line))) {
|
|
149
155
|
rendered.push(trimmed
|
|
150
156
|
.split("\n")
|
|
151
|
-
.map((line) => line.replace(
|
|
157
|
+
.map((line) => line.replace(/^\s*>\s?/, ""))
|
|
152
158
|
.map((line) => `\u001b[2m│\u001b[0m ${renderInlineConsoleMarkdown(line)}`)
|
|
153
159
|
.join("\n"));
|
|
154
160
|
continue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Do not stop at a plan or ask the user to choose the next obvious diagnostic step when the request is for deep investigation, root-cause analysis, or step-by-step execution and tool evidence already exists in the conversation. Continue the investigation yourself with the next concrete tool call. If the task is non-trivial, call write_todos, then keep executing the next diagnostic steps until you can explain the likely causes, impact, and recommended next actions.
|
|
@@ -11,4 +11,4 @@ export declare function resolveExecutionWithoutToolEvidenceTextInstruction(reque
|
|
|
11
11
|
export declare function resolveToolCallRecoveryInstruction(error: unknown): string | null;
|
|
12
12
|
export declare function appendToolRecoveryInstruction(input: unknown, instruction: string): unknown;
|
|
13
13
|
export declare function wrapResolvedModel<T>(value: T): T;
|
|
14
|
-
export { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION } from "../prompts/runtime-prompts.js";
|
|
14
|
+
export { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION } from "../prompts/runtime-prompts.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION, } from "../prompts/runtime-prompts.js";
|
|
1
|
+
import { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION, } from "../prompts/runtime-prompts.js";
|
|
2
2
|
import { hasToolCalls, readTextContent, wrapNormalizedMessage } from "./output-content.js";
|
|
3
3
|
function isToolCallParseFailure(error) {
|
|
4
4
|
if (!(error instanceof Error))
|
|
@@ -123,6 +123,71 @@ function extractLastUserMessageText(input) {
|
|
|
123
123
|
}
|
|
124
124
|
return "";
|
|
125
125
|
}
|
|
126
|
+
function extractAllUserMessageText(input) {
|
|
127
|
+
if (!Array.isArray(input) && !(typeof input === "object" && input && Array.isArray(input.messages))) {
|
|
128
|
+
return "";
|
|
129
|
+
}
|
|
130
|
+
const messages = Array.isArray(input) ? input : input.messages;
|
|
131
|
+
const values = [];
|
|
132
|
+
for (const message of messages) {
|
|
133
|
+
if (typeof message !== "object" || !message)
|
|
134
|
+
continue;
|
|
135
|
+
const typed = message;
|
|
136
|
+
if (typed.role === "user") {
|
|
137
|
+
const text = extractMessageContent(message).trim();
|
|
138
|
+
if (text)
|
|
139
|
+
values.push(text);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const ids = Array.isArray(typed.id) ? typed.id.filter((item) => typeof item === "string") : [];
|
|
143
|
+
const typeName = ids.at(-1);
|
|
144
|
+
const runtimeType = typeof message._getType === "function"
|
|
145
|
+
? message._getType()
|
|
146
|
+
: typeof message.getType === "function"
|
|
147
|
+
? message.getType()
|
|
148
|
+
: undefined;
|
|
149
|
+
if (typeName === "HumanMessage" || runtimeType === "human") {
|
|
150
|
+
const text = extractMessageContent(message).trim();
|
|
151
|
+
if (text)
|
|
152
|
+
values.push(text);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (typeof typed.kwargs === "object" && typed.kwargs && typed.kwargs.role === "user") {
|
|
156
|
+
const text = extractMessageContent(message).trim();
|
|
157
|
+
if (text)
|
|
158
|
+
values.push(text);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return values.join("\n").trim();
|
|
162
|
+
}
|
|
163
|
+
function hasToolResultEvidence(input) {
|
|
164
|
+
if (!Array.isArray(input) && !(typeof input === "object" && input && Array.isArray(input.messages))) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
const messages = Array.isArray(input) ? input : input.messages;
|
|
168
|
+
for (const message of messages) {
|
|
169
|
+
if (typeof message !== "object" || !message)
|
|
170
|
+
continue;
|
|
171
|
+
const typed = message;
|
|
172
|
+
if (typed.role === "tool") {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
const ids = Array.isArray(typed.id) ? typed.id.filter((item) => typeof item === "string") : [];
|
|
176
|
+
const typeName = ids.at(-1);
|
|
177
|
+
const runtimeType = typeof message._getType === "function"
|
|
178
|
+
? message._getType()
|
|
179
|
+
: typeof message.getType === "function"
|
|
180
|
+
? message.getType()
|
|
181
|
+
: undefined;
|
|
182
|
+
if (typeName === "ToolMessage" || runtimeType === "tool") {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (typeof typed.kwargs === "object" && typed.kwargs && typed.kwargs.role === "tool") {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
126
191
|
function isToolRequiredExecutionPrompt(text) {
|
|
127
192
|
if (!text)
|
|
128
193
|
return false;
|
|
@@ -130,6 +195,12 @@ function isToolRequiredExecutionPrompt(text) {
|
|
|
130
195
|
/\b(create|write|edit|read|show|display|append|run|execute|wait|sleep|repeat|loop|file|files|command)\b/i.test(text) ||
|
|
131
196
|
/(创建|写入|读取|显示|追加|执行|运行|等待|重复|文件|命令|步骤)/.test(text));
|
|
132
197
|
}
|
|
198
|
+
function isAutonomousInvestigationPrompt(text) {
|
|
199
|
+
if (!text)
|
|
200
|
+
return false;
|
|
201
|
+
return (/\b(root cause|rca|deep investigation|investigate deeply|investigate fully|step by step|find all (?:issues|problems|causes)|continue investigating|keep digging|until complete|until you find)\b/i.test(text) ||
|
|
202
|
+
/(根因分析|深度调查|深入调查|一步一步|逐步分析|逐个分析|继续排查|排查到底|找到所有问题|查出所有问题|直到完成|直到找到.*原因)/.test(text));
|
|
203
|
+
}
|
|
133
204
|
function isBrowserOrUrlTask(text) {
|
|
134
205
|
if (!text)
|
|
135
206
|
return false;
|
|
@@ -149,6 +220,18 @@ function claimsMissingBrowserCapability(text) {
|
|
|
149
220
|
return (/\b(i do not have the capability to access external websites|i do not have access to external websites|i cannot access external websites|i can(?:not|'t) browse|i do not have (?:direct )?(?:web|browser|browsing) access|i do not have .*tool.*(?:website|url|browser)|i cannot summarize .* because .*tool.*failed|please provide (?:the )?text content.*i (?:will|can) summarize)\b/i.test(text) ||
|
|
150
221
|
/(我没有直接访问外部网站|我无法直接访问外部网站|我无法访问外部网站|我不能访问外部网站|我无法直接访问外部网站内容|我无法访问网页|请提供文本内容.*我将为您进行总结|我没有.*浏览.*工具|我没有.*网页抓取.*工具|我没有.*访问.*网站.*工具|我无法总结该网页内容,因为.*工具执行失败)/.test(text));
|
|
151
222
|
}
|
|
223
|
+
function asksUserToChooseObviousNextDiagnosticStep(text) {
|
|
224
|
+
if (!text)
|
|
225
|
+
return false;
|
|
226
|
+
return (/\b(which (?:direction|aspect|node|namespace|part)|what would you like me to check|please choose|please tell me (?:which|what|where) .* (?:check|inspect|investigate)|which .* should we start with)\b/i.test(text) ||
|
|
227
|
+
/(请告诉我.*(哪个|哪一个|什么方向)|请选择.*(方向|项目|节点)|您希望我.*(检查|查看).*(哪个|哪一个|方向)|从哪个方向开始)/.test(text));
|
|
228
|
+
}
|
|
229
|
+
function claimsFutureExecutionWithoutToolEvidence(text) {
|
|
230
|
+
if (!text)
|
|
231
|
+
return false;
|
|
232
|
+
return (/\b(i will|i'll|we will|next i(?:'ll| will)|i am going to)\b.*\b(run|execute|inspect|check|investigate|continue|start)\b/i.test(text) ||
|
|
233
|
+
/(我将|我会|接下来我会|现在我将|我将继续).*(执行|检查|查看|调查|排查|开始|继续)/.test(text));
|
|
234
|
+
}
|
|
152
235
|
export function isRetrySafeInvalidToolSelectionError(value) {
|
|
153
236
|
const text = readTextContent(value).trim();
|
|
154
237
|
if (!text)
|
|
@@ -156,9 +239,9 @@ export function isRetrySafeInvalidToolSelectionError(value) {
|
|
|
156
239
|
return /is not a valid tool, try one of \[/i.test(text);
|
|
157
240
|
}
|
|
158
241
|
export function shouldValidateExecutionWithoutToolEvidence(request) {
|
|
159
|
-
const userText =
|
|
242
|
+
const userText = extractAllUserMessageText(request);
|
|
160
243
|
const browserOrUrlTask = isBrowserOrUrlTask(userText);
|
|
161
|
-
return browserOrUrlTask || isToolRequiredExecutionPrompt(userText);
|
|
244
|
+
return browserOrUrlTask || isToolRequiredExecutionPrompt(userText) || isAutonomousInvestigationPrompt(userText);
|
|
162
245
|
}
|
|
163
246
|
function extractAssistantTextFromResult(result) {
|
|
164
247
|
if (typeof result === "object" && result && "messages" in result) {
|
|
@@ -192,14 +275,21 @@ export function resolveExecutionWithoutToolEvidenceInstruction(request, result)
|
|
|
192
275
|
return resolveExecutionWithoutToolEvidenceTextInstruction(request, assistantText, hasToolCalls(result));
|
|
193
276
|
}
|
|
194
277
|
export function resolveExecutionWithoutToolEvidenceTextInstruction(request, assistantText, toolCallEvidence = false) {
|
|
195
|
-
const userText =
|
|
278
|
+
const userText = extractAllUserMessageText(request);
|
|
196
279
|
const browserOrUrlTask = isBrowserOrUrlTask(userText);
|
|
280
|
+
const autonomousInvestigationTask = isAutonomousInvestigationPrompt(userText);
|
|
281
|
+
const toolResultEvidence = hasToolResultEvidence(request);
|
|
197
282
|
if (!shouldValidateExecutionWithoutToolEvidence(request)) {
|
|
198
283
|
return null;
|
|
199
284
|
}
|
|
200
285
|
if (!assistantText || toolCallEvidence) {
|
|
201
286
|
return null;
|
|
202
287
|
}
|
|
288
|
+
if (autonomousInvestigationTask &&
|
|
289
|
+
toolResultEvidence &&
|
|
290
|
+
(asksUserToChooseObviousNextDiagnosticStep(assistantText) || claimsFutureExecutionWithoutToolEvidence(assistantText))) {
|
|
291
|
+
return AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION;
|
|
292
|
+
}
|
|
203
293
|
if (browserOrUrlTask && claimsMissingBrowserCapability(assistantText)) {
|
|
204
294
|
return BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION;
|
|
205
295
|
}
|
|
@@ -285,4 +375,4 @@ export function wrapResolvedModel(value) {
|
|
|
285
375
|
},
|
|
286
376
|
});
|
|
287
377
|
}
|
|
288
|
-
export { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION } from "../prompts/runtime-prompts.js";
|
|
378
|
+
export { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION } from "../prompts/runtime-prompts.js";
|
|
@@ -9,6 +9,7 @@ export declare const WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION: string;
|
|
|
9
9
|
export declare const WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION: string;
|
|
10
10
|
export declare const EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION: string;
|
|
11
11
|
export declare const EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION: string;
|
|
12
|
+
export declare const AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION: string;
|
|
12
13
|
export declare const WORKSPACE_RELATIVE_PATH_INSTRUCTION: string;
|
|
13
14
|
export declare function renderDurableMemoryContextPrompt(memoryContext: string): string;
|
|
14
15
|
export declare function renderSlashCommandSkillInstruction(input: {
|
|
@@ -12,6 +12,7 @@ export const WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION = readRuntimePrompt(
|
|
|
12
12
|
export const WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION = readRuntimePrompt("write-todos-descriptive-content");
|
|
13
13
|
export const EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION = readRuntimePrompt("execution-with-tool-evidence");
|
|
14
14
|
export const EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION = readRuntimePrompt("execution-with-tool-evidence-retry");
|
|
15
|
+
export const AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION = readRuntimePrompt("autonomous-investigation-recovery");
|
|
15
16
|
export const WORKSPACE_RELATIVE_PATH_INSTRUCTION = readRuntimePrompt("workspace-relative-path");
|
|
16
17
|
export function renderDurableMemoryContextPrompt(memoryContext) {
|
|
17
18
|
return renderBundledTemplate("prompts/runtime/durable-memory-context.md", {
|