@botbotgo/agent-harness 0.0.298 → 0.0.299

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.
Files changed (166) hide show
  1. package/README.md +77 -37
  2. package/README.zh.md +79 -30
  3. package/dist/acp.d.ts +3 -0
  4. package/dist/acp.js +10 -2
  5. package/dist/api.d.ts +14 -2
  6. package/dist/api.js +19 -3
  7. package/dist/cli.d.ts +18 -1
  8. package/dist/cli.js +1408 -319
  9. package/dist/client/acp.d.ts +9 -3
  10. package/dist/client/acp.js +55 -1
  11. package/dist/client/in-process.d.ts +5 -2
  12. package/dist/client/in-process.js +4 -6
  13. package/dist/client/index.d.ts +1 -1
  14. package/dist/client/types.d.ts +6 -5
  15. package/dist/config/agents/direct.yaml +7 -17
  16. package/dist/config/agents/orchestra.yaml +9 -65
  17. package/dist/config/catalogs/embedding-models.yaml +1 -1
  18. package/dist/config/catalogs/stores.yaml +1 -1
  19. package/dist/config/knowledge/knowledge-runtime.yaml +36 -2
  20. package/dist/config/knowledge/procedural-memory-runtime.yaml +78 -0
  21. package/dist/config/{catalogs/models.yaml → models.yaml} +2 -2
  22. package/dist/config/prompts/direct-system.md +16 -0
  23. package/dist/config/prompts/orchestra-system.md +62 -0
  24. package/dist/config/prompts/routing-system.md +14 -0
  25. package/dist/config/runtime/runtime-memory.yaml +39 -5
  26. package/dist/config/runtime/workspace.yaml +7 -16
  27. package/dist/contracts/runtime.d.ts +242 -1
  28. package/dist/contracts/workspace.d.ts +2 -0
  29. package/dist/index.d.ts +5 -3
  30. package/dist/index.js +2 -1
  31. package/dist/init-project.js +178 -33
  32. package/dist/knowledge/contracts.d.ts +5 -0
  33. package/dist/knowledge/module.d.ts +5 -0
  34. package/dist/knowledge/module.js +340 -18
  35. package/dist/package-version.d.ts +1 -1
  36. package/dist/package-version.js +1 -1
  37. package/dist/persistence/file-store.d.ts +5 -1
  38. package/dist/persistence/file-store.js +16 -0
  39. package/dist/persistence/sqlite-store.d.ts +4 -1
  40. package/dist/persistence/sqlite-store.js +88 -14
  41. package/dist/persistence/types.d.ts +4 -1
  42. package/dist/procedural/config.d.ts +63 -0
  43. package/dist/procedural/config.js +125 -0
  44. package/dist/procedural/index.d.ts +2 -0
  45. package/dist/procedural/index.js +1 -0
  46. package/dist/protocol/ag-ui/http.d.ts +3 -0
  47. package/dist/protocol/ag-ui/http.js +10 -0
  48. package/dist/request-events.d.ts +63 -0
  49. package/dist/request-events.js +400 -0
  50. package/dist/resource/isolation.js +11 -0
  51. package/dist/resource/resource-impl.d.ts +1 -0
  52. package/dist/resource/resource-impl.js +103 -12
  53. package/dist/resources/init-templates/agent-context/deep-research.md +5 -0
  54. package/dist/resources/init-templates/prompts/research-analyst-basic.md +1 -0
  55. package/dist/resources/init-templates/prompts/research-analyst-web-search.md +1 -0
  56. package/dist/resources/init-templates/prompts/research-host-deep-research-basic.md +1 -0
  57. package/dist/resources/init-templates/prompts/research-host-deep-research-web-search.md +1 -0
  58. package/dist/resources/init-templates/prompts/research-host-single-agent-basic.md +1 -0
  59. package/dist/resources/init-templates/prompts/research-host-single-agent-web-search.md +1 -0
  60. package/dist/resources/prompts/runtime/browser-capability-disclaimer-recovery.md +1 -0
  61. package/dist/resources/prompts/runtime/default-subagent.md +2 -0
  62. package/dist/resources/prompts/runtime/durable-memory-context.md +7 -0
  63. package/dist/resources/prompts/runtime/execution-with-tool-evidence-retry.md +1 -0
  64. package/dist/resources/prompts/runtime/execution-with-tool-evidence.md +1 -0
  65. package/dist/resources/prompts/runtime/invalid-tool-selection-recovery.md +1 -0
  66. package/dist/resources/prompts/runtime/memory-manager.md +31 -0
  67. package/dist/resources/prompts/runtime/memory-mutation-reconciliation.md +22 -0
  68. package/dist/resources/prompts/runtime/slash-command-skill.md +6 -0
  69. package/dist/resources/prompts/runtime/strict-tool-json.md +1 -0
  70. package/dist/resources/prompts/runtime/workspace-boundary-guidance.md +3 -0
  71. package/dist/resources/prompts/runtime/workspace-relative-path.md +1 -0
  72. package/dist/resources/prompts/runtime/write-todos-descriptive-content.md +1 -0
  73. package/dist/resources/prompts/runtime/write-todos-full-entry.md +1 -0
  74. package/dist/resources/prompts/runtime/write-todos-non-empty-initial-list.md +1 -0
  75. package/dist/resources/tools/_runtime_tool_helpers.mjs +152 -0
  76. package/dist/resources/tools/cancel_request.mjs +21 -0
  77. package/dist/resources/tools/fetch_url.mjs +23 -0
  78. package/dist/resources/tools/http_request.mjs +30 -0
  79. package/dist/resources/tools/inspect_approvals.mjs +27 -0
  80. package/dist/resources/tools/inspect_artifacts.mjs +21 -0
  81. package/dist/resources/tools/inspect_events.mjs +21 -0
  82. package/dist/resources/tools/inspect_requests.mjs +27 -0
  83. package/dist/resources/tools/inspect_sessions.mjs +21 -0
  84. package/dist/resources/tools/list_files.mjs +27 -0
  85. package/dist/resources/tools/read_artifact.mjs +22 -0
  86. package/dist/resources/tools/request_approval.mjs +27 -0
  87. package/dist/resources/tools/run_command.mjs +21 -0
  88. package/dist/resources/tools/schedule_task.mjs +76 -0
  89. package/dist/resources/tools/search_files.mjs +47 -0
  90. package/dist/resources/tools/send_message.mjs +23 -0
  91. package/dist/runtime/adapter/direct-builtin-utility.d.ts +1 -0
  92. package/dist/runtime/adapter/direct-builtin-utility.js +90 -0
  93. package/dist/runtime/adapter/flow/execution-context.d.ts +1 -1
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -1
  95. package/dist/runtime/adapter/flow/invocation-flow.d.ts +1 -0
  96. package/dist/runtime/adapter/flow/invocation-flow.js +9 -1
  97. package/dist/runtime/adapter/flow/invoke-runtime.d.ts +1 -1
  98. package/dist/runtime/adapter/flow/stream-runtime.d.ts +5 -1
  99. package/dist/runtime/adapter/flow/stream-runtime.js +556 -35
  100. package/dist/runtime/adapter/invocation-result.js +3 -2
  101. package/dist/runtime/adapter/local-tool-invocation.d.ts +1 -1
  102. package/dist/runtime/adapter/local-tool-invocation.js +28 -4
  103. package/dist/runtime/adapter/middleware-assembly.js +3 -1
  104. package/dist/runtime/adapter/model/invocation-request.d.ts +4 -1
  105. package/dist/runtime/adapter/model/invocation-request.js +138 -16
  106. package/dist/runtime/adapter/model/message-assembly.js +2 -6
  107. package/dist/runtime/adapter/model/model-providers.js +103 -5
  108. package/dist/runtime/adapter/resilience.js +17 -2
  109. package/dist/runtime/adapter/runtime-adapter-support.d.ts +11 -7
  110. package/dist/runtime/adapter/runtime-adapter-support.js +39 -5
  111. package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +63 -1
  112. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +193 -21
  113. package/dist/runtime/adapter/tool/tool-arguments.d.ts +3 -1
  114. package/dist/runtime/adapter/tool/tool-arguments.js +52 -17
  115. package/dist/runtime/adapter/tool-resolution.d.ts +1 -0
  116. package/dist/runtime/adapter/tool-resolution.js +4 -2
  117. package/dist/runtime/agent-runtime-adapter.d.ts +27 -0
  118. package/dist/runtime/agent-runtime-adapter.js +163 -11
  119. package/dist/runtime/harness/events/event-bus.d.ts +1 -0
  120. package/dist/runtime/harness/events/event-bus.js +3 -0
  121. package/dist/runtime/harness/events/event-sink.d.ts +3 -0
  122. package/dist/runtime/harness/events/event-sink.js +16 -7
  123. package/dist/runtime/harness/events/streaming.d.ts +18 -1
  124. package/dist/runtime/harness/events/streaming.js +23 -10
  125. package/dist/runtime/harness/run/inspection.js +26 -5
  126. package/dist/runtime/harness/run/stream-run.d.ts +13 -4
  127. package/dist/runtime/harness/run/stream-run.js +448 -4
  128. package/dist/runtime/harness/run/surface-semantics.js +7 -34
  129. package/dist/runtime/harness/system/runtime-memory-manager.d.ts +3 -0
  130. package/dist/runtime/harness/system/runtime-memory-manager.js +384 -69
  131. package/dist/runtime/harness/system/runtime-memory-policy.d.ts +20 -1
  132. package/dist/runtime/harness/system/runtime-memory-policy.js +65 -17
  133. package/dist/runtime/harness/system/runtime-memory-records.js +100 -0
  134. package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
  135. package/dist/runtime/harness/system/store.d.ts +4 -0
  136. package/dist/runtime/harness/system/store.js +153 -0
  137. package/dist/runtime/harness.d.ts +9 -1
  138. package/dist/runtime/harness.js +141 -7
  139. package/dist/runtime/maintenance/sqlite-checkpoint-saver.d.ts +8 -3
  140. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +152 -53
  141. package/dist/runtime/parsing/output-parsing.d.ts +10 -2
  142. package/dist/runtime/parsing/output-parsing.js +223 -16
  143. package/dist/runtime/parsing/stream-event-parsing.d.ts +7 -0
  144. package/dist/runtime/parsing/stream-event-parsing.js +51 -1
  145. package/dist/runtime/scheduling/system-schedule-manager.d.ts +41 -0
  146. package/dist/runtime/scheduling/system-schedule-manager.js +532 -0
  147. package/dist/runtime/support/embedding-models.d.ts +1 -1
  148. package/dist/runtime/support/embedding-models.js +5 -2
  149. package/dist/runtime/support/runtime-factories.js +1 -1
  150. package/dist/runtime/support/runtime-layout.d.ts +3 -0
  151. package/dist/runtime/support/runtime-layout.js +10 -1
  152. package/dist/runtime/support/runtime-prompts.d.ts +30 -0
  153. package/dist/runtime/support/runtime-prompts.js +55 -0
  154. package/dist/runtime/support/vector-stores.d.ts +1 -1
  155. package/dist/runtime/support/vector-stores.js +5 -2
  156. package/dist/upstream-events.js +8 -7
  157. package/dist/utils/bundled-text.d.ts +3 -0
  158. package/dist/utils/bundled-text.js +25 -0
  159. package/dist/utils/id.js +3 -2
  160. package/dist/workspace/agent-binding-compiler.js +53 -13
  161. package/dist/workspace/object-loader.js +64 -2
  162. package/dist/workspace/support/workspace-ref-utils.d.ts +2 -1
  163. package/dist/workspace/support/workspace-ref-utils.js +24 -5
  164. package/dist/workspace/yaml-object-reader.d.ts +1 -0
  165. package/dist/workspace/yaml-object-reader.js +95 -17
  166. package/package.json +11 -5
