@opengeni/react 0.23.0 → 0.25.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/{chunk-UQS7OQDE.js → chunk-F4CFWKVI.js} +334 -64
  2. package/dist/chunk-F4CFWKVI.js.map +1 -0
  3. package/dist/chunk-GQN2QIR2.js +3767 -0
  4. package/dist/chunk-GQN2QIR2.js.map +1 -0
  5. package/dist/{chunk-I3BJZIG5.js → chunk-HIWPQYWI.js} +2 -120
  6. package/dist/chunk-HIWPQYWI.js.map +1 -0
  7. package/dist/chunk-M7X4JZOD.js +121 -0
  8. package/dist/chunk-M7X4JZOD.js.map +1 -0
  9. package/dist/{chunk-UAHPKLB6.js → chunk-MP6237JB.js} +571 -975
  10. package/dist/chunk-MP6237JB.js.map +1 -0
  11. package/dist/chunk-OZDLELJQ.js +937 -0
  12. package/dist/chunk-OZDLELJQ.js.map +1 -0
  13. package/dist/{chunk-CATATY77.js → chunk-TMH6HZWF.js} +8 -7
  14. package/dist/chunk-TMH6HZWF.js.map +1 -0
  15. package/dist/{chunk-6XUS5VFM.js → chunk-YU5PGUK7.js} +6 -4
  16. package/dist/{chunk-6XUS5VFM.js.map → chunk-YU5PGUK7.js.map} +1 -1
  17. package/dist/{composer-CVm5uoUI.d.ts → composer-DoC4veX1.d.ts} +6 -63
  18. package/dist/composer.d.ts +3 -2
  19. package/dist/composer.js +4 -3
  20. package/dist/fleet-decision-projection-SLNZMS42.js +241 -0
  21. package/dist/fleet-decision-projection-SLNZMS42.js.map +1 -0
  22. package/dist/fleet-decision-row-GGCAT4E4.js +351 -0
  23. package/dist/fleet-decision-row-GGCAT4E4.js.map +1 -0
  24. package/dist/index.d.ts +17 -259
  25. package/dist/index.js +1042 -5058
  26. package/dist/index.js.map +1 -1
  27. package/dist/machines.js +3 -2
  28. package/dist/session-Du_FsrZ1.d.ts +264 -0
  29. package/dist/session-ui-BqQDH7YV.d.ts +183 -0
  30. package/dist/session-ui.d.ts +7 -0
  31. package/dist/session-ui.js +17 -0
  32. package/dist/session-ui.js.map +1 -0
  33. package/dist/session.d.ts +4 -2
  34. package/dist/session.js +26 -9
  35. package/dist/{use-composer-By1wn3MM.d.ts → use-composer-BnEzheSk.d.ts} +8 -2
  36. package/dist/use-file-attachments-C0kpHrs9.d.ts +76 -0
  37. package/dist/use-turn-queue-3rkJwjFv.d.ts +290 -0
  38. package/package.json +6 -2
  39. package/src/components/composer.tsx +7 -6
  40. package/src/components/message-timeline.tsx +94 -54
  41. package/src/hooks/use-composer.ts +470 -73
  42. package/src/hooks/use-file-attachments.ts +96 -3
  43. package/src/hooks/use-goal.ts +23 -5
  44. package/src/hooks/use-session-events.ts +5 -0
  45. package/src/hooks/use-session-lineage.ts +1 -1
  46. package/src/hooks/use-session.ts +9 -6
  47. package/src/hooks/use-workspace-sessions.ts +30 -5
  48. package/src/session-ui.ts +13 -0
  49. package/src/session.ts +15 -0
  50. package/src/timeline/activity-rail.tsx +18 -2
  51. package/src/timeline/fleet-decision-projection.ts +366 -0
  52. package/src/timeline/fleet-decision-row.tsx +412 -0
  53. package/src/timeline/index.ts +2 -0
  54. package/src/timeline/projection.ts +19 -8
  55. package/src/timeline/tool-display-name.ts +16 -0
  56. package/src/timeline/tool-renderers.tsx +1 -1
  57. package/src/timeline/types.ts +68 -1
  58. package/dist/chunk-CATATY77.js.map +0 -1
  59. package/dist/chunk-I3BJZIG5.js.map +0 -1
  60. package/dist/chunk-UAHPKLB6.js.map +0 -1
  61. package/dist/chunk-UQS7OQDE.js.map +0 -1
  62. package/dist/session-Db00TRwl.d.ts +0 -446
