@pasko70/pibo 3.0.1 → 3.1.0
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 +20 -6
- package/compute-image/Dockerfile +47 -0
- package/compute-image/Dockerfile.dockerignore +5 -0
- package/dist/agent-runtime/context-build.js +26 -2
- package/dist/agent-runtime/contract.js +78 -28
- package/dist/agent-runtime/portable-history.js +19 -9
- package/dist/agent-runtime/registry.js +8 -2
- package/dist/agent-runtime/routed-session.js +120 -15
- package/dist/agent-runtimes/codex-native/adapter.js +12 -0
- package/dist/agent-runtimes/codex-native/resource-delivery.js +35 -7
- package/dist/agent-runtimes/omp/adapter.js +3 -7
- package/dist/agent-runtimes/pi/adapter.js +5 -3
- package/dist/agent-runtimes/pi/routed-session.js +59 -12
- package/dist/agent-runtimes/pi/runtime.js +6 -0
- package/dist/apps/chat/agent-profiles.js +31 -2
- package/dist/apps/chat/agent-store.js +98 -6
- package/dist/apps/chat/chat-request-normalizers.js +31 -0
- package/dist/apps/chat/data/chat-data-mappers.js +61 -11
- package/dist/apps/chat/data/project-service.js +119 -15
- package/dist/apps/chat/data/room-service.js +21 -0
- package/dist/apps/chat/data/session-query-service.js +33 -10
- package/dist/apps/chat/data/timeline-query-service.js +60 -35
- package/dist/apps/chat/loop-api.js +10 -2
- package/dist/apps/chat/output-compactor.js +144 -21
- package/dist/apps/chat/output-event-policy.js +179 -2
- package/dist/apps/chat/stream.js +16 -7
- package/dist/apps/chat/trace-v2.js +1 -0
- package/dist/apps/chat/web-app.js +317 -86
- package/dist/apps/chat-ui/assets/{dist-BDIATCQt.js → dist-CUQJqggN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-mqCviI-c.js → dist-ClUlQWYN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-JnW4v8UE.js → dist-Djul9BmZ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-lRiLP9rr.js → dist-GD0JGdCi.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BBDMeU5-.js → dist-W5HOqHym.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BcjkX-iP.js +228 -0
- package/dist/apps/chat-ui/assets/index-CmqRSbBU.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-JvrPUGvI.js +43 -0
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/cli-ui/InkSessionApp.js +111 -12
- package/dist/apps/cli-ui/cliSessionsCommand.js +34 -8
- package/dist/cli-session/localSessionSource.js +153 -161
- package/dist/cli.js +7 -11
- package/dist/compute/cli.js +35 -16
- package/dist/compute/docker.js +341 -94
- package/dist/config/config.js +3 -0
- package/dist/core/context-build.js +7 -16
- package/dist/core/output-persistence-retry.js +484 -0
- package/dist/core/output-render-sequence.js +331 -0
- package/dist/core/profiles.js +24 -0
- package/dist/core/provider-recovery.js +7 -1
- package/dist/core/session-model.js +37 -1
- package/dist/core/session-router.js +78 -110
- package/dist/data/ingest-service.js +91 -9
- package/dist/data/navigation-store.js +5 -5
- package/dist/data/pibo-store.js +8 -1
- package/dist/data/schema.js +243 -3
- package/dist/data/session-store.js +3 -3
- package/dist/debug/agents.js +91 -89
- package/dist/debug/index.js +46 -2
- package/dist/debug/pty.js +127 -48
- package/dist/gateway/cli.js +4 -0
- package/dist/gateway/web.js +8 -8
- package/dist/local/client.js +3 -2
- package/dist/loops/channel.js +3 -1
- package/dist/loops/cli.js +2 -1
- package/dist/loops/service.js +90 -11
- package/dist/loops/store.js +100 -74
- package/dist/mcp/agent-context.js +13 -26
- package/dist/mcp/commands/info.js +3 -1
- package/dist/mcp/config-command.js +46 -2
- package/dist/mcp/config.js +18 -4
- package/dist/plugins/context-files-store.js +36 -6
- package/dist/plugins/context-files.js +52 -1
- package/dist/plugins/registry.js +2 -0
- package/dist/plugins/user-profile-resources.js +22 -0
- package/dist/previews/base-url.js +34 -0
- package/dist/previews/config.js +2 -32
- package/dist/ralph/store.js +5 -0
- package/dist/reliability/store.js +378 -106
- package/dist/session-ui/terminalRows.js +8 -4
- package/dist/sessions/pibo-data-store.js +145 -0
- package/dist/sessions/store.js +42 -0
- package/dist/setup/cli.js +422 -6
- package/dist/setup/installation-profiles.js +464 -0
- package/dist/shared/deterministic-digest.js +94 -0
- package/dist/shared/trace-engine.js +54 -0
- package/dist/shared/trace-event-projection.js +124 -67
- package/dist/shared/trace-history.js +47 -12
- package/dist/shared/trace-live-reducer.js +23 -4
- package/dist/shared/trace-nodes.js +17 -28
- package/dist/shared/trace-order.js +41 -5
- package/dist/shared/trace-page-merge.js +44 -14
- package/dist/shared/trace-patch-nodes.js +2 -0
- package/dist/shared/trace-subagent-links.js +4 -1
- package/dist/shared/trace-tool-identity.js +15 -8
- package/dist/signals/projector.js +28 -6
- package/dist/subagents/observation-query.js +121 -0
- package/dist/subagents/tool.js +7 -3
- package/dist/tools/agent-browser-leases.js +58 -23
- package/dist/tools/agent-browser-wrapper.js +1 -1
- package/dist/tools/browser-use-leases.js +129 -16
- package/dist/tools/browser-use-wrapper.js +1 -1
- package/dist/tools/index.js +27 -11
- package/dist/tools/python-runtime.js +10 -3
- package/dist/tools/registry.js +1 -1
- package/dist/tools/runtime/node-backend.js +16 -5
- package/dist/tools/runtime/node-worker-source.js +112 -33
- package/dist/tools/runtime/python-backend.js +16 -5
- package/dist/tools/runtime/python-worker-source.js +167 -16
- package/dist/tools/runtime/registry.js +23 -10
- package/dist/user-skills/store.js +0 -1
- package/docs/ops/vscode-extension-release.md +9 -1
- package/npm-shrinkwrap.json +9 -2
- package/package.json +9 -2
- package/scripts/docker-entrypoint.sh +46 -0
- package/scripts/prepare-agent-browser-wrapper.sh +70 -0
- package/scripts/prepare-browser-use-wrapper.sh +255 -0
- package/dist/apps/chat-ui/assets/index-0XOOVxLP.js +0 -228
- package/dist/apps/chat-ui/assets/index-DV7_CgsC.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-Dtw2Z7jz.js +0 -43
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-3.0.1.vsix +0 -0
|
@@ -3,10 +3,19 @@ import { compareTraceNodes, flattenTraceNodes } from "./trace-nodes.js";
|
|
|
3
3
|
import { attachAsyncAgentRunNode, isRunStartToolNode } from "./trace-async-agent-runs.js";
|
|
4
4
|
import { createRunNotificationNode, parseRunNotificationText } from "./trace-run-notifications.js";
|
|
5
5
|
import { findLikelyTraceChildSession, isSubagentToolName, } from "./trace-subagent-links.js";
|
|
6
|
+
import { qualifiedToolNodeId } from "./trace-tool-identity.js";
|
|
6
7
|
export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent, childByParent, linkedChildByToolCallId, historyCoverage, openTranscriptEventIds, sessionStatus) {
|
|
7
8
|
const payload = storedEvent.payload;
|
|
9
|
+
if (payload.type === "message_started" && payload.source === "user" && payload.eventId) {
|
|
10
|
+
const persistedUser = flattenTraceNodes([...nodes]).find((node) => node.type === "user.message"
|
|
11
|
+
&& isPersistedHistorySource(node.source)
|
|
12
|
+
&& node.eventId === payload.eventId);
|
|
13
|
+
if (persistedUser)
|
|
14
|
+
applyRenderSequence(persistedUser, storedEvent, payload);
|
|
15
|
+
}
|
|
8
16
|
const confirmedUserMessage = historyCoverage.mode !== "none" ? confirmedUserMessageEchoNode(nodes, storedEvent) : undefined;
|
|
9
17
|
if (confirmedUserMessage) {
|
|
18
|
+
applyRenderSequence(confirmedUserMessage, storedEvent, payload);
|
|
10
19
|
if (payload.type === "message_steered" && payload.activeEventId) {
|
|
11
20
|
confirmedUserMessage.parentId = messageTurnNodeId(payload.activeEventId);
|
|
12
21
|
}
|
|
@@ -16,21 +25,23 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
16
25
|
|| (historyCoverage.mode === "product" && isProductHistoryEchoEvent(payload))) &&
|
|
17
26
|
historyCoversEvent(payload, historyCoverage) &&
|
|
18
27
|
!shouldKeepTranscriptEchoEvent(payload, openTranscriptEventIds)) {
|
|
28
|
+
applyRenderSequenceToHistoryNode(byId, storedEvent, payload);
|
|
19
29
|
return;
|
|
20
30
|
}
|
|
21
31
|
if (isNativeHistoryToolEchoEvent(payload, historyCoverage, sessionStatus)) {
|
|
32
|
+
applyRenderSequenceToHistoryNode(byId, storedEvent, payload);
|
|
22
33
|
return;
|
|
23
34
|
}
|
|
24
35
|
if (payload.type === "assistant_delta") {
|
|
25
|
-
mergeAssistantDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
36
|
+
mergeAssistantDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource, storedEvent.id);
|
|
26
37
|
return;
|
|
27
38
|
}
|
|
28
39
|
if (payload.type === "thinking_delta") {
|
|
29
|
-
mergeThinkingDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
40
|
+
mergeThinkingDeltaEvent(nodes, byId, payload, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource, storedEvent.id);
|
|
30
41
|
return;
|
|
31
42
|
}
|
|
32
43
|
if (payload.type === "assistant_message") {
|
|
33
|
-
const node = assistantMessageNodeFromEvent(piboSessionId, payload, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
44
|
+
const node = assistantMessageNodeFromEvent(piboSessionId, payload, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource, storedEvent.id);
|
|
34
45
|
const existing = byId.get(node.id) ?? findMatchingContentNode(byId, node);
|
|
35
46
|
if (existing) {
|
|
36
47
|
mergeAssistantMessageEvent(existing, node);
|
|
@@ -40,7 +51,7 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
40
51
|
byId.set(node.id, node);
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
43
|
-
const node = traceNodeFromEvent(piboSessionId, payload, childByParent, linkedChildByToolCallId, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource);
|
|
54
|
+
const node = traceNodeFromEvent(piboSessionId, payload, childByParent, linkedChildByToolCallId, sessionStatus, storedEvent.createdAt, storedEvent.eventSequence, storedEvent.streamId, storedEvent.streamFrameIndex, storedEvent.traceSource, storedEvent.id);
|
|
44
55
|
if (!node)
|
|
45
56
|
return;
|
|
46
57
|
applyStoredPayloadRef(node, payload, storedEvent.storedPayloadRef);
|
|
@@ -89,8 +100,7 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
89
100
|
}
|
|
90
101
|
}
|
|
91
102
|
if (node.toolCallId) {
|
|
92
|
-
const existing =
|
|
93
|
-
(candidate.type === "tool.call" || candidate.type === "agent.delegation"));
|
|
103
|
+
const existing = byId.get(node.id) ?? findUniqueLegacyToolTarget(byId, node, payload);
|
|
94
104
|
if (existing) {
|
|
95
105
|
if (isRunStartToolNode(existing) && node.type === "agent.delegation") {
|
|
96
106
|
attachAsyncAgentRunNode(existing, piboSessionId, storedEvent.createdAt, node);
|
|
@@ -125,6 +135,36 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
125
135
|
for (const indexed of flattenTraceNodes([node]))
|
|
126
136
|
byId.set(indexed.id, indexed);
|
|
127
137
|
}
|
|
138
|
+
function findUniqueLegacyToolTarget(byId, update, event) {
|
|
139
|
+
if ("eventId" in event && event.eventId)
|
|
140
|
+
return undefined;
|
|
141
|
+
const candidates = [...byId.values()].filter((candidate) => candidate.toolCallId === update.toolCallId
|
|
142
|
+
&& (candidate.type === "tool.call" || candidate.type === "tool.result" || candidate.type === "agent.delegation"));
|
|
143
|
+
return candidates.length === 1 ? candidates[0] : undefined;
|
|
144
|
+
}
|
|
145
|
+
function applyRenderSequenceToHistoryNode(byId, storedEvent, event) {
|
|
146
|
+
const stableKey = eventStableKey(event, traceEventInstanceKey(storedEvent.eventSequence, storedEvent.streamId, event, storedEvent.id));
|
|
147
|
+
const eventId = "eventId" in event && typeof event.eventId === "string" ? event.eventId : undefined;
|
|
148
|
+
const target = [...byId.values()].find((node) => node.stableKey === stableKey
|
|
149
|
+
|| ("toolCallId" in event
|
|
150
|
+
&& typeof event.toolCallId === "string"
|
|
151
|
+
&& node.toolCallId === event.toolCallId
|
|
152
|
+
&& (!eventId || !node.eventId || node.eventId === eventId)));
|
|
153
|
+
if (target)
|
|
154
|
+
applyRenderSequence(target, storedEvent, event);
|
|
155
|
+
}
|
|
156
|
+
function applyRenderSequence(node, storedEvent, event) {
|
|
157
|
+
const renderSequence = storedEvent.renderSequence ?? event.renderSequence;
|
|
158
|
+
const eventSequence = storedEvent.eventSequence ?? storedEvent.streamId;
|
|
159
|
+
if (renderSequence === undefined && eventSequence === undefined)
|
|
160
|
+
return;
|
|
161
|
+
const orderKey = node.orderKey ?? eventTraceOrder(eventSequence, eventNodeKind(event.type));
|
|
162
|
+
node.orderKey = {
|
|
163
|
+
...orderKey,
|
|
164
|
+
...(eventSequence === undefined ? {} : { turnSeq: eventSequence, eventSequence }),
|
|
165
|
+
...(renderSequence === undefined ? {} : { renderSequence }),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
128
168
|
function applyStoredPayloadRef(node, event, storedPayloadRef) {
|
|
129
169
|
if (!storedPayloadRef)
|
|
130
170
|
return;
|
|
@@ -135,10 +175,11 @@ function applyStoredPayloadRef(node, event, storedPayloadRef) {
|
|
|
135
175
|
node.payloadRefs = { ...node.payloadRefs, output: storedPayloadRef };
|
|
136
176
|
}
|
|
137
177
|
}
|
|
138
|
-
function assistantMessageNodeFromEvent(piboSessionId, event, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
178
|
+
function assistantMessageNodeFromEvent(piboSessionId, event, createdAt, eventSequence, streamId, streamFrameIndex, traceSource, storedInstanceId) {
|
|
139
179
|
const eventId = typeof event.eventId === "string" ? event.eventId : undefined;
|
|
140
180
|
const assistantId = assistantEventNodeId(event);
|
|
141
|
-
const
|
|
181
|
+
const fallbackIdentity = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
182
|
+
const id = assistantId ? assistantMessageNodeId(assistantId) : `event:${event.type}:${fallbackIdentity}`;
|
|
142
183
|
return {
|
|
143
184
|
id,
|
|
144
185
|
piboSessionId,
|
|
@@ -152,8 +193,8 @@ function assistantMessageNodeFromEvent(piboSessionId, event, createdAt, eventSeq
|
|
|
152
193
|
summary: event.text,
|
|
153
194
|
output: event.text,
|
|
154
195
|
source: "event-log",
|
|
155
|
-
stableKey: assistantId ? `assistant:${assistantId}` : eventStableKey(event),
|
|
156
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
196
|
+
stableKey: assistantId ? `assistant:${assistantId}` : eventStableKey(event, fallbackIdentity),
|
|
197
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource, event.renderSequence, createdAt),
|
|
157
198
|
children: [],
|
|
158
199
|
};
|
|
159
200
|
}
|
|
@@ -267,8 +308,9 @@ export function reconcileTranscriptUserMessages(nodes, events, turnTimings = [])
|
|
|
267
308
|
continue;
|
|
268
309
|
const payloadEventId = typeof event.eventId === "string" ? event.eventId : undefined;
|
|
269
310
|
const eventId = payloadEventId ?? storedEvent.eventId;
|
|
270
|
-
const
|
|
271
|
-
const
|
|
311
|
+
const fallbackIdentity = storedEvent.id ? `instance:${storedEvent.id}` : liveProjectionIdentity(event);
|
|
312
|
+
const canonicalId = `event:${event.type}:${payloadEventId ?? fallbackIdentity}`;
|
|
313
|
+
const stableKey = eventStableKey(event, fallbackIdentity);
|
|
272
314
|
const text = typeof event.text === "string" ? event.text : undefined;
|
|
273
315
|
const identityMatchIndex = transcriptUsers.findIndex((node) => transcriptUserMessageMatchesIdentity(node, canonicalId, stableKey, eventId));
|
|
274
316
|
const matchIndex = identityMatchIndex !== -1
|
|
@@ -294,8 +336,9 @@ function confirmedUserMessageEchoNode(nodes, event) {
|
|
|
294
336
|
return undefined;
|
|
295
337
|
const payloadEventId = typeof payload.eventId === "string" ? payload.eventId : undefined;
|
|
296
338
|
const eventId = payloadEventId ?? event.eventId;
|
|
297
|
-
const
|
|
298
|
-
const
|
|
339
|
+
const fallbackIdentity = event.id ? `instance:${event.id}` : liveProjectionIdentity(payload);
|
|
340
|
+
const canonicalId = `event:${payload.type}:${payloadEventId ?? fallbackIdentity}`;
|
|
341
|
+
const stableKey = eventStableKey(payload, fallbackIdentity);
|
|
299
342
|
const text = typeof payload.text === "string" ? payload.text : undefined;
|
|
300
343
|
const transcriptUsers = flattenTraceNodes([...nodes]).filter((node) => node.type === "user.message" && isPersistedHistorySource(node.source));
|
|
301
344
|
const identityMatch = transcriptUsers.find((node) => transcriptUserMessageMatchesIdentity(node, canonicalId, stableKey, eventId));
|
|
@@ -377,9 +420,10 @@ export function latestTraceStreamId(events, initial) {
|
|
|
377
420
|
return latest;
|
|
378
421
|
}
|
|
379
422
|
// ── event → node helpers ─────────────────────────────────────────
|
|
380
|
-
function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByToolCallId, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
423
|
+
function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByToolCallId, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource, storedInstanceId) {
|
|
381
424
|
const eventId = "eventId" in event && typeof event.eventId === "string" ? event.eventId : undefined;
|
|
382
|
-
const
|
|
425
|
+
const fallbackIdentity = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
426
|
+
const id = `event:${event.type}:${eventId ?? fallbackIdentity}`;
|
|
383
427
|
const turnParentId = eventId ? messageTurnNodeId(eventId) : undefined;
|
|
384
428
|
const base = {
|
|
385
429
|
id,
|
|
@@ -387,8 +431,8 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
387
431
|
eventId,
|
|
388
432
|
startedAt: createdAt,
|
|
389
433
|
source: "event-log",
|
|
390
|
-
stableKey: eventStableKey(event),
|
|
391
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
434
|
+
stableKey: eventStableKey(event, fallbackIdentity),
|
|
435
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource, event.renderSequence, createdAt),
|
|
392
436
|
children: [],
|
|
393
437
|
};
|
|
394
438
|
switch (event.type) {
|
|
@@ -403,7 +447,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
403
447
|
startedAt: createdAt,
|
|
404
448
|
source: "event-log",
|
|
405
449
|
stableKey: eventId ? `run-notification:${eventId}` : id,
|
|
406
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
450
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource, event.renderSequence, createdAt),
|
|
407
451
|
notification,
|
|
408
452
|
});
|
|
409
453
|
}
|
|
@@ -419,8 +463,6 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
419
463
|
}
|
|
420
464
|
case "message_started":
|
|
421
465
|
case "message_finished":
|
|
422
|
-
if (event.source === "service")
|
|
423
|
-
return undefined;
|
|
424
466
|
return {
|
|
425
467
|
...base,
|
|
426
468
|
id: eventId ? messageTurnNodeId(eventId) : id,
|
|
@@ -466,16 +508,18 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
466
508
|
case "tool_execution_started":
|
|
467
509
|
case "tool_execution_updated":
|
|
468
510
|
case "tool_execution_finished": {
|
|
511
|
+
const toolNodeId = toolInvocationNodeId(event);
|
|
469
512
|
const subagentTool = isSubagentToolName(event.toolName);
|
|
470
|
-
const linkedPiboSessionId = linkedChildByToolCallId.get(
|
|
513
|
+
const linkedPiboSessionId = linkedChildByToolCallId.get(toolNodeId) ??
|
|
471
514
|
(subagentTool
|
|
472
515
|
? findLikelyTraceChildSession(piboSessionId, event.toolName, event, childByParent)
|
|
473
516
|
: undefined);
|
|
474
517
|
return {
|
|
475
518
|
...base,
|
|
476
|
-
id:
|
|
519
|
+
id: toolNodeId,
|
|
477
520
|
parentId: turnParentId,
|
|
478
521
|
toolCallId: event.toolCallId,
|
|
522
|
+
toolInvocationOrdinal: event.toolInvocationOrdinal ?? 0,
|
|
479
523
|
intent: event.intent,
|
|
480
524
|
type: subagentTool ? "agent.delegation" : "tool.call",
|
|
481
525
|
title: event.toolName,
|
|
@@ -498,26 +542,28 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
498
542
|
? stringifyPreview(event.result)
|
|
499
543
|
: undefined,
|
|
500
544
|
linkedPiboSessionId,
|
|
501
|
-
stableKey:
|
|
545
|
+
stableKey: toolNodeId,
|
|
502
546
|
children: [],
|
|
503
547
|
};
|
|
504
548
|
}
|
|
505
549
|
case "subagent_session": {
|
|
506
550
|
const childPiboSessionId = nonEmptyString(event.childPiboSessionId);
|
|
507
|
-
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event);
|
|
551
|
+
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
552
|
+
const toolNodeId = event.toolCallId ? toolInvocationNodeId(event) : undefined;
|
|
508
553
|
return {
|
|
509
554
|
...base,
|
|
510
|
-
id:
|
|
555
|
+
id: toolNodeId ?? `event:subagent_session:${eventInstanceKey}`,
|
|
511
556
|
eventId,
|
|
512
557
|
toolCallId: event.toolCallId,
|
|
558
|
+
toolInvocationOrdinal: event.toolInvocationOrdinal,
|
|
513
559
|
type: "agent.delegation",
|
|
514
560
|
title: event.toolName,
|
|
515
561
|
status: sessionStatus === "running" ? "running" : "done",
|
|
516
562
|
summary: event.subagentName,
|
|
517
563
|
input: { subagentName: event.subagentName, threadKey: event.threadKey },
|
|
518
564
|
linkedPiboSessionId: childPiboSessionId,
|
|
519
|
-
stableKey:
|
|
520
|
-
?
|
|
565
|
+
stableKey: toolNodeId
|
|
566
|
+
? toolNodeId
|
|
521
567
|
: childPiboSessionId ? `subagent:${childPiboSessionId}` : `subagent:event:${eventInstanceKey}`,
|
|
522
568
|
children: [],
|
|
523
569
|
};
|
|
@@ -534,7 +580,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
534
580
|
output: event.result,
|
|
535
581
|
};
|
|
536
582
|
case "compaction_start": {
|
|
537
|
-
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event);
|
|
583
|
+
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
538
584
|
return {
|
|
539
585
|
...base,
|
|
540
586
|
id: `event:compaction:${eventInstanceKey}`,
|
|
@@ -547,7 +593,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
547
593
|
};
|
|
548
594
|
}
|
|
549
595
|
case "compaction_end": {
|
|
550
|
-
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event);
|
|
596
|
+
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
551
597
|
return {
|
|
552
598
|
...base,
|
|
553
599
|
id: `event:compaction:end:${eventInstanceKey}`,
|
|
@@ -577,11 +623,12 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
577
623
|
return undefined;
|
|
578
624
|
}
|
|
579
625
|
}
|
|
580
|
-
function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
626
|
+
function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource, storedInstanceId) {
|
|
581
627
|
if (typeof event.text !== "string" || event.text.length === 0)
|
|
582
628
|
return;
|
|
583
629
|
const assistantId = assistantEventNodeId(event);
|
|
584
|
-
const
|
|
630
|
+
const fallbackIdentity = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
631
|
+
const id = assistantId ? assistantMessageNodeId(assistantId) : `event:assistant_delta:${fallbackIdentity}`;
|
|
585
632
|
const existing = byId.get(id);
|
|
586
633
|
if (existing) {
|
|
587
634
|
const text = `${typeof existing.output === "string" ? existing.output : ""}${event.text}`;
|
|
@@ -603,7 +650,7 @@ function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt,
|
|
|
603
650
|
output: event.text,
|
|
604
651
|
source: "event-log",
|
|
605
652
|
stableKey: assistantId ? `assistant:${assistantId}` : id,
|
|
606
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
653
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource, event.renderSequence, createdAt),
|
|
607
654
|
children: [],
|
|
608
655
|
};
|
|
609
656
|
nodes.push(node);
|
|
@@ -621,11 +668,12 @@ function mergeAssistantMessageEvent(target, update) {
|
|
|
621
668
|
target.error = update.error ?? target.error;
|
|
622
669
|
target.completedAt = update.completedAt ?? target.completedAt;
|
|
623
670
|
}
|
|
624
|
-
function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource) {
|
|
671
|
+
function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex, traceSource, storedInstanceId) {
|
|
625
672
|
if (typeof event.text !== "string" || event.text.length === 0)
|
|
626
673
|
return;
|
|
627
674
|
const thinkingId = thinkingEventNodeId(event);
|
|
628
|
-
const
|
|
675
|
+
const fallbackIdentity = traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId);
|
|
676
|
+
const id = thinkingId ? thinkingNodeId(thinkingId) : `event:thinking_delta:${fallbackIdentity}`;
|
|
629
677
|
const stableKey = thinkingId ? `reasoning:${thinkingId}` : id;
|
|
630
678
|
const existing = byId.get(id) ?? [...byId.values()].find((candidate) => candidate.type === "model.reasoning" && candidate.stableKey === stableKey);
|
|
631
679
|
if (existing) {
|
|
@@ -648,7 +696,7 @@ function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, e
|
|
|
648
696
|
output: event.text,
|
|
649
697
|
source: "event-log",
|
|
650
698
|
stableKey,
|
|
651
|
-
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource),
|
|
699
|
+
orderKey: eventTraceNodeOrder(eventSequence, event.type, streamId, streamFrameIndex, traceSource, event.renderSequence, createdAt),
|
|
652
700
|
children: [],
|
|
653
701
|
};
|
|
654
702
|
nodes.push(node);
|
|
@@ -848,11 +896,24 @@ function isOpenTranscriptEvent(event) {
|
|
|
848
896
|
event.type === "thinking_delta" ||
|
|
849
897
|
event.type === "thinking_finished");
|
|
850
898
|
}
|
|
851
|
-
function eventTraceNodeOrder(eventSequence, type, streamId, streamFrameIndex, traceSource) {
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
899
|
+
function eventTraceNodeOrder(eventSequence, type, streamId, streamFrameIndex, traceSource, renderSequence, createdAt) {
|
|
900
|
+
const order = traceSource === "live"
|
|
901
|
+
? liveTraceOrder(streamId, streamFrameIndex, eventNodeKind(type))
|
|
902
|
+
: eventTraceOrder(eventSequence ?? streamId, eventNodeKind(type));
|
|
903
|
+
// Modern render sequences encode the first-visible millisecond plus a local
|
|
904
|
+
// slot. Deriving chronology from that immutable segment position keeps a
|
|
905
|
+
// live node in the same place when its persisted final receives a later
|
|
906
|
+
// database created_at timestamp.
|
|
907
|
+
const renderChronologyMs = renderSequence !== undefined && renderSequence >= 946_684_800_000_000
|
|
908
|
+
? Math.floor(renderSequence / 1_000)
|
|
909
|
+
: undefined;
|
|
910
|
+
const chronologyMs = renderChronologyMs
|
|
911
|
+
?? (createdAt && Number.isFinite(Date.parse(createdAt)) ? Date.parse(createdAt) : undefined);
|
|
912
|
+
return {
|
|
913
|
+
...order,
|
|
914
|
+
...(renderSequence === undefined ? {} : { renderSequence }),
|
|
915
|
+
...(chronologyMs === undefined ? {} : { chronologyMs }),
|
|
916
|
+
};
|
|
856
917
|
}
|
|
857
918
|
function eventNodeKind(type) {
|
|
858
919
|
switch (type) {
|
|
@@ -886,16 +947,16 @@ function eventNodeKind(type) {
|
|
|
886
947
|
return "execution.command";
|
|
887
948
|
}
|
|
888
949
|
}
|
|
889
|
-
function eventStableKey(event) {
|
|
950
|
+
function eventStableKey(event, fallbackIdentity) {
|
|
890
951
|
const eventId = "eventId" in event && typeof event.eventId === "string" ? event.eventId : undefined;
|
|
891
952
|
if (event.type === "tool_call" ||
|
|
892
953
|
event.type === "tool_execution_started" ||
|
|
893
954
|
event.type === "tool_execution_updated" ||
|
|
894
955
|
event.type === "tool_execution_finished") {
|
|
895
|
-
return
|
|
956
|
+
return toolInvocationNodeId(event);
|
|
896
957
|
}
|
|
897
958
|
if (event.type === "subagent_session" && event.toolCallId)
|
|
898
|
-
return
|
|
959
|
+
return toolInvocationNodeId(event);
|
|
899
960
|
if (eventId && (event.type === "message_started" || event.type === "message_finished"))
|
|
900
961
|
return `turn:${eventId}`;
|
|
901
962
|
if (event.type === "thinking_started" ||
|
|
@@ -910,7 +971,7 @@ function eventStableKey(event) {
|
|
|
910
971
|
if (assistantId)
|
|
911
972
|
return `assistant:${assistantId}`;
|
|
912
973
|
}
|
|
913
|
-
return `event:${event.type}:${eventId ??
|
|
974
|
+
return `event:${event.type}:${eventId ?? fallbackIdentity ?? liveProjectionIdentity(event)}`;
|
|
914
975
|
}
|
|
915
976
|
export function messageTurnNodeId(eventId) {
|
|
916
977
|
return `event:message:${eventId}`;
|
|
@@ -1016,36 +1077,32 @@ function parseTimestamp(value) {
|
|
|
1016
1077
|
const timestamp = new Date(value).getTime();
|
|
1017
1078
|
return Number.isFinite(timestamp) ? timestamp : undefined;
|
|
1018
1079
|
}
|
|
1019
|
-
function traceEventInstanceKey(eventSequence, streamId, event) {
|
|
1080
|
+
function traceEventInstanceKey(eventSequence, streamId, event, storedInstanceId) {
|
|
1020
1081
|
if (eventSequence !== undefined)
|
|
1021
1082
|
return `sequence:${eventSequence}`;
|
|
1022
1083
|
if (streamId !== undefined)
|
|
1023
1084
|
return `stream:${streamId}`;
|
|
1024
|
-
|
|
1085
|
+
if (storedInstanceId)
|
|
1086
|
+
return `instance:${storedInstanceId}`;
|
|
1087
|
+
return liveProjectionIdentity(event);
|
|
1088
|
+
}
|
|
1089
|
+
function toolInvocationNodeId(event) {
|
|
1090
|
+
const eventId = event.eventId
|
|
1091
|
+
?? (event.renderSequence !== undefined ? `render:${event.renderSequence}` : "unscoped");
|
|
1092
|
+
return qualifiedToolNodeId(event.toolCallId ?? "unlinked", eventId, event.toolInvocationOrdinal ?? 0);
|
|
1025
1093
|
}
|
|
1026
1094
|
function nonEmptyString(value) {
|
|
1027
1095
|
if (typeof value !== "string")
|
|
1028
1096
|
return undefined;
|
|
1029
1097
|
return value.trim() || undefined;
|
|
1030
1098
|
}
|
|
1031
|
-
function
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
for (; index + 2 < bytes.length; index += 3) {
|
|
1039
|
-
const value = (bytes[index] << 16) | (bytes[index + 1] << 8) | bytes[index + 2];
|
|
1040
|
-
output += alphabet[(value >> 18) & 63] + alphabet[(value >> 12) & 63] + alphabet[(value >> 6) & 63] + alphabet[value & 63];
|
|
1041
|
-
}
|
|
1042
|
-
if (index < bytes.length) {
|
|
1043
|
-
const first = bytes[index];
|
|
1044
|
-
const second = index + 1 < bytes.length ? bytes[index + 1] : 0;
|
|
1045
|
-
const value = (first << 16) | (second << 8);
|
|
1046
|
-
output += alphabet[(value >> 18) & 63] + alphabet[(value >> 12) & 63];
|
|
1047
|
-
if (index + 1 < bytes.length)
|
|
1048
|
-
output += alphabet[(value >> 6) & 63];
|
|
1049
|
-
}
|
|
1050
|
-
return output;
|
|
1099
|
+
function liveProjectionIdentity(value) {
|
|
1100
|
+
const existing = liveProjectionIdentityCache.get(value);
|
|
1101
|
+
if (existing)
|
|
1102
|
+
return existing;
|
|
1103
|
+
const identity = `live:${++liveProjectionIdentitySequence}`;
|
|
1104
|
+
liveProjectionIdentityCache.set(value, identity);
|
|
1105
|
+
return identity;
|
|
1051
1106
|
}
|
|
1107
|
+
const liveProjectionIdentityCache = new WeakMap();
|
|
1108
|
+
let liveProjectionIdentitySequence = 0;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { historyReconciliationDigest, historyReconciliationEntrySignature, } from "../agent-runtime/history.js";
|
|
2
2
|
import { historyTraceOrder } from "./trace-order.js";
|
|
3
3
|
import { attachAsyncAgentRunNode, reconcileAsyncAgentRunStatuses } from "./trace-async-agent-runs.js";
|
|
4
|
-
import { sortTraceNodes } from "./trace-nodes.js";
|
|
4
|
+
import { flattenTraceNodes, sortTraceNodes } from "./trace-nodes.js";
|
|
5
5
|
import { createRunNotificationNode, parseRunNotificationText } from "./trace-run-notifications.js";
|
|
6
6
|
import { isSubagentToolName } from "./trace-subagent-links.js";
|
|
7
7
|
import { assistantMessageNodeId, messageTurnNodeId, thinkingNodeId } from "./trace-event-projection.js";
|
|
8
8
|
import { TRACE_RECONCILIATION_ENTRY_CAP, TRACE_RECONCILIATION_TIMING_CAP } from "./trace-limits.js";
|
|
9
|
-
import {
|
|
9
|
+
import { qualifiedToolNodeId } from "./trace-tool-identity.js";
|
|
10
10
|
const MAX_CONFIDENT_TIMESTAMP_DISTANCE_MS = 5 * 60 * 1_000;
|
|
11
11
|
const PERSISTED_TIMESTAMP_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?(Z|([+-])(\d{2}):(\d{2}))$/;
|
|
12
12
|
export function projectHistoryEntries(entries, sessionStatus, openHistoryEventIds, turnTimings = [], reconciliationProof, reconciliationAuthoritative = false) {
|
|
@@ -73,15 +73,44 @@ export function traceNodesFromHistoryEntries(piboSessionId, entries, turnTimings
|
|
|
73
73
|
output: { name: entry.name },
|
|
74
74
|
source,
|
|
75
75
|
stableKey: historyEntryStableKey(entry),
|
|
76
|
-
orderKey: historyTraceOrder(entryIndex, 0, "execution.command", source),
|
|
76
|
+
orderKey: historyTraceOrder(entryIndex, 0, "execution.command", source, entry.createdAt),
|
|
77
77
|
children: [],
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
applyMonotoneHistoryChronology(nodes, entries);
|
|
81
82
|
reconcileAsyncAgentRunStatuses(nodes);
|
|
82
83
|
sortTraceNodes(nodes);
|
|
83
84
|
return nodes;
|
|
84
85
|
}
|
|
86
|
+
function applyMonotoneHistoryChronology(nodes, entries) {
|
|
87
|
+
const nextValid = new Array(entries.length);
|
|
88
|
+
let next;
|
|
89
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
90
|
+
const parsed = parsedTimestamp(entries[index]?.createdAt);
|
|
91
|
+
if (parsed !== undefined)
|
|
92
|
+
next = parsed;
|
|
93
|
+
nextValid[index] = next;
|
|
94
|
+
}
|
|
95
|
+
const chronologyByIndex = new Map();
|
|
96
|
+
let previous;
|
|
97
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
98
|
+
const entry = entries[index];
|
|
99
|
+
const parsed = parsedTimestamp(entry.createdAt);
|
|
100
|
+
const candidate = parsed ?? nextValid[index] ?? previous;
|
|
101
|
+
if (candidate === undefined)
|
|
102
|
+
continue;
|
|
103
|
+
const monotone = previous === undefined ? candidate : Math.max(previous, candidate);
|
|
104
|
+
chronologyByIndex.set(historyIndex(entry, index), monotone);
|
|
105
|
+
previous = monotone;
|
|
106
|
+
}
|
|
107
|
+
for (const node of flattenTraceNodes(nodes)) {
|
|
108
|
+
if (!node.orderKey)
|
|
109
|
+
continue;
|
|
110
|
+
const chronologyMs = chronologyByIndex.get(node.orderKey.transcriptIndex ?? node.orderKey.turnSeq);
|
|
111
|
+
node.orderKey = { ...node.orderKey, chronologyMs };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
85
114
|
function collectHistoryTurnTimingTargets(entries) {
|
|
86
115
|
const targets = [];
|
|
87
116
|
let latestUserText;
|
|
@@ -630,6 +659,8 @@ function findConfidentTimingMatch(target, turnTimings) {
|
|
|
630
659
|
}
|
|
631
660
|
function collectAssistantTurn(entries, startIndex) {
|
|
632
661
|
const turnEntries = [];
|
|
662
|
+
const first = entries[startIndex];
|
|
663
|
+
const explicitTurnId = first?.type === "message" ? first.turnId : undefined;
|
|
633
664
|
let index = startIndex;
|
|
634
665
|
while (index < entries.length) {
|
|
635
666
|
const entry = entries[index];
|
|
@@ -637,6 +668,8 @@ function collectAssistantTurn(entries, startIndex) {
|
|
|
637
668
|
break;
|
|
638
669
|
if (entry.role !== "assistant" && entry.role !== "tool")
|
|
639
670
|
break;
|
|
671
|
+
if (index !== startIndex && explicitTurnId && entry.turnId && entry.turnId !== explicitTurnId)
|
|
672
|
+
break;
|
|
640
673
|
turnEntries.push({ entry, index });
|
|
641
674
|
index += 1;
|
|
642
675
|
}
|
|
@@ -653,7 +686,7 @@ function createUserMessageNode(piboSessionId, entry, entryIndex, timing, fallbac
|
|
|
653
686
|
entryId: entry.nativeEntryId,
|
|
654
687
|
piboSessionId,
|
|
655
688
|
startedAt: entry.createdAt,
|
|
656
|
-
orderKey: historyTraceOrder(orderIndex, 0, "yielded.run", source),
|
|
689
|
+
orderKey: historyTraceOrder(orderIndex, 0, "yielded.run", source, entry.createdAt),
|
|
657
690
|
source,
|
|
658
691
|
stableKey: historyEntryStableKey(entry),
|
|
659
692
|
notification,
|
|
@@ -680,7 +713,7 @@ function createUserMessageNode(piboSessionId, entry, entryIndex, timing, fallbac
|
|
|
680
713
|
error: entry.error,
|
|
681
714
|
source,
|
|
682
715
|
stableKey: eventIdentity ?? historyEntryStableKey(entry),
|
|
683
|
-
orderKey: historyTraceOrder(orderIndex, 0, "user.message", source),
|
|
716
|
+
orderKey: historyTraceOrder(orderIndex, 0, "user.message", source, entry.createdAt),
|
|
684
717
|
children: [],
|
|
685
718
|
};
|
|
686
719
|
}
|
|
@@ -783,7 +816,7 @@ function createReasoningNode(input) {
|
|
|
783
816
|
output: input.thinking,
|
|
784
817
|
source,
|
|
785
818
|
stableKey: eventIdentity ? `reasoning:${eventIdentity}` : `${historyEntryStableKey(input.entry)}:thinking:${input.contentPartIndex}`,
|
|
786
|
-
orderKey: historyTraceOrder(historyIndex(input.entry, input.entryIndex), input.contentPartIndex, "model.reasoning", source),
|
|
819
|
+
orderKey: historyTraceOrder(historyIndex(input.entry, input.entryIndex), input.contentPartIndex, "model.reasoning", source, input.entry.createdAt),
|
|
787
820
|
children: [],
|
|
788
821
|
};
|
|
789
822
|
}
|
|
@@ -798,6 +831,7 @@ function createToolCallNode(piboSessionId, entry, entryIndex, contentPartIndex,
|
|
|
798
831
|
eventId,
|
|
799
832
|
parentId: historyTurnParentId(entry, eventId),
|
|
800
833
|
toolCallId: part.toolCallId,
|
|
834
|
+
toolInvocationOrdinal,
|
|
801
835
|
type: isSubagentToolName(part.toolName) ? "agent.delegation" : "tool.call",
|
|
802
836
|
title: part.toolName,
|
|
803
837
|
status: "done",
|
|
@@ -805,7 +839,7 @@ function createToolCallNode(piboSessionId, entry, entryIndex, contentPartIndex,
|
|
|
805
839
|
input: part.input ?? {},
|
|
806
840
|
source,
|
|
807
841
|
stableKey: toolNodeId,
|
|
808
|
-
orderKey: historyTraceOrder(historyIndex(entry, entryIndex), contentPartIndex, isSubagentToolName(part.toolName) ? "agent.delegation" : "tool.call", source),
|
|
842
|
+
orderKey: historyTraceOrder(historyIndex(entry, entryIndex), contentPartIndex, isSubagentToolName(part.toolName) ? "agent.delegation" : "tool.call", source, entry.createdAt),
|
|
809
843
|
children: [],
|
|
810
844
|
};
|
|
811
845
|
}
|
|
@@ -840,13 +874,14 @@ function createMissingToolResultNode(piboSessionId, entry, entryIndex, toolCallI
|
|
|
840
874
|
eventId,
|
|
841
875
|
parentId: historyTurnParentId(entry, eventId),
|
|
842
876
|
toolCallId,
|
|
877
|
+
toolInvocationOrdinal,
|
|
843
878
|
type: "tool.result",
|
|
844
879
|
title: entry.toolName ?? "Tool Result",
|
|
845
880
|
status: "done",
|
|
846
881
|
startedAt: entry.createdAt,
|
|
847
882
|
source,
|
|
848
883
|
stableKey: toolNodeId,
|
|
849
|
-
orderKey: historyTraceOrder(historyIndex(entry, entryIndex), 0, "tool.result", source),
|
|
884
|
+
orderKey: historyTraceOrder(historyIndex(entry, entryIndex), 0, "tool.result", source, entry.createdAt),
|
|
850
885
|
children: [],
|
|
851
886
|
};
|
|
852
887
|
}
|
|
@@ -870,7 +905,7 @@ function createAssistantMessageNode(input) {
|
|
|
870
905
|
error: input.error,
|
|
871
906
|
source,
|
|
872
907
|
stableKey: eventIdentity ? `assistant:${eventIdentity}` : `${historyEntryStableKey(input.entry)}:response:${input.contentPartIndex}`,
|
|
873
|
-
orderKey: historyTraceOrder(historyIndex(input.entry, input.entryIndex), input.contentPartIndex, "assistant.message", source),
|
|
908
|
+
orderKey: historyTraceOrder(historyIndex(input.entry, input.entryIndex), input.contentPartIndex, "assistant.message", source, input.startedAt ?? input.entry.createdAt),
|
|
874
909
|
children: input.children ?? [],
|
|
875
910
|
};
|
|
876
911
|
}
|
|
@@ -890,6 +925,8 @@ function historyMessageStatus(entry) {
|
|
|
890
925
|
return "done";
|
|
891
926
|
}
|
|
892
927
|
function canonicalProductTurnId(entry, timing, fallbackEventId) {
|
|
928
|
+
if (entry.source === "product" && entry.turnId)
|
|
929
|
+
return entry.turnId;
|
|
893
930
|
return fallbackEventId ?? timing?.eventId ?? entry.turnId;
|
|
894
931
|
}
|
|
895
932
|
function nativeHistoryTurnId(entry) {
|
|
@@ -904,9 +941,7 @@ function historyEntryNodeId(entry) {
|
|
|
904
941
|
return entry.source === "native" && entry.nativeEntryId ? `entry:${entry.nativeEntryId}` : `history:${entry.id}`;
|
|
905
942
|
}
|
|
906
943
|
function historyToolNodeId(entry, toolCallId, eventId, toolInvocationOrdinal, qualifyProjectionIdentity) {
|
|
907
|
-
|
|
908
|
-
return `tool:${toolCallId}`;
|
|
909
|
-
return qualifiedHistoryToolNodeId(toolCallId, eventId ?? `native-history-tool:${entry.historyPosition ?? entry.id}`, toolInvocationOrdinal);
|
|
944
|
+
return qualifiedToolNodeId(toolCallId, eventId ?? `native-history-tool:${entry.historyPosition ?? entry.id}`, toolInvocationOrdinal);
|
|
910
945
|
}
|
|
911
946
|
function nativeToolCallIdsRequiringQualification(entries, reconciliationProof) {
|
|
912
947
|
const localNativeToolCallIds = nativeToolCallIds(entries);
|