@botbotgo/agent-harness 0.0.419 → 0.0.421

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.
@@ -19,7 +19,7 @@ const MODEL_EXPOSED_BUILTIN_MIDDLEWARE_TOOL_NAMES = new Set([
19
19
  "schedule_task",
20
20
  ]);
21
21
  export function materializeModelExposedBuiltinMiddlewareTools(input) {
22
- if (input.modelExposed === false) {
22
+ if (input.modelExposed === false || input.modelExposed === undefined) {
23
23
  return [];
24
24
  }
25
25
  const explicitToolNames = new Set(input.explicitToolNames ?? []);
@@ -114,7 +114,15 @@ export function buildRequestRuntimeSnapshot(binding, options) {
114
114
  description: tool.description,
115
115
  }));
116
116
  const builtinToolsConfig = getBindingBuiltinToolsConfig(binding);
117
- const builtinToolDescriptors = filterBuiltinMiddlewareToolDescriptors(builtinToolsConfig)
117
+ const effectiveBuiltinToolsConfig = builtinToolsConfig === undefined
118
+ ? isDeepAgentBinding(binding)
119
+ ? { modelExposed: false }
120
+ : undefined
121
+ : {
122
+ ...builtinToolsConfig,
123
+ modelExposed: builtinToolsConfig.modelExposed ?? false,
124
+ };
125
+ const builtinToolDescriptors = filterBuiltinMiddlewareToolDescriptors(effectiveBuiltinToolsConfig)
118
126
  .filter((descriptor) => !declaredTools.some((tool) => tool.name === descriptor.name));
119
127
  const tools = isDeepAgentBinding(binding)
120
128
  ? [
@@ -62,6 +62,12 @@ function inferPlanItemStatusFromTerminalAssistantOutput(value) {
62
62
  }
63
63
  return isSubstantiveTerminalAssistantOutput(value) ? "completed" : null;
64
64
  }
