@botbotgo/agent-harness 0.0.250 → 0.0.252

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 (48) hide show
  1. package/README.md +13 -14
  2. package/README.zh.md +11 -12
  3. package/dist/api.d.ts +13 -6
  4. package/dist/api.js +70 -6
  5. package/dist/config/agents/direct.yaml +3 -3
  6. package/dist/config/agents/orchestra.yaml +3 -3
  7. package/dist/config/catalogs/stores.yaml +3 -9
  8. package/dist/config/runtime/workspace.yaml +1 -2
  9. package/dist/contracts/runtime.d.ts +9 -14
  10. package/dist/flow/build-flow-graph.js +198 -67
  11. package/dist/flow/export-mermaid.js +314 -4
  12. package/dist/flow/export-sequence-mermaid.js +149 -2
  13. package/dist/flow/types.d.ts +11 -1
  14. package/dist/index.d.ts +2 -3
  15. package/dist/index.js +1 -1
  16. package/dist/package-version.d.ts +1 -1
  17. package/dist/package-version.js +1 -1
  18. package/dist/persistence/file-store.d.ts +3 -2
  19. package/dist/persistence/file-store.js +34 -8
  20. package/dist/persistence/sqlite-store.d.ts +2 -2
  21. package/dist/persistence/sqlite-store.js +64 -11
  22. package/dist/persistence/types.d.ts +3 -3
  23. package/dist/protocol/a2a/http.js +2 -4
  24. package/dist/resource/isolation.js +30 -2
  25. package/dist/resource/resource-impl.js +1 -4
  26. package/dist/runtime/harness/events/streaming.js +8 -8
  27. package/dist/runtime/harness/run/inspection.d.ts +2 -0
  28. package/dist/runtime/harness/run/inspection.js +91 -46
  29. package/dist/runtime/harness/run/stream-run.d.ts +2 -2
  30. package/dist/runtime/harness/run/stream-run.js +34 -23
  31. package/dist/runtime/harness/run/surface-semantics.d.ts +14 -0
  32. package/dist/runtime/harness/run/surface-semantics.js +106 -0
  33. package/dist/runtime/harness/run/thread-records.js +2 -34
  34. package/dist/runtime/harness/system/store.d.ts +6 -4
  35. package/dist/runtime/harness/system/store.js +76 -42
  36. package/dist/runtime/harness.js +7 -7
  37. package/dist/runtime/maintenance/checkpoint-maintenance.js +4 -119
  38. package/dist/runtime/maintenance/index.d.ts +0 -1
  39. package/dist/runtime/maintenance/index.js +0 -1
  40. package/dist/runtime/support/runtime-env.d.ts +1 -0
  41. package/dist/runtime/support/runtime-env.js +5 -0
  42. package/dist/runtime/support/runtime-factories.js +2 -42
  43. package/dist/upstream-events.js +14 -0
  44. package/package.json +1 -3
  45. package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.d.ts +0 -9
  46. package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.js +0 -39
  47. package/dist/runtime/support/sqlite-drivers.d.ts +0 -12
  48. package/dist/runtime/support/sqlite-drivers.js +0 -24
@@ -1,6 +1,7 @@
1
1
  import { projectRuntimeTimeline } from "../runtime/harness/events/timeline.js";
2
2
  import { createUpstreamTimelineReducer } from "../upstream-events.js";
3
3
  import { formatAgentName } from "../utils/agent-display.js";
4
+ import { buildSurfaceId, resolveSurfaceAction, stripStepPrefix, } from "../runtime/harness/run/surface-semantics.js";
4
5
  function asObject(value) {
5
6
  return typeof value === "object" && value !== null ? value : null;
6
7
  }