@@ -0,0 +1,937 @@
1
+ import {
2
+ CREDIT_EXHAUSTION_MESSAGE,
3
+ humanizeFailureReason,
4
+ isCreditExhaustion,
5
+ tryParseJson
6
+ } from "./chunk-M7X4JZOD.js";
7
+
8
+ // src/timeline/projection.ts
9
+ var { default: fleetDecisionItem } = await import("./fleet-decision-projection-SLNZMS42.js");
10
+ function toolDisplayName(name) {
11
+ const boundary = name.indexOf("__");
12
+ const toolPart = boundary >= 0 ? name.slice(boundary + 2) : name;
13
+ return toolPart.replace(/[_-]+/g, " ").trim();
14
+ }
15
+ var WORKER_SPAWN_TOOL = "session_create";
16
+ var WORKER_MESSAGE_TOOL = "session_send_message";
17
+ function buildTimeline(events) {
18
+ const items = [];
19
+ const prescan = prescanTurnAnchors(events);
20
+ const ordered = orderTimelineEvents(events, prescan);
21
+ const last = () => items[items.length - 1];
22
+ const closeStreamingTail = () => {
23
+ const open = last();
24
+ if ((open?.kind === "agent-message" || open?.kind === "reasoning") && open.streaming) {
25
+ open.streaming = false;
26
+ }
27
+ };
28
+ const finalizeOpen = (turnId, disposition = "complete") => {
29
+ for (const item of items) {
30
+ if (turnId !== void 0 && "turnId" in item && item.turnId && turnId && item.turnId !== turnId) {
31
+ continue;
32
+ }
33
+ if ((item.kind === "agent-message" || item.kind === "reasoning") && item.streaming) {
34
+ item.streaming = false;
35
+ }
36
+ if ((item.kind === "tool-call" || item.kind === "worker") && item.status === "running") {
37
+ item.status = disposition;
38
+ }
39
+ if (item.kind === "sandbox" && item.status === "running") {
40
+ item.status = disposition;
41
+ }
42
+ }
43
+ };
44
+ for (const event of ordered) {
45
+ const payload = asRecord(event.payload);
46
+ const turnId = event.turnId ?? null;
47
+ switch (event.type) {
48
+ case "user.message": {
49
+ closeStreamingTail();
50
+ const childCompletion = workerCompletionPayload(payload.childCompletion);
51
+ if (childCompletion) {
52
+ items.push({
53
+ kind: "worker-completion",
54
+ id: event.id,
55
+ turnId,
56
+ occurredAt: event.occurredAt,
57
+ childSessionId: childCompletion.childSessionId,
58
+ childStatus: childCompletion.childStatus,
59
+ goalStatus: childCompletion.goalStatus,
60
+ goalText: childCompletion.goalText,
61
+ evidence: childCompletion.evidence,
62
+ pausedReason: childCompletion.pausedReason,
63
+ text: typeof payload.text === "string" ? payload.text : ""
64
+ });
65
+ break;
66
+ }
67
+ items.push({
68
+ kind: "user-message",
69
+ id: event.id,
70
+ text: typeof payload.text === "string" ? payload.text : "",
71
+ resources: resourceRefs(payload.resources),
72
+ tools: toolRefs(payload.tools),
73
+ occurredAt: event.occurredAt
74
+ });
75
+ break;
76
+ }
77
+ case "agent.message.delta": {
78
+ const text = typeof payload.text === "string" ? payload.text : "";
79
+ if (!text) {
80
+ break;
81
+ }
82
+ const open = last();
83
+ if (open?.kind === "agent-message" && open.streaming && open.turnId === turnId) {
84
+ open.text += text;
85
+ break;
86
+ }
87
+ closeStreamingTail();
88
+ items.push({
89
+ kind: "agent-message",
90
+ id: event.id,
91
+ turnId,
92
+ text,
93
+ streaming: true,
94
+ occurredAt: event.occurredAt
95
+ });
96
+ break;
97
+ }
98
+ case "agent.message.completed": {
99
+ const text = typeof payload.text === "string" ? payload.text : "";
100
+ const open = [...items].reverse().find(
101
+ (item) => item.kind === "agent-message" && item.turnId === turnId
102
+ );
103
+ if (open && (open.streaming || !open.text || text === open.text || text.startsWith(open.text))) {
104
+ if (!open.text || text && text.startsWith(open.text)) {
105
+ open.text = text || open.text;
106
+ }
107
+ open.streaming = false;
108
+ break;
109
+ }
110
+ if (text) {
111
+ items.push({
112
+ kind: "agent-message",
113
+ id: event.id,
114
+ turnId,
115
+ text,
116
+ streaming: false,
117
+ occurredAt: event.occurredAt
118
+ });
119
+ }
120
+ break;
121
+ }
122
+ case "agent.reasoning.delta": {
123
+ const text = reasoningText(event.payload);
124
+ if (!text) {
125
+ break;
126
+ }
127
+ const open = last();
128
+ if (open?.kind === "reasoning" && open.streaming && open.turnId === turnId) {
129
+ open.text += text;
130
+ break;
131
+ }
132
+ closeStreamingTail();
133
+ items.push({
134
+ kind: "reasoning",
135
+ id: event.id,
136
+ turnId,
137
+ text,
138
+ streaming: true,
139
+ occurredAt: event.occurredAt
140
+ });
141
+ break;
142
+ }
143
+ case "agent.toolCall.created": {
144
+ const name = typeof payload.name === "string" ? payload.name : "tool";
145
+ const callId = typeof payload.id === "string" ? payload.id : null;
146
+ const args = payload.arguments ?? null;
147
+ closeStreamingTail();
148
+ if (name === WORKER_SPAWN_TOOL || name === WORKER_MESSAGE_TOOL) {
149
+ items.push({
150
+ kind: "worker",
151
+ id: event.id,
152
+ turnId,
153
+ callId,
154
+ action: name === WORKER_SPAWN_TOOL ? "spawn" : "message",
155
+ prompt: workerPrompt(args),
156
+ workerSessionId: extractSessionRef(args),
157
+ status: "running",
158
+ occurredAt: event.occurredAt
159
+ });
160
+ break;
161
+ }
162
+ items.push({
163
+ kind: "tool-call",
164
+ id: event.id,
165
+ turnId,
166
+ callId,
167
+ name,
168
+ arguments: args,
169
+ output: void 0,
170
+ // The provider-native item drives the per-tool renderers (apply_patch
171
+ // operation, computer_call action, web_search providerData, …).
172
+ raw: payload.raw,
173
+ status: "running",
174
+ occurredAt: event.occurredAt
175
+ });
176
+ break;
177
+ }
178
+ case "agent.toolCall.output": {
179
+ const callId = typeof payload.id === "string" ? payload.id : null;
180
+ const target = findOpenCall(items, callId);
181
+ if (!target) {
182
+ break;
183
+ }
184
+ if (target.kind === "worker") {
185
+ target.status = isErrorOutput(payload) ? "failed" : "complete";
186
+ target.workerSessionId = target.workerSessionId ?? extractSessionRef(payload.output);
187
+ break;
188
+ }
189
+ target.status = isErrorOutput(payload) ? "failed" : "complete";
190
+ target.output = payload.output;
191
+ break;
192
+ }
193
+ case "sandbox.operation.started":
194
+ case "sandbox.operation.completed":
195
+ case "sandbox.operation.failed": {
196
+ const name = typeof payload.name === "string" ? payload.name : "sandbox";
197
+ const status = event.type.endsWith(".failed") ? "failed" : event.type.endsWith(".completed") ? "complete" : "running";
198
+ if ((name === "repository-clone" || name === "file-resource-download") && status !== "failed") {
199
+ break;
200
+ }
201
+ const existing = findOpenSandbox(items, name);
202
+ if (existing && status !== "running") {
203
+ existing.status = status;
204
+ if (payload.origin === "created" || payload.origin === "restored" || payload.origin === "resumed") {
205
+ existing.origin = payload.origin;
206
+ }
207
+ const message = failureMessage(payload);
208
+ if (message) {
209
+ existing.output = existing.output ? `${existing.output}
210
+ ${message}` : message;
211
+ }
212
+ break;
213
+ }
214
+ if (!existing) {
215
+ closeStreamingTail();
216
+ items.push({
217
+ kind: "sandbox",
218
+ id: event.id,
219
+ turnId,
220
+ name,
221
+ command: typeof payload.command === "string" ? payload.command : null,
222
+ output: failureMessage(payload) ?? "",
223
+ origin: payload.origin === "created" || payload.origin === "restored" || payload.origin === "resumed" ? payload.origin : null,
224
+ status,
225
+ occurredAt: event.occurredAt
226
+ });
227
+ }
228
+ break;
229
+ }
230
+ case "sandbox.command.output.delta": {
231
+ const text = typeof payload.chunk === "string" ? payload.chunk : typeof payload.text === "string" ? payload.text : typeof payload.output === "string" ? payload.output : "";
232
+ if (!text) {
233
+ break;
234
+ }
235
+ const open = (typeof payload.name === "string" ? findOpenSandbox(items, payload.name) : void 0) ?? [...items].reverse().find(
236
+ (item) => item.kind === "sandbox" && item.status === "running"
237
+ );
238
+ if (open) {
239
+ open.output += text;
240
+ }
241
+ break;
242
+ }
243
+ case "session.status.changed": {
244
+ const status = payload.status;
245
+ if (!isSessionStatus(status)) {
246
+ break;
247
+ }
248
+ if (!ATTENTION_STATUSES.has(status)) {
249
+ break;
250
+ }
251
+ const previous = [...items].reverse().find((item) => item.kind === "session-status");
252
+ if (previous?.status === status) {
253
+ break;
254
+ }
255
+ items.push({ kind: "session-status", id: event.id, status, occurredAt: event.occurredAt });
256
+ break;
257
+ }
258
+ case "session.requiresAction": {
259
+ finalizeOpen(turnId);
260
+ items.push({
261
+ kind: "notice",
262
+ id: event.id,
263
+ tone: "waiting",
264
+ text: "Approval needed \u2014 the turn is paused until someone decides.",
265
+ occurredAt: event.occurredAt
266
+ });
267
+ break;
268
+ }
269
+ case "session.context.compacted": {
270
+ closeStreamingTail();
271
+ const before = typeof payload.estimatedTokensBefore === "number" ? Math.round(payload.estimatedTokensBefore).toLocaleString("en-US") : null;
272
+ const after = typeof payload.estimatedTokensAfter === "number" ? Math.round(payload.estimatedTokensAfter).toLocaleString("en-US") : null;
273
+ items.push({
274
+ kind: "notice",
275
+ id: event.id,
276
+ tone: "waiting",
277
+ text: before && after ? `Active conversation history compacted from approximately ${before} to ${after} tokens.` : "Context compacted so the turn could continue.",
278
+ occurredAt: event.occurredAt
279
+ });
280
+ break;
281
+ }
282
+ case "session.context.compaction.skipped": {
283
+ closeStreamingTail();
284
+ const reason = typeof payload.reason === "string" ? payload.reason : null;
285
+ items.push({
286
+ kind: "notice",
287
+ id: event.id,
288
+ tone: reason === "summarization_failed" ? "failed" : "waiting",
289
+ text: reason === "no_history" ? "Context compaction skipped because there is no active history to compact." : reason === "replacement_not_smaller" ? "Context compaction skipped because the generated checkpoint would not reduce the context." : reason === "replacement_unchanged" ? "Context compaction stopped because it reproduced the same checkpoint without making progress." : reason === "summarization_failed" ? "Context compaction failed without replacing the active conversation history. Request it again to retry." : "Context compaction was not needed.",
290
+ occurredAt: event.occurredAt
291
+ });
292
+ break;
293
+ }
294
+ case "turn.recovery.requested": {
295
+ break;
296
+ }
297
+ case "turn.event.rejected_late": {
298
+ break;
299
+ }
300
+ case "tool.auth_needed":
301
+ case "credential.auth_needed": {
302
+ closeStreamingTail();
303
+ items.push({
304
+ kind: "auth-needed",
305
+ id: event.id,
306
+ turnId,
307
+ providerDomain: typeof payload.providerDomain === "string" ? payload.providerDomain : "",
308
+ connectionId: typeof payload.connectionId === "string" ? payload.connectionId : null,
309
+ reason: authNeededReason(payload.reason),
310
+ scopes: stringList(payload.scopes),
311
+ resource: typeof payload.resource === "string" ? payload.resource : null,
312
+ toolName: typeof payload.toolName === "string" ? payload.toolName : null,
313
+ authorizationUrl: typeof payload.authorizationUrl === "string" ? payload.authorizationUrl : null,
314
+ occurredAt: event.occurredAt
315
+ });
316
+ break;
317
+ }
318
+ case "turn.completed": {
319
+ if (payload.maintenance === "context_compaction") {
320
+ finalizeOpen(turnId);
321
+ break;
322
+ }
323
+ if (isCreditExhaustionPayload(payload)) {
324
+ finalizeOpen(turnId);
325
+ items.push(turnEndItem(event, "failed", CREDIT_EXHAUSTION_MESSAGE));
326
+ items.push({
327
+ kind: "notice",
328
+ id: event.id,
329
+ tone: "failed",
330
+ text: CREDIT_EXHAUSTION_MESSAGE,
331
+ occurredAt: event.occurredAt
332
+ });
333
+ break;
334
+ }
335
+ finalizeOpen(turnId);
336
+ items.push(turnEndItem(event, "complete", null));
337
+ break;
338
+ }
339
+ case "turn.failed": {
340
+ const hadActivity = hasTurnActivity(items, turnId);
341
+ const failureText = isCreditExhaustionPayload(payload) ? CREDIT_EXHAUSTION_MESSAGE : failureMessage(payload);
342
+ finalizeOpen(turnId, "cancelled");
343
+ items.push(turnEndItem(event, "failed", failureText));
344
+ if (!hadActivity) {
345
+ items.push({
346
+ kind: "notice",
347
+ id: event.id,
348
+ tone: "failed",
349
+ text: failureText ?? "The turn failed.",
350
+ occurredAt: event.occurredAt
351
+ });
352
+ }
353
+ break;
354
+ }
355
+ case "turn.cancelled": {
356
+ if (turnId && !prescan.startedTurnIds.has(turnId)) {
357
+ break;
358
+ }
359
+ const hadActivity = hasTurnActivity(items, turnId);
360
+ finalizeOpen(turnId, "cancelled");
361
+ items.push(turnEndItem(event, "cancelled", null));
362
+ if (!hadActivity) {
363
+ items.push({
364
+ kind: "notice",
365
+ id: event.id,
366
+ tone: "cancelled",
367
+ text: "Interrupted.",
368
+ occurredAt: event.occurredAt
369
+ });
370
+ }
371
+ break;
372
+ }
373
+ case "memory.saved":
374
+ case "memory.corrected": {
375
+ const memory = memoryItem(event.id, event.type, turnId, payload, event.occurredAt);
376
+ if (memory) {
377
+ closeStreamingTail();
378
+ items.push(memory);
379
+ }
380
+ break;
381
+ }
382
+ case "codex.fleet.decision": {
383
+ const decision = fleetDecisionItem(event, payload);
384
+ if (decision) {
385
+ closeStreamingTail();
386
+ items.push(decision);
387
+ }
388
+ break;
389
+ }
390
+ case "goal.set":
391
+ case "goal.updated":
392
+ case "goal.completed":
393
+ case "goal.paused":
394
+ case "goal.resumed":
395
+ case "goal.cleared":
396
+ case "goal.continuation": {
397
+ items.push({
398
+ kind: "goal",
399
+ id: event.id,
400
+ action: event.type.slice("goal.".length),
401
+ text: goalText(payload),
402
+ occurredAt: event.occurredAt
403
+ });
404
+ break;
405
+ }
406
+ default:
407
+ break;
408
+ }
409
+ }
410
+ return items;
411
+ }
412
+ function isCreditExhaustionPayload(payload) {
413
+ return isCreditExhaustion({
414
+ error: typeof payload.error === "string" ? payload.error : null,
415
+ detail: typeof payload.detail === "string" ? payload.detail : null,
416
+ segmentLimit: typeof payload.segmentLimit === "string" ? payload.segmentLimit : null
417
+ });
418
+ }
419
+ function creditExhaustedFromEvents(events) {
420
+ const ordered = [...events].sort((a, b) => a.sequence - b.sequence);
421
+ for (let index = ordered.length - 1; index >= 0; index -= 1) {
422
+ const event = ordered[index];
423
+ if (event?.type !== "turn.completed" && event?.type !== "turn.failed" && event?.type !== "turn.cancelled") {
424
+ continue;
425
+ }
426
+ return isCreditExhaustionPayload(asRecord(event.payload));
427
+ }
428
+ return false;
429
+ }
430
+ function sessionStatusFromEvents(events) {
431
+ for (let index = events.length - 1; index >= 0; index -= 1) {
432
+ const event = events[index];
433
+ if (event?.type !== "session.status.changed") {
434
+ continue;
435
+ }
436
+ const status = asRecord(event.payload).status;
437
+ if (isSessionStatus(status)) {
438
+ return status;
439
+ }
440
+ }
441
+ return null;
442
+ }
443
+ function isActivityItem(item) {
444
+ switch (item.kind) {
445
+ case "reasoning":
446
+ case "tool-call":
447
+ case "worker":
448
+ case "sandbox":
449
+ case "memory":
450
+ case "fleet-decision":
451
+ return true;
452
+ default:
453
+ return false;
454
+ }
455
+ }
456
+ function groupTimeline(items) {
457
+ const groups = [];
458
+ for (const item of items) {
459
+ if (isActivityItem(item)) {
460
+ const open = groups[groups.length - 1];
461
+ if (open?.kind === "activity" && open.outcome === void 0) {
462
+ open.items.push(item);
463
+ } else {
464
+ groups.push({ kind: "activity", id: `activity-${item.id}`, items: [item] });
465
+ }
466
+ continue;
467
+ }
468
+ if (item.kind === "turn-end") {
469
+ stampTurnOutcome(groups, item);
470
+ foldSettledTurn(groups, item);
471
+ continue;
472
+ }
473
+ groups.push({ kind: "item", item });
474
+ }
475
+ return groups;
476
+ }
477
+ function prescanTurnAnchors(events) {
478
+ const ordered = [...events].sort((a, b) => a.sequence - b.sequence);
479
+ const queuedTurnByTrigger = /* @__PURE__ */ new Map();
480
+ const startSeqByTrigger = /* @__PURE__ */ new Map();
481
+ const cancelledTurnIds = /* @__PURE__ */ new Set();
482
+ const fallbackSeqByTurn = /* @__PURE__ */ new Map();
483
+ const startedTurnIds = /* @__PURE__ */ new Set();
484
+ for (const event of ordered) {
485
+ const payload = asRecord(event.payload);
486
+ const turnId = event.turnId ?? null;
487
+ if (event.type === "turn.queued") {
488
+ const triggerEventId = typeof payload.triggerEventId === "string" ? payload.triggerEventId : null;
489
+ const queuedTurnId = typeof payload.turnId === "string" ? payload.turnId : turnId;
490
+ if (triggerEventId && queuedTurnId) {
491
+ queuedTurnByTrigger.set(triggerEventId, queuedTurnId);
492
+ }
493
+ continue;
494
+ }
495
+ if (event.type === "turn.started") {
496
+ const triggerEventId = typeof payload.triggerEventId === "string" ? payload.triggerEventId : null;
497
+ if (triggerEventId && !startSeqByTrigger.has(triggerEventId)) {
498
+ startSeqByTrigger.set(triggerEventId, event.sequence);
499
+ }
500
+ if (turnId) {
501
+ startedTurnIds.add(turnId);
502
+ }
503
+ } else if (event.type === "turn.cancelled" && turnId) {
504
+ cancelledTurnIds.add(turnId);
505
+ }
506
+ if (turnId && isTurnExecutionEvidence(event.type)) {
507
+ const previous = fallbackSeqByTurn.get(turnId);
508
+ if (previous === void 0 || event.sequence < previous) {
509
+ fallbackSeqByTurn.set(turnId, event.sequence);
510
+ }
511
+ }
512
+ if (turnId && isTurnExecutionEvidence(event.type)) {
513
+ startedTurnIds.add(turnId);
514
+ }
515
+ }
516
+ for (const [triggerEventId, turnId] of queuedTurnByTrigger) {
517
+ if (!startSeqByTrigger.has(triggerEventId)) {
518
+ const fallbackSeq = fallbackSeqByTurn.get(turnId);
519
+ if (fallbackSeq !== void 0) {
520
+ startSeqByTrigger.set(triggerEventId, fallbackSeq);
521
+ }
522
+ }
523
+ }
524
+ const cancelledBeforeStartTriggers = /* @__PURE__ */ new Set();
525
+ for (const [triggerEventId, turnId] of queuedTurnByTrigger) {
526
+ if (cancelledTurnIds.has(turnId) && !startSeqByTrigger.has(triggerEventId) && !fallbackSeqByTurn.has(turnId)) {
527
+ cancelledBeforeStartTriggers.add(triggerEventId);
528
+ }
529
+ }
530
+ return { queuedTurnByTrigger, startSeqByTrigger, cancelledBeforeStartTriggers, startedTurnIds };
531
+ }
532
+ function orderTimelineEvents(events, prescan) {
533
+ const ordered = [...events].sort((a, b) => a.sequence - b.sequence);
534
+ const insertions = /* @__PURE__ */ new Map();
535
+ for (const event of ordered) {
536
+ if (event.type !== "user.message") {
537
+ continue;
538
+ }
539
+ const queuedTurnId = prescan.queuedTurnByTrigger.get(event.id);
540
+ if (!queuedTurnId) {
541
+ pushInsertion(insertions, event.sequence, event);
542
+ continue;
543
+ }
544
+ if (prescan.cancelledBeforeStartTriggers.has(event.id)) {
545
+ continue;
546
+ }
547
+ const startSeq = prescan.startSeqByTrigger.get(event.id);
548
+ if (startSeq !== void 0) {
549
+ pushInsertion(insertions, startSeq, event);
550
+ continue;
551
+ }
552
+ }
553
+ const projected = [];
554
+ for (const event of ordered) {
555
+ const before = insertions.get(event.sequence);
556
+ if (before) {
557
+ projected.push(...before);
558
+ }
559
+ if (event.type !== "user.message") {
560
+ projected.push(event);
561
+ }
562
+ }
563
+ return projected;
564
+ }
565
+ function pushInsertion(insertions, sequence, event) {
566
+ const bucket = insertions.get(sequence);
567
+ if (bucket) {
568
+ bucket.push(event);
569
+ } else {
570
+ insertions.set(sequence, [event]);
571
+ }
572
+ }
573
+ function isAgentActivityEvent(type) {
574
+ return type.startsWith("agent.") || type.startsWith("sandbox.");
575
+ }
576
+ function isTurnExecutionEvidence(type) {
577
+ return isAgentActivityEvent(type) || type === "turn.completed" || type === "turn.failed" || type === "turn.recovery.requested" || type === "turn.capacity_waiting" || type === "session.requiresAction" || type === "tool.auth_needed" || type === "credential.auth_needed" || type.startsWith("rig.setup.") || type === "codex.capacity.waiting" || type === "codex.capacity.resumed" || type === "codex.fleet.decision";
578
+ }
579
+ function turnEndItem(event, outcome, failureText) {
580
+ return {
581
+ kind: "turn-end",
582
+ id: `${event.id}-turn-end`,
583
+ turnId: event.turnId ?? null,
584
+ outcome,
585
+ failureText,
586
+ occurredAt: event.occurredAt
587
+ };
588
+ }
589
+ function hasTurnActivity(items, turnId) {
590
+ if (turnId) {
591
+ return items.some((item) => isActivityItem(item) && item.turnId === turnId);
592
+ }
593
+ for (let index = items.length - 1; index >= 0; index -= 1) {
594
+ const item = items[index];
595
+ if (!item || item.kind === "turn-end" || item.kind === "user-message") {
596
+ return false;
597
+ }
598
+ if (isActivityItem(item)) {
599
+ return true;
600
+ }
601
+ }
602
+ return false;
603
+ }
604
+ function stampTurnOutcome(groups, turnEnd) {
605
+ if (turnEnd.turnId === null) {
606
+ const trailing = groups[groups.length - 1];
607
+ if (trailing?.kind === "activity" && trailing.outcome === void 0) {
608
+ applyTurnOutcome(trailing, turnEnd);
609
+ }
610
+ return;
611
+ }
612
+ for (const group of groups) {
613
+ if (group.kind !== "activity" || group.outcome !== void 0) {
614
+ continue;
615
+ }
616
+ if (group.items.some((activity) => activity.turnId === turnEnd.turnId)) {
617
+ applyTurnOutcome(group, turnEnd);
618
+ }
619
+ }
620
+ }
621
+ function applyTurnOutcome(group, turnEnd) {
622
+ if (turnEnd.outcome === "complete") {
623
+ group.outcome = "complete";
624
+ return;
625
+ }
626
+ const hasFailed = group.items.some((item) => "status" in item && item.status === "failed");
627
+ const hasInterrupted = group.items.some(
628
+ (item) => "status" in item && item.status === "cancelled"
629
+ );
630
+ group.outcome = hasFailed ? "failed" : hasInterrupted ? "cancelled" : "complete";
631
+ if (turnEnd.failureText && hasFailed) {
632
+ group.failureText = turnEnd.failureText;
633
+ }
634
+ }
635
+ function foldSettledTurn(groups, turnEnd) {
636
+ let startIndex = groups.length;
637
+ let stoppedAtForeignTurn = false;
638
+ while (startIndex > 0) {
639
+ const previous = groups[startIndex - 1];
640
+ if (isTurnBoundary(previous)) {
641
+ break;
642
+ }
643
+ if (belongsToDifferentTurn(previous, turnEnd.turnId)) {
644
+ stoppedAtForeignTurn = true;
645
+ break;
646
+ }
647
+ startIndex -= 1;
648
+ }
649
+ if (stoppedAtForeignTurn) {
650
+ while (startIndex < groups.length && isBetweenTurnDivider(groups[startIndex])) {
651
+ startIndex += 1;
652
+ }
653
+ }
654
+ const collected = groups.slice(startIndex);
655
+ if (collected.length === 0) {
656
+ return;
657
+ }
658
+ const finalMessage = extractFinalAgentMessage(collected, turnEnd);
659
+ const body = finalMessage ? collected.slice(0, -1) : collected;
660
+ if (body.length === 0) {
661
+ return;
662
+ }
663
+ const firstOccurredAt = groupStartedAt(body[0]) ?? turnEnd.occurredAt;
664
+ const turnGroup = {
665
+ kind: "turn",
666
+ id: `turn-${turnEnd.turnId ?? turnEnd.id}`,
667
+ outcome: turnEnd.outcome,
668
+ startedAt: firstOccurredAt,
669
+ endedAt: turnEnd.occurredAt,
670
+ groups: body
671
+ };
672
+ if (turnEnd.failureText) {
673
+ turnGroup.failureText = turnEnd.failureText;
674
+ }
675
+ groups.splice(
676
+ startIndex,
677
+ collected.length,
678
+ ...finalMessage ? [turnGroup, finalMessage] : [turnGroup]
679
+ );
680
+ }
681
+ function isTurnBoundary(group) {
682
+ return group?.kind === "turn" || group?.kind === "item" && group.item.kind === "user-message";
683
+ }
684
+ function belongsToDifferentTurn(group, turnId) {
685
+ if (!group || !turnId) {
686
+ return false;
687
+ }
688
+ if (group.kind === "activity") {
689
+ return group.items.length > 0 && group.items.every((item) => item.turnId !== null && item.turnId !== turnId);
690
+ }
691
+ return group.kind === "item" && group.item.kind === "agent-message" && group.item.turnId !== null && group.item.turnId !== turnId;
692
+ }
693
+ function isBetweenTurnDivider(group) {
694
+ return group?.kind === "item" && group.item.kind === "session-status" && group.item.status !== "running";
695
+ }
696
+ function extractFinalAgentMessage(groups, turnEnd) {
697
+ const tail = groups[groups.length - 1];
698
+ if (tail?.kind !== "item" || tail.item.kind !== "agent-message" || tail.item.streaming) {
699
+ return null;
700
+ }
701
+ if (tail.item.turnId && turnEnd.turnId && tail.item.turnId !== turnEnd.turnId) {
702
+ return null;
703
+ }
704
+ return tail;
705
+ }
706
+ function groupStartedAt(group) {
707
+ if (!group) {
708
+ return void 0;
709
+ }
710
+ switch (group.kind) {
711
+ case "item":
712
+ return group.item.occurredAt;
713
+ case "activity":
714
+ return group.items[0]?.occurredAt;
715
+ case "turn":
716
+ return group.startedAt;
717
+ }
718
+ }
719
+ function asRecord(value) {
720
+ return value !== null && typeof value === "object" ? value : {};
721
+ }
722
+ var SESSION_STATUSES = [
723
+ "queued",
724
+ "running",
725
+ "idle",
726
+ "requires_action",
727
+ "failed",
728
+ "cancelled"
729
+ ];
730
+ var ATTENTION_STATUSES = /* @__PURE__ */ new Set([
731
+ "requires_action",
732
+ "failed",
733
+ "cancelled"
734
+ ]);
735
+ function resourceRefs(value) {
736
+ if (!Array.isArray(value)) {
737
+ return [];
738
+ }
739
+ return value.filter((entry) => {
740
+ const record = asRecord(entry);
741
+ if (record.kind === "repository") {
742
+ return typeof record.uri === "string" && typeof record.ref === "string";
743
+ }
744
+ return record.kind === "file" && typeof record.fileId === "string";
745
+ });
746
+ }
747
+ function toolRefs(value) {
748
+ if (!Array.isArray(value)) {
749
+ return [];
750
+ }
751
+ return value.filter((entry) => {
752
+ const record = asRecord(entry);
753
+ return record.kind === "mcp" && typeof record.id === "string";
754
+ });
755
+ }
756
+ function workerCompletionPayload(value) {
757
+ const payload = asRecord(value);
758
+ const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
759
+ if (typeof payload.childSessionId !== "string" || !uuidPattern.test(payload.childSessionId) || typeof payload.status !== "string" || payload.status.trim() === "") {
760
+ return null;
761
+ }
762
+ const goal = asRecord(payload.goal);
763
+ return {
764
+ childSessionId: payload.childSessionId,
765
+ childStatus: payload.status,
766
+ goalStatus: typeof goal.status === "string" ? goal.status : null,
767
+ goalText: typeof goal.text === "string" ? goal.text : null,
768
+ evidence: typeof goal.evidence === "string" ? goal.evidence : null,
769
+ // Console pauses and several server paths put the human explanation on
770
+ // `rationale`, not `pausedReason` — same fallback the goal pill uses, so a
771
+ // paused worker card never shows "Worker paused" with the reason missing.
772
+ pausedReason: typeof goal.pausedReason === "string" ? goal.pausedReason : typeof goal.rationale === "string" ? goal.rationale : null
773
+ };
774
+ }
775
+ function isSessionStatus(value) {
776
+ return typeof value === "string" && SESSION_STATUSES.includes(value);
777
+ }
778
+ function isErrorOutput(payload) {
779
+ if (payload.error === true || payload.failed === true) {
780
+ return true;
781
+ }
782
+ const output = payload.output;
783
+ return !!output && typeof output === "object" && output.isError === true;
784
+ }
785
+ function findOpenCall(items, callId) {
786
+ const reversed = [...items].reverse();
787
+ const isCall = (item) => item.kind === "tool-call" || item.kind === "worker";
788
+ if (callId) {
789
+ const byId = reversed.find((item) => isCall(item) && item.callId === callId);
790
+ if (byId) {
791
+ return byId;
792
+ }
793
+ }
794
+ return reversed.find(
795
+ (item) => isCall(item) && item.status === "running"
796
+ );
797
+ }
798
+ function findOpenSandbox(items, name) {
799
+ return [...items].reverse().find(
800
+ (item) => item.kind === "sandbox" && item.name === name && item.status === "running"
801
+ );
802
+ }
803
+ function failureMessage(payload) {
804
+ for (const key of ["error", "message"]) {
805
+ const value = payload[key];
806
+ if (typeof value === "string" && value.trim().length > 0) {
807
+ return humanizeFailureReason(value);
808
+ }
809
+ }
810
+ return null;
811
+ }
812
+ function goalText(payload) {
813
+ if (typeof payload.text === "string" && payload.text) {
814
+ return payload.text;
815
+ }
816
+ const goal = asRecord(payload.goal);
817
+ if (typeof goal.text === "string" && goal.text) {
818
+ return goal.text;
819
+ }
820
+ if (typeof payload.prompt === "string" && payload.prompt) {
821
+ return payload.prompt;
822
+ }
823
+ return null;
824
+ }
825
+ function memoryItem(id, type, turnId, payload, occurredAt) {
826
+ const memoryId = typeof payload.memoryId === "string" && payload.memoryId ? payload.memoryId : null;
827
+ if (!memoryId) {
828
+ return null;
829
+ }
830
+ const replacementPreview = typeof payload.replacementPreview === "string" ? payload.replacementPreview : void 0;
831
+ const replacementMemoryId = typeof payload.replacementMemoryId === "string" ? payload.replacementMemoryId : void 0;
832
+ const action = typeof payload.action === "string" ? payload.action : void 0;
833
+ return {
834
+ kind: "memory",
835
+ id,
836
+ turnId,
837
+ variant: type === "memory.corrected" ? "corrected" : "saved",
838
+ memoryKind: typeof payload.kind === "string" ? payload.kind : "",
839
+ preview: typeof payload.preview === "string" ? payload.preview : "",
840
+ ...payload.deduped === true ? { deduped: true } : {},
841
+ ...replacementPreview ? { replacementPreview } : {},
842
+ ...action ? { action } : {},
843
+ memoryId,
844
+ ...replacementMemoryId ? { replacementMemoryId } : {},
845
+ occurredAt
846
+ };
847
+ }
848
+ var AUTH_NEEDED_REASONS = /* @__PURE__ */ new Set([
849
+ "missing_connection",
850
+ "expired",
851
+ "insufficient_scope",
852
+ "refresh_failed",
853
+ "unsupported_auth",
854
+ "resource_scope_unavailable"
855
+ ]);
856
+ function authNeededReason(value) {
857
+ return typeof value === "string" && AUTH_NEEDED_REASONS.has(value) ? value : null;
858
+ }
859
+ function stringList(value) {
860
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
861
+ }
862
+ function reasoningText(payload) {
863
+ const record = asRecord(payload);
864
+ if (typeof record.text === "string") {
865
+ return record.text;
866
+ }
867
+ const content = asRecord(asRecord(record.item).rawItem).content;
868
+ if (!Array.isArray(content)) {
869
+ return "";
870
+ }
871
+ return content.map((part) => {
872
+ const text = asRecord(part).text;
873
+ return typeof text === "string" ? text : "";
874
+ }).join("");
875
+ }
876
+ function workerPrompt(args) {
877
+ const record = asRecord(typeof args === "string" ? tryParseJson(args) : args);
878
+ for (const key of ["initialMessage", "message", "text", "prompt"]) {
879
+ const value = record[key];
880
+ if (typeof value === "string" && value.trim().length > 0) {
881
+ return value;
882
+ }
883
+ }
884
+ return null;
885
+ }
886
+ function extractSessionRef(value, depth = 0) {
887
+ if (depth > 6 || value === null || value === void 0) {
888
+ return null;
889
+ }
890
+ if (typeof value === "string") {
891
+ return extractSessionRef(tryParseJson(value), depth + 1);
892
+ }
893
+ if (Array.isArray(value)) {
894
+ for (const entry of value) {
895
+ const found = extractSessionRef(entry, depth + 1);
896
+ if (found) {
897
+ return found;
898
+ }
899
+ }
900
+ return null;
901
+ }
902
+ if (typeof value !== "object") {
903
+ return null;
904
+ }
905
+ const record = value;
906
+ if (typeof record.sessionId === "string" && looksLikeId(record.sessionId)) {
907
+ return record.sessionId;
908
+ }
909
+ if (typeof record.id === "string" && looksLikeId(record.id) && ("status" in record || "workspaceId" in record || "initialMessage" in record)) {
910
+ return record.id;
911
+ }
912
+ for (const key of ["structuredContent", "session", "result", "content"]) {
913
+ if (key in record) {
914
+ const found = extractSessionRef(record[key], depth + 1);
915
+ if (found) {
916
+ return found;
917
+ }
918
+ }
919
+ }
920
+ if (typeof record.text === "string") {
921
+ return extractSessionRef(tryParseJson(record.text), depth + 1);
922
+ }
923
+ return null;
924
+ }
925
+ function looksLikeId(value) {
926
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
927
+ }
928
+
929
+ export {
930
+ toolDisplayName,
931
+ buildTimeline,
932
+ creditExhaustedFromEvents,
933
+ sessionStatusFromEvents,
934
+ groupTimeline,
935
+ extractSessionRef
936
+ };
937
+ //# sourceMappingURL=chunk-OZDLELJQ.js.map