@opengeni/react 2.2.0-canary.0 → 2.5.0-canary.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.
Files changed (47) hide show
  1. package/README.md +9 -2
  2. package/dist/{chunk-5RZN3DD5.js → chunk-6H6S5V4Z.js} +280 -113
  3. package/dist/chunk-6H6S5V4Z.js.map +1 -0
  4. package/dist/{chunk-UOLJWT5Y.js → chunk-ATQJEWCA.js} +154 -114
  5. package/dist/chunk-ATQJEWCA.js.map +1 -0
  6. package/dist/{chunk-XSA2QAKP.js → chunk-MXJGO7LE.js} +65 -3
  7. package/dist/chunk-MXJGO7LE.js.map +1 -0
  8. package/dist/{chunk-LTCHJ4MS.js → chunk-NVREJA6V.js} +2 -2
  9. package/dist/{chunk-JOAVA2TW.js → chunk-T7VAYG2I.js} +8 -7
  10. package/dist/{chunk-JOAVA2TW.js.map → chunk-T7VAYG2I.js.map} +1 -1
  11. package/dist/components/fleet-tile.d.ts +1 -1
  12. package/dist/components/message-timeline.d.ts +7 -2
  13. package/dist/composer.js +2 -2
  14. package/dist/hooks/use-session-events.d.ts +2 -1
  15. package/dist/hooks/use-session-lineage.d.ts +4 -0
  16. package/dist/hooks/use-session.d.ts +6 -0
  17. package/dist/hooks/use-workspace-sessions.d.ts +6 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +41 -19
  20. package/dist/index.js.map +1 -1
  21. package/dist/older-history.d.ts +29 -0
  22. package/dist/session-ui.d.ts +2 -0
  23. package/dist/session-ui.js +5 -2
  24. package/dist/session.d.ts +2 -0
  25. package/dist/session.js +5 -3
  26. package/dist/timeline/types.d.ts +2 -0
  27. package/package.json +2 -2
  28. package/src/components/fleet-tile.tsx +7 -5
  29. package/src/components/human-input-form.tsx +14 -6
  30. package/src/components/message-timeline.tsx +428 -137
  31. package/src/components/tip-follow.ts +18 -7
  32. package/src/hooks/use-composer.ts +20 -6
  33. package/src/hooks/use-session-events.ts +84 -76
  34. package/src/hooks/use-session-lineage.ts +26 -8
  35. package/src/hooks/use-session.ts +35 -8
  36. package/src/hooks/use-workspace-sessions.ts +38 -13
  37. package/src/index.ts +2 -0
  38. package/src/older-history.ts +69 -0
  39. package/src/session-ui.ts +2 -0
  40. package/src/session.ts +2 -0
  41. package/src/timeline/activity-rail.tsx +1 -0
  42. package/src/timeline/projection.ts +53 -2
  43. package/src/timeline/types.ts +2 -0
  44. package/dist/chunk-5RZN3DD5.js.map +0 -1
  45. package/dist/chunk-UOLJWT5Y.js.map +0 -1
  46. package/dist/chunk-XSA2QAKP.js.map +0 -1
  47. /package/dist/{chunk-LTCHJ4MS.js.map → chunk-NVREJA6V.js.map} +0 -0
