@botbotgo/agent-harness 0.0.391 → 0.0.393

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.
@@ -1,2 +1,2 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.391";
2
- export declare const AGENT_HARNESS_RELEASE_DATE = "2026-05-01";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.393";
2
+ export declare const AGENT_HARNESS_RELEASE_DATE = "2026-05-02";
@@ -1,2 +1,2 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.391";
2
- export const AGENT_HARNESS_RELEASE_DATE = "2026-05-01";
1
+ export const AGENT_HARNESS_VERSION = "0.0.393";
2
+ export const AGENT_HARNESS_RELEASE_DATE = "2026-05-02";
@@ -61,12 +61,48 @@ function hasIncompletePlanStateInExecutedToolResults(executedToolResults) {
61
61
  }
62
62
  return false;
63
63
  }
64
+ function hasIncompleteTodosArray(value) {
65
+ if (!Array.isArray(value)) {
66
+ return null;
67
+ }
68
+ return value.some((todo) => typeof todo === "object"
69
+ && todo !== null
70
+ && typeof todo.status === "string"
71
+ && ["pending", "in_progress"].includes(todo.status.trim().toLowerCase()));
72
+ }
73
+ function hasIncompletePlanOutput(value) {
74
+ if (typeof value !== "object" || value === null) {
75
+ return null;
76
+ }
77
+ const typed = value;
78
+ if (typeof typed.pending === "number" || typeof typed.inProgress === "number") {
79
+ return (typeof typed.pending === "number" ? typed.pending : 0) > 0
80
+ || (typeof typed.inProgress === "number" ? typed.inProgress : 0) > 0;
81
+ }
82
+ const directTodos = hasIncompleteTodosArray(typed.todos);
83
+ if (directTodos !== null) {
84
+ return directTodos;
85
+ }
86
+ for (const nested of [typed.summary, typed.update, typed.data, typed.output]) {
87
+ const nestedCompleteness = hasIncompletePlanOutput(nested);
88
+ if (nestedCompleteness !== null) {
89
+ return nestedCompleteness;
90
+ }
91
+ }
92
+ return null;
93
+ }
64
94
  function isPlanToolName(toolName) {
65
95
  return toolName === "write_todos"
66
96
  || toolName === "read_todos"
67
97
  || toolName === "tool_call_write_todos"
68
98
  || toolName === "tool_call_read_todos";
69
99
  }
100
+ function isCompletedPlanToolResultChunk(chunk) {
101
+ if (chunk.kind !== "tool-result" || !isPlanToolName(chunk.toolName)) {
102
+ return false;
103
+ }
104
+ return hasIncompletePlanOutput(chunk.output) === false;
105
+ }
70
106
  function hasNonTodoToolEvidence(executedToolResults) {
71
107
  return executedToolResults.some((item) => !isPlanToolName(item.toolName));
72
108
  }
@@ -460,6 +496,8 @@ export async function* streamRuntimeExecution(options) {
460
496
  if (shouldProfile)
461
497
  yield streamEventsConsume.chunk;
462
498
  try {
499
+ let sawCompletedPlanToolResult = false;
500
+ let sawSuccessfulNonTodoToolResult = false;
463
501
  for await (const event of options.iterateWithTimeout(events, options.streamIdleTimeoutMs, "agent streamEvents", options.streamDeadlineAt, options.invokeTimeoutMs)) {
464
502
  const projectedChunks = projectRuntimeStreamEvent({
465
503
  event,
@@ -484,6 +522,12 @@ export async function* streamRuntimeExecution(options) {
484
522
  if (chunk.kind === "tool-result" && chunk.isError === true && isRetrySafeInvalidToolSelectionError(chunk.output)) {
485
523
  sawRetrySafeInvalidToolSelectionError = true;
486
524
  }
525
+ if (chunk.kind === "tool-result" && !isPlanToolName(chunk.toolName) && chunk.isError !== true) {
526
+ sawSuccessfulNonTodoToolResult = true;
527
+ }
528
+ if (isCompletedPlanToolResultChunk(chunk)) {
529
+ sawCompletedPlanToolResult = true;
530
+ }
487
531
  if ((eventContainsNonTodoToolResult || eventContainsNonRetrySafeChunk) && deferredStreamContent.length > 0) {
488
532
  yield* flushDeferredStreamContent();
489
533
  }
@@ -496,6 +540,19 @@ export async function* streamRuntimeExecution(options) {
496
540
  }
497
541
  yield chunk;
498
542
  }
543
+ if (requiresPlanEvidence(options.binding) && sawCompletedPlanToolResult && sawSuccessfulNonTodoToolResult) {
544
+ if (deferredStreamContent.length > 0) {
545
+ yield* flushDeferredStreamContent();
546
+ }
547
+ return;
548
+ }
549
+ const eventExecutionEvidence = buildExecutionRecoveryEvidence({ projectionState });
550
+ if (requiresPlanEvidence(options.binding) && hasCompletedPlanWithEvidence(eventExecutionEvidence)) {
551
+ if (deferredStreamContent.length > 0) {
552
+ yield* flushDeferredStreamContent();
553
+ }
554
+ return;
555
+ }
499
556
  const terminalVisibleOutput = readTerminalEventVisibleOutput(event);
500
557
  if (terminalVisibleOutput) {
501
558
  const terminalExecutionEvidence = buildExecutionRecoveryEvidence({ projectionState });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.391",
3
+ "version": "0.0.393",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -97,7 +97,9 @@
97
97
  "axios": "^1.15.0",
98
98
  "follow-redirects": "^1.16.0",
99
99
  "hono": "^4.12.14",
100
+ "@anthropic-ai/sdk": "^0.92.0",
100
101
  "langsmith": "^0.5.20",
102
+ "uuid": "^14.0.0",
101
103
  "undici": "^6.24.0",
102
104
  "@qdrant/js-client-rest": "1.17.0",
103
105
  "vite": "^7.3.2",