@botbotgo/agent-harness 0.0.475 → 0.0.476
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.
- package/README.md +3 -1234
- package/README.zh.md +3 -1191
- package/dist/acp.js +1 -1
- package/dist/api.js +1 -404
- package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
- package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
- package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
- package/dist/cli/chat-interactive.js +25 -244
- package/dist/cli/chat-rendering.js +6 -100
- package/dist/cli/chat-stream.js +23 -512
- package/dist/cli/chat-ui.js +21 -199
- package/dist/cli/chat-workspace.js +2 -210
- package/dist/cli/main.js +21 -428
- package/dist/cli/managed-service-commands.js +9 -63
- package/dist/cli/managed-service.js +2 -137
- package/dist/cli/options-init-chat.js +1 -108
- package/dist/cli/options-runtime.js +1 -158
- package/dist/cli/options-serve.js +1 -282
- package/dist/cli/options.js +2 -19
- package/dist/cli/process-guards.js +1 -139
- package/dist/cli/request-tree.js +7 -296
- package/dist/cli/runtime-commands.js +12 -258
- package/dist/cli/runtime-output.js +16 -155
- package/dist/cli/server-commands.js +16 -270
- package/dist/cli/workspace.js +1 -67
- package/dist/cli.js +1 -7
- package/dist/client/acp.js +1 -1
- package/dist/client/in-process.js +1 -67
- package/dist/client/index.js +1 -2
- package/dist/client/types.js +0 -1
- package/dist/client.js +1 -1
- package/dist/contracts/core.js +1 -1
- package/dist/contracts/runtime-evaluation.js +0 -1
- package/dist/contracts/runtime-memory.js +0 -1
- package/dist/contracts/runtime-observability.js +0 -1
- package/dist/contracts/runtime-requests.js +0 -1
- package/dist/contracts/runtime-scheduling.js +0 -1
- package/dist/contracts/runtime.js +1 -27
- package/dist/contracts/types.js +1 -3
- package/dist/contracts/workspace.js +0 -1
- package/dist/flow/build-flow-graph.js +1 -50
- package/dist/flow/export-mermaid.js +2 -464
- package/dist/flow/export-sequence-mermaid.js +2 -325
- package/dist/flow/flow-graph-normalization.js +1 -214
- package/dist/flow/flow-graph-runtime.js +1 -107
- package/dist/flow/flow-graph-upstream.js +1 -494
- package/dist/flow/index.js +1 -3
- package/dist/flow/types.js +0 -1
- package/dist/index.js +1 -5
- package/dist/init-project.js +1 -1
- package/dist/knowledge/config.js +1 -32
- package/dist/knowledge/contracts.js +0 -1
- package/dist/knowledge/index.js +1 -2
- package/dist/knowledge/module.js +12 -909
- package/dist/knowledge/procedural/config.js +1 -125
- package/dist/knowledge/procedural/index.js +1 -2
- package/dist/knowledge/procedural/manager.js +9 -345
- package/dist/mcp.js +1 -2
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -2
- package/dist/persistence/file-store.js +3 -758
- package/dist/persistence/sqlite-request-context-store.js +5 -54
- package/dist/persistence/sqlite-request-queue-store.js +10 -108
- package/dist/persistence/sqlite-runtime.js +1 -86
- package/dist/persistence/sqlite-store.js +62 -810
- package/dist/persistence/types.js +0 -1
- package/dist/projections/presentation.js +37 -206
- package/dist/projections/request-events.js +2 -502
- package/dist/projections/upstream-events.js +1 -201
- package/dist/protocol/a2a/http-discovery.js +1 -178
- package/dist/protocol/a2a/http-rpc.js +6 -622
- package/dist/protocol/a2a/http.js +1 -138
- package/dist/protocol/a2a/task-state.js +3 -317
- package/dist/protocol/acp/client.js +8 -294
- package/dist/protocol/acp/harness-client.js +1 -218
- package/dist/protocol/acp/http.js +5 -130
- package/dist/protocol/acp/server.js +1 -310
- package/dist/protocol/acp/stdio.js +2 -69
- package/dist/protocol/ag-ui/http.js +3 -378
- package/dist/protocol/mcp/server.js +1 -428
- package/dist/resource/backend/workspace-scoped-backend.js +1 -319
- package/dist/resource/isolation.js +1 -237
- package/dist/resource/mcp/tool-support.js +3 -296
- package/dist/resource/mcp-tool-support.js +1 -2
- package/dist/resource/providers/resource-provider.js +1 -215
- package/dist/resource/resource-impl.js +1 -3
- package/dist/resource/resource-types.js +0 -1
- package/dist/resource/resource.js +1 -1
- package/dist/resource/sources.js +1 -247
- package/dist/resource/tools/function-tool-resolver.js +2 -272
- package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
- package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
- package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
- package/dist/runtime/adapter/flow/execution-context.js +1 -71
- package/dist/runtime/adapter/flow/invocation-flow.js +8 -425
- package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
- package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
- package/dist/runtime/adapter/invocation-result.js +2 -473
- package/dist/runtime/adapter/local-tool-invocation.js +6 -638
- package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
- package/dist/runtime/adapter/middleware-assembly.js +5 -477
- package/dist/runtime/adapter/model/invocation-request.js +3 -183
- package/dist/runtime/adapter/model/message-assembly.js +1 -28
- package/dist/runtime/adapter/model/model-providers.js +23 -1115
- package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
- package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
- package/dist/runtime/adapter/resilience.js +1 -104
- package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
- package/dist/runtime/adapter/runtime-shell.js +5 -166
- package/dist/runtime/adapter/stream-event-projection.js +2 -622
- package/dist/runtime/adapter/stream-text-consumption.js +1 -18
- package/dist/runtime/adapter/terminal-status.js +2 -67
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
- package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
- package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
- package/dist/runtime/adapter/tool/provider-tool.js +1 -25
- package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
- package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
- package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
- package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
- package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
- package/dist/runtime/adapter/tool/tool-replay.js +1 -37
- package/dist/runtime/adapter/tool-resolution.js +1 -86
- package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
- package/dist/runtime/agent-runtime-adapter.js +60 -2338
- package/dist/runtime/agent-runtime-assembly.js +7 -249
- package/dist/runtime/env/runtime-env.js +1 -62
- package/dist/runtime/harness/background-runtime.js +1 -8
- package/dist/runtime/harness/bindings.js +1 -58
- package/dist/runtime/harness/events/event-bus.js +1 -16
- package/dist/runtime/harness/events/event-sink.js +1 -61
- package/dist/runtime/harness/events/events.js +1 -80
- package/dist/runtime/harness/events/listener-runtime.js +1 -13
- package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
- package/dist/runtime/harness/events/streaming.js +1 -100
- package/dist/runtime/harness/events/timeline.js +1 -52
- package/dist/runtime/harness/public-shapes.js +1 -186
- package/dist/runtime/harness/run/artifact-paths.js +1 -15
- package/dist/runtime/harness/run/governance.js +1 -295
- package/dist/runtime/harness/run/helpers.js +1 -71
- package/dist/runtime/harness/run/inspection.js +1 -409
- package/dist/runtime/harness/run/operator-overview.js +1 -80
- package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
- package/dist/runtime/harness/run/recovery.js +1 -162
- package/dist/runtime/harness/run/resources.js +1 -60
- package/dist/runtime/harness/run/resume.js +1 -56
- package/dist/runtime/harness/run/routing.js +1 -48
- package/dist/runtime/harness/run/run-lifecycle.js +1 -66
- package/dist/runtime/harness/run/run-operations.js +1 -217
- package/dist/runtime/harness/run/run-queue.js +1 -43
- package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
- package/dist/runtime/harness/run/session-records.js +1 -97
- package/dist/runtime/harness/run/start-run.js +1 -120
- package/dist/runtime/harness/run/startup-runtime.js +1 -69
- package/dist/runtime/harness/run/stream-run.js +8 -1418
- package/dist/runtime/harness/run/surface-semantics.js +1 -79
- package/dist/runtime/harness/runtime-defaults.js +1 -39
- package/dist/runtime/harness/system/boundary-analysis.js +1 -234
- package/dist/runtime/harness/system/health-monitor.js +1 -258
- package/dist/runtime/harness/system/inventory.js +1 -129
- package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
- package/dist/runtime/harness/system/policy-engine.js +1 -175
- package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
- package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
- package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
- package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
- package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
- package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
- package/dist/runtime/harness/system/session-memory-sync.js +3 -113
- package/dist/runtime/harness/system/skill-requirements.js +1 -112
- package/dist/runtime/harness/system/store.js +9 -365
- package/dist/runtime/harness/tool-gateway/index.js +1 -2
- package/dist/runtime/harness/tool-gateway/policy.js +1 -45
- package/dist/runtime/harness/tool-gateway/validation.js +1 -176
- package/dist/runtime/harness/tool-schema.js +1 -3
- package/dist/runtime/harness.js +3 -1490
- package/dist/runtime/index.js +1 -3
- package/dist/runtime/layout/runtime-layout.js +1 -31
- package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
- package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
- package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
- package/dist/runtime/parsing/output-content.js +10 -550
- package/dist/runtime/parsing/output-parsing.js +1 -4
- package/dist/runtime/parsing/output-recovery.js +3 -213
- package/dist/runtime/parsing/output-tool-args.js +7 -663
- package/dist/runtime/parsing/stream-event-parsing.js +3 -362
- package/dist/runtime/prompts/runtime-prompts.js +4 -73
- package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
- package/dist/runtime/skills/skill-metadata.js +1 -197
- package/dist/runtime/startup-tracing.js +2 -37
- package/dist/runtime/support/compiled-binding.js +1 -290
- package/dist/runtime/support/embedding-models.js +1 -118
- package/dist/runtime/support/harness-support.js +5 -137
- package/dist/runtime/support/llamaindex.js +1 -108
- package/dist/runtime/support/runtime-adapter-options.js +1 -29
- package/dist/runtime/support/runtime-factories.js +1 -51
- package/dist/runtime/support/vector-stores.js +9 -270
- package/dist/scaffold/init-project.js +54 -233
- package/dist/tooling/extensions.js +1 -311
- package/dist/tooling/module-loader.js +1 -55
- package/dist/tools.js +1 -176
- package/dist/utils/agent-display.js +1 -18
- package/dist/utils/bundled-text.js +4 -39
- package/dist/utils/compiled-binding.js +1 -33
- package/dist/utils/fs.js +2 -45
- package/dist/utils/id.js +1 -9
- package/dist/utils/message-content.js +1 -30
- package/dist/utils/object.js +1 -6
- package/dist/workspace/agent-binding-compiler.js +3 -613
- package/dist/workspace/compile.js +1 -472
- package/dist/workspace/framework-contract-validation.js +2 -322
- package/dist/workspace/index.js +1 -1
- package/dist/workspace/object-loader-paths.js +1 -71
- package/dist/workspace/object-loader-readers.js +1 -187
- package/dist/workspace/object-loader.js +1 -754
- package/dist/workspace/resource-compilers.js +1 -374
- package/dist/workspace/support/agent-capabilities.js +1 -37
- package/dist/workspace/support/agent-execution-config.js +1 -44
- package/dist/workspace/support/discovery.js +1 -147
- package/dist/workspace/support/source-collectors.js +1 -30
- package/dist/workspace/support/source-protocols.js +2 -192
- package/dist/workspace/support/workspace-ref-utils.js +1 -362
- package/dist/workspace/tool-hydration.js +1 -280
- package/dist/workspace/validate.js +1 -99
- package/dist/workspace/yaml-object-reader.js +1 -285
- package/package.json +7 -3
package/dist/contracts/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const o="auto";export{o as AUTO_AGENT_ID};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,27 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Stable contract anchors for source-layout tests:
|
|
3
|
-
export type SessionSummary = {
|
|
4
|
-
export type SessionListSummary = SessionSummary & {
|
|
5
|
-
export type SessionRecord = {
|
|
6
|
-
export type SessionRequestRecord = {
|
|
7
|
-
export type RequestSummary = SessionRequestRecord;
|
|
8
|
-
export type RequestResult = {
|
|
9
|
-
export type RequestListeners = RuntimeListeners & {
|
|
10
|
-
eventListener?: (snapshot: RequestEventSnapshot) => void | Promise<void>;
|
|
11
|
-
dataListener?: (event: RequestDataEvent) => void | Promise<void>;
|
|
12
|
-
export type RequestOptions = RequestStartOptions | RequestDecisionOptions;
|
|
13
|
-
export type RuntimeHistoryItem =
|
|
14
|
-
export type RequestRecord = RequestSummary & {
|
|
15
|
-
traceItems?: unknown[];
|
|
16
|
-
runtimeTimeline?: RuntimeTimelineItem[];
|
|
17
|
-
requests: RequestRecord[];
|
|
18
|
-
export type RuntimeRequestPackageInput = {
|
|
19
|
-
export type RuntimeRequestPackage = {
|
|
20
|
-
requestsPackages: RuntimeRequestPackage[];
|
|
21
|
-
export type UpstreamRuntimeEvent = unknown;
|
|
22
|
-
*/
|
|
23
|
-
export * from "./runtime-observability.js";
|
|
24
|
-
export * from "./runtime-memory.js";
|
|
25
|
-
export * from "./runtime-requests.js";
|
|
26
|
-
export * from "./runtime-scheduling.js";
|
|
27
|
-
export * from "./runtime-evaluation.js";
|
|
1
|
+
export*from"./runtime-observability.js";export*from"./runtime-memory.js";export*from"./runtime-requests.js";export*from"./runtime-scheduling.js";export*from"./runtime-evaluation.js";
|
package/dist/contracts/types.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,50 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { buildRuntimeSurface, buildAttempts, convertUpstreamEventsWithAgents, resolveContext, } from "./flow-graph-upstream.js";
|
|
3
|
-
import { deriveAgentName, deriveInitialAgentId, normalizeRuntimeEvents, readRequestId, readSessionId, } from "./flow-graph-normalization.js";
|
|
4
|
-
import { buildRuntimeNodes } from "./flow-graph-runtime.js";
|
|
5
|
-
export function buildFlowGraph(input) {
|
|
6
|
-
const runtimeData = input.runtimeTimeline
|
|
7
|
-
?? (input.runtimeEvents ? projectRuntimeTimeline(normalizeRuntimeEvents(input.runtimeEvents), {
|
|
8
|
-
...(readSessionId(input) ? { sessionId: readSessionId(input) } : {}),
|
|
9
|
-
...(readRequestId(input) ? { requestId: readRequestId(input) } : {}),
|
|
10
|
-
}) : []);
|
|
11
|
-
const initialAgentId = deriveInitialAgentId(input, runtimeData);
|
|
12
|
-
const upstreamContext = input.upstreamEvents
|
|
13
|
-
? convertUpstreamEventsWithAgents(input.upstreamEvents, initialAgentId)
|
|
14
|
-
: { projections: [], delegationNodes: [] };
|
|
15
|
-
const upstreamProjections = input.upstreamProjections ?? upstreamContext.projections.map((record) => record.projection);
|
|
16
|
-
const { sessionId, requestId } = resolveContext(input, runtimeData, upstreamProjections);
|
|
17
|
-
const { nodes: runtimeNodes, edges: runtimeEdges, groups: runtimeGroups } = buildRuntimeNodes(runtimeData);
|
|
18
|
-
for (const node of runtimeNodes) {
|
|
19
|
-
node.agentId = typeof node.detail.agentId === "string" ? node.detail.agentId : initialAgentId;
|
|
20
|
-
node.agentName = deriveAgentName(node.agentId);
|
|
21
|
-
}
|
|
22
|
-
const projectionRecords = input.upstreamProjections
|
|
23
|
-
? input.upstreamProjections.map((projection, index) => ({
|
|
24
|
-
projection,
|
|
25
|
-
agentId: initialAgentId,
|
|
26
|
-
agentName: deriveAgentName(initialAgentId),
|
|
27
|
-
sourceEventId: "key" in projection ? projection.key : `projection:${index + 1}`,
|
|
28
|
-
}))
|
|
29
|
-
: upstreamContext.projections;
|
|
30
|
-
const { nodes: attemptNodes, edges: attemptEdges, groups: attemptGroups } = buildAttempts(projectionRecords, upstreamContext.delegationNodes, runtimeGroups, sessionId, requestId);
|
|
31
|
-
const runtimeSurface = buildRuntimeSurface([...upstreamContext.delegationNodes, ...attemptNodes]);
|
|
32
|
-
return {
|
|
33
|
-
graphId: `${sessionId}/${requestId}`,
|
|
34
|
-
scope: input.scope === "session" || input.scope === "request" ? input.scope : "request",
|
|
35
|
-
sessionId,
|
|
36
|
-
requestId,
|
|
37
|
-
nodes: [...runtimeNodes, ...attemptNodes],
|
|
38
|
-
edges: [...runtimeEdges, ...attemptEdges],
|
|
39
|
-
groups: [...runtimeGroups, ...attemptGroups],
|
|
40
|
-
metadata: {
|
|
41
|
-
initialAgentId,
|
|
42
|
-
initialAgentName: deriveAgentName(initialAgentId),
|
|
43
|
-
runtimeTimelineCount: runtimeData.length,
|
|
44
|
-
upstreamProjectionCount: upstreamProjections.length,
|
|
45
|
-
delegationCount: upstreamContext.delegationNodes.length,
|
|
46
|
-
runtimeSurface,
|
|
47
|
-
...(input.metadata ?? {}),
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
1
|
+
import{projectRuntimeTimeline as E}from"../runtime/harness/events/timeline.js";import{buildRuntimeSurface as h,buildAttempts as A,convertUpstreamEventsWithAgents as R,resolveContext as q}from"./flow-graph-upstream.js";import{deriveAgentName as d,deriveInitialAgentId as C,normalizeRuntimeEvents as P,readRequestId as u,readSessionId as l}from"./flow-graph-normalization.js";import{buildRuntimeNodes as b}from"./flow-graph-runtime.js";function T(e){const n=e.runtimeTimeline??(e.runtimeEvents?E(P(e.runtimeEvents),{...l(e)?{sessionId:l(e)}:{},...u(e)?{requestId:u(e)}:{}}):[]),o=C(e,n),s=e.upstreamEvents?R(e.upstreamEvents,o):{projections:[],delegationNodes:[]},m=e.upstreamProjections??s.projections.map(t=>t.projection),{sessionId:r,requestId:a}=q(e,n,m),{nodes:i,edges:p,groups:c}=b(n);for(const t of i)t.agentId=typeof t.detail.agentId=="string"?t.detail.agentId:o,t.agentName=d(t.agentId);const I=e.upstreamProjections?e.upstreamProjections.map((t,j)=>({projection:t,agentId:o,agentName:d(o),sourceEventId:"key"in t?t.key:`projection:${j+1}`})):s.projections,{nodes:g,edges:v,groups:N}=A(I,s.delegationNodes,c,r,a),f=h([...s.delegationNodes,...g]);return{graphId:`${r}/${a}`,scope:e.scope==="session"||e.scope==="request"?e.scope:"request",sessionId:r,requestId:a,nodes:[...i,...g],edges:[...p,...v],groups:[...c,...N],metadata:{initialAgentId:o,initialAgentName:d(o),runtimeTimelineCount:n.length,upstreamProjectionCount:m.length,delegationCount:s.delegationNodes.length,runtimeSurface:f,...e.metadata??{}}}}export{T as buildFlowGraph};
|
|
@@ -1,464 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
const STRUCTURAL_EDGE_KINDS = new Set(["sequence", "contains"]);
|
|
4
|
-
const PRODUCT_VIEW_EDGE_KINDS = new Set(["sequence", "approval", "resume", "result"]);
|
|
5
|
-
const GENERIC_PRODUCT_TOOL_FAMILIES = new Set([
|
|
6
|
-
"ls",
|
|
7
|
-
"read-file",
|
|
8
|
-
"write-file",
|
|
9
|
-
"task",
|
|
10
|
-
"glob",
|
|
11
|
-
"grep",
|
|
12
|
-
"bash",
|
|
13
|
-
"sh",
|
|
14
|
-
"cat",
|
|
15
|
-
]);
|
|
16
|
-
function sanitizeMermaidId(value) {
|
|
17
|
-
return value.replace(/[^A-Za-z0-9_]/g, "_");
|
|
18
|
-
}
|
|
19
|
-
function escapeMermaidLabel(value) {
|
|
20
|
-
return value.replace(/"/g, '\\"');
|
|
21
|
-
}
|
|
22
|
-
function renderNode(node, mermaidId) {
|
|
23
|
-
const label = escapeMermaidLabel(`${node.label} [${node.status}]`);
|
|
24
|
-
switch (node.kind) {
|
|
25
|
-
case "approval":
|
|
26
|
-
return ` ${mermaidId}{"${label}"}`;
|
|
27
|
-
case "queue":
|
|
28
|
-
return ` ${mermaidId}[/"${label}"/]`;
|
|
29
|
-
case "recovery":
|
|
30
|
-
return ` ${mermaidId}{{"${label}"}}`;
|
|
31
|
-
case "artifact":
|
|
32
|
-
return ` ${mermaidId}[("${label}")]`;
|
|
33
|
-
case "skill":
|
|
34
|
-
return ` ${mermaidId}[["${label}"]]`;
|
|
35
|
-
case "memory":
|
|
36
|
-
return ` ${mermaidId}[("${label}")]`;
|
|
37
|
-
default:
|
|
38
|
-
return ` ${mermaidId}["${label}"]`;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
function renderAgentRoot(label, mermaidId) {
|
|
42
|
-
return ` ${mermaidId}["${escapeMermaidLabel(label)}"]`;
|
|
43
|
-
}
|
|
44
|
-
function renderStartNode(mermaidId) {
|
|
45
|
-
return ` ${mermaidId}(("Start"))`;
|
|
46
|
-
}
|
|
47
|
-
function renderEndNode(mermaidId) {
|
|
48
|
-
return ` ${mermaidId}(("End"))`;
|
|
49
|
-
}
|
|
50
|
-
function renderEdge(edge, fromId, toId) {
|
|
51
|
-
const connector = edge.kind === "retry" || edge.kind === "fallback" ? "-.->" : edge.kind === "resume" ? "==>" : "-->";
|
|
52
|
-
const label = edge.label ?? edge.condition ?? (edge.kind !== "sequence" && edge.kind !== "contains" ? edge.kind : "");
|
|
53
|
-
return label
|
|
54
|
-
? ` ${fromId} ${connector}|"${escapeMermaidLabel(label)}"| ${toId}`
|
|
55
|
-
: ` ${fromId} ${connector} ${toId}`;
|
|
56
|
-
}
|
|
57
|
-
function edgeKey(edge) {
|
|
58
|
-
return `${edge.from}::${edge.to}::${edge.kind}::${edge.label ?? ""}::${edge.condition ?? ""}`;
|
|
59
|
-
}
|
|
60
|
-
function collapseEdgePath(source, target, path) {
|
|
61
|
-
const representative = [...path].reverse().find((edge) => !STRUCTURAL_EDGE_KINDS.has(edge.kind) || edge.label || edge.condition);
|
|
62
|
-
const sourceEventIds = [...new Set(path.flatMap((edge) => edge.sourceEventIds))];
|
|
63
|
-
return {
|
|
64
|
-
id: `collapsed:${source}:${target}:${sourceEventIds.join(",")}`,
|
|
65
|
-
from: source,
|
|
66
|
-
to: target,
|
|
67
|
-
kind: representative?.kind ?? "sequence",
|
|
68
|
-
label: representative?.label,
|
|
69
|
-
condition: representative?.condition,
|
|
70
|
-
sourceEventIds,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
function nodeIdentity(node) {
|
|
74
|
-
if (node.kind === "agent") {
|
|
75
|
-
const fromAgentId = typeof node.detail.fromAgentId === "string" ? node.detail.fromAgentId : "agent";
|
|
76
|
-
const toAgentId = node.agentId ?? "agent";
|
|
77
|
-
return `${node.kind}:${fromAgentId}:${toAgentId}`;
|
|
78
|
-
}
|
|
79
|
-
return `${node.kind}:${node.agentId ?? "-"}:${node.label}`;
|
|
80
|
-
}
|
|
81
|
-
function findCrossAgentBridgeNodeIds(nodes, edges) {
|
|
82
|
-
const nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
83
|
-
const incidentAgentIdsByNodeId = new Map();
|
|
84
|
-
for (const edge of edges) {
|
|
85
|
-
const fromNode = nodeById.get(edge.from);
|
|
86
|
-
const toNode = nodeById.get(edge.to);
|
|
87
|
-
if (!fromNode || !toNode) {
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (toNode.agentId) {
|
|
91
|
-
let agentIds = incidentAgentIdsByNodeId.get(fromNode.id);
|
|
92
|
-
if (!agentIds) {
|
|
93
|
-
agentIds = new Set();
|
|
94
|
-
incidentAgentIdsByNodeId.set(fromNode.id, agentIds);
|
|
95
|
-
}
|
|
96
|
-
agentIds.add(toNode.agentId);
|
|
97
|
-
}
|
|
98
|
-
if (fromNode.agentId) {
|
|
99
|
-
let agentIds = incidentAgentIdsByNodeId.get(toNode.id);
|
|
100
|
-
if (!agentIds) {
|
|
101
|
-
agentIds = new Set();
|
|
102
|
-
incidentAgentIdsByNodeId.set(toNode.id, agentIds);
|
|
103
|
-
}
|
|
104
|
-
agentIds.add(fromNode.agentId);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const bridgeNodeIds = new Set();
|
|
108
|
-
for (const node of nodes) {
|
|
109
|
-
if (node.kind === "agent") {
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
const agentIds = incidentAgentIdsByNodeId.get(node.id) ?? new Set();
|
|
113
|
-
if (node.agentId) {
|
|
114
|
-
agentIds.add(node.agentId);
|
|
115
|
-
}
|
|
116
|
-
if (agentIds.size > 1) {
|
|
117
|
-
bridgeNodeIds.add(node.id);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return bridgeNodeIds;
|
|
121
|
-
}
|
|
122
|
-
function findDelegationCarrierToolNodeIds(nodes) {
|
|
123
|
-
const delegationSourceEventIds = new Set(nodes
|
|
124
|
-
.filter((node) => node.kind === "agent")
|
|
125
|
-
.flatMap((node) => node.sourceEventIds));
|
|
126
|
-
return new Set(nodes
|
|
127
|
-
.filter((node) => node.kind === "tool" && node.sourceEventIds.some((id) => delegationSourceEventIds.has(id)))
|
|
128
|
-
.map((node) => node.id));
|
|
129
|
-
}
|
|
130
|
-
function selectProductViewNodes(nodes) {
|
|
131
|
-
const selected = new Map();
|
|
132
|
-
for (const node of nodes) {
|
|
133
|
-
const key = nodeIdentity(node);
|
|
134
|
-
const existing = selected.get(key);
|
|
135
|
-
if (!existing) {
|
|
136
|
-
selected.set(key, node);
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
const existingCompleted = existing.status === "completed";
|
|
140
|
-
const nodeCompleted = node.status === "completed";
|
|
141
|
-
const preferCompleted = !existingCompleted && nodeCompleted;
|
|
142
|
-
const preserveCompleted = existingCompleted && !nodeCompleted;
|
|
143
|
-
const preferLatest = !preserveCompleted && (existing.sequenceEnd ?? 0) <= (node.sequenceEnd ?? 0);
|
|
144
|
-
if (preferCompleted || preferLatest) {
|
|
145
|
-
selected.set(key, node);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return [...selected.values()].sort((left, right) => (left.sequenceStart ?? 0) - (right.sequenceStart ?? 0));
|
|
149
|
-
}
|
|
150
|
-
function trimToolNodesForProductView(nodes, delegatingAgentIds) {
|
|
151
|
-
const keptToolKeys = new Set();
|
|
152
|
-
const orderedToolKeysByAgentId = new Map();
|
|
153
|
-
const toolKeyByNodeId = new Map();
|
|
154
|
-
const genericToolKeysByAgentId = new Map();
|
|
155
|
-
for (const node of nodes) {
|
|
156
|
-
if (node.kind !== "tool") {
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const agentId = node.agentId ?? "";
|
|
160
|
-
const toolName = (() => {
|
|
161
|
-
if (typeof node.detail.toolName === "string" && node.detail.toolName.trim().length > 0) {
|
|
162
|
-
return node.detail.toolName.trim();
|
|
163
|
-
}
|
|
164
|
-
const labelMatch = /^(?:Calling|Completed) tool (.+?)(?: \[[^\]]+\])?$/i.exec(node.label);
|
|
165
|
-
return labelMatch?.[1]?.trim() || node.label;
|
|
166
|
-
})();
|
|
167
|
-
const normalizedToolName = toolName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
168
|
-
const toolKey = `${agentId}:${normalizedToolName}`;
|
|
169
|
-
toolKeyByNodeId.set(node.id, toolKey);
|
|
170
|
-
if (GENERIC_PRODUCT_TOOL_FAMILIES.has(normalizedToolName)) {
|
|
171
|
-
let genericToolKeys = genericToolKeysByAgentId.get(agentId);
|
|
172
|
-
if (!genericToolKeys) {
|
|
173
|
-
genericToolKeys = new Set();
|
|
174
|
-
genericToolKeysByAgentId.set(agentId, genericToolKeys);
|
|
175
|
-
}
|
|
176
|
-
genericToolKeys.add(toolKey);
|
|
177
|
-
}
|
|
178
|
-
const toolKeys = orderedToolKeysByAgentId.get(agentId);
|
|
179
|
-
if (toolKeys) {
|
|
180
|
-
if (!toolKeys.includes(toolKey)) {
|
|
181
|
-
toolKeys.push(toolKey);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
orderedToolKeysByAgentId.set(agentId, [toolKey]);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
for (const [agentId, toolKeys] of orderedToolKeysByAgentId.entries()) {
|
|
189
|
-
const genericToolKeys = genericToolKeysByAgentId.get(agentId) ?? new Set();
|
|
190
|
-
const preferredToolKeys = toolKeys.filter((toolKey) => !genericToolKeys.has(toolKey));
|
|
191
|
-
const selectedToolKeys = preferredToolKeys.length > 0
|
|
192
|
-
? preferredToolKeys.slice(-2)
|
|
193
|
-
: delegatingAgentIds.has(agentId)
|
|
194
|
-
? []
|
|
195
|
-
: toolKeys.slice(-2);
|
|
196
|
-
selectedToolKeys.forEach((toolKey) => keptToolKeys.add(toolKey));
|
|
197
|
-
}
|
|
198
|
-
return nodes.filter((node) => node.kind !== "tool" || keptToolKeys.has(toolKeyByNodeId.get(node.id) ?? ""));
|
|
199
|
-
}
|
|
200
|
-
function collectVisibleEdges(graph, visibleNodes, includedEdgeKinds) {
|
|
201
|
-
const visibleNodeIds = new Set(visibleNodes.map((node) => node.id));
|
|
202
|
-
const candidateEdges = graph.edges.filter((edge) => includedEdgeKinds ? includedEdgeKinds.has(edge.kind) : true);
|
|
203
|
-
const outgoingByNodeId = new Map();
|
|
204
|
-
for (const edge of candidateEdges) {
|
|
205
|
-
const outgoing = outgoingByNodeId.get(edge.from);
|
|
206
|
-
if (outgoing) {
|
|
207
|
-
outgoing.push(edge);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
outgoingByNodeId.set(edge.from, [edge]);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
const visibleEdges = candidateEdges.filter((edge) => visibleNodeIds.has(edge.from) && visibleNodeIds.has(edge.to));
|
|
214
|
-
const seenEdgeKeys = new Set(visibleEdges.map((edge) => edgeKey(edge)));
|
|
215
|
-
for (const node of visibleNodes) {
|
|
216
|
-
const queue = (outgoingByNodeId.get(node.id) ?? [])
|
|
217
|
-
.filter((edge) => !visibleNodeIds.has(edge.to))
|
|
218
|
-
.map((edge) => ({ nodeId: edge.to, path: [edge] }));
|
|
219
|
-
const visitedHiddenNodes = new Set();
|
|
220
|
-
while (queue.length > 0) {
|
|
221
|
-
const current = queue.shift();
|
|
222
|
-
if (visitedHiddenNodes.has(current.nodeId)) {
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
visitedHiddenNodes.add(current.nodeId);
|
|
226
|
-
for (const edge of outgoingByNodeId.get(current.nodeId) ?? []) {
|
|
227
|
-
const nextPath = [...current.path, edge];
|
|
228
|
-
if (visibleNodeIds.has(edge.to)) {
|
|
229
|
-
if (edge.to === node.id) {
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
const collapsed = collapseEdgePath(node.id, edge.to, nextPath);
|
|
233
|
-
const key = edgeKey(collapsed);
|
|
234
|
-
if (!seenEdgeKeys.has(key)) {
|
|
235
|
-
seenEdgeKeys.add(key);
|
|
236
|
-
visibleEdges.push(collapsed);
|
|
237
|
-
}
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
queue.push({ nodeId: edge.to, path: nextPath });
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return visibleEdges;
|
|
245
|
-
}
|
|
246
|
-
function getRuntimeSurface(graph) {
|
|
247
|
-
const runtimeSurface = graph.metadata.runtimeSurface;
|
|
248
|
-
return Array.isArray(runtimeSurface) ? runtimeSurface : [];
|
|
249
|
-
}
|
|
250
|
-
export function exportFlowGraphToMermaid(graph, options = {}) {
|
|
251
|
-
const direction = options.direction ?? "TD";
|
|
252
|
-
const view = options.view ?? "product";
|
|
253
|
-
const productView = view === "product";
|
|
254
|
-
const includedKinds = options.includeKinds
|
|
255
|
-
? new Set(options.includeKinds)
|
|
256
|
-
: view === "debug"
|
|
257
|
-
? null
|
|
258
|
-
: PRODUCT_VIEW_KINDS;
|
|
259
|
-
const includedEdgeKinds = options.includeEdgeKinds
|
|
260
|
-
? new Set(options.includeEdgeKinds)
|
|
261
|
-
: view === "debug"
|
|
262
|
-
? null
|
|
263
|
-
: new Set(PRODUCT_VIEW_EDGE_KINDS);
|
|
264
|
-
const includeGroups = options.includeGroups ?? true;
|
|
265
|
-
const includeDetails = options.includeDetails ?? false;
|
|
266
|
-
const allFilteredNodes = graph.nodes.filter((node) => {
|
|
267
|
-
if (!includeDetails && node.layer === "detail") {
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
return includedKinds ? includedKinds.has(node.kind) : true;
|
|
271
|
-
});
|
|
272
|
-
const hiddenDelegationNodes = productView
|
|
273
|
-
? allFilteredNodes.filter((node) => node.kind === "agent")
|
|
274
|
-
: [];
|
|
275
|
-
const delegationCarrierToolNodeIds = productView
|
|
276
|
-
? findDelegationCarrierToolNodeIds(allFilteredNodes)
|
|
277
|
-
: new Set();
|
|
278
|
-
const delegatingAgentIds = productView
|
|
279
|
-
? new Set(allFilteredNodes
|
|
280
|
-
.filter((node) => node.kind === "agent" && typeof node.detail.fromAgentId === "string")
|
|
281
|
-
.map((node) => node.detail.fromAgentId))
|
|
282
|
-
: new Set();
|
|
283
|
-
const filteredNodes = productView
|
|
284
|
-
? allFilteredNodes.filter((node) => node.kind !== "agent" && !delegationCarrierToolNodeIds.has(node.id))
|
|
285
|
-
: allFilteredNodes;
|
|
286
|
-
const initiallySelectedNodes = productView
|
|
287
|
-
? trimToolNodesForProductView(selectProductViewNodes(filteredNodes), delegatingAgentIds)
|
|
288
|
-
: filteredNodes;
|
|
289
|
-
let nodes = initiallySelectedNodes;
|
|
290
|
-
let edges = collectVisibleEdges(graph, nodes, includedEdgeKinds);
|
|
291
|
-
if (productView) {
|
|
292
|
-
const crossAgentBridgeNodeIds = findCrossAgentBridgeNodeIds(nodes, edges);
|
|
293
|
-
if (crossAgentBridgeNodeIds.size > 0) {
|
|
294
|
-
nodes = nodes.filter((node) => !crossAgentBridgeNodeIds.has(node.id));
|
|
295
|
-
edges = collectVisibleEdges(graph, nodes, includedEdgeKinds);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
const nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
299
|
-
const nodeIdSet = new Set(nodes.map((node) => node.id));
|
|
300
|
-
if (productView) {
|
|
301
|
-
edges = edges.filter((edge) => {
|
|
302
|
-
const fromNode = nodeById.get(edge.from);
|
|
303
|
-
const toNode = nodeById.get(edge.to);
|
|
304
|
-
if (!fromNode || !toNode) {
|
|
305
|
-
return true;
|
|
306
|
-
}
|
|
307
|
-
return !fromNode.agentId || !toNode.agentId || fromNode.agentId === toNode.agentId;
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
const lines = [`flowchart ${direction}`];
|
|
311
|
-
const mermaidIdByNodeId = new Map();
|
|
312
|
-
const initialAgentId = typeof graph.metadata.initialAgentId === "string" ? graph.metadata.initialAgentId : null;
|
|
313
|
-
const startNodeId = productView && initialAgentId ? "graph_start" : null;
|
|
314
|
-
const endNodeId = productView ? "graph_end" : null;
|
|
315
|
-
const agentRootIdByAgentId = new Map();
|
|
316
|
-
for (const node of nodes) {
|
|
317
|
-
mermaidIdByNodeId.set(node.id, sanitizeMermaidId(node.id));
|
|
318
|
-
}
|
|
319
|
-
if (productView) {
|
|
320
|
-
const seenAgentIds = new Set();
|
|
321
|
-
for (const node of allFilteredNodes) {
|
|
322
|
-
const agentId = node.agentId;
|
|
323
|
-
if (!agentId || seenAgentIds.has(agentId)) {
|
|
324
|
-
// noop
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
seenAgentIds.add(agentId);
|
|
328
|
-
agentRootIdByAgentId.set(agentId, sanitizeMermaidId(`agent_root:${agentId}`));
|
|
329
|
-
}
|
|
330
|
-
if (node.kind !== "agent") {
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
333
|
-
const fromAgentId = typeof node.detail.fromAgentId === "string" ? node.detail.fromAgentId : null;
|
|
334
|
-
if (!fromAgentId || seenAgentIds.has(fromAgentId)) {
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
seenAgentIds.add(fromAgentId);
|
|
338
|
-
agentRootIdByAgentId.set(fromAgentId, sanitizeMermaidId(`agent_root:${fromAgentId}`));
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
for (const [agentId, mermaidId] of agentRootIdByAgentId) {
|
|
342
|
-
const representative = nodes.find((node) => node.agentId === agentId
|
|
343
|
-
|| (node.kind === "agent" && typeof node.detail.fromAgentId === "string" && node.detail.fromAgentId === agentId));
|
|
344
|
-
const representativeName = representative?.agentId === agentId
|
|
345
|
-
? representative.agentName
|
|
346
|
-
: (typeof representative?.detail.fromAgentName === "string" ? representative.detail.fromAgentName : undefined);
|
|
347
|
-
lines.push(renderAgentRoot(representativeName ?? formatAgentName(agentId), mermaidId));
|
|
348
|
-
}
|
|
349
|
-
if (startNodeId) {
|
|
350
|
-
lines.push(renderStartNode(startNodeId));
|
|
351
|
-
}
|
|
352
|
-
if (endNodeId) {
|
|
353
|
-
lines.push(renderEndNode(endNodeId));
|
|
354
|
-
}
|
|
355
|
-
if (includeGroups) {
|
|
356
|
-
const groupedNodeIds = new Set();
|
|
357
|
-
for (const group of graph.groups) {
|
|
358
|
-
const groupNodes = group.nodeIds.filter((nodeId) => nodeIdSet.has(nodeId));
|
|
359
|
-
if (groupNodes.length === 0) {
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
lines.push(` subgraph ${sanitizeMermaidId(group.id)}["${escapeMermaidLabel(group.label)}"]`);
|
|
363
|
-
for (const nodeId of groupNodes) {
|
|
364
|
-
groupedNodeIds.add(nodeId);
|
|
365
|
-
const node = nodes.find((candidate) => candidate.id === nodeId);
|
|
366
|
-
if (!node) {
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
lines.push(renderNode(node, mermaidIdByNodeId.get(node.id)));
|
|
370
|
-
}
|
|
371
|
-
lines.push(" end");
|
|
372
|
-
}
|
|
373
|
-
for (const node of nodes) {
|
|
374
|
-
if (!groupedNodeIds.has(node.id)) {
|
|
375
|
-
lines.push(renderNode(node, mermaidIdByNodeId.get(node.id)));
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
for (const node of nodes) {
|
|
381
|
-
lines.push(renderNode(node, mermaidIdByNodeId.get(node.id)));
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
for (const edge of edges) {
|
|
385
|
-
lines.push(renderEdge(edge, mermaidIdByNodeId.get(edge.from), mermaidIdByNodeId.get(edge.to)));
|
|
386
|
-
}
|
|
387
|
-
if (productView) {
|
|
388
|
-
const handoffPairs = new Set();
|
|
389
|
-
for (const item of getRuntimeSurface(graph)) {
|
|
390
|
-
if (item.kind !== "agent") {
|
|
391
|
-
continue;
|
|
392
|
-
}
|
|
393
|
-
const fromAgentId = item.ownerAgentId ?? null;
|
|
394
|
-
const toAgentId = item.agentId ?? null;
|
|
395
|
-
if (!fromAgentId || !toAgentId) {
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
const fromRoot = agentRootIdByAgentId.get(fromAgentId);
|
|
399
|
-
const toRoot = agentRootIdByAgentId.get(toAgentId);
|
|
400
|
-
if (!fromRoot || !toRoot || fromRoot === toRoot) {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
const pairKey = `${fromAgentId}:${toAgentId}`;
|
|
404
|
-
if (handoffPairs.has(pairKey)) {
|
|
405
|
-
// noop
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
handoffPairs.add(pairKey);
|
|
409
|
-
lines.push(renderEdge({
|
|
410
|
-
id: `synthetic:handoff:${pairKey}`,
|
|
411
|
-
from: `agent_root:${fromAgentId}`,
|
|
412
|
-
to: `agent_root:${toAgentId}`,
|
|
413
|
-
kind: "spawn",
|
|
414
|
-
label: "handoff",
|
|
415
|
-
sourceEventIds: item.sourceEventId ? [item.sourceEventId] : [],
|
|
416
|
-
}, fromRoot, toRoot));
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
if (startNodeId && initialAgentId) {
|
|
421
|
-
const initialRootId = agentRootIdByAgentId.get(initialAgentId);
|
|
422
|
-
if (initialRootId) {
|
|
423
|
-
lines.push(` ${startNodeId} --> ${initialRootId}`);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
for (const [agentId, rootMermaidId] of agentRootIdByAgentId) {
|
|
427
|
-
const firstAgentStep = nodes.find((node) => node.agentId === agentId && node.kind !== "agent");
|
|
428
|
-
if (!firstAgentStep) {
|
|
429
|
-
continue;
|
|
430
|
-
}
|
|
431
|
-
const incomingDelegation = !productView
|
|
432
|
-
? hiddenDelegationNodes.find((node) => node.agentId === agentId)
|
|
433
|
-
: null;
|
|
434
|
-
if (incomingDelegation) {
|
|
435
|
-
lines.push(renderEdge({
|
|
436
|
-
id: `synthetic:${incomingDelegation.id}->agent-root:${agentId}`,
|
|
437
|
-
from: incomingDelegation.id,
|
|
438
|
-
to: `agent_root:${agentId}`,
|
|
439
|
-
kind: "spawn",
|
|
440
|
-
label: "spawn",
|
|
441
|
-
sourceEventIds: [],
|
|
442
|
-
}, mermaidIdByNodeId.get(incomingDelegation.id), rootMermaidId));
|
|
443
|
-
}
|
|
444
|
-
lines.push(renderEdge({
|
|
445
|
-
id: `synthetic:agent-root:${agentId}->${firstAgentStep.id}`,
|
|
446
|
-
from: `agent_root:${agentId}`,
|
|
447
|
-
to: firstAgentStep.id,
|
|
448
|
-
kind: "sequence",
|
|
449
|
-
sourceEventIds: [],
|
|
450
|
-
}, rootMermaidId, mermaidIdByNodeId.get(firstAgentStep.id)));
|
|
451
|
-
}
|
|
452
|
-
if (endNodeId) {
|
|
453
|
-
const finalVisibleStep = [...nodes]
|
|
454
|
-
.filter((node) => node.kind !== "agent")
|
|
455
|
-
.sort((left, right) => (right.sequenceEnd ?? right.sequenceStart ?? 0) - (left.sequenceEnd ?? left.sequenceStart ?? 0))[0];
|
|
456
|
-
const finalAnchorId = finalVisibleStep
|
|
457
|
-
? mermaidIdByNodeId.get(finalVisibleStep.id)
|
|
458
|
-
: (initialAgentId ? agentRootIdByAgentId.get(initialAgentId) : undefined);
|
|
459
|
-
if (finalAnchorId) {
|
|
460
|
-
lines.push(` ${finalAnchorId} --> ${endNodeId}`);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
return lines.join("\n");
|
|
464
|
-
}
|
|
1
|
+
import{formatAgentName as V}from"../utils/agent-display.js";const x=new Set(["agent","tool","skill","memory"]),z=new Set(["sequence","contains"]),G=new Set(["sequence","approval","resume","result"]),L=new Set(["ls","read-file","write-file","task","glob","grep","bash","sh","cat"]);function K(e){return e.replace(/[^A-Za-z0-9_]/g,"_")}function T(e){return e.replace(/"/g,'\\"')}function q(e,n){const o=T(`${e.label} [${e.status}]`);switch(e.kind){case"approval":return` ${n}{"${o}"}`;case"queue":return` ${n}[/"${o}"/]`;case"recovery":return` ${n}{{"${o}"}}`;case"artifact":return` ${n}[("${o}")]`;case"skill":return` ${n}[["${o}"]]`;case"memory":return` ${n}[("${o}")]`;default:return` ${n}["${o}"]`}}function O(e,n){return` ${n}["${T(e)}"]`}function U(e){return` ${e}(("Start"))`}function F(e){return` ${e}(("End"))`}function _(e,n,o){const i=e.kind==="retry"||e.kind==="fallback"?"-.->":e.kind==="resume"?"==>":"-->",l=e.label??e.condition??(e.kind!=="sequence"&&e.kind!=="contains"?e.kind:"");return l?` ${n} ${i}|"${T(l)}"| ${o}`:` ${n} ${i} ${o}`}function R(e){return`${e.from}::${e.to}::${e.kind}::${e.label??""}::${e.condition??""}`}function j(e,n,o){const i=[...o].reverse().find(r=>!z.has(r.kind)||r.label||r.condition),l=[...new Set(o.flatMap(r=>r.sourceEventIds))];return{id:`collapsed:${e}:${n}:${l.join(",")}`,from:e,to:n,kind:i?.kind??"sequence",label:i?.label,condition:i?.condition,sourceEventIds:l}}function W(e){if(e.kind==="agent"){const n=typeof e.detail.fromAgentId=="string"?e.detail.fromAgentId:"agent",o=e.agentId??"agent";return`${e.kind}:${n}:${o}`}return`${e.kind}:${e.agentId??"-"}:${e.label}`}function H(e,n){const o=new Map(e.map(r=>[r.id,r])),i=new Map;for(const r of n){const s=o.get(r.from),u=o.get(r.to);if(!(!s||!u)){if(u.agentId){let d=i.get(s.id);d||(d=new Set,i.set(s.id,d)),d.add(u.agentId)}if(s.agentId){let d=i.get(u.id);d||(d=new Set,i.set(u.id,d)),d.add(s.agentId)}}}const l=new Set;for(const r of e){if(r.kind==="agent")continue;const s=i.get(r.id)??new Set;r.agentId&&s.add(r.agentId),s.size>1&&l.add(r.id)}return l}function Z(e){const n=new Set(e.filter(o=>o.kind==="agent").flatMap(o=>o.sourceEventIds));return new Set(e.filter(o=>o.kind==="tool"&&o.sourceEventIds.some(i=>n.has(i))).map(o=>o.id))}function J(e){const n=new Map;for(const o of e){const i=W(o),l=n.get(i);if(!l){n.set(i,o);continue}const r=l.status==="completed",s=o.status==="completed",u=!r&&s,g=!(r&&!s)&&(l.sequenceEnd??0)<=(o.sequenceEnd??0);(u||g)&&n.set(i,o)}return[...n.values()].sort((o,i)=>(o.sequenceStart??0)-(i.sequenceStart??0))}function Q(e,n){const o=new Set,i=new Map,l=new Map,r=new Map;for(const s of e){if(s.kind!=="tool")continue;const u=s.agentId??"",g=(typeof s.detail.toolName=="string"&&s.detail.toolName.trim().length>0?s.detail.toolName.trim():/^(?:Calling|Completed) tool (.+?)(?: \[[^\]]+\])?$/i.exec(s.label)?.[1]?.trim()||s.label).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),w=`${u}:${g}`;if(l.set(s.id,w),L.has(g)){let h=r.get(u);h||(h=new Set,r.set(u,h)),h.add(w)}const I=i.get(u);I?I.includes(w)||I.push(w):i.set(u,[w])}for(const[s,u]of i.entries()){const d=r.get(s)??new Set,g=u.filter(I=>!d.has(I));(g.length>0?g.slice(-2):n.has(s)?[]:u.slice(-2)).forEach(I=>o.add(I))}return e.filter(s=>s.kind!=="tool"||o.has(l.get(s.id)??""))}function B(e,n,o){const i=new Set(n.map(d=>d.id)),l=e.edges.filter(d=>o?o.has(d.kind):!0),r=new Map;for(const d of l){const g=r.get(d.from);g?g.push(d):r.set(d.from,[d])}const s=l.filter(d=>i.has(d.from)&&i.has(d.to)),u=new Set(s.map(d=>R(d)));for(const d of n){const g=(r.get(d.id)??[]).filter(I=>!i.has(I.to)).map(I=>({nodeId:I.to,path:[I]})),w=new Set;for(;g.length>0;){const I=g.shift();if(!w.has(I.nodeId)){w.add(I.nodeId);for(const h of r.get(I.nodeId)??[]){const N=[...I.path,h];if(i.has(h.to)){if(h.to===d.id)continue;const M=j(d.id,h.to,N),p=R(M);u.has(p)||(u.add(p),s.push(M));continue}g.push({nodeId:h.to,path:N})}}}}return s}function X(e){const n=e.metadata.runtimeSurface;return Array.isArray(n)?n:[]}function ee(e,n={}){const o=n.direction??"TD",i=n.view??"product",l=i==="product",r=n.includeKinds?new Set(n.includeKinds):i==="debug"?null:x,s=n.includeEdgeKinds?new Set(n.includeEdgeKinds):i==="debug"?null:new Set(G),u=n.includeGroups??!0,d=n.includeDetails??!1,g=e.nodes.filter(t=>!d&&t.layer==="detail"?!1:r?r.has(t.kind):!0),w=l?g.filter(t=>t.kind==="agent"):[],I=l?Z(g):new Set,h=l?new Set(g.filter(t=>t.kind==="agent"&&typeof t.detail.fromAgentId=="string").map(t=>t.detail.fromAgentId)):new Set,N=l?g.filter(t=>t.kind!=="agent"&&!I.has(t.id)):g;let p=l?Q(J(N),h):N,k=B(e,p,s);if(l){const t=H(p,k);t.size>0&&(p=p.filter(a=>!t.has(a.id)),k=B(e,p,s))}const D=new Map(p.map(t=>[t.id,t])),P=new Set(p.map(t=>t.id));l&&(k=k.filter(t=>{const a=D.get(t.from),c=D.get(t.to);return!a||!c?!0:!a.agentId||!c.agentId||a.agentId===c.agentId}));const $=[`flowchart ${o}`],S=new Map,A=typeof e.metadata.initialAgentId=="string"?e.metadata.initialAgentId:null,b=l&&A?"graph_start":null,v=l?"graph_end":null,y=new Map;for(const t of p)S.set(t.id,K(t.id));if(l){const t=new Set;for(const a of g){const c=a.agentId;if(!c||t.has(c)||(t.add(c),y.set(c,K(`agent_root:${c}`))),a.kind!=="agent")continue;const f=typeof a.detail.fromAgentId=="string"?a.detail.fromAgentId:null;!f||t.has(f)||(t.add(f),y.set(f,K(`agent_root:${f}`)))}}for(const[t,a]of y){const c=p.find(m=>m.agentId===t||m.kind==="agent"&&typeof m.detail.fromAgentId=="string"&&m.detail.fromAgentId===t),f=c?.agentId===t?c.agentName:typeof c?.detail.fromAgentName=="string"?c.detail.fromAgentName:void 0;$.push(O(f??V(t),a))}if(b&&$.push(U(b)),v&&$.push(F(v)),u){const t=new Set;for(const a of e.groups){const c=a.nodeIds.filter(f=>P.has(f));if(c.length!==0){$.push(` subgraph ${K(a.id)}["${T(a.label)}"]`);for(const f of c){t.add(f);const m=p.find(E=>E.id===f);m&&$.push(q(m,S.get(m.id)))}$.push(" end")}}for(const a of p)t.has(a.id)||$.push(q(a,S.get(a.id)))}else for(const t of p)$.push(q(t,S.get(t.id)));for(const t of k)$.push(_(t,S.get(t.from),S.get(t.to)));if(l){const t=new Set;for(const a of X(e)){if(a.kind!=="agent")continue;const c=a.ownerAgentId??null,f=a.agentId??null;if(!c||!f)continue;const m=y.get(c),E=y.get(f);if(!m||!E||m===E)continue;const C=`${c}:${f}`;t.has(C)||(t.add(C),$.push(_({id:`synthetic:handoff:${C}`,from:`agent_root:${c}`,to:`agent_root:${f}`,kind:"spawn",label:"handoff",sourceEventIds:a.sourceEventId?[a.sourceEventId]:[]},m,E)))}}if(b&&A){const t=y.get(A);t&&$.push(` ${b} --> ${t}`)}for(const[t,a]of y){const c=p.find(m=>m.agentId===t&&m.kind!=="agent");if(!c)continue;const f=l?null:w.find(m=>m.agentId===t);f&&$.push(_({id:`synthetic:${f.id}->agent-root:${t}`,from:f.id,to:`agent_root:${t}`,kind:"spawn",label:"spawn",sourceEventIds:[]},S.get(f.id),a)),$.push(_({id:`synthetic:agent-root:${t}->${c.id}`,from:`agent_root:${t}`,to:c.id,kind:"sequence",sourceEventIds:[]},a,S.get(c.id)))}if(v){const t=[...p].filter(c=>c.kind!=="agent").sort((c,f)=>(f.sequenceEnd??f.sequenceStart??0)-(c.sequenceEnd??c.sequenceStart??0))[0],a=t?S.get(t.id):A?y.get(A):void 0;a&&$.push(` ${a} --> ${v}`)}return $.join(`
|
|
2
|
+
`)}export{ee as exportFlowGraphToMermaid};
|