65
+ function mapTerminalStatusToObservedPlanItemStatus(status, sawSuccessfulToolResult) {
66
+ if (status === "blocked" && sawSuccessfulToolResult) {
67
+ return "completed";
68
+ }
69
+ return mapTerminalStatusToPlanItemStatus(status);
70
+ }
65
71
  function reconcilePlanStateToTerminalStatus(planState, status, updatedAt) {
66
72
  const items = planState.items.map((item) => ({
67
73
  ...item,
@@ -1027,7 +1033,7 @@ export async function* streamHarnessRun(options) {
1027
1033
  currentPlanState = await refreshPlanStateFromPersistence(options, currentPlanState);
1028
1034
  const terminalStructuredStatus = readTerminalExecutionStatus(actual.structuredResponse);
1029
1035
  if (terminalStructuredStatus && currentPlanState && planStateHasActiveItems(currentPlanState)) {
1030
- const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToPlanItemStatus(terminalStructuredStatus), new Date().toISOString());
1036
+ const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToObservedPlanItemStatus(terminalStructuredStatus, sawSuccessfulToolResult), new Date().toISOString());
1031
1037
  const signature = buildPlanStateSignature(reconciledPlanState);
1032
1038
  if (signature !== lastPlanStateSignature) {
1033
1039
  const previousPlanState = currentPlanState;
@@ -1053,6 +1059,9 @@ export async function* streamHarnessRun(options) {
1053
1059
  currentPlanState = await refreshPlanStateFromPersistence(options, currentPlanState);
1054
1060
  const explicitTerminalAssistantStatus = readTerminalExecutionStatus(assistantOutput);
1055
1061
  let terminalAssistantPlanItemStatus = inferPlanItemStatusFromTerminalAssistantOutput(assistantOutput);
1062
+ if (explicitTerminalAssistantStatus === "blocked" && sawSuccessfulToolResult) {
1063
+ terminalAssistantPlanItemStatus = "completed";
1064
+ }
1056
1065
  if (terminalAssistantPlanItemStatus === "failed"
1057
1066
  && sawSuccessfulToolResult
1058
1067
  && !explicitTerminalAssistantStatus
@@ -1135,7 +1144,7 @@ export async function* streamHarnessRun(options) {
1135
1144
  const canUseDeterministicToolEvidenceOutput = !currentPlanState || !planStateHasActiveItems(currentPlanState) || Boolean(terminalStructuredStatus);
1136
1145
  if (!assistantOutput && sawSuccessfulToolResult && deterministicToolEvidenceOutput && canUseDeterministicToolEvidenceOutput) {
1137
1146
  if (terminalStructuredStatus && currentPlanState && planStateHasActiveItems(currentPlanState)) {
1138
- const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToPlanItemStatus(terminalStructuredStatus), new Date().toISOString());
1147
+ const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToObservedPlanItemStatus(terminalStructuredStatus, sawSuccessfulToolResult), new Date().toISOString());
1139
1148
  const signature = buildPlanStateSignature(reconciledPlanState);
1140
1149
  if (signature !== lastPlanStateSignature) {
1141
1150
  const previousPlanState = currentPlanState;
@@ -309,6 +309,89 @@ function normalizePythonLikeJson(value) {
309
309
  }
310
310
  return output;
311
311
  }
312
+ function repairMissingArrayObjectOpenBraces(value) {
313
+ let output = "";
314
+ let changed = false;
315
+ let inString = false;
316
+ let escaping = false;
317
+ const stack = [];
318
+ for (let index = 0; index < value.length; index += 1) {
319
+ const char = value[index];
320
+ if (inString) {
321
+ output += char;
322
+ if (escaping) {
323
+ escaping = false;
324
+ continue;
325
+ }
326
+ if (char === "\\") {
327
+ escaping = true;
328
+ continue;
329
+ }
330
+ if (char === "\"") {
331
+ inString = false;
332
+ }
333
+ continue;
334
+ }
335
+ if (char === "\"") {
336
+ output += char;
337
+ inString = true;
338
+ continue;
339
+ }
340
+ if (char === "{" || char === "[") {
341
+ stack.push(char);
342
+ output += char;
343
+ continue;
344
+ }
345
+ if (char === "}" || char === "]") {
346
+ const expectedOpen = char === "}" ? "{" : "[";
347
+ if (stack.at(-1) === expectedOpen) {
348
+ stack.pop();
349
+ }
350
+ output += char;
351
+ continue;
352
+ }
353
+ if (char !== "," || stack.at(-1) !== "[") {
354
+ output += char;
355
+ continue;
356
+ }
357
+ output += char;
358
+ let lookahead = index + 1;
359
+ while (lookahead < value.length && /\s/u.test(value[lookahead] ?? "")) {
360
+ output += value[lookahead];
361
+ lookahead += 1;
362
+ }
363
+ if (value[lookahead] !== "\"") {
364
+ index = lookahead - 1;
365
+ continue;
366
+ }
367
+ let cursor = lookahead + 1;
368
+ let keyEscaping = false;
369
+ while (cursor < value.length) {
370
+ const next = value[cursor];
371
+ if (keyEscaping) {
372
+ keyEscaping = false;
373
+ }
374
+ else if (next === "\\") {
375
+ keyEscaping = true;
376
+ }
377
+ else if (next === "\"") {
378
+ break;
379
+ }
380
+ cursor += 1;
381
+ }
382
+ let colonCursor = cursor + 1;
383
+ while (colonCursor < value.length && /\s/u.test(value[colonCursor] ?? "")) {
384
+ colonCursor += 1;
385
+ }
386
+ if (value[colonCursor] === ":") {
387
+ output += "{";
388
+ stack.push("{");
389
+ changed = true;
390
+ }
391
+ index = lookahead - 1;
392
+ }
393
+ return changed ? output : null;
394
+ }
312
395
  export function salvageToolArgs(value) {
313
396
  if (typeof value === "object" && value && !Array.isArray(value)) {
314
397
  return value;
@@ -359,6 +442,13 @@ export function salvageJsonToolCalls(value) {
359
442
  if (direct) {
360
443
  return direct;
361
444
  }
445
+ const repairedArrayObjects = repairMissingArrayObjectOpenBraces(trimmed);
446
+ if (repairedArrayObjects) {
447
+ const parsed = tryParseJson(repairedArrayObjects);
448
+ if (parsed) {
449
+ return parsed;
450
+ }
451
+ }
362
452
  const pythonLike = normalizePythonLikeJson(trimmed);
363
453
  if (pythonLike) {
364
454
  const parsed = tryParseJson(pythonLike);
@@ -366,6 +456,15 @@ export function salvageJsonToolCalls(value) {
366
456
  return parsed;
367
457
  }
368
458
  }
459
+ if (pythonLike) {
460
+ const repairedPythonLike = repairMissingArrayObjectOpenBraces(pythonLike);
461
+ if (repairedPythonLike) {
462
+ const parsed = tryParseJson(repairedPythonLike);
463
+ if (parsed) {
464
+ return parsed;
465
+ }
466
+ }
467
+ }
369
468
  const closed = closeJsonContainerSuffix(trimmed);
370
469
  if (closed) {
371
470
  const parsed = tryParseJson(closed);
@@ -373,6 +472,15 @@ export function salvageJsonToolCalls(value) {
373
472
  return parsed;
374
473
  }
375
474
  }
475
+ if (repairedArrayObjects) {
476
+ const closedRepaired = closeJsonContainerSuffix(repairedArrayObjects);
477
+ if (closedRepaired) {
478
+ const parsed = tryParseJson(closedRepaired);
479
+ if (parsed) {
480
+ return parsed;
481
+ }
482
+ }
483
+ }
376
484
  const embeddedObject = extractBalancedJsonObject(trimmed);
377
485
  if (embeddedObject) {
378
486
  const parsed = tryParseJson(embeddedObject);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.419",
3
+ "version": "0.0.421",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",