@@ -10,16 +11,54 @@ function readString(value) {
10
11
  function extractUpstreamEventEnvelope(value) {
11
12
  const typed = asObject(value);
12
13
  const nestedEvent = typed && Object.prototype.hasOwnProperty.call(typed, "event") ? typed.event : undefined;
14
+ const surfaceItem = asObject(typed?.surfaceItem);
13
15
  const event = typed
14
16
  && nestedEvent
15
17
  && typeof nestedEvent === "object"
16
18
  && !Array.isArray(nestedEvent)
17
- && Object.prototype.hasOwnProperty.call(typed, "agentId")
18
19
  ? nestedEvent
19
20
  : value;
20
- const agentId = readString(typed?.agentId);
21
- const agentName = readString(typed?.agentName);
22
- return { event, agentId: agentId ?? undefined, agentName: agentName ?? undefined };
21
+ const agentId = readString(typed?.agentId) ?? readString(surfaceItem?.agentId);
22
+ const agentName = readString(typed?.agentName) ?? readString(surfaceItem?.agentName);
23
+ return {
24
+ event,
25
+ agentId: agentId ?? undefined,
26
+ agentName: agentName ?? undefined,
27
+ ...(surfaceItem ? { surfaceItem } : {}),
28
+ };
29
+ }
30
+ function normalizeRuntimeEventType(eventType) {
31
+ switch (eventType) {
32
+ case "request.created":
33
+ return "run.created";
34
+ case "request.queued":
35
+ return "run.queued";
36
+ case "request.dequeued":
37
+ return "run.dequeued";
38
+ case "request.state.changed":
39
+ return "run.state.changed";
40
+ case "request.resumed":
41
+ return "run.resumed";
42
+ default:
43
+ return eventType;
44
+ }
45
+ }
46
+ function normalizeRuntimeEvents(events) {
47
+ return events.map((event) => {
48
+ const typed = event;
49
+ const threadId = readString(typed.threadId) ?? readString(typed.sessionId) ?? "";
50
+ const runId = readString(typed.runId) ?? readString(typed.requestId) ?? "";
51
+ return {
52
+ eventId: String(event.eventId),
53
+ eventType: normalizeRuntimeEventType(String(event.eventType)),
54
+ timestamp: String(event.timestamp),
55
+ threadId,
56
+ runId,
57
+ sequence: Number(event.sequence),
58
+ source: event.source,
59
+ payload: event.payload ?? {},
60
+ };
61
+ });
23
62
  }
24
63
  function collectNestedAgentNames(value, names = new Set()) {
25
64
  if (Array.isArray(value)) {
@@ -50,9 +89,6 @@ function slugify(value) {
50
89
  .replace(/^-+|-+$/g, "")
51
90
  .slice(0, 80) || "node";
52
91
  }
53
- function buildSurfaceId(kind, value) {
54
- return `${kind}:${slugify(value)}`;
55
- }
56
92
  function titleCase(value) {
57
93
  return value
58
94
  .replace(/[_-]+/g, " ")
@@ -360,6 +396,68 @@ function deriveInitialAgentId(input, runtimeTimeline) {
360
396
  function deriveAgentName(agentId, explicitName) {
361
397
  return explicitName && explicitName.trim().length > 0 ? explicitName.trim() : formatAgentName(agentId);
362
398
  }
399
+ function buildSurfaceStepLabel(surfaceItem) {
400
+ const kind = surfaceItem.kind;
401
+ const name = typeof surfaceItem.name === "string" && surfaceItem.name.trim().length > 0
402
+ ? surfaceItem.name.trim()
403
+ : typeof surfaceItem.id === "string"
404
+ ? surfaceItem.id
405
+ : "";
406
+ const status = surfaceItem.status;
407
+ if (!kind || !name || !status || (status !== "started" && status !== "completed" && status !== "failed")) {
408
+ return null;
409
+ }
410
+ if (kind === "llm") {
411
+ return status === "started" ? `Calling LLM ${name}` : `Completed LLM ${name}`;
412
+ }
413
+ if (kind === "tool") {
414
+ if (status === "failed") {
415
+ return `Tool ${name} failed`;
416
+ }
417
+ return status === "started" ? `Calling tool ${name}` : `Completed tool ${name}`;
418
+ }
419
+ if (kind === "skill") {
420
+ return status === "started" ? `Calling skill ${name}` : `Completed skill ${name}`;
421
+ }
422
+ if (kind === "memory") {
423
+ return status === "started" ? `Accessing memory ${name}` : `Completed memory ${name}`;
424
+ }
425
+ return null;
426
+ }
427
+ function createDelegationNodeFromSurfaceItem(surfaceItem, fallbackAgentId, fallbackAgentName, sourceEventId, ordinal) {
428
+ if (surfaceItem.kind !== "agent") {
429
+ return null;
430
+ }
431
+ const toAgentId = typeof surfaceItem.agentId === "string" && surfaceItem.agentId.trim().length > 0
432
+ ? surfaceItem.agentId.trim()
433
+ : fallbackAgentId;
434
+ const toAgentName = deriveAgentName(toAgentId, typeof surfaceItem.agentName === "string" ? surfaceItem.agentName : undefined);
435
+ const fromAgentId = typeof surfaceItem.ownerAgentId === "string" && surfaceItem.ownerAgentId.trim().length > 0
436
+ ? surfaceItem.ownerAgentId.trim()
437
+ : fallbackAgentId;
438
+ const fromAgentName = deriveAgentName(fromAgentId, typeof surfaceItem.ownerAgentName === "string" ? surfaceItem.ownerAgentName : fallbackAgentName);
439
+ return {
440
+ id: `delegate:${slugify(fromAgentId)}:${slugify(toAgentId)}:${ordinal}`,
441
+ layer: "execution",
442
+ kind: "agent",
443
+ label: `Delegate to ${titleCase(typeof surfaceItem.name === "string" ? surfaceItem.name : toAgentId)}`,
444
+ status: surfaceItem.status === "failed" ? "failed" : surfaceItem.status === "started" ? "started" : "completed",
445
+ sessionId: "",
446
+ requestId: "",
447
+ threadId: "",
448
+ runId: "",
449
+ agentId: toAgentId,
450
+ agentName: toAgentName,
451
+ sourceEventIds: [sourceEventId],
452
+ detail: {
453
+ fromAgentId,
454
+ fromAgentName,
455
+ toAgentId,
456
+ toAgentName,
457
+ ...(typeof surfaceItem.action === "string" ? { action: surfaceItem.action } : {}),
458
+ },
459
+ };
460
+ }
363
461
  function extractDelegatedAgentId(event) {
364
462
  const typed = asObject(event);
365
463
  if (!typed) {
@@ -372,26 +470,20 @@ function extractDelegatedAgentId(event) {
372
470
  }
373
471
  const data = asObject(typed.data);
374
472
  const input = asObject(data?.input);
473
+ const nestedInput = typeof input?.input === "string"
474
+ ? asObject(JSON.parse(input.input))
475
+ : asObject(input?.input);
375
476
  const subagentType = typeof input?.subagent_type === "string"
376
477
  ? input.subagent_type
377
478
  : typeof input?.subagentType === "string"
378
479
  ? input.subagentType
379
- : null;
480
+ : typeof nestedInput?.subagent_type === "string"
481
+ ? nestedInput.subagent_type
482
+ : typeof nestedInput?.subagentType === "string"
483
+ ? nestedInput.subagentType
484
+ : null;
380
485
  return subagentType && subagentType.trim().length > 0 ? subagentType.trim() : null;
381
486
  }
382
- function extractAgentFromNestedMessages(event, currentAgentId) {
383
- const typed = asObject(event);
384
- if (!typed) {
385
- return null;
386
- }
387
- const data = asObject(typed.data);
388
- const input = asObject(data?.input);
389
- const output = asObject(data?.output);
390
- const names = new Set();
391
- collectNestedAgentNames(input?.messages, names);
392
- collectNestedAgentNames(output?.messages, names);
393
- return [...names].find((name) => name !== currentAgentId) ?? null;
394
- }
395
487
  function convertUpstreamEventsWithAgents(upstreamEvents, initialAgentId) {
396
488
  const reducer = createUpstreamTimelineReducer();
397
489
  const projections = [];
@@ -409,35 +501,11 @@ function convertUpstreamEventsWithAgents(upstreamEvents, initialAgentId) {
409
501
  else if (envelope.agentName) {
410
502
  currentAgentName = deriveAgentName(currentAgentId, envelope.agentName);
411
503
  }
412
- const nestedAgentId = extractAgentFromNestedMessages(envelope.event, currentAgentId);
413
- if (nestedAgentId && nestedAgentId !== currentAgentId) {
414
- const nestedAgentName = deriveAgentName(nestedAgentId);
415
- ordinal += 1;
416
- delegationNodes.push({
417
- id: `delegate:${slugify(currentAgentId)}:${slugify(nestedAgentId)}:${ordinal}`,
418
- layer: "execution",
419
- kind: "agent",
420
- label: `Delegate to ${titleCase(nestedAgentId)}`,
421
- status: "completed",
422
- sessionId: "",
423
- requestId: "",
424
- threadId: "",
425
- runId: "",
426
- agentId: nestedAgentId,
427
- agentName: nestedAgentName,
428
- sourceEventIds: [sourceEventId],
429
- detail: {
430
- fromAgentId: currentAgentId,
431
- fromAgentName: currentAgentName,
432
- toAgentId: nestedAgentId,
433
- toAgentName: nestedAgentName,
434
- },
435
- });
436
- currentAgentId = nestedAgentId;
437
- currentAgentName = nestedAgentName;
438
- }
439
504
  const emitted = reducer.consume(envelope.event);
440
505
  for (const projection of emitted) {
506
+ if (envelope.surfaceItem && projection.type === "step") {
507
+ continue;
508
+ }
441
509
  projections.push({
442
510
  projection,
443
511
  agentId: currentAgentId,
@@ -445,6 +513,33 @@ function convertUpstreamEventsWithAgents(upstreamEvents, initialAgentId) {
445
513
  sourceEventId,
446
514
  });
447
515
  }
516
+ if (envelope.surfaceItem) {
517
+ const delegationNode = createDelegationNodeFromSurfaceItem(envelope.surfaceItem, currentAgentId, currentAgentName, sourceEventId, ordinal + 1);
518
+ if (delegationNode) {
519
+ ordinal += 1;
520
+ delegationNodes.push(delegationNode);
521
+ }
522
+ else {
523
+ const step = buildSurfaceStepLabel(envelope.surfaceItem);
524
+ if (step) {
525
+ projections.push({
526
+ projection: {
527
+ type: "step",
528
+ key: `surface:${index + 1}:${envelope.surfaceItem.id ?? step}`,
529
+ category: envelope.surfaceItem.kind,
530
+ status: envelope.surfaceItem.status,
531
+ step,
532
+ },
533
+ agentId: currentAgentId,
534
+ agentName: currentAgentName,
535
+ sourceEventId,
536
+ });
537
+ }
538
+ }
539
+ }
540
+ if (envelope.surfaceItem) {
541
+ return;
542
+ }
448
543
  const delegatedAgentId = extractDelegatedAgentId(envelope.event);
449
544
  if (!delegatedAgentId || delegatedAgentId === currentAgentId) {
450
545
  return;
@@ -544,6 +639,44 @@ function buildAttempts(projectionRecords, delegationNodes, runtimeGroups, thread
544
639
  }
545
640
  for (const record of projectionRecords) {
546
641
  const projection = record.projection;
642
+ if (!pendingDelegationNode
643
+ && delegationIndex < delegationNodes.length
644
+ && delegationNodes[delegationIndex]?.agentId === record.agentId
645
+ && (!previousAttempt || previousAttempt.agentId !== record.agentId)) {
646
+ const sourceNode = delegationNodes[delegationIndex];
647
+ delegationIndex += 1;
648
+ pendingDelegationNode = {
649
+ ...sourceNode,
650
+ sessionId: threadId,
651
+ requestId: runId,
652
+ threadId,
653
+ runId,
654
+ groupId: currentGroup?.id,
655
+ };
656
+ nodes.push(pendingDelegationNode);
657
+ if (previousAttempt) {
658
+ edges.push({
659
+ id: `edge:${previousAttempt.id}->${pendingDelegationNode.id}`,
660
+ from: previousAttempt.id,
661
+ to: pendingDelegationNode.id,
662
+ kind: "spawn",
663
+ label: "delegate",
664
+ sourceEventIds: [...pendingDelegationNode.sourceEventIds],
665
+ confidence: 0.9,
666
+ });
667
+ }
668
+ else if (currentGroup?.anchorNodeId) {
669
+ edges.push({
670
+ id: `edge:${currentGroup.anchorNodeId}->${pendingDelegationNode.id}`,
671
+ from: currentGroup.anchorNodeId,
672
+ to: pendingDelegationNode.id,
673
+ kind: "spawn",
674
+ label: "delegate",
675
+ sourceEventIds: [...pendingDelegationNode.sourceEventIds],
676
+ confidence: 0.9,
677
+ });
678
+ }
679
+ }
547
680
  if (previousAttempt
548
681
  && previousAttempt.agentId
549
682
  && record.agentId !== previousAttempt.agentId
@@ -743,18 +876,18 @@ function resolveContext(input, runtimeTimeline, projections) {
743
876
  return { sessionId: inputSessionId, requestId: inputRequestId };
744
877
  }
745
878
  export function buildFlowGraph(input) {
746
- const runtimeTimeline = input.runtimeTimeline
747
- ?? (input.runtimeEvents ? projectRuntimeTimeline(input.runtimeEvents, {
879
+ const runtimeData = input.runtimeTimeline
880
+ ?? (input.runtimeEvents ? projectRuntimeTimeline(normalizeRuntimeEvents(input.runtimeEvents), {
748
881
  ...(readSessionId(input) ? { threadId: readSessionId(input) } : {}),
749
882
  ...(readRequestId(input) ? { runId: readRequestId(input) } : {}),
750
883
  }) : []);
751
- const initialAgentId = deriveInitialAgentId(input, runtimeTimeline);
884
+ const initialAgentId = deriveInitialAgentId(input, runtimeData);
752
885
  const upstreamContext = input.upstreamEvents
753
886
  ? convertUpstreamEventsWithAgents(input.upstreamEvents, initialAgentId)
754
887
  : { projections: [], delegationNodes: [] };
755
888
  const upstreamProjections = input.upstreamProjections ?? upstreamContext.projections.map((record) => record.projection);
756
- const { sessionId, requestId } = resolveContext(input, runtimeTimeline, upstreamProjections);
757
- const { nodes: runtimeNodes, edges: runtimeEdges, groups: runtimeGroups } = buildRuntimeNodes(runtimeTimeline);
889
+ const { sessionId, requestId } = resolveContext(input, runtimeData, upstreamProjections);
890
+ const { nodes: runtimeNodes, edges: runtimeEdges, groups: runtimeGroups } = buildRuntimeNodes(runtimeData);
758
891
  for (const node of runtimeNodes) {
759
892
  node.agentId = typeof node.detail.agentId === "string" ? node.detail.agentId : initialAgentId;
760
893
  node.agentName = deriveAgentName(node.agentId);
@@ -776,20 +909,15 @@ export function buildFlowGraph(input) {
776
909
  id: buildSurfaceId(node.kind, node.kind === "agent" ? (node.agentId ?? node.agentName ?? "agent") : node.label),
777
910
  name: node.kind === "agent"
778
911
  ? (node.agentName ?? node.agentId ?? "Agent")
779
- : normalizeLabel(node.label)
780
- .replace(/^Delegate to\s+/i, "")
781
- .replace(/^Calling LLM\s+/i, "")
782
- .replace(/^Completed LLM\s+/i, "")
783
- .replace(/^Calling tool\s+/i, "")
784
- .replace(/^Completed tool\s+/i, "")
785
- .replace(/^Tool\s+/i, "")
786
- .replace(/\s+failed$/i, "")
787
- .replace(/^Calling skill\s+/i, "")
788
- .replace(/^Completed skill\s+/i, "")
789
- .replace(/^Accessing memory\s+/i, "")
790
- .replace(/^Completed memory\s+/i, ""),
791
- label: node.label,
912
+ : stripStepPrefix(node.label),
913
+ action: resolveSurfaceAction({
914
+ kind: node.kind,
915
+ step: node.label,
916
+ event: node.detail,
917
+ }),
792
918
  status: node.status === "resolved" ? "completed" : node.status,
919
+ agentId: node.agentId,
920
+ agentName: node.agentName,
793
921
  ownerAgentId: node.kind === "agent"
794
922
  ? (typeof node.detail.fromAgentId === "string" ? node.detail.fromAgentId : node.agentId)
795
923
  : node.agentId,
@@ -797,6 +925,7 @@ export function buildFlowGraph(input) {
797
925
  ? (typeof node.detail.fromAgentName === "string" ? node.detail.fromAgentName : node.agentName)
798
926
  : node.agentName,
799
927
  sourceEventId: node.sourceEventIds[0],
928
+ detail: { ...node.detail },
800
929
  }));
801
930
  return {
802
931
  graphId: `${sessionId}/${requestId}`,
@@ -809,7 +938,9 @@ export function buildFlowGraph(input) {
809
938
  edges: [...runtimeEdges, ...attemptEdges],
810
939
  groups: [...runtimeGroups, ...attemptGroups],
811
940
  metadata: {
812
- runtimeTimelineCount: runtimeTimeline.length,
941
+ initialAgentId,
942
+ initialAgentName: deriveAgentName(initialAgentId),
943
+ runtimeTimelineCount: runtimeData.length,
813
944
  upstreamProjectionCount: upstreamProjections.length,
814
945
  delegationCount: upstreamContext.delegationNodes.length,
815
946
  runtimeSurface,