@botbotgo/runtime 1.0.3 → 1.1.0

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.
@@ -4,7 +4,6 @@ on:
4
4
  push:
5
5
  branches:
6
6
  - master
7
- - main
8
7
  workflow_dispatch:
9
8
  repository_dispatch:
10
9
  types:
package/dist/index.d.ts CHANGED
@@ -6,4 +6,6 @@ export { createRuntime2TreeEventListener } from "@botbotgo/common";
6
6
  export type { Runtime2EventDebugConfig, Runtime2EventRuntimeConfig, Runtime2TreeEventListenerOptions, } from "@botbotgo/common";
7
7
  export { clearAgentRuntimeGlobalContext, getAgentRuntimeGlobal, getAgentRuntimeGlobalContext, getOrRegisterAgentRuntimeGlobal, registerAgentRuntimeGlobal, requireAgentRuntimeChatModel, requireAgentRuntimeContextValue, requireAgentRuntimeMemory, requireAgentRuntimeTools, } from "./runtime/index.js";
8
8
  export type { AgentRuntimeGlobalContext } from "./runtime/index.js";
9
+ export { runWithTextToolCallRecovery } from "./runtime/toolCallRecovery.js";
10
+ export type { ToolCallRecoveryResult } from "./runtime/toolCallRecovery.js";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EACV,kCAAkC,EAClC,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,4BAA4B,EAC5B,+BAA+B,EAC/B,0BAA0B,EAC1B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EACV,kCAAkC,EAClC,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,4BAA4B,EAC5B,+BAA+B,EAC/B,0BAA0B,EAC1B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/index.js CHANGED
@@ -2,4 +2,5 @@ export { AgentRuntimeService, createAgentRuntime2, initializeAgentRuntimeModules
2
2
  export { ConsoleHumanLoopService, createDefaultHumanLoopToolPolicy, } from "./runtime/index.js";
3
3
  export { createRuntime2TreeEventListener } from "@botbotgo/common";
4
4
  export { clearAgentRuntimeGlobalContext, getAgentRuntimeGlobal, getAgentRuntimeGlobalContext, getOrRegisterAgentRuntimeGlobal, registerAgentRuntimeGlobal, requireAgentRuntimeChatModel, requireAgentRuntimeContextValue, requireAgentRuntimeMemory, requireAgentRuntimeTools, } from "./runtime/index.js";
5
+ export { runWithTextToolCallRecovery } from "./runtime/toolCallRecovery.js";
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAU5B,OAAO,EACL,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AAMnE,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,4BAA4B,EAC5B,+BAA+B,EAC/B,0BAA0B,EAC1B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAU5B,OAAO,EACL,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AAMnE,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,4BAA4B,EAC5B,+BAA+B,EAC/B,0BAA0B,EAC1B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,18 @@
1
+ type RuntimeLike = {
2
+ context?: {
3
+ get?: (token: unknown) => unknown;
4
+ };
5
+ run: (input: string, onProgress?: (event: unknown) => void) => Promise<unknown>;
6
+ };
7
+ type RecoveryHint = {
8
+ windowId?: number;
9
+ tabIndex?: number;
10
+ sessionId?: string;
11
+ };
12
+ export type ToolCallRecoveryResult = {
13
+ recovered: boolean;
14
+ text: string;
15
+ };
16
+ export declare function runWithTextToolCallRecovery(runtime: RuntimeLike, input: string, onProgress: (event: unknown) => void, hint?: RecoveryHint): Promise<ToolCallRecoveryResult>;
17
+ export {};
18
+ //# sourceMappingURL=toolCallRecovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolCallRecovery.d.ts","sourceRoot":"","sources":["../../src/runtime/toolCallRecovery.ts"],"names":[],"mappings":"AAEA,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;KAAE,CAAC;IAChD,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACjF,CAAC;AAOF,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAcF,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAoOF,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACpC,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,sBAAsB,CAAC,CAoFjC"}
@@ -0,0 +1,304 @@
1
+ import { AgentContextTokens } from "@botbotgo/common";
2
+ function asString(value) {
3
+ return typeof value === "string" ? value : "";
4
+ }
5
+ function extractText(response) {
6
+ if (typeof response === "string")
7
+ return response;
8
+ if (!response || typeof response !== "object")
9
+ return "";
10
+ const typed = response;
11
+ if (typeof typed.text === "string")
12
+ return typed.text;
13
+ if (Array.isArray(typed.messages)) {
14
+ const last = [...typed.messages].reverse().find((m) => typeof m?.content === "string");
15
+ if (last && typeof last.content === "string")
16
+ return last.content;
17
+ }
18
+ return "";
19
+ }
20
+ function normalizeSimpleName(name) {
21
+ const trimmed = name.trim().replace(/^['"]|['"]$/g, "");
22
+ const base = trimmed.includes(".") ? trimmed.split(".").pop() ?? trimmed : trimmed;
23
+ return base.replace(/^tool[-_.]buildin[-_.]/i, "").replace(/[^a-z0-9]/gi, "").toLowerCase();
24
+ }
25
+ function canonicalToolName(name) {
26
+ const simple = normalizeSimpleName(name);
27
+ if (simple === "ls" || simple === "listdir")
28
+ return "listdir";
29
+ if (simple === "readtext")
30
+ return "readtext";
31
+ if (simple === "runcommandinsession" || simple === "itermruncommandinsession" || simple === "executeshell") {
32
+ return "itermruncommandinsession";
33
+ }
34
+ return simple;
35
+ }
36
+ function extractJsonObject(raw) {
37
+ const start = raw.indexOf("{");
38
+ const end = raw.lastIndexOf("}");
39
+ if (start === -1 || end === -1 || end <= start)
40
+ return null;
41
+ return raw.slice(start, end + 1);
42
+ }
43
+ function parseJsonObject(raw) {
44
+ const jsonSlice = extractJsonObject(raw);
45
+ if (!jsonSlice)
46
+ return null;
47
+ try {
48
+ const parsed = JSON.parse(jsonSlice);
49
+ return parsed && typeof parsed === "object" ? parsed : null;
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ function parseToolCall(text) {
56
+ const toolCallBlock = text.match(/<tool[-_]call>\s*([\s\S]*?)(?:<\/tool[-_]call>|$)/i);
57
+ if (toolCallBlock) {
58
+ const obj = parseJsonObject(toolCallBlock[1]);
59
+ if (obj && typeof obj.name === "string") {
60
+ const args = obj.arguments && typeof obj.arguments === "object" ? obj.arguments : {};
61
+ return { name: obj.name, arguments: args, raw: toolCallBlock[0] };
62
+ }
63
+ }
64
+ const callTool = text.match(/<call-tool\s+name="([^"]+)"\s+arguments=({[\s\S]*?})[^>]*>/i);
65
+ if (callTool) {
66
+ const args = parseJsonObject(callTool[2]) ?? {};
67
+ return { name: callTool[1], arguments: args, raw: callTool[0] };
68
+ }
69
+ const executeShell = text.match(/<function=execute_shell>[\s\S]*?<parameter=command>([\s\S]*?)<\/parameter>/i);
70
+ if (executeShell) {
71
+ return {
72
+ name: "itermRunCommandInSession",
73
+ arguments: { command: executeShell[1].trim() },
74
+ raw: executeShell[0],
75
+ };
76
+ }
77
+ const simpleLs = text.match(/\bls\s*\(\s*path\s*=\s*"([^"]+)"\s*\)/i);
78
+ if (simpleLs) {
79
+ return { name: "listDir", arguments: { path: simpleLs[1] }, raw: simpleLs[0] };
80
+ }
81
+ return null;
82
+ }
83
+ function getTools(runtime) {
84
+ const tools = runtime.context?.get?.(AgentContextTokens.Tools);
85
+ return Array.isArray(tools) ? tools : [];
86
+ }
87
+ function findTool(tools, requestedName) {
88
+ const requested = canonicalToolName(requestedName);
89
+ return tools.find((tool) => typeof tool.name === "string" && canonicalToolName(tool.name) === requested) ?? null;
90
+ }
91
+ function extractToolOutput(result) {
92
+ if (typeof result === "string")
93
+ return result;
94
+ if (!result || typeof result !== "object")
95
+ return "";
96
+ const top = result;
97
+ const root = (top.result && typeof top.result === "object" ? top.result : top);
98
+ if (typeof root.outputText === "string")
99
+ return root.outputText;
100
+ if (typeof root.output === "string")
101
+ return root.output;
102
+ if (root.output && typeof root.output === "object") {
103
+ const outputObj = root.output;
104
+ if (typeof outputObj.output === "string")
105
+ return outputObj.output;
106
+ if (outputObj.result && typeof outputObj.result === "object") {
107
+ const nested = outputObj.result;
108
+ if (typeof nested.output === "string")
109
+ return nested.output;
110
+ }
111
+ }
112
+ return "";
113
+ }
114
+ function extractListEntries(result) {
115
+ if (!result || typeof result !== "object")
116
+ return [];
117
+ const top = result;
118
+ const root = (top.result && typeof top.result === "object" ? top.result : top);
119
+ const entries = root.entries;
120
+ if (Array.isArray(entries)) {
121
+ return entries
122
+ .map((entry) => (entry && typeof entry === "object" ? asString(entry.name) : ""))
123
+ .filter(Boolean)
124
+ .slice(0, 8);
125
+ }
126
+ return [];
127
+ }
128
+ function hasToolMessage(response) {
129
+ if (!response || typeof response !== "object")
130
+ return false;
131
+ const typed = response;
132
+ return Array.isArray(typed.messages) && typed.messages.some((m) => m?.type === "tool");
133
+ }
134
+ function findBlockedToolHint(response) {
135
+ if (!response || typeof response !== "object")
136
+ return null;
137
+ const typed = response;
138
+ if (!Array.isArray(typed.messages))
139
+ return null;
140
+ for (const msg of typed.messages) {
141
+ if (msg?.type !== "tool" || typeof msg.content !== "string")
142
+ continue;
143
+ const parsed = parseJsonObject(msg.content);
144
+ if (!parsed)
145
+ continue;
146
+ const result = parsed.result;
147
+ if (!result || typeof result !== "object")
148
+ continue;
149
+ const obj = result;
150
+ if (obj.blocked === true || typeof obj.blockedTool === "string") {
151
+ const required = asString(obj.requiredTool);
152
+ const blockedTool = asString(obj.blockedTool);
153
+ const toolName = required || blockedTool || "required tool";
154
+ return `I found blocked local tool result evidence and need \`${toolName}\` to continue safely.`;
155
+ }
156
+ }
157
+ return null;
158
+ }
159
+ function buildEvidenceSummary(records) {
160
+ const lines = [];
161
+ lines.push("### Baseline Evidence");
162
+ for (const rec of records) {
163
+ lines.push(`- Tool: ${rec.toolName}`);
164
+ if (rec.entries.length > 0) {
165
+ lines.push(`- Entries: ${rec.entries.join(", ")}`);
166
+ }
167
+ if (rec.output) {
168
+ lines.push(`- Evidence Preview:\n${rec.output.slice(0, 1600)}`);
169
+ }
170
+ }
171
+ return lines.join("\n");
172
+ }
173
+ function buildRecoveryPrompt(userInput, records) {
174
+ return [
175
+ `User request: ${userInput}`,
176
+ "",
177
+ buildEvidenceSummary(records),
178
+ "",
179
+ "Use only the evidence above to continue.",
180
+ "If another tool is absolutely required, return exactly one tool call.",
181
+ ].join("\n");
182
+ }
183
+ function buildScopeNarrowing(records, operational) {
184
+ const latest = records[records.length - 1];
185
+ const names = latest?.entries ?? [];
186
+ if (operational) {
187
+ return [
188
+ "I need a narrower operational scope before continuing from this command evidence.",
189
+ "Specify the target service/pod/node, exact command family, and expected signal.",
190
+ ].join(" ");
191
+ }
192
+ if (names.length === 0) {
193
+ return [
194
+ "I need a narrower scope before continuing from the current directory context.",
195
+ "Specify the file, folder, diff, or PR you want analyzed next.",
196
+ ].join(" ");
197
+ }
198
+ return [
199
+ `I need a narrower scope before continuing. Current directory context includes: ${names.join(", ")}.`,
200
+ "Specify the file, folder, diff, or PR you want analyzed next.",
201
+ ].join(" ");
202
+ }
203
+ function shouldForceScopeQuestion(text) {
204
+ return /function:\s*ask_/i.test(text) || /please specify the file/i.test(text);
205
+ }
206
+ function isHiddenSubagentRequest(text) {
207
+ return /<function=task>/i.test(text) || /subagent_to_spawn/i.test(text);
208
+ }
209
+ function isRawShellOutput(text) {
210
+ return /^Filesystem/m.test(text) || /\n\/dev\//.test(text);
211
+ }
212
+ async function bootstrapTargetPanelEvidence(runtime, hint) {
213
+ const tools = getTools(runtime);
214
+ const commandTool = findTool(tools, "itermRunCommandInSession");
215
+ if (!commandTool?.invoke)
216
+ return "";
217
+ const command = process.env.ITB_BOOTSTRAP_EVIDENCE_COMMAND || "pwd";
218
+ const output = await commandTool.invoke({
219
+ command,
220
+ windowId: hint?.windowId,
221
+ tabIndex: hint?.tabIndex,
222
+ sessionId: hint?.sessionId,
223
+ maxOutputLines: 120,
224
+ });
225
+ return extractToolOutput(output);
226
+ }
227
+ export async function runWithTextToolCallRecovery(runtime, input, onProgress, hint) {
228
+ const firstResponse = await runtime.run(input, onProgress);
229
+ let currentResponse = firstResponse;
230
+ let currentText = extractText(firstResponse);
231
+ const tools = getTools(runtime);
232
+ const records = [];
233
+ let recovered = false;
234
+ if (isHiddenSubagentRequest(currentText)) {
235
+ return {
236
+ recovered: true,
237
+ text: "I will not spawn a hidden subagent. I need a narrower operational scope to continue safely.",
238
+ };
239
+ }
240
+ for (let i = 0; i < 3; i += 1) {
241
+ const parsed = parseToolCall(currentText);
242
+ if (!parsed)
243
+ break;
244
+ const tool = findTool(tools, parsed.name);
245
+ if (!tool?.invoke) {
246
+ return { recovered: false, text: currentText || parsed.raw };
247
+ }
248
+ const toolResult = await tool.invoke(parsed.arguments);
249
+ recovered = true;
250
+ const output = extractToolOutput(toolResult);
251
+ const entries = extractListEntries(toolResult);
252
+ records.push({ toolName: parsed.name, output, entries });
253
+ currentResponse = await runtime.run(buildRecoveryPrompt(input, records), onProgress);
254
+ currentText = extractText(currentResponse);
255
+ if (isHiddenSubagentRequest(currentText)) {
256
+ return {
257
+ recovered: true,
258
+ text: "I will not spawn a hidden subagent. I need a narrower operational scope to continue safely.",
259
+ };
260
+ }
261
+ }
262
+ if (recovered) {
263
+ if (parseToolCall(currentText) || shouldForceScopeQuestion(currentText)) {
264
+ const operational = records.some((r) => canonicalToolName(r.toolName) === "itermruncommandinsession");
265
+ return { recovered: true, text: buildScopeNarrowing(records, operational) };
266
+ }
267
+ if (isRawShellOutput(currentText)) {
268
+ const summarizePrompt = [
269
+ buildRecoveryPrompt(input, records),
270
+ "",
271
+ "Do not paste the raw shell output back. Summarize only the key findings briefly.",
272
+ ].join("\n");
273
+ const summaryResponse = await runtime.run(summarizePrompt, onProgress);
274
+ const summaryText = extractText(summaryResponse);
275
+ if (summaryText)
276
+ return { recovered: true, text: summaryText };
277
+ }
278
+ return { recovered: true, text: currentText };
279
+ }
280
+ const blockedHint = findBlockedToolHint(firstResponse);
281
+ if (blockedHint)
282
+ return { recovered: false, text: blockedHint };
283
+ if (hasToolMessage(firstResponse)) {
284
+ return { recovered: false, text: currentText };
285
+ }
286
+ const bootstrapOutput = await bootstrapTargetPanelEvidence(runtime, hint);
287
+ if (bootstrapOutput) {
288
+ return {
289
+ recovered: false,
290
+ text: [
291
+ "No target-panel evidence was collected from tool activity yet.",
292
+ `Current target-panel working directory / evidence:\n${bootstrapOutput}`.trim(),
293
+ ].join("\n\n"),
294
+ };
295
+ }
296
+ return {
297
+ recovered: false,
298
+ text: [
299
+ "No target-panel evidence was collected yet.",
300
+ currentText ? `Initial response: ${currentText}` : "",
301
+ ].filter(Boolean).join("\n\n"),
302
+ };
303
+ }
304
+ //# sourceMappingURL=toolCallRecovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolCallRecovery.js","sourceRoot":"","sources":["../../src/runtime/toolCallRecovery.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/runtime",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Runtime service and YAML config loader for deepagents-based agent apps",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -4,25 +4,26 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
 
7
- const scriptDir = dirname(fileURLToPath(import.meta.url));
8
- const helperPath = resolve(scriptDir, "../../../scripts/internal-package-refs.mjs");
9
- const packageJsonPath = resolve(scriptDir, "../package.json");
7
+ const DEP_SECTIONS = ["dependencies", "devDependencies", "optionalDependencies"];
10
8
 
11
- function fallbackRewriteCurrentPackage() {
9
+ function fallbackRewriteCurrentPackage(scriptUrl) {
10
+ const scriptDir = dirname(fileURLToPath(scriptUrl));
11
+ const packageDir = resolve(scriptDir, "..");
12
+ const packageJsonPath = resolve(packageDir, "package.json");
12
13
  const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
13
14
  let changed = false;
14
- const packageDir = resolve(scriptDir, "..");
15
15
 
16
- for (const section of ["dependencies", "devDependencies", "optionalDependencies"]) {
16
+ for (const section of DEP_SECTIONS) {
17
17
  const deps = pkg[section];
18
18
  if (!deps || typeof deps !== "object") continue;
19
19
  for (const [name, version] of Object.entries(deps)) {
20
20
  if (!name.startsWith("@botbotgo/")) continue;
21
21
  if (typeof version !== "string" || !version.startsWith("file:")) continue;
22
- if (existsSync(resolve(packageDir, version.slice("file:".length)))) continue;
22
+ const target = resolve(packageDir, version.slice("file:".length));
23
+ if (existsSync(target)) continue;
23
24
  deps[name] = "latest";
24
25
  changed = true;
25
- console.log(`[resolve-deps:fallback] ${section}.${name}: ${version} -> ${deps[name]}`);
26
+ console.log(`[resolve-deps:fallback] ${section}.${name}: ${version} -> latest`);
26
27
  }
27
28
  }
28
29
 
@@ -31,10 +32,18 @@ function fallbackRewriteCurrentPackage() {
31
32
  }
32
33
  }
33
34
 
34
- if (!existsSync(helperPath)) {
35
- fallbackRewriteCurrentPackage();
36
- process.exit(0);
35
+ async function run() {
36
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
37
+ const workspaceRunner = resolve(scriptDir, "../../../scripts/resolve-deps-runner.mjs");
38
+
39
+ if (existsSync(workspaceRunner)) {
40
+ const { runResolveDeps } = await import(pathToFileURL(workspaceRunner).href);
41
+ await runResolveDeps(import.meta.url, "../../../scripts/internal-package-refs.mjs");
42
+ return;
43
+ }
44
+
45
+ console.log(`[resolve-deps] workspace helper not found at ${workspaceRunner}; using local fallback`);
46
+ fallbackRewriteCurrentPackage(import.meta.url);
37
47
  }
38
48
 
39
- const { syncCurrentPackageFromScript } = await import(pathToFileURL(helperPath).href);
40
- syncCurrentPackageFromScript(import.meta.url, "auto");
49
+ await run();
package/src/index.ts CHANGED
@@ -34,3 +34,5 @@ export {
34
34
  requireAgentRuntimeTools,
35
35
  } from "./runtime/index.js";
36
36
  export type { AgentRuntimeGlobalContext } from "./runtime/index.js";
37
+ export { runWithTextToolCallRecovery } from "./runtime/toolCallRecovery.js";
38
+ export type { ToolCallRecoveryResult } from "./runtime/toolCallRecovery.js";
@@ -0,0 +1,351 @@
1
+ import { AgentContextTokens } from "@botbotgo/common";
2
+
3
+ type RuntimeLike = {
4
+ context?: { get?: (token: unknown) => unknown };
5
+ run: (input: string, onProgress?: (event: unknown) => void) => Promise<unknown>;
6
+ };
7
+
8
+ type ToolLike = {
9
+ name?: string;
10
+ invoke?: (args?: Record<string, unknown>) => Promise<unknown>;
11
+ };
12
+
13
+ type RecoveryHint = {
14
+ windowId?: number;
15
+ tabIndex?: number;
16
+ sessionId?: string;
17
+ };
18
+
19
+ type ParsedToolCall = {
20
+ name: string;
21
+ arguments: Record<string, unknown>;
22
+ raw: string;
23
+ };
24
+
25
+ type EvidenceRecord = {
26
+ toolName: string;
27
+ output: string;
28
+ entries: string[];
29
+ };
30
+
31
+ export type ToolCallRecoveryResult = {
32
+ recovered: boolean;
33
+ text: string;
34
+ };
35
+
36
+ function asString(value: unknown): string {
37
+ return typeof value === "string" ? value : "";
38
+ }
39
+
40
+ function extractText(response: unknown): string {
41
+ if (typeof response === "string") return response;
42
+ if (!response || typeof response !== "object") return "";
43
+ const typed = response as { text?: unknown; messages?: Array<{ type?: string; content?: unknown }> };
44
+ if (typeof typed.text === "string") return typed.text;
45
+ if (Array.isArray(typed.messages)) {
46
+ const last = [...typed.messages].reverse().find((m) => typeof m?.content === "string");
47
+ if (last && typeof last.content === "string") return last.content;
48
+ }
49
+ return "";
50
+ }
51
+
52
+ function normalizeSimpleName(name: string): string {
53
+ const trimmed = name.trim().replace(/^['"]|['"]$/g, "");
54
+ const base = trimmed.includes(".") ? trimmed.split(".").pop() ?? trimmed : trimmed;
55
+ return base.replace(/^tool[-_.]buildin[-_.]/i, "").replace(/[^a-z0-9]/gi, "").toLowerCase();
56
+ }
57
+
58
+ function canonicalToolName(name: string): string {
59
+ const simple = normalizeSimpleName(name);
60
+ if (simple === "ls" || simple === "listdir") return "listdir";
61
+ if (simple === "readtext") return "readtext";
62
+ if (simple === "runcommandinsession" || simple === "itermruncommandinsession" || simple === "executeshell") {
63
+ return "itermruncommandinsession";
64
+ }
65
+ return simple;
66
+ }
67
+
68
+ function extractJsonObject(raw: string): string | null {
69
+ const start = raw.indexOf("{");
70
+ const end = raw.lastIndexOf("}");
71
+ if (start === -1 || end === -1 || end <= start) return null;
72
+ return raw.slice(start, end + 1);
73
+ }
74
+
75
+ function parseJsonObject(raw: string): Record<string, unknown> | null {
76
+ const jsonSlice = extractJsonObject(raw);
77
+ if (!jsonSlice) return null;
78
+ try {
79
+ const parsed = JSON.parse(jsonSlice);
80
+ return parsed && typeof parsed === "object" ? (parsed as Record<string, unknown>) : null;
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+
86
+ function parseToolCall(text: string): ParsedToolCall | null {
87
+ const toolCallBlock = text.match(/<tool[-_]call>\s*([\s\S]*?)(?:<\/tool[-_]call>|$)/i);
88
+ if (toolCallBlock) {
89
+ const obj = parseJsonObject(toolCallBlock[1]);
90
+ if (obj && typeof obj.name === "string") {
91
+ const args = obj.arguments && typeof obj.arguments === "object" ? (obj.arguments as Record<string, unknown>) : {};
92
+ return { name: obj.name, arguments: args, raw: toolCallBlock[0] };
93
+ }
94
+ }
95
+
96
+ const callTool = text.match(/<call-tool\s+name="([^"]+)"\s+arguments=({[\s\S]*?})[^>]*>/i);
97
+ if (callTool) {
98
+ const args = parseJsonObject(callTool[2]) ?? {};
99
+ return { name: callTool[1], arguments: args, raw: callTool[0] };
100
+ }
101
+
102
+ const executeShell = text.match(/<function=execute_shell>[\s\S]*?<parameter=command>([\s\S]*?)<\/parameter>/i);
103
+ if (executeShell) {
104
+ return {
105
+ name: "itermRunCommandInSession",
106
+ arguments: { command: executeShell[1].trim() },
107
+ raw: executeShell[0],
108
+ };
109
+ }
110
+
111
+ const simpleLs = text.match(/\bls\s*\(\s*path\s*=\s*"([^"]+)"\s*\)/i);
112
+ if (simpleLs) {
113
+ return { name: "listDir", arguments: { path: simpleLs[1] }, raw: simpleLs[0] };
114
+ }
115
+
116
+ return null;
117
+ }
118
+
119
+ function getTools(runtime: RuntimeLike): ToolLike[] {
120
+ const tools = runtime.context?.get?.(AgentContextTokens.Tools);
121
+ return Array.isArray(tools) ? (tools as ToolLike[]) : [];
122
+ }
123
+
124
+ function findTool(tools: ToolLike[], requestedName: string): ToolLike | null {
125
+ const requested = canonicalToolName(requestedName);
126
+ return tools.find((tool) => typeof tool.name === "string" && canonicalToolName(tool.name) === requested) ?? null;
127
+ }
128
+
129
+ function extractToolOutput(result: unknown): string {
130
+ if (typeof result === "string") return result;
131
+ if (!result || typeof result !== "object") return "";
132
+ const top = result as Record<string, unknown>;
133
+ const root = (top.result && typeof top.result === "object" ? top.result : top) as Record<string, unknown>;
134
+ if (typeof root.outputText === "string") return root.outputText;
135
+ if (typeof root.output === "string") return root.output;
136
+ if (root.output && typeof root.output === "object") {
137
+ const outputObj = root.output as Record<string, unknown>;
138
+ if (typeof outputObj.output === "string") return outputObj.output;
139
+ if (outputObj.result && typeof outputObj.result === "object") {
140
+ const nested = outputObj.result as Record<string, unknown>;
141
+ if (typeof nested.output === "string") return nested.output;
142
+ }
143
+ }
144
+ return "";
145
+ }
146
+
147
+ function extractListEntries(result: unknown): string[] {
148
+ if (!result || typeof result !== "object") return [];
149
+ const top = result as Record<string, unknown>;
150
+ const root = (top.result && typeof top.result === "object" ? top.result : top) as Record<string, unknown>;
151
+ const entries = root.entries;
152
+ if (Array.isArray(entries)) {
153
+ return entries
154
+ .map((entry) => (entry && typeof entry === "object" ? asString((entry as Record<string, unknown>).name) : ""))
155
+ .filter(Boolean)
156
+ .slice(0, 8);
157
+ }
158
+ return [];
159
+ }
160
+
161
+ function hasToolMessage(response: unknown): boolean {
162
+ if (!response || typeof response !== "object") return false;
163
+ const typed = response as { messages?: Array<{ type?: string }> };
164
+ return Array.isArray(typed.messages) && typed.messages.some((m) => m?.type === "tool");
165
+ }
166
+
167
+ function findBlockedToolHint(response: unknown): string | null {
168
+ if (!response || typeof response !== "object") return null;
169
+ const typed = response as { messages?: Array<{ type?: string; content?: unknown }> };
170
+ if (!Array.isArray(typed.messages)) return null;
171
+ for (const msg of typed.messages) {
172
+ if (msg?.type !== "tool" || typeof msg.content !== "string") continue;
173
+ const parsed = parseJsonObject(msg.content);
174
+ if (!parsed) continue;
175
+ const result = parsed.result;
176
+ if (!result || typeof result !== "object") continue;
177
+ const obj = result as Record<string, unknown>;
178
+ if (obj.blocked === true || typeof obj.blockedTool === "string") {
179
+ const required = asString(obj.requiredTool);
180
+ const blockedTool = asString(obj.blockedTool);
181
+ const toolName = required || blockedTool || "required tool";
182
+ return `I found blocked local tool result evidence and need \`${toolName}\` to continue safely.`;
183
+ }
184
+ }
185
+ return null;
186
+ }
187
+
188
+ function buildEvidenceSummary(records: EvidenceRecord[]): string {
189
+ const lines: string[] = [];
190
+ lines.push("### Baseline Evidence");
191
+ for (const rec of records) {
192
+ lines.push(`- Tool: ${rec.toolName}`);
193
+ if (rec.entries.length > 0) {
194
+ lines.push(`- Entries: ${rec.entries.join(", ")}`);
195
+ }
196
+ if (rec.output) {
197
+ lines.push(`- Evidence Preview:\n${rec.output.slice(0, 1600)}`);
198
+ }
199
+ }
200
+ return lines.join("\n");
201
+ }
202
+
203
+ function buildRecoveryPrompt(userInput: string, records: EvidenceRecord[]): string {
204
+ return [
205
+ `User request: ${userInput}`,
206
+ "",
207
+ buildEvidenceSummary(records),
208
+ "",
209
+ "Use only the evidence above to continue.",
210
+ "If another tool is absolutely required, return exactly one tool call.",
211
+ ].join("\n");
212
+ }
213
+
214
+ function buildScopeNarrowing(records: EvidenceRecord[], operational: boolean): string {
215
+ const latest = records[records.length - 1];
216
+ const names = latest?.entries ?? [];
217
+ if (operational) {
218
+ return [
219
+ "I need a narrower operational scope before continuing from this command evidence.",
220
+ "Specify the target service/pod/node, exact command family, and expected signal.",
221
+ ].join(" ");
222
+ }
223
+ if (names.length === 0) {
224
+ return [
225
+ "I need a narrower scope before continuing from the current directory context.",
226
+ "Specify the file, folder, diff, or PR you want analyzed next.",
227
+ ].join(" ");
228
+ }
229
+ return [
230
+ `I need a narrower scope before continuing. Current directory context includes: ${names.join(", ")}.`,
231
+ "Specify the file, folder, diff, or PR you want analyzed next.",
232
+ ].join(" ");
233
+ }
234
+
235
+ function shouldForceScopeQuestion(text: string): boolean {
236
+ return /function:\s*ask_/i.test(text) || /please specify the file/i.test(text);
237
+ }
238
+
239
+ function isHiddenSubagentRequest(text: string): boolean {
240
+ return /<function=task>/i.test(text) || /subagent_to_spawn/i.test(text);
241
+ }
242
+
243
+ function isRawShellOutput(text: string): boolean {
244
+ return /^Filesystem/m.test(text) || /\n\/dev\//.test(text);
245
+ }
246
+
247
+ async function bootstrapTargetPanelEvidence(runtime: RuntimeLike, hint?: RecoveryHint): Promise<string> {
248
+ const tools = getTools(runtime);
249
+ const commandTool = findTool(tools, "itermRunCommandInSession");
250
+ if (!commandTool?.invoke) return "";
251
+ const command = process.env.ITB_BOOTSTRAP_EVIDENCE_COMMAND || "pwd";
252
+ const output = await commandTool.invoke({
253
+ command,
254
+ windowId: hint?.windowId,
255
+ tabIndex: hint?.tabIndex,
256
+ sessionId: hint?.sessionId,
257
+ maxOutputLines: 120,
258
+ });
259
+ return extractToolOutput(output);
260
+ }
261
+
262
+ export async function runWithTextToolCallRecovery(
263
+ runtime: RuntimeLike,
264
+ input: string,
265
+ onProgress: (event: unknown) => void,
266
+ hint?: RecoveryHint,
267
+ ): Promise<ToolCallRecoveryResult> {
268
+ const firstResponse = await runtime.run(input, onProgress);
269
+ let currentResponse = firstResponse;
270
+ let currentText = extractText(firstResponse);
271
+ const tools = getTools(runtime);
272
+ const records: EvidenceRecord[] = [];
273
+ let recovered = false;
274
+
275
+ if (isHiddenSubagentRequest(currentText)) {
276
+ return {
277
+ recovered: true,
278
+ text: "I will not spawn a hidden subagent. I need a narrower operational scope to continue safely.",
279
+ };
280
+ }
281
+
282
+ for (let i = 0; i < 3; i += 1) {
283
+ const parsed = parseToolCall(currentText);
284
+ if (!parsed) break;
285
+ const tool = findTool(tools, parsed.name);
286
+ if (!tool?.invoke) {
287
+ return { recovered: false, text: currentText || parsed.raw };
288
+ }
289
+
290
+ const toolResult = await tool.invoke(parsed.arguments);
291
+ recovered = true;
292
+ const output = extractToolOutput(toolResult);
293
+ const entries = extractListEntries(toolResult);
294
+ records.push({ toolName: parsed.name, output, entries });
295
+
296
+ currentResponse = await runtime.run(buildRecoveryPrompt(input, records), onProgress);
297
+ currentText = extractText(currentResponse);
298
+ if (isHiddenSubagentRequest(currentText)) {
299
+ return {
300
+ recovered: true,
301
+ text: "I will not spawn a hidden subagent. I need a narrower operational scope to continue safely.",
302
+ };
303
+ }
304
+ }
305
+
306
+ if (recovered) {
307
+ if (parseToolCall(currentText) || shouldForceScopeQuestion(currentText)) {
308
+ const operational = records.some((r) => canonicalToolName(r.toolName) === "itermruncommandinsession");
309
+ return { recovered: true, text: buildScopeNarrowing(records, operational) };
310
+ }
311
+
312
+ if (isRawShellOutput(currentText)) {
313
+ const summarizePrompt = [
314
+ buildRecoveryPrompt(input, records),
315
+ "",
316
+ "Do not paste the raw shell output back. Summarize only the key findings briefly.",
317
+ ].join("\n");
318
+ const summaryResponse = await runtime.run(summarizePrompt, onProgress);
319
+ const summaryText = extractText(summaryResponse);
320
+ if (summaryText) return { recovered: true, text: summaryText };
321
+ }
322
+
323
+ return { recovered: true, text: currentText };
324
+ }
325
+
326
+ const blockedHint = findBlockedToolHint(firstResponse);
327
+ if (blockedHint) return { recovered: false, text: blockedHint };
328
+
329
+ if (hasToolMessage(firstResponse)) {
330
+ return { recovered: false, text: currentText };
331
+ }
332
+
333
+ const bootstrapOutput = await bootstrapTargetPanelEvidence(runtime, hint);
334
+ if (bootstrapOutput) {
335
+ return {
336
+ recovered: false,
337
+ text: [
338
+ "No target-panel evidence was collected from tool activity yet.",
339
+ `Current target-panel working directory / evidence:\n${bootstrapOutput}`.trim(),
340
+ ].join("\n\n"),
341
+ };
342
+ }
343
+
344
+ return {
345
+ recovered: false,
346
+ text: [
347
+ "No target-panel evidence was collected yet.",
348
+ currentText ? `Initial response: ${currentText}` : "",
349
+ ].filter(Boolean).join("\n\n"),
350
+ };
351
+ }