@botbotgo/agent-harness 0.0.245 → 0.0.247
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,4 +1,5 @@
|
|
|
1
1
|
const PRODUCT_VIEW_KINDS = new Set(["agent", "llm", "tool", "skill"]);
|
|
2
|
+
const STRUCTURAL_EDGE_KINDS = new Set(["sequence", "contains"]);
|
|
2
3
|
function sanitizeMermaidId(value) {
|
|
3
4
|
return value.replace(/[^A-Za-z0-9_]/g, "_");
|
|
4
5
|
}
|
|
@@ -31,6 +32,68 @@ function renderEdge(edge, fromId, toId) {
|
|
|
31
32
|
? ` ${fromId} ${connector}|"${escapeMermaidLabel(label)}"| ${toId}`
|
|
32
33
|
: ` ${fromId} ${connector} ${toId}`;
|
|
33
34
|
}
|
|
35
|
+
function edgeKey(edge) {
|
|
36
|
+
return `${edge.from}::${edge.to}::${edge.kind}::${edge.label ?? ""}::${edge.condition ?? ""}`;
|
|
37
|
+
}
|
|
38
|
+
function collapseEdgePath(source, target, path) {
|
|
39
|
+
const representative = [...path].reverse().find((edge) => !STRUCTURAL_EDGE_KINDS.has(edge.kind) || edge.label || edge.condition);
|
|
40
|
+
const sourceEventIds = [...new Set(path.flatMap((edge) => edge.sourceEventIds))];
|
|
41
|
+
return {
|
|
42
|
+
id: `collapsed:${source}:${target}:${sourceEventIds.join(",")}`,
|
|
43
|
+
from: source,
|
|
44
|
+
to: target,
|
|
45
|
+
kind: representative?.kind ?? "sequence",
|
|
46
|
+
label: representative?.label,
|
|
47
|
+
condition: representative?.condition,
|
|
48
|
+
sourceEventIds,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function collectVisibleEdges(graph, visibleNodes, includedEdgeKinds) {
|
|
52
|
+
const visibleNodeIds = new Set(visibleNodes.map((node) => node.id));
|
|
53
|
+
const candidateEdges = graph.edges.filter((edge) => includedEdgeKinds ? includedEdgeKinds.has(edge.kind) : true);
|
|
54
|
+
const outgoingByNodeId = new Map();
|
|
55
|
+
for (const edge of candidateEdges) {
|
|
56
|
+
const outgoing = outgoingByNodeId.get(edge.from);
|
|
57
|
+
if (outgoing) {
|
|
58
|
+
outgoing.push(edge);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
outgoingByNodeId.set(edge.from, [edge]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const visibleEdges = candidateEdges.filter((edge) => visibleNodeIds.has(edge.from) && visibleNodeIds.has(edge.to));
|
|
65
|
+
const seenEdgeKeys = new Set(visibleEdges.map((edge) => edgeKey(edge)));
|
|
66
|
+
for (const node of visibleNodes) {
|
|
67
|
+
const queue = (outgoingByNodeId.get(node.id) ?? [])
|
|
68
|
+
.filter((edge) => !visibleNodeIds.has(edge.to))
|
|
69
|
+
.map((edge) => ({ nodeId: edge.to, path: [edge] }));
|
|
70
|
+
const visitedHiddenNodes = new Set();
|
|
71
|
+
while (queue.length > 0) {
|
|
72
|
+
const current = queue.shift();
|
|
73
|
+
if (visitedHiddenNodes.has(current.nodeId)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
visitedHiddenNodes.add(current.nodeId);
|
|
77
|
+
for (const edge of outgoingByNodeId.get(current.nodeId) ?? []) {
|
|
78
|
+
const nextPath = [...current.path, edge];
|
|
79
|
+
if (visibleNodeIds.has(edge.to)) {
|
|
80
|
+
if (edge.to === node.id) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const collapsed = collapseEdgePath(node.id, edge.to, nextPath);
|
|
84
|
+
const key = edgeKey(collapsed);
|
|
85
|
+
if (!seenEdgeKeys.has(key)) {
|
|
86
|
+
seenEdgeKeys.add(key);
|
|
87
|
+
visibleEdges.push(collapsed);
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
queue.push({ nodeId: edge.to, path: nextPath });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return visibleEdges;
|
|
96
|
+
}
|
|
34
97
|
export function exportFlowGraphToMermaid(graph, options = {}) {
|
|
35
98
|
const direction = options.direction ?? "TD";
|
|
36
99
|
const view = options.view ?? "product";
|
|
@@ -49,12 +112,7 @@ export function exportFlowGraphToMermaid(graph, options = {}) {
|
|
|
49
112
|
return includedKinds ? includedKinds.has(node.kind) : true;
|
|
50
113
|
});
|
|
51
114
|
const nodeIdSet = new Set(nodes.map((node) => node.id));
|
|
52
|
-
const edges = graph
|
|
53
|
-
if (!nodeIdSet.has(edge.from) || !nodeIdSet.has(edge.to)) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
return includedEdgeKinds ? includedEdgeKinds.has(edge.kind) : true;
|
|
57
|
-
});
|
|
115
|
+
const edges = collectVisibleEdges(graph, nodes, includedEdgeKinds);
|
|
58
116
|
const lines = [`flowchart ${direction}`];
|
|
59
117
|
const mermaidIdByNodeId = new Map();
|
|
60
118
|
for (const node of nodes) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.246";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.246";
|
|
@@ -158,6 +158,13 @@ export async function* streamHarnessRun(options) {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
await options.appendAssistantMessage(options.threadId, options.runId, assistantOutput);
|
|
161
|
+
const completedEvent = await options.setRunStateAndEmit(options.threadId, options.runId, 6, "completed", {
|
|
162
|
+
previousState: "running",
|
|
163
|
+
});
|
|
164
|
+
yield {
|
|
165
|
+
type: "event",
|
|
166
|
+
event: completedEvent,
|
|
167
|
+
};
|
|
161
168
|
yield {
|
|
162
169
|
type: "result",
|
|
163
170
|
result: {
|
|
@@ -169,12 +176,6 @@ export async function* streamHarnessRun(options) {
|
|
|
169
176
|
finalMessageText: assistantOutput,
|
|
170
177
|
},
|
|
171
178
|
};
|
|
172
|
-
yield {
|
|
173
|
-
type: "event",
|
|
174
|
-
event: await options.setRunStateAndEmit(options.threadId, options.runId, 6, "completed", {
|
|
175
|
-
previousState: "running",
|
|
176
|
-
}),
|
|
177
|
-
};
|
|
178
179
|
}
|
|
179
180
|
catch (error) {
|
|
180
181
|
const shouldRetryAfterStreamingCompatibilityError = streamActivityObserved &&
|
|
@@ -251,6 +252,13 @@ export async function* streamHarnessRun(options) {
|
|
|
251
252
|
if (Array.isArray(actual.contentBlocks) && actual.contentBlocks.length > 0) {
|
|
252
253
|
yield createContentBlocksItem(options.threadId, options.runId, options.selectedAgentId, actual.contentBlocks);
|
|
253
254
|
}
|
|
255
|
+
const terminalEvent = await options.setRunStateAndEmit(options.threadId, options.runId, 6, actual.state, {
|
|
256
|
+
previousState: "running",
|
|
257
|
+
});
|
|
258
|
+
yield {
|
|
259
|
+
type: "event",
|
|
260
|
+
event: terminalEvent,
|
|
261
|
+
};
|
|
254
262
|
yield {
|
|
255
263
|
type: "result",
|
|
256
264
|
result: {
|
|
@@ -264,12 +272,6 @@ export async function* streamHarnessRun(options) {
|
|
|
264
272
|
},
|
|
265
273
|
},
|
|
266
274
|
};
|
|
267
|
-
yield {
|
|
268
|
-
type: "event",
|
|
269
|
-
event: await options.setRunStateAndEmit(options.threadId, options.runId, 6, actual.state, {
|
|
270
|
-
previousState: "running",
|
|
271
|
-
}),
|
|
272
|
-
};
|
|
273
275
|
return;
|
|
274
276
|
}
|
|
275
277
|
catch (invokeError) {
|
package/dist/upstream-events.js
CHANGED
|
@@ -31,8 +31,17 @@ function readEventContext(event) {
|
|
|
31
31
|
function containsSemanticHint(values, hint) {
|
|
32
32
|
return values.some((value) => hint.test(value));
|
|
33
33
|
}
|
|
34
|
+
function normalizeSemanticHint(value) {
|
|
35
|
+
return value
|
|
36
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
37
|
+
.replace(/[.:/]+/g, " ")
|
|
38
|
+
.replace(/[_-]+/g, " ")
|
|
39
|
+
.replace(/\s+/g, " ")
|
|
40
|
+
.trim()
|
|
41
|
+
.toLowerCase();
|
|
42
|
+
}
|
|
34
43
|
function classifyStepCategory(context) {
|
|
35
|
-
const hints = [context.name, context.runType, ...context.tags, ...context.ns].map(
|
|
44
|
+
const hints = [context.name, context.runType, ...context.tags, ...context.ns].map(normalizeSemanticHint);
|
|
36
45
|
if (containsSemanticHint(hints, /\b(skill|skills)\b/)) {
|
|
37
46
|
return "skill";
|
|
38
47
|
}
|