@@ -124,6 +124,7 @@ export function ActivityRail({
124
124
  <div
125
125
  key={item.id}
126
126
  data-og-timeline-row-anchor=""
127
+ data-og-item={item.id}
127
128
  data-og-annotation-source-key={
128
129
  item.kind === "tool-call" ? item.annotationSource?.eventId : undefined
129
130
  }
@@ -397,6 +397,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
397
397
 
398
398
  case "agent.message.completed": {
399
399
  const text = stringValue(payload.text);
400
+ const phase = assistantMessagePhase(payload.phase);
400
401
  // Reconcile the most recent same-turn agent message — even when
401
402
  // activity (tool calls, reasoning) landed after its deltas — so the
402
403
  // completed text never duplicates the streamed one.
@@ -420,6 +421,9 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
420
421
  open.text = text || open.text;
421
422
  }
422
423
  open.streaming = false;
424
+ // A phase-less settlement mirror (the worker's final-output receipt)
425
+ // must not erase the provider-declared phase captured by the SDK item.
426
+ if (phase) open.phase = phase;
423
427
  // Completion time is what the footer shows ("finished at"); keep the
424
428
  // first-delta stamp only until this event arrives.
425
429
  open.occurredAt = event.occurredAt;
@@ -451,6 +455,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
451
455
  id: event.id,
452
456
  turnId,
453
457
  text,
458
+ ...(phase ? { phase } : {}),
454
459
  streaming: false,
455
460
  occurredAt: event.occurredAt,
456
461
  annotationSource: {
@@ -1675,7 +1680,12 @@ function foldSettledTurn(groups: TimelineGroup[], turnEnd: TurnEndItem): void {
1675
1680
  }
1676
1681
 
1677
1682
  const finalMessage = extractFinalAgentMessage(collected, turnEnd);
1678
- const body = finalMessage ? collected.slice(0, -1) : collected;
1683
+ const fallbackMessage =
1684
+ finalMessage || hasOrdinaryFinalAgentMessage(collected, turnEnd)
1685
+ ? null
1686
+ : extractLatestCompletedCommentary(collected, turnEnd);
1687
+ const visibleMessage = finalMessage ?? fallbackMessage;
1688
+ const body = visibleMessage ? collected.filter((group) => group !== visibleMessage) : collected;
1679
1689
  if (body.length === 0) {
1680
1690
  return;
1681
1691
  }
@@ -1704,7 +1714,7 @@ function foldSettledTurn(groups: TimelineGroup[], turnEnd: TurnEndItem): void {
1704
1714
  groups.splice(
1705
1715
  startIndex,
1706
1716
  collected.length,
1707
- ...(finalMessage ? [turnGroup, finalMessage] : [turnGroup]),
1717
+ ...(visibleMessage ? [turnGroup, visibleMessage] : [turnGroup]),
1708
1718
  );
1709
1719
  }
1710
1720
 
@@ -1761,6 +1771,43 @@ function extractFinalAgentMessage(
1761
1771
  return tail;
1762
1772
  }
1763
1773
 
1774
+ function hasOrdinaryFinalAgentMessage(groups: TimelineGroup[], turnEnd: TurnEndItem): boolean {
1775
+ return groups.some((group) => {
1776
+ if (group.kind !== "item" || group.item.kind !== "agent-message") return false;
1777
+ const message = group.item;
1778
+ return (
1779
+ !message.streaming &&
1780
+ message.phase !== "commentary" &&
1781
+ message.text.trim().length > 0 &&
1782
+ belongsToTurn(message, turnEnd.turnId)
1783
+ );
1784
+ });
1785
+ }
1786
+
1787
+ function extractLatestCompletedCommentary(
1788
+ groups: TimelineGroup[],
1789
+ turnEnd: TurnEndItem,
1790
+ ): Extract<TimelineGroup, { kind: "item" }> | null {
1791
+ for (let index = groups.length - 1; index >= 0; index -= 1) {
1792
+ const group = groups[index];
1793
+ if (group?.kind !== "item" || group.item.kind !== "agent-message") continue;
1794
+ const message = group.item;
1795
+ if (
1796
+ !message.streaming &&
1797
+ message.phase === "commentary" &&
1798
+ message.text.trim().length > 0 &&
1799
+ belongsToTurn(message, turnEnd.turnId)
1800
+ ) {
1801
+ return group;
1802
+ }
1803
+ }
1804
+ return null;
1805
+ }
1806
+
1807
+ function belongsToTurn(message: AgentMessageItem, turnId: string | null): boolean {
1808
+ return !message.turnId || !turnId || message.turnId === turnId;
1809
+ }
1810
+
1764
1811
  function groupStartedAt(group: TimelineGroup | undefined): string | undefined {
1765
1812
  if (!group) {
1766
1813
  return undefined;
@@ -1783,6 +1830,10 @@ function stringValue(value: unknown): string {
1783
1830
  return typeof value === "string" ? value : "";
1784
1831
  }
1785
1832
 
1833
+ function assistantMessagePhase(value: unknown): AgentMessageItem["phase"] {
1834
+ return value === "commentary" || value === "final_answer" ? value : undefined;
1835
+ }
1836
+
1786
1837
  function numberOrNull(value: unknown): number | null {
1787
1838
  return typeof value === "number" && Number.isFinite(value) ? value : null;
1788
1839
  }
@@ -88,6 +88,8 @@ export type AgentMessageItem = {
88
88
  id: string;
89
89
  turnId: string | null;
90
90
  text: string;
91
+ /** Provider-declared assistant channel. Absent on legacy and non-Responses events. */
92
+ phase?: "commentary" | "final_answer" | undefined;
91
93
  /** Still receiving deltas (no completed/turn-end seen yet). */
92
94
  streaming: boolean;
93
95
  occurredAt: string;