@@ -1,4 +1,6 @@
1
1
  import { AIMessage } from "langchain";
2
+ import { 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 "../support/runtime-prompts.js";
3
+ 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, };
2
4
  export function sanitizeVisibleText(value) {
3
5
  return value
4
6
  .replace(/[A-Za-z0-9_]*Middleware\.after_model/g, "")
@@ -218,6 +220,13 @@ function extractAssistantTextFromMessages(messages) {
218
220
  if (typeof message !== "object" || !message)
219
221
  continue;
220
222
  const typed = message;
223
+ const explicitRole = typeof typed.role === "string" ? typed.role.trim().toLowerCase() : undefined;
224
+ if (explicitRole === "assistant" || explicitRole === "ai") {
225
+ const content = extractMessageContent(message);
226
+ if (content)
227
+ return content;
228
+ continue;
229
+ }
221
230
  const ids = Array.isArray(typed.id) ? typed.id.filter((item) => typeof item === "string") : [];
222
231
  const typeName = ids.at(-1);
223
232
  const runtimeType = typeof message._getType === "function"
@@ -295,11 +304,54 @@ function extractStructuredOutputText(value) {
295
304
  }
296
305
  return readTextContent(typed.content);
297
306
  }
307
+ function normalizePotentialLineNumberedDocument(value) {
308
+ return value
309
+ .split("\n")
310
+ .map((line) => line.replace(/^\s*\d+\s+/, ""))
311
+ .join("\n")
312
+ .trim();
313
+ }
314
+ function isLikelySkillDocumentText(value) {
315
+ const normalized = normalizePotentialLineNumberedDocument(value);
316
+ if (!normalized.startsWith("---")) {
317
+ return false;
318
+ }
319
+ const lower = normalized.toLowerCase();
320
+ return (lower.includes("\nname: ") &&
321
+ lower.includes("\ndescription: ") &&
322
+ lower.includes("\n# ") &&
323
+ lower.includes("## workflow"));
324
+ }
325
+ export function containsLikelySkillDocument(value) {
326
+ if (typeof value === "string") {
327
+ return isLikelySkillDocumentText(value);
328
+ }
329
+ if (Array.isArray(value)) {
330
+ return value.some((item) => containsLikelySkillDocument(item));
331
+ }
332
+ if (typeof value === "object" && value) {
333
+ const typed = value;
334
+ if (typed.content !== undefined && containsLikelySkillDocument(typed.content)) {
335
+ return true;
336
+ }
337
+ if (typed.output !== undefined && containsLikelySkillDocument(typed.output)) {
338
+ return true;
339
+ }
340
+ if (typed.messages !== undefined && containsLikelySkillDocument(typed.messages)) {
341
+ return true;
342
+ }
343
+ if (typed.kwargs !== undefined && containsLikelySkillDocument(typed.kwargs)) {
344
+ return true;
345
+ }
346
+ return Object.values(typed).some((item) => containsLikelySkillDocument(item));
347
+ }
348
+ return false;
349
+ }
298
350
  export function extractToolFallbackContext(value) {
299
351
  if (typeof value !== "object" || !value)
300
352
  return "";
301
353
  const typed = value;
302
- const messages = extractToolMessageContents(typed.messages);
354
+ const messages = extractToolMessageContents(typed.messages).filter((message) => !isLikelySkillDocumentText(message));
303
355
  if (messages.length > 0)
304
356
  return messages.slice(-3).join("\n\n");
305
357
  if (typed.output && typeof typed.output === "object") {
@@ -311,7 +363,7 @@ export function extractToolFallbackContext(value) {
311
363
  }
312
364
  export function extractVisibleOutput(value) {
313
365
  const structured = extractStructuredOutputText(value);
314
- if (structured)
366
+ if (structured && !isLikelySkillDocumentText(structured))
315
367
  return structured;
316
368
  if (typeof value === "string") {
317
369
  const parsed = tryParseJson(value);
@@ -319,11 +371,13 @@ export function extractVisibleOutput(value) {
319
371
  if (isLikelyMemoryWriteArgsObject(parsed))
320
372
  return "";
321
373
  const parsedStructured = extractStructuredOutputText(parsed);
322
- if (parsedStructured)
374
+ if (parsedStructured && !isLikelySkillDocumentText(parsedStructured))
323
375
  return parsedStructured;
324
376
  if (isLikelyToolArgsObject(parsed))
325
377
  return "";
326
378
  }
379
+ if (isLikelySkillDocumentText(value))
380
+ return "";
327
381
  return value;
328
382
  }
329
383
  if (typeof value === "object" && value) {
@@ -515,10 +569,128 @@ export function isToolCallValidationFailure(error) {
515
569
  return /Received tool input did not match expected schema/i.test(message) && /(?:→\s*at|at)\s+[\w[\].]+/i.test(message);
516
570
  }
517
571
  export function isToolCallRecoveryFailure(error) {
518
- return isToolCallParseFailure(error) || isToolCallValidationFailure(error);
572
+ return (isToolCallParseFailure(error) ||
573
+ isToolCallValidationFailure(error) ||
574
+ isRepairableWriteTodosEmptyFailure(error) ||
575
+ isRepairableWriteTodosPlaceholderFailure(error) ||
576
+ isWorkspacePathScopeFailure(error));
577
+ }
578
+ function collectErrorMessages(error) {
579
+ if (!error) {
580
+ return [];
581
+ }
582
+ if (error instanceof Error) {
583
+ const nested = Array.isArray(error.errors)
584
+ ? (error.errors ?? []).flatMap((item) => collectErrorMessages(item))
585
+ : [];
586
+ return [error.message, ...nested].filter((value) => typeof value === "string" && value.trim().length > 0);
587
+ }
588
+ if (typeof error === "string" && error.trim().length > 0) {
589
+ return [error];
590
+ }
591
+ if (typeof error === "object") {
592
+ const record = error;
593
+ return [record.message, record.error, record.details].flatMap((item) => collectErrorMessages(item));
594
+ }
595
+ return [];
596
+ }
597
+ export function isWorkspacePathScopeFailure(error) {
598
+ return collectErrorMessages(error).some((message) => /outside the workspace root|workspace-relative path/i.test(message));
599
+ }
600
+ export function isRepairableWriteTodosPlaceholderFailure(error) {
601
+ if (!(error instanceof Error))
602
+ return false;
603
+ const message = error.message.trim();
604
+ if (!message)
605
+ return false;
606
+ return /write_todos/i.test(message) && /descriptive task content|placeholder entries/i.test(message);
607
+ }
608
+ function extractLastUserMessageText(input) {
609
+ if (!Array.isArray(input) && !(typeof input === "object" && input && Array.isArray(input.messages))) {
610
+ return "";
611
+ }
612
+ const messages = Array.isArray(input) ? input : input.messages;
613
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
614
+ const message = messages[index];
615
+ if (typeof message !== "object" || !message)
616
+ continue;
617
+ const typed = message;
618
+ if (typed.role === "user") {
619
+ return extractMessageContent(message).trim();
620
+ }
621
+ const ids = Array.isArray(typed.id) ? typed.id.filter((item) => typeof item === "string") : [];
622
+ const typeName = ids.at(-1);
623
+ const runtimeType = typeof message._getType === "function"
624
+ ? message._getType()
625
+ : typeof message.getType === "function"
626
+ ? message.getType()
627
+ : undefined;
628
+ if (typeName === "HumanMessage" || runtimeType === "human") {
629
+ return extractMessageContent(message).trim();
630
+ }
631
+ if (typeof typed.kwargs === "object" && typed.kwargs && typed.kwargs.role === "user") {
632
+ return extractMessageContent(message).trim();
633
+ }
634
+ }
635
+ return "";
636
+ }
637
+ function isToolRequiredExecutionPrompt(text) {
638
+ if (!text)
639
+ return false;
640
+ return (/write_todos/i.test(text) ||
641
+ /\b(create|write|edit|read|show|display|append|run|execute|wait|sleep|repeat|loop|file|files|command)\b/i.test(text) ||
642
+ /(创建|写入|读取|显示|追加|执行|运行|等待|重复|文件|命令|步骤)/.test(text));
643
+ }
644
+ function isBrowserOrUrlTask(text) {
645
+ if (!text)
646
+ return false;
647
+ return (/https?:\/\/\S+/i.test(text) ||
648
+ /\b(url|urls|website|websites|web page|webpage|browser|browse|page summary|summari[sz]e.*page|open.*page)\b/i.test(text) ||
649
+ /(网址|链接|网页|网站|页面|浏览器|总结.*网页|总结.*页面|打开.*网页)/.test(text));
650
+ }
651
+ function claimsExecutionWithoutToolEvidence(text) {
652
+ if (!text)
653
+ return false;
654
+ return (/\b(completed|done|created|wrote|written|read|displayed|appended|executed|waited|result|results)\b/i.test(text) ||
655
+ /(已创建|已写入|已读取|已显示|已追加|已执行|已等待|执行结果|状态更新|步骤\s*\d+|文件内容)/.test(text));
656
+ }
657
+ function claimsMissingBrowserCapability(text) {
658
+ if (!text)
659
+ return false;
660
+ 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) ||
661
+ /(我没有直接访问外部网站|我无法直接访问外部网站|我无法访问外部网站|我不能访问外部网站|我无法直接访问外部网站内容|我无法访问网页|请提供文本内容.*我将为您进行总结|我没有.*浏览.*工具|我没有.*网页抓取.*工具|我没有.*访问.*网站.*工具|我无法总结该网页内容,因为.*工具执行失败)/.test(text));
662
+ }
663
+ export function isRetrySafeInvalidToolSelectionError(value) {
664
+ const text = readTextContent(value).trim();
665
+ if (!text)
666
+ return false;
667
+ return /is not a valid tool, try one of \[/i.test(text);
668
+ }
669
+ export function shouldValidateExecutionWithoutToolEvidence(request) {
670
+ const userText = extractLastUserMessageText(request);
671
+ const browserOrUrlTask = isBrowserOrUrlTask(userText);
672
+ return browserOrUrlTask || isToolRequiredExecutionPrompt(userText);
673
+ }
674
+ export function resolveExecutionWithoutToolEvidenceInstruction(request, result) {
675
+ const assistantText = AIMessage.isInstance(result)
676
+ ? readTextContent(result.content).trim()
677
+ : extractAssistantTextFromMessages(result?.messages).trim();
678
+ return resolveExecutionWithoutToolEvidenceTextInstruction(request, assistantText, hasToolCalls(result));
679
+ }
680
+ export function resolveExecutionWithoutToolEvidenceTextInstruction(request, assistantText, toolCallEvidence = false) {
681
+ const userText = extractLastUserMessageText(request);
682
+ const browserOrUrlTask = isBrowserOrUrlTask(userText);
683
+ if (!shouldValidateExecutionWithoutToolEvidence(request)) {
684
+ return null;
685
+ }
686
+ if (!assistantText || toolCallEvidence) {
687
+ return null;
688
+ }
689
+ if (browserOrUrlTask && claimsMissingBrowserCapability(assistantText)) {
690
+ return BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION;
691
+ }
692
+ return claimsExecutionWithoutToolEvidence(assistantText) ? EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION : null;
519
693
  }
520
- export 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.";
521
- export const WRITE_TODOS_FULL_ENTRY_INSTRUCTION = "When calling write_todos, every todo item must include both content and status. Do not send status-only updates. Retry by resending the full todo entry with the original content preserved.";
522
694
  export function isRepairableWriteTodosContentFailure(error) {
523
695
  if (!(error instanceof Error))
524
696
  return false;
@@ -527,10 +699,27 @@ export function isRepairableWriteTodosContentFailure(error) {
527
699
  return false;
528
700
  return /write_todos/i.test(message) && /todos\[\d+\]\.content/i.test(message);
529
701
  }
702
+ export function isRepairableWriteTodosEmptyFailure(error) {
703
+ if (!(error instanceof Error))
704
+ return false;
705
+ const message = error.message.trim();
706
+ if (!message)
707
+ return false;
708
+ return /write_todos/i.test(message) && /Initial write_todos call cannot use an empty todo list/i.test(message);
709
+ }
530
710
  export function resolveToolCallRecoveryInstruction(error) {
711
+ if (isRepairableWriteTodosEmptyFailure(error)) {
712
+ return WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION;
713
+ }
531
714
  if (isRepairableWriteTodosContentFailure(error)) {
532
715
  return WRITE_TODOS_FULL_ENTRY_INSTRUCTION;
533
716
  }
717
+ if (isRepairableWriteTodosPlaceholderFailure(error)) {
718
+ return WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION;
719
+ }
720
+ if (isWorkspacePathScopeFailure(error)) {
721
+ return WORKSPACE_RELATIVE_PATH_INSTRUCTION;
722
+ }
534
723
  if (isToolCallRecoveryFailure(error)) {
535
724
  return STRICT_TOOL_JSON_INSTRUCTION;
536
725
  }
@@ -557,18 +746,36 @@ export function wrapResolvedModel(value) {
557
746
  const member = Reflect.get(currentTarget, prop, receiver);
558
747
  if (prop === "invoke" && typeof member === "function") {
559
748
  return async (...args) => {
560
- try {
561
- return normalizeAgentMessage(await member.apply(currentTarget, args));
562
- }
563
- catch (error) {
564
- const recoveryInstruction = resolveToolCallRecoveryInstruction(error);
565
- if (!recoveryInstruction) {
566
- throw error;
749
+ let activeArgs = [...args];
750
+ for (let attempt = 0; attempt < 3; attempt += 1) {
751
+ try {
752
+ const normalized = normalizeAgentMessage(await member.apply(currentTarget, activeArgs));
753
+ const executionRecoveryInstruction = resolveExecutionWithoutToolEvidenceInstruction(activeArgs[0], normalized);
754
+ if (!executionRecoveryInstruction) {
755
+ return normalized;
756
+ }
757
+ if (attempt === 2) {
758
+ throw new Error("Model claimed task execution without any tool calls after repeated recovery attempts. Refusing to treat that response as a successful execution.");
759
+ }
760
+ const nextInstruction = attempt === 0
761
+ ? executionRecoveryInstruction
762
+ : EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION;
763
+ activeArgs = [...activeArgs];
764
+ activeArgs[0] = appendToolRecoveryInstruction(activeArgs[0], nextInstruction);
765
+ }
766
+ catch (error) {
767
+ const recoveryInstruction = resolveToolCallRecoveryInstruction(error);
768
+ if (!recoveryInstruction) {
769
+ throw error;
770
+ }
771
+ if (attempt === 2) {
772
+ throw error;
773
+ }
774
+ activeArgs = [...activeArgs];
775
+ activeArgs[0] = appendToolRecoveryInstruction(activeArgs[0], recoveryInstruction);
567
776
  }
568
- const retryArgs = [...args];
569
- retryArgs[0] = appendToolRecoveryInstruction(retryArgs[0], recoveryInstruction);
570
- return normalizeAgentMessage(await member.apply(currentTarget, retryArgs));
571
777
  }
778
+ throw new Error("Model invocation retry loop exited unexpectedly.");
572
779
  };
573
780
  }
574
781
  if ((prop === "bindTools" || prop === "withConfig" || prop === "withStructuredOutput") && typeof member === "function") {
@@ -1,6 +1,10 @@
1
+ import type { RequestExecutionStep } from "../../contracts/types.js";
1
2
  export type RuntimeStreamChunk = {
2
3
  kind: "upstream-event";
3
4
  event: unknown;
5
+ } | {
6
+ kind: "commentary";
7
+ content: string;
4
8
  } | {
5
9
  kind: "content";
6
10
  content: string;
@@ -15,6 +19,9 @@ export type RuntimeStreamChunk = {
15
19
  toolName: string;
16
20
  output: unknown;
17
21
  isError?: boolean;
22
+ } | {
23
+ kind: "profile";
24
+ step: RequestExecutionStep;
18
25
  };
19
26
  export declare function extractTerminalStreamOutput(event: unknown): string;
20
27
  export declare function extractReasoningStreamOutput(event: unknown): string;
@@ -1,3 +1,4 @@
1
+ import { isLowSignalTodoContent } from "../adapter/runtime-adapter-support.js";
1
2
  import { extractReasoningText, extractVisibleOutput, hasToolCalls, readTextContent } from "./output-parsing.js";
2
3
  function parseMaybeJson(value) {
3
4
  const trimmed = value.trim();
@@ -11,6 +12,22 @@ function parseMaybeJson(value) {
11
12
  return value;
12
13
  }
13
14
  }
15
+ function unwrapToolMessageOutput(value) {
16
+ if (typeof value !== "object" || !value || Array.isArray(value)) {
17
+ return value;
18
+ }
19
+ const record = value;
20
+ if (typeof record.content === "string") {
21
+ return parseMaybeJson(record.content);
22
+ }
23
+ const kwargs = typeof record.kwargs === "object" && record.kwargs !== null
24
+ ? record.kwargs
25
+ : undefined;
26
+ if (typeof kwargs?.content === "string") {
27
+ return parseMaybeJson(kwargs.content);
28
+ }
29
+ return value;
30
+ }
14
31
  function readToolErrorText(value) {
15
32
  if (typeof value === "string") {
16
33
  return value;
@@ -36,6 +53,31 @@ function isErrorLikeToolOutput(value) {
36
53
  }
37
54
  return /(^|\b)(error|exception|failed|failure|denied|timed out|timeout|not permitted|eperm|eacces)(\b|:)/i.test(message);
38
55
  }
56
+ function isEmptyInitialWriteTodosResult(value) {
57
+ if (typeof value !== "object" || !value || Array.isArray(value)) {
58
+ return false;
59
+ }
60
+ const typed = value;
61
+ if (typeof typed.summary === "object" && typed.summary && Array.isArray(typed.summary.items)) {
62
+ return (typed.summary.items).length === 0;
63
+ }
64
+ if (typeof typed.update === "object" && typed.update && Array.isArray(typed.update.todos)) {
65
+ return (typed.update.todos).length === 0;
66
+ }
67
+ return false;
68
+ }
69
+ function hasLowSignalInitialWriteTodos(value) {
70
+ if (typeof value !== "object" || !value || Array.isArray(value)) {
71
+ return false;
72
+ }
73
+ const typed = value;
74
+ const items = typeof typed.summary === "object" && typed.summary && Array.isArray(typed.summary.items)
75
+ ? (typed.summary.items ?? [])
76
+ : typeof typed.update === "object" && typed.update && Array.isArray(typed.update.todos)
77
+ ? (typed.update.todos ?? [])
78
+ : [];
79
+ return items.length > 0 && items.every((item) => typeof item?.content === "string" && isLowSignalTodoContent(item.content));
80
+ }
39
81
  export function extractTerminalStreamOutput(event) {
40
82
  if (typeof event !== "object" || !event)
41
83
  return "";
@@ -93,7 +135,15 @@ export function extractToolResult(event) {
93
135
  return null;
94
136
  }
95
137
  const rawOutput = isToolError ? typed.data?.error ?? typed.data?.output : typed.data?.output;
96
- const normalizedOutput = typeof rawOutput === "string" ? parseMaybeJson(rawOutput) : rawOutput;
138
+ const normalizedOutput = typeof rawOutput === "string"
139
+ ? parseMaybeJson(rawOutput)
140
+ : unwrapToolMessageOutput(rawOutput);
141
+ if (!isToolError && toolName === "write_todos" && isEmptyInitialWriteTodosResult(normalizedOutput)) {
142
+ throw new Error("Error invoking tool 'write_todos' with kwargs {\"todos\":[]} with error: Error: Initial write_todos call cannot use an empty todo list. Send the concrete task steps with both content and status.");
143
+ }
144
+ if (!isToolError && toolName === "write_todos" && hasLowSignalInitialWriteTodos(normalizedOutput)) {
145
+ throw new Error("Error invoking tool 'write_todos' with placeholder todo content with error: Error: Initial write_todos call must use descriptive task content. Do not use placeholder entries like '1', '2', or 'step 1'.");
146
+ }
97
147
  return {
98
148
  toolName,
99
149
  output: normalizedOutput,
@@ -0,0 +1,41 @@
1
+ import type { RuntimeScheduleManageInput, RuntimeScheduleManageResult, RuntimeScheduleManager, RuntimeScheduleRecord } from "../../contracts/types.js";
2
+ type CommandResult = {
3
+ stdout: string;
4
+ stderr: string;
5
+ exitCode: number;
6
+ };
7
+ type CommandRunner = (command: string, args: string[], options?: {
8
+ input?: string;
9
+ }) => Promise<CommandResult>;
10
+ type SystemScheduleManagerOptions = {
11
+ workspaceRoot: string;
12
+ runtimeRoot: string;
13
+ platform?: NodeJS.Platform;
14
+ nodePath?: string;
15
+ cliPath?: string;
16
+ runCommand?: CommandRunner;
17
+ };
18
+ export declare class SystemScheduleManager implements RuntimeScheduleManager {
19
+ private readonly options;
20
+ private readonly schedulesRoot;
21
+ private readonly platform;
22
+ private readonly nodePath;
23
+ private readonly cliPath;
24
+ private readonly adapter;
25
+ constructor(options: SystemScheduleManagerOptions);
26
+ private manifestPath;
27
+ private ensureSchedulesRoot;
28
+ private writeManifest;
29
+ private toPublicRecord;
30
+ private loadStoredRecord;
31
+ private resolveStatus;
32
+ getSchedule(scheduleId: string): Promise<RuntimeScheduleRecord | null>;
33
+ private listStoredRecords;
34
+ private createSchedule;
35
+ private listSchedules;
36
+ private updateSchedule;
37
+ private deleteSchedule;
38
+ manageSchedule(input: RuntimeScheduleManageInput): Promise<RuntimeScheduleManageResult>;
39
+ describeSchedule(record: RuntimeScheduleRecord): string;
40
+ }
41
+ export {};