@pasko70/pibo 3.0.0 → 3.0.2
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/dist/agent-runtime/context-build.js +26 -2
- package/dist/agent-runtime/routed-session.js +108 -9
- 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 +49 -8
- 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 +43 -3
- 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/session-query-service.js +33 -10
- package/dist/apps/chat/data/timeline-query-service.js +60 -35
- 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 +236 -64
- package/dist/apps/chat-ui/assets/{dist-BBDMeU5-.js → dist-B6GZgWSj.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-mqCviI-c.js → dist-BPotHecb.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-JnW4v8UE.js → dist-BzqQKeVO.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BDIATCQt.js → dist-CvaPTBTN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-lRiLP9rr.js → dist-paagejNj.js} +1 -1
- package/dist/apps/chat-ui/assets/index-6JJV-eic.js +228 -0
- package/dist/apps/chat-ui/assets/index-CeL9JPP5.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/{index-Dtw2Z7jz.js → index-U-MSErGa.js} +4 -4
- package/dist/apps/chat-vscode-web/index.html +1 -1
- 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/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 +67 -20
- package/dist/data/ingest-service.js +91 -9
- package/dist/data/navigation-store.js +5 -5
- package/dist/data/schema.js +122 -2
- package/dist/data/session-store.js +3 -3
- package/dist/debug/index.js +44 -2
- package/dist/gateway/web.js +8 -8
- package/dist/local/client.js +3 -2
- package/dist/plugins/context-files-store.js +30 -0
- 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/reliability/store.js +246 -37
- package/dist/session-ui/terminalRows.js +6 -3
- 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/tool.js +7 -3
- package/docs/ops/vscode-extension-release.md +9 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
- 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/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-3.0.0.vsix +0 -0
|
@@ -1,62 +1,90 @@
|
|
|
1
1
|
import { assistantOutputKey, isLiveOnlyOutputEvent, thinkingOutputKey, toolOutputKey } from "./output-event-policy.js";
|
|
2
|
+
const MAX_TRACKED_COMPACTOR_SESSIONS = 1_024;
|
|
2
3
|
export class OutputCompactor {
|
|
3
4
|
assistantBuffers = new Map();
|
|
4
5
|
thinkingBuffers = new Map();
|
|
5
6
|
toolSnapshots = new Map();
|
|
7
|
+
sessionRecency = new Map();
|
|
8
|
+
sessionBufferCounts = new Map();
|
|
6
9
|
compact(event) {
|
|
10
|
+
const prepared = this.prepare(event);
|
|
11
|
+
prepared.ack();
|
|
12
|
+
return prepared;
|
|
13
|
+
}
|
|
14
|
+
prepare(event) {
|
|
7
15
|
const persistedEvents = [];
|
|
8
16
|
const snapshots = [];
|
|
17
|
+
let liveEvents = [event];
|
|
18
|
+
const mutations = [];
|
|
9
19
|
switch (event.type) {
|
|
10
20
|
case "assistant_delta": {
|
|
11
21
|
const key = assistantOutputKey(event);
|
|
12
22
|
const previous = this.assistantBuffers.get(key);
|
|
13
|
-
const
|
|
14
|
-
this.assistantBuffers
|
|
15
|
-
snapshots.push({ ...event, text });
|
|
23
|
+
const next = { event, text: `${previous?.text ?? ""}${event.text}` };
|
|
24
|
+
mutations.push(() => this.setBuffer(this.assistantBuffers, key, next, event.piboSessionId));
|
|
25
|
+
snapshots.push({ ...event, text: next.text });
|
|
16
26
|
break;
|
|
17
27
|
}
|
|
18
28
|
case "assistant_message": {
|
|
19
29
|
const key = assistantOutputKey(event);
|
|
20
30
|
const buffered = this.assistantBuffers.get(key);
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
const canonical = { ...event, text: event.text || buffered?.text || "" };
|
|
32
|
+
mutations.push(() => {
|
|
33
|
+
this.deleteBuffer(this.assistantBuffers, key, buffered, event.piboSessionId);
|
|
34
|
+
});
|
|
35
|
+
persistedEvents.push(canonical);
|
|
36
|
+
liveEvents = [canonical];
|
|
23
37
|
break;
|
|
24
38
|
}
|
|
25
39
|
case "thinking_started": {
|
|
26
40
|
const key = thinkingOutputKey(event);
|
|
27
|
-
|
|
41
|
+
const next = { base: event, text: "" };
|
|
42
|
+
mutations.push(() => {
|
|
43
|
+
if (!this.thinkingBuffers.has(key))
|
|
44
|
+
this.setBuffer(this.thinkingBuffers, key, next, event.piboSessionId);
|
|
45
|
+
});
|
|
28
46
|
persistedEvents.push(event);
|
|
29
47
|
break;
|
|
30
48
|
}
|
|
31
49
|
case "thinking_delta": {
|
|
32
50
|
const key = thinkingOutputKey(event);
|
|
33
51
|
const previous = this.thinkingBuffers.get(key);
|
|
34
|
-
const
|
|
35
|
-
this.thinkingBuffers
|
|
36
|
-
snapshots.push({ ...event, text });
|
|
52
|
+
const next = { base: previous?.base ?? event, text: `${previous?.text ?? ""}${event.text}` };
|
|
53
|
+
mutations.push(() => this.setBuffer(this.thinkingBuffers, key, next, event.piboSessionId));
|
|
54
|
+
snapshots.push({ ...event, text: next.text });
|
|
37
55
|
break;
|
|
38
56
|
}
|
|
39
57
|
case "thinking_finished": {
|
|
40
58
|
const key = thinkingOutputKey(event);
|
|
41
59
|
const buffered = this.thinkingBuffers.get(key);
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
const canonical = { ...event, text: event.text || buffered?.text || "" };
|
|
61
|
+
mutations.push(() => {
|
|
62
|
+
this.deleteBuffer(this.thinkingBuffers, key, buffered, event.piboSessionId);
|
|
63
|
+
});
|
|
64
|
+
persistedEvents.push(canonical);
|
|
65
|
+
liveEvents = [canonical];
|
|
44
66
|
break;
|
|
45
67
|
}
|
|
46
68
|
case "tool_execution_updated": {
|
|
47
|
-
|
|
69
|
+
const key = toolOutputKey(event);
|
|
70
|
+
mutations.push(() => this.setBuffer(this.toolSnapshots, key, event, event.piboSessionId));
|
|
48
71
|
snapshots.push(event);
|
|
49
72
|
break;
|
|
50
73
|
}
|
|
51
74
|
case "tool_execution_finished": {
|
|
52
|
-
|
|
75
|
+
const key = toolOutputKey(event);
|
|
76
|
+
const previous = this.toolSnapshots.get(key);
|
|
77
|
+
mutations.push(() => {
|
|
78
|
+
this.deleteBuffer(this.toolSnapshots, key, previous, event.piboSessionId);
|
|
79
|
+
});
|
|
53
80
|
persistedEvents.push(event);
|
|
54
81
|
break;
|
|
55
82
|
}
|
|
56
83
|
case "message_finished":
|
|
57
84
|
case "session_error": {
|
|
58
|
-
|
|
59
|
-
persistedEvents.push(event);
|
|
85
|
+
const flushed = this.prepareBoundaryFlush(event, mutations);
|
|
86
|
+
persistedEvents.push(...flushed, event);
|
|
87
|
+
liveEvents = [...flushed, event];
|
|
60
88
|
break;
|
|
61
89
|
}
|
|
62
90
|
default:
|
|
@@ -64,7 +92,23 @@ export class OutputCompactor {
|
|
|
64
92
|
persistedEvents.push(event);
|
|
65
93
|
break;
|
|
66
94
|
}
|
|
67
|
-
|
|
95
|
+
let settled = false;
|
|
96
|
+
return {
|
|
97
|
+
liveEvents,
|
|
98
|
+
persistedEvents,
|
|
99
|
+
snapshots,
|
|
100
|
+
ack: () => {
|
|
101
|
+
if (settled)
|
|
102
|
+
return;
|
|
103
|
+
settled = true;
|
|
104
|
+
for (const mutate of mutations)
|
|
105
|
+
mutate();
|
|
106
|
+
this.touchSession(event.piboSessionId);
|
|
107
|
+
},
|
|
108
|
+
rollback: () => {
|
|
109
|
+
settled = true;
|
|
110
|
+
},
|
|
111
|
+
};
|
|
68
112
|
}
|
|
69
113
|
snapshotsForSession(piboSessionId) {
|
|
70
114
|
const snapshots = [];
|
|
@@ -86,29 +130,68 @@ export class OutputCompactor {
|
|
|
86
130
|
}
|
|
87
131
|
return snapshots;
|
|
88
132
|
}
|
|
89
|
-
|
|
133
|
+
disposeSession(piboSessionId) {
|
|
134
|
+
for (const [key, buffer] of this.assistantBuffers) {
|
|
135
|
+
if (buffer.event.piboSessionId === piboSessionId)
|
|
136
|
+
this.deleteBuffer(this.assistantBuffers, key, buffer, piboSessionId);
|
|
137
|
+
}
|
|
138
|
+
for (const [key, buffer] of this.thinkingBuffers) {
|
|
139
|
+
if (buffer.base.piboSessionId === piboSessionId)
|
|
140
|
+
this.deleteBuffer(this.thinkingBuffers, key, buffer, piboSessionId);
|
|
141
|
+
}
|
|
142
|
+
for (const [key, event] of this.toolSnapshots) {
|
|
143
|
+
if (event.piboSessionId === piboSessionId)
|
|
144
|
+
this.deleteBuffer(this.toolSnapshots, key, event, piboSessionId);
|
|
145
|
+
}
|
|
146
|
+
this.sessionBufferCounts.delete(piboSessionId);
|
|
147
|
+
this.sessionRecency.delete(piboSessionId);
|
|
148
|
+
}
|
|
149
|
+
disposeAll() {
|
|
150
|
+
this.assistantBuffers.clear();
|
|
151
|
+
this.thinkingBuffers.clear();
|
|
152
|
+
this.toolSnapshots.clear();
|
|
153
|
+
this.sessionRecency.clear();
|
|
154
|
+
this.sessionBufferCounts.clear();
|
|
155
|
+
}
|
|
156
|
+
debugState() {
|
|
157
|
+
return {
|
|
158
|
+
sessionCount: this.sessionRecency.size,
|
|
159
|
+
completedSessionCount: [...this.sessionRecency.keys()].filter((sessionId) => !this.sessionHasBuffers(sessionId)).length,
|
|
160
|
+
sessions: [...this.sessionRecency.keys()],
|
|
161
|
+
assistantBufferCount: this.assistantBuffers.size,
|
|
162
|
+
thinkingBufferCount: this.thinkingBuffers.size,
|
|
163
|
+
toolSnapshotCount: this.toolSnapshots.size,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
prepareBoundaryFlush(event, mutations) {
|
|
90
167
|
const flushed = [];
|
|
91
|
-
for (const [key, buffer] of
|
|
168
|
+
for (const [key, buffer] of this.assistantBuffers) {
|
|
92
169
|
if (!matchesBoundary(buffer.event, event))
|
|
93
170
|
continue;
|
|
94
|
-
|
|
171
|
+
mutations.push(() => {
|
|
172
|
+
this.deleteBuffer(this.assistantBuffers, key, buffer, buffer.event.piboSessionId);
|
|
173
|
+
});
|
|
95
174
|
flushed.push({
|
|
96
175
|
type: "assistant_message",
|
|
97
176
|
piboSessionId: buffer.event.piboSessionId,
|
|
98
177
|
eventId: buffer.event.eventId,
|
|
178
|
+
renderSequence: buffer.event.renderSequence,
|
|
99
179
|
assistantIndex: buffer.event.assistantIndex,
|
|
100
180
|
contentIndex: buffer.event.contentIndex,
|
|
101
181
|
text: buffer.text,
|
|
102
182
|
});
|
|
103
183
|
}
|
|
104
|
-
for (const [key, buffer] of
|
|
184
|
+
for (const [key, buffer] of this.thinkingBuffers) {
|
|
105
185
|
if (!matchesBoundary(buffer.base, event))
|
|
106
186
|
continue;
|
|
107
|
-
|
|
187
|
+
mutations.push(() => {
|
|
188
|
+
this.deleteBuffer(this.thinkingBuffers, key, buffer, buffer.base.piboSessionId);
|
|
189
|
+
});
|
|
108
190
|
flushed.push({
|
|
109
191
|
type: "thinking_finished",
|
|
110
192
|
piboSessionId: buffer.base.piboSessionId,
|
|
111
193
|
eventId: buffer.base.eventId,
|
|
194
|
+
renderSequence: buffer.base.renderSequence,
|
|
112
195
|
thinkingIndex: "thinkingIndex" in buffer.base ? buffer.base.thinkingIndex : undefined,
|
|
113
196
|
contentIndex: buffer.base.contentIndex,
|
|
114
197
|
text: buffer.text,
|
|
@@ -116,6 +199,46 @@ export class OutputCompactor {
|
|
|
116
199
|
}
|
|
117
200
|
return flushed;
|
|
118
201
|
}
|
|
202
|
+
touchSession(piboSessionId) {
|
|
203
|
+
this.sessionRecency.delete(piboSessionId);
|
|
204
|
+
this.sessionRecency.set(piboSessionId, true);
|
|
205
|
+
let completedCount = [...this.sessionRecency.keys()].filter((sessionId) => !this.sessionHasBuffers(sessionId)).length;
|
|
206
|
+
while (completedCount > MAX_TRACKED_COMPACTOR_SESSIONS) {
|
|
207
|
+
let removed = false;
|
|
208
|
+
for (const sessionId of this.sessionRecency.keys()) {
|
|
209
|
+
if (this.sessionHasBuffers(sessionId))
|
|
210
|
+
continue;
|
|
211
|
+
this.sessionRecency.delete(sessionId);
|
|
212
|
+
completedCount -= 1;
|
|
213
|
+
removed = true;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
if (!removed)
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
sessionHasBuffers(piboSessionId) {
|
|
221
|
+
return (this.sessionBufferCounts.get(piboSessionId) ?? 0) > 0;
|
|
222
|
+
}
|
|
223
|
+
setBuffer(map, key, value, piboSessionId) {
|
|
224
|
+
if (!map.has(key))
|
|
225
|
+
this.sessionBufferCounts.set(piboSessionId, (this.sessionBufferCounts.get(piboSessionId) ?? 0) + 1);
|
|
226
|
+
setLatest(map, key, value);
|
|
227
|
+
}
|
|
228
|
+
deleteBuffer(map, key, expected, piboSessionId) {
|
|
229
|
+
if (expected === undefined || map.get(key) !== expected)
|
|
230
|
+
return;
|
|
231
|
+
map.delete(key);
|
|
232
|
+
const next = (this.sessionBufferCounts.get(piboSessionId) ?? 1) - 1;
|
|
233
|
+
if (next > 0)
|
|
234
|
+
this.sessionBufferCounts.set(piboSessionId, next);
|
|
235
|
+
else
|
|
236
|
+
this.sessionBufferCounts.delete(piboSessionId);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function setLatest(map, key, value) {
|
|
240
|
+
map.delete(key);
|
|
241
|
+
map.set(key, value);
|
|
119
242
|
}
|
|
120
243
|
function matchesBoundary(bufferEvent, boundary) {
|
|
121
244
|
if (bufferEvent.piboSessionId !== boundary.piboSessionId)
|
|
@@ -2,7 +2,184 @@ export function isLiveOnlyOutputEvent(event) {
|
|
|
2
2
|
return event.type === "assistant_delta" || event.type === "thinking_delta" || event.type === "tool_execution_updated";
|
|
3
3
|
}
|
|
4
4
|
export function isPersistableOutputEvent(event) {
|
|
5
|
-
return !isLiveOnlyOutputEvent(event);
|
|
5
|
+
return isPiboOutputEvent(event) && !isLiveOnlyOutputEvent(event);
|
|
6
|
+
}
|
|
7
|
+
export function isPiboOutputEvent(value) {
|
|
8
|
+
if (!isRecord(value) || typeof value.type !== "string" || typeof value.piboSessionId !== "string")
|
|
9
|
+
return false;
|
|
10
|
+
if (value.eventId !== undefined && typeof value.eventId !== "string")
|
|
11
|
+
return false;
|
|
12
|
+
if (value.renderSequence !== undefined && !isPositiveSafeInteger(value.renderSequence))
|
|
13
|
+
return false;
|
|
14
|
+
if (value.toolInvocationOrdinal !== undefined && !isNonNegativeSafeInteger(value.toolInvocationOrdinal))
|
|
15
|
+
return false;
|
|
16
|
+
if (value.provenance !== undefined && !isMessageProvenance(value.provenance))
|
|
17
|
+
return false;
|
|
18
|
+
switch (value.type) {
|
|
19
|
+
case "message_queued":
|
|
20
|
+
return typeof value.text === "string"
|
|
21
|
+
&& isNonNegativeSafeInteger(value.queuedMessages)
|
|
22
|
+
&& isOptionalEventSource(value.source);
|
|
23
|
+
case "message_steered":
|
|
24
|
+
return typeof value.text === "string"
|
|
25
|
+
&& isOptionalEventSource(value.source)
|
|
26
|
+
&& isOptionalString(value.activeEventId);
|
|
27
|
+
case "message_started":
|
|
28
|
+
return typeof value.text === "string" && isOptionalEventSource(value.source);
|
|
29
|
+
case "assistant_delta":
|
|
30
|
+
case "assistant_message":
|
|
31
|
+
return typeof value.text === "string"
|
|
32
|
+
&& isOptionalNonNegativeSafeInteger(value.assistantIndex)
|
|
33
|
+
&& isOptionalNonNegativeSafeInteger(value.contentIndex);
|
|
34
|
+
case "thinking_delta":
|
|
35
|
+
return typeof value.text === "string"
|
|
36
|
+
&& isOptionalNonNegativeSafeInteger(value.thinkingIndex)
|
|
37
|
+
&& isOptionalNonNegativeSafeInteger(value.contentIndex);
|
|
38
|
+
case "message_finished":
|
|
39
|
+
return isOptionalEventSource(value.source);
|
|
40
|
+
case "thinking_started":
|
|
41
|
+
return isOptionalNonNegativeSafeInteger(value.thinkingIndex) && isOptionalNonNegativeSafeInteger(value.contentIndex);
|
|
42
|
+
case "thinking_finished":
|
|
43
|
+
return isOptionalString(value.text)
|
|
44
|
+
&& isOptionalNonNegativeSafeInteger(value.thinkingIndex)
|
|
45
|
+
&& isOptionalNonNegativeSafeInteger(value.contentIndex);
|
|
46
|
+
case "tool_call":
|
|
47
|
+
return hasOwn(value, "args")
|
|
48
|
+
&& typeof value.toolCallId === "string"
|
|
49
|
+
&& typeof value.toolName === "string"
|
|
50
|
+
&& typeof value.argsComplete === "boolean"
|
|
51
|
+
&& isOptionalString(value.intent);
|
|
52
|
+
case "tool_execution_started":
|
|
53
|
+
return hasOwn(value, "args")
|
|
54
|
+
&& typeof value.toolCallId === "string"
|
|
55
|
+
&& typeof value.toolName === "string"
|
|
56
|
+
&& isOptionalString(value.intent);
|
|
57
|
+
case "tool_execution_updated":
|
|
58
|
+
return hasOwn(value, "args")
|
|
59
|
+
&& hasOwn(value, "partialResult")
|
|
60
|
+
&& typeof value.toolCallId === "string"
|
|
61
|
+
&& typeof value.toolName === "string"
|
|
62
|
+
&& isOptionalString(value.intent);
|
|
63
|
+
case "tool_execution_finished":
|
|
64
|
+
return hasOwn(value, "result")
|
|
65
|
+
&& typeof value.toolCallId === "string"
|
|
66
|
+
&& typeof value.toolName === "string"
|
|
67
|
+
&& typeof value.isError === "boolean"
|
|
68
|
+
&& isOptionalString(value.intent);
|
|
69
|
+
case "subagent_session":
|
|
70
|
+
return typeof value.toolName === "string"
|
|
71
|
+
&& typeof value.subagentName === "string"
|
|
72
|
+
&& typeof value.childPiboSessionId === "string"
|
|
73
|
+
&& isOptionalString(value.requestId)
|
|
74
|
+
&& isOptionalString(value.toolCallId)
|
|
75
|
+
&& isOptionalString(value.threadKey);
|
|
76
|
+
case "assistant_usage":
|
|
77
|
+
return isFiniteNumber(value.totalTokens)
|
|
78
|
+
&& isOptionalNonNegativeSafeInteger(value.usageIndex)
|
|
79
|
+
&& ["inputTokens", "outputTokens", "cacheReadTokens", "cacheWriteTokens", "reasoningTokens"].every((key) => isOptionalFiniteNumber(value[key]))
|
|
80
|
+
&& isOptionalFiniteNumber(value.costUsd);
|
|
81
|
+
case "compaction_start":
|
|
82
|
+
return typeof value.reason === "string" && isOptionalNonNegativeSafeInteger(value.compactionIndex);
|
|
83
|
+
case "compaction_end":
|
|
84
|
+
return typeof value.reason === "string"
|
|
85
|
+
&& typeof value.aborted === "boolean"
|
|
86
|
+
&& isOptionalNonNegativeSafeInteger(value.compactionIndex)
|
|
87
|
+
&& isOptionalString(value.errorMessage);
|
|
88
|
+
case "approval_requested":
|
|
89
|
+
return isApprovalRequest(value.request);
|
|
90
|
+
case "approval_resolved":
|
|
91
|
+
case "user_input_resolved":
|
|
92
|
+
return typeof value.requestId === "string" && isRuntimeRequestResolution(value.resolution);
|
|
93
|
+
case "user_input_requested":
|
|
94
|
+
return isUserInputRequest(value.request);
|
|
95
|
+
case "execution_result":
|
|
96
|
+
return typeof value.action === "string" && hasOwn(value, "result");
|
|
97
|
+
case "session_error":
|
|
98
|
+
return typeof value.error === "string" && (value.errorDetails === undefined || isRecord(value.errorDetails));
|
|
99
|
+
case "pi_event":
|
|
100
|
+
return hasOwn(value, "event");
|
|
101
|
+
default:
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function isRecord(value) {
|
|
106
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
107
|
+
}
|
|
108
|
+
function hasOwn(value, key) {
|
|
109
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
110
|
+
}
|
|
111
|
+
function isFiniteNumber(value) {
|
|
112
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
113
|
+
}
|
|
114
|
+
function isOptionalFiniteNumber(value) {
|
|
115
|
+
return value === undefined || isFiniteNumber(value);
|
|
116
|
+
}
|
|
117
|
+
function isOptionalString(value) {
|
|
118
|
+
return value === undefined || typeof value === "string";
|
|
119
|
+
}
|
|
120
|
+
function isOptionalNonNegativeSafeInteger(value) {
|
|
121
|
+
return value === undefined || isNonNegativeSafeInteger(value);
|
|
122
|
+
}
|
|
123
|
+
function isPositiveSafeInteger(value) {
|
|
124
|
+
return Number.isSafeInteger(value) && value > 0;
|
|
125
|
+
}
|
|
126
|
+
function isNonNegativeSafeInteger(value) {
|
|
127
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
128
|
+
}
|
|
129
|
+
function isRuntimeRequestResolution(value) {
|
|
130
|
+
return value === "responded" || value === "cleared" || value === "aborted" || value === "expired";
|
|
131
|
+
}
|
|
132
|
+
function isOptionalEventSource(value) {
|
|
133
|
+
return value === undefined || value === "user" || value === "ui" || value === "service" || value === "actor";
|
|
134
|
+
}
|
|
135
|
+
function isMessageProvenance(value) {
|
|
136
|
+
if (!isRecord(value) || typeof value.kind !== "string")
|
|
137
|
+
return false;
|
|
138
|
+
if (value.kind === "loop-run") {
|
|
139
|
+
return typeof value.jobId === "string"
|
|
140
|
+
&& typeof value.runId === "string"
|
|
141
|
+
&& (value.cause === undefined || value.cause === "run-reminder")
|
|
142
|
+
&& isOptionalString(value.rootEventId);
|
|
143
|
+
}
|
|
144
|
+
if (value.kind === "subagent-request") {
|
|
145
|
+
return typeof value.requestId === "string"
|
|
146
|
+
&& typeof value.controllerPiboSessionId === "string"
|
|
147
|
+
&& isOptionalString(value.loopJobId)
|
|
148
|
+
&& isOptionalString(value.loopRunId);
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
function isApprovalRequest(value) {
|
|
153
|
+
return isRecord(value)
|
|
154
|
+
&& typeof value.requestId === "string"
|
|
155
|
+
&& typeof value.requestType === "string"
|
|
156
|
+
&& isOptionalString(value.title)
|
|
157
|
+
&& isOptionalString(value.detail)
|
|
158
|
+
&& (value.decisions === undefined || (Array.isArray(value.decisions)
|
|
159
|
+
&& value.decisions.every((decision) => isRecord(decision)
|
|
160
|
+
&& typeof decision.id === "string"
|
|
161
|
+
&& typeof decision.label === "string"
|
|
162
|
+
&& isOptionalString(decision.description))));
|
|
163
|
+
}
|
|
164
|
+
function isUserInputRequest(value) {
|
|
165
|
+
return isRecord(value)
|
|
166
|
+
&& typeof value.requestId === "string"
|
|
167
|
+
&& Array.isArray(value.questions)
|
|
168
|
+
&& isOptionalBoolean(value.blocking)
|
|
169
|
+
&& value.questions.every((question) => isRecord(question)
|
|
170
|
+
&& typeof question.id === "string"
|
|
171
|
+
&& typeof question.question === "string"
|
|
172
|
+
&& isOptionalString(question.header)
|
|
173
|
+
&& isOptionalBoolean(question.multiSelect)
|
|
174
|
+
&& isOptionalBoolean(question.allowFreeform)
|
|
175
|
+
&& isOptionalBoolean(question.secret)
|
|
176
|
+
&& (question.options === undefined || (Array.isArray(question.options)
|
|
177
|
+
&& question.options.every((option) => isRecord(option)
|
|
178
|
+
&& typeof option.label === "string"
|
|
179
|
+
&& isOptionalString(option.description)))));
|
|
180
|
+
}
|
|
181
|
+
function isOptionalBoolean(value) {
|
|
182
|
+
return value === undefined || typeof value === "boolean";
|
|
6
183
|
}
|
|
7
184
|
export function assistantOutputKey(event) {
|
|
8
185
|
const partIndex = event.assistantIndex ?? event.contentIndex ?? 0;
|
|
@@ -13,5 +190,5 @@ export function thinkingOutputKey(event) {
|
|
|
13
190
|
return [event.piboSessionId, event.eventId ?? "", partIndex].join(":");
|
|
14
191
|
}
|
|
15
192
|
export function toolOutputKey(event) {
|
|
16
|
-
return [event.piboSessionId, event.eventId ?? "", event.toolCallId].join(":");
|
|
193
|
+
return [event.piboSessionId, event.eventId ?? "", event.toolCallId, event.toolInvocationOrdinal ?? 0].join(":");
|
|
17
194
|
}
|
package/dist/apps/chat/stream.js
CHANGED
|
@@ -58,7 +58,7 @@ export function chatStreamFramesFromOutputEvent(event, state, options = {}) {
|
|
|
58
58
|
}
|
|
59
59
|
break;
|
|
60
60
|
case "tool_call":
|
|
61
|
-
ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, event.args, event.intent, eventId);
|
|
61
|
+
ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, event.args, event.intent, eventId, event.toolInvocationOrdinal);
|
|
62
62
|
frames.push({
|
|
63
63
|
type: "TOOL_CALL_ARGS",
|
|
64
64
|
toolCallId: event.toolCallId,
|
|
@@ -71,7 +71,7 @@ export function chatStreamFramesFromOutputEvent(event, state, options = {}) {
|
|
|
71
71
|
});
|
|
72
72
|
break;
|
|
73
73
|
case "tool_execution_started": {
|
|
74
|
-
const started = ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, event.args, event.intent, eventId);
|
|
74
|
+
const started = ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, event.args, event.intent, eventId, event.toolInvocationOrdinal);
|
|
75
75
|
if (!started && event.intent) {
|
|
76
76
|
frames.push({
|
|
77
77
|
type: "TOOL_CALL_START",
|
|
@@ -85,7 +85,7 @@ export function chatStreamFramesFromOutputEvent(event, state, options = {}) {
|
|
|
85
85
|
break;
|
|
86
86
|
}
|
|
87
87
|
case "tool_execution_updated":
|
|
88
|
-
ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, event.args, event.intent, eventId);
|
|
88
|
+
ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, event.args, event.intent, eventId, event.toolInvocationOrdinal);
|
|
89
89
|
frames.push({
|
|
90
90
|
type: "TOOL_CALL_ARGS",
|
|
91
91
|
toolCallId: event.toolCallId,
|
|
@@ -99,7 +99,7 @@ export function chatStreamFramesFromOutputEvent(event, state, options = {}) {
|
|
|
99
99
|
});
|
|
100
100
|
break;
|
|
101
101
|
case "tool_execution_finished":
|
|
102
|
-
ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, undefined, event.intent, eventId);
|
|
102
|
+
ensureToolCallStarted(frames, state, event.toolCallId, event.toolName, undefined, event.intent, eventId, event.toolInvocationOrdinal);
|
|
103
103
|
frames.push({ type: "TOOL_CALL_RESULT", toolCallId: event.toolCallId, toolName: event.toolName, result: event.result, isError: event.isError, ...(event.intent ? { intent: event.intent } : {}), runId: eventId });
|
|
104
104
|
break;
|
|
105
105
|
case "subagent_session":
|
|
@@ -135,6 +135,14 @@ export function chatStreamFramesFromOutputEvent(event, state, options = {}) {
|
|
|
135
135
|
}
|
|
136
136
|
if (options.includeRawEvent ?? true)
|
|
137
137
|
frames.push({ type: "RAW_EVENT", event });
|
|
138
|
+
if (event.renderSequence !== undefined) {
|
|
139
|
+
for (const frame of frames)
|
|
140
|
+
frame.renderSequence = event.renderSequence;
|
|
141
|
+
}
|
|
142
|
+
if (event.toolInvocationOrdinal !== undefined) {
|
|
143
|
+
for (const frame of frames)
|
|
144
|
+
frame.toolInvocationOrdinal = event.toolInvocationOrdinal;
|
|
145
|
+
}
|
|
138
146
|
return frames;
|
|
139
147
|
}
|
|
140
148
|
function reasoningIdFromOutputEvent(event) {
|
|
@@ -162,10 +170,11 @@ function ensureReasoningStarted(frames, state, messageId, runId) {
|
|
|
162
170
|
state.reasoningMessageIds.add(messageId);
|
|
163
171
|
frames.push({ type: "REASONING_MESSAGE_START", messageId, runId });
|
|
164
172
|
}
|
|
165
|
-
function ensureToolCallStarted(frames, state, toolCallId, toolName, args, intent, runId) {
|
|
166
|
-
|
|
173
|
+
function ensureToolCallStarted(frames, state, toolCallId, toolName, args, intent, runId, toolInvocationOrdinal) {
|
|
174
|
+
const invocationKey = JSON.stringify([runId ?? "", toolCallId, toolInvocationOrdinal ?? 0]);
|
|
175
|
+
if (state.toolCallIds.has(invocationKey))
|
|
167
176
|
return false;
|
|
168
|
-
state.toolCallIds.add(
|
|
177
|
+
state.toolCallIds.add(invocationKey);
|
|
169
178
|
frames.push({ type: "TOOL_CALL_START", toolCallId, toolName, args, ...(intent ? { intent } : {}), runId });
|
|
170
179
|
return true;
|
|
171
180
|
}
|
|
@@ -255,6 +255,7 @@ function compactTraceNode(node, payloadStore, piboSessionId, depth) {
|
|
|
255
255
|
payloadRefs: Object.keys(payloadRefs).length ? payloadRefs : undefined,
|
|
256
256
|
linkedPiboSessionId: node.linkedPiboSessionId,
|
|
257
257
|
toolCallId: node.toolCallId,
|
|
258
|
+
toolInvocationOrdinal: node.toolInvocationOrdinal,
|
|
258
259
|
runId: node.runId,
|
|
259
260
|
intent: node.intent,
|
|
260
261
|
eventId: node.eventId,
|