@opengeni/react 6.1.0 → 7.0.0-canary.35625901699001

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 (214) hide show
  1. package/README.md +83 -2
  2. package/dist/approvals.d.ts +2 -1
  3. package/dist/artifacts-document.js +1 -1
  4. package/dist/artifacts-presentation.js +1 -1
  5. package/dist/artifacts-spreadsheet.js +1 -1
  6. package/dist/artifacts.js +3 -3
  7. package/dist/{browser-viewer-NTD6UIPR.js → browser-viewer-LGH4IP47.js} +3 -3
  8. package/dist/capability-catalog-row.d.ts +20 -0
  9. package/dist/capability-logo-fallback.d.ts +3 -0
  10. package/dist/{chunk-NOSYBS2D.js → chunk-2VHARTBL.js} +2 -1
  11. package/dist/{chunk-VRBL3F5E.js → chunk-5GAL23FF.js} +10 -2
  12. package/dist/{chunk-VRBL3F5E.js.map → chunk-5GAL23FF.js.map} +1 -1
  13. package/dist/chunk-5UONOQ3Y.js +635 -0
  14. package/dist/chunk-5UONOQ3Y.js.map +1 -0
  15. package/dist/{chunk-NYESIADM.js → chunk-AKOMC3VO.js} +3 -3
  16. package/dist/chunk-AKOMC3VO.js.map +1 -0
  17. package/dist/chunk-BRM6FVZA.js +302 -0
  18. package/dist/chunk-BRM6FVZA.js.map +1 -0
  19. package/dist/{chunk-KANFU34B.js → chunk-DBPVUGQT.js} +11 -2
  20. package/dist/chunk-DBPVUGQT.js.map +1 -0
  21. package/dist/chunk-FHIGTPME.js +1589 -0
  22. package/dist/chunk-FHIGTPME.js.map +1 -0
  23. package/dist/{chunk-5M6VTFJ5.js → chunk-GBPCZH3Y.js} +2 -2
  24. package/dist/{chunk-YBM6CQRU.js → chunk-GEN54DU5.js} +4 -4
  25. package/dist/{chunk-UMECRJRV.js → chunk-HJ5VJ4JB.js} +21 -12
  26. package/dist/chunk-HJ5VJ4JB.js.map +1 -0
  27. package/dist/{chunk-R4KRSFGA.js → chunk-IP4BUBKH.js} +3 -3
  28. package/dist/{chunk-NLTS7JHI.js → chunk-JPHDWKZE.js} +5 -5
  29. package/dist/{chunk-TDSEILUH.js → chunk-MI6ALLLD.js} +1297 -1535
  30. package/dist/chunk-MI6ALLLD.js.map +1 -0
  31. package/dist/{chunk-ICA6R6TW.js → chunk-OWHPKAOV.js} +28 -20
  32. package/dist/chunk-OWHPKAOV.js.map +1 -0
  33. package/dist/{chunk-24M4YBCL.js → chunk-PNAVEK2U.js} +4 -4
  34. package/dist/{chunk-L2NBTKRX.js → chunk-TXCBE32L.js} +203 -19
  35. package/dist/chunk-TXCBE32L.js.map +1 -0
  36. package/dist/{chunk-45XEUVTK.js → chunk-UXE5SSNN.js} +293 -463
  37. package/dist/chunk-UXE5SSNN.js.map +1 -0
  38. package/dist/{chunk-PEI6RANI.js → chunk-VR4Z73EU.js} +203 -9
  39. package/dist/chunk-VR4Z73EU.js.map +1 -0
  40. package/dist/{chunk-HUIKIDM5.js → chunk-XMXRI5JK.js} +65 -18
  41. package/dist/chunk-XMXRI5JK.js.map +1 -0
  42. package/dist/client.d.ts +1 -1
  43. package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
  44. package/dist/components/chat-composer.d.ts +13 -3
  45. package/dist/components/markdown.d.ts +6 -3
  46. package/dist/components/message-timeline.d.ts +7 -2
  47. package/dist/components/preview-loading.d.ts +2 -0
  48. package/dist/components/session-capability-frame.d.ts +24 -0
  49. package/dist/components/session-chrome.d.ts +1 -2
  50. package/dist/components/session-commands.d.ts +6 -0
  51. package/dist/components/session-connection-request.d.ts +8 -0
  52. package/dist/components/session-conversation.d.ts +3 -0
  53. package/dist/components/session-mcp-capability-card.d.ts +22 -0
  54. package/dist/components/timeline-search.d.ts +34 -0
  55. package/dist/composer.js +7 -7
  56. package/dist/connect-account-identity.d.ts +8 -0
  57. package/dist/connect-accounts.d.ts +5 -0
  58. package/dist/connect-chooser.d.ts +6 -0
  59. package/dist/connect-panel.d.ts +9 -2
  60. package/dist/connect-setup.d.ts +5 -1
  61. package/dist/connect.d.ts +5 -21
  62. package/dist/connect.js +1268 -584
  63. package/dist/connect.js.map +1 -1
  64. package/dist/connection-catalog.d.ts +6 -1
  65. package/dist/connection-discovery.d.ts +12 -0
  66. package/dist/connection-installed.d.ts +1 -0
  67. package/dist/connection-logo.d.ts +5 -2
  68. package/dist/connection-service-logo.d.ts +8 -0
  69. package/dist/connection-service-presentation.d.ts +13 -0
  70. package/dist/connection-skeleton.d.ts +5 -0
  71. package/dist/discovery-cache.d.ts +5 -0
  72. package/dist/hooks/use-codex-accounts.d.ts +11 -5
  73. package/dist/hooks/use-connect.d.ts +22 -0
  74. package/dist/hooks/use-session-events.d.ts +5 -0
  75. package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
  76. package/dist/hooks/use-workspace-sessions.d.ts +2 -0
  77. package/dist/index.d.ts +8 -2
  78. package/dist/index.js +771 -793
  79. package/dist/index.js.map +1 -1
  80. package/dist/interaction.js +2 -2
  81. package/dist/machines.js +2 -2
  82. package/dist/mcp-connection-status.d.ts +14 -0
  83. package/dist/{model-policy-picker-menu-3R336DP2.js → model-policy-picker-menu-RVOQ4ZZG.js} +4 -4
  84. package/dist/model-policy.d.ts +6 -2
  85. package/dist/model-policy.js +1 -1
  86. package/dist/{platform-activity-row-DUE2W74J.js → platform-activity-row-HLOH7FW4.js} +9 -4
  87. package/dist/platform-activity-row-HLOH7FW4.js.map +1 -0
  88. package/dist/plugin-discovery.d.ts +6 -0
  89. package/dist/{queue-surface-implementation-LK3S4BIW.js → queue-surface-implementation-3RIFK2BS.js} +4 -4
  90. package/dist/realtime.js +22 -22
  91. package/dist/realtime.js.map +1 -1
  92. package/dist/session-auth-recommendation.d.ts +5 -0
  93. package/dist/session-capability-policy.d.ts +12 -0
  94. package/dist/session-ui.d.ts +2 -0
  95. package/dist/session-ui.js +14 -12
  96. package/dist/session.d.ts +1 -0
  97. package/dist/session.js +6 -4
  98. package/dist/skill-discovery.d.ts +11 -0
  99. package/dist/timeline/compaction-copy.d.ts +10 -0
  100. package/dist/timeline/projection.d.ts +3 -1
  101. package/dist/timeline/tool-display-name.d.ts +2 -1
  102. package/dist/timeline/turn-summary.d.ts +2 -2
  103. package/dist/timeline/types.d.ts +24 -2
  104. package/dist/{timeline-annotation-markers-DRSTLEM6.js → timeline-annotation-markers-OY6OWR3V.js} +2 -2
  105. package/dist/{timeline-annotation-selection-IHLUGVND.js → timeline-annotation-selection-BOXA2TIN.js} +2 -2
  106. package/dist/{timeline-annotations-dialog-6Q53N5FG.js → timeline-annotations-dialog-RGY3MHL3.js} +3 -3
  107. package/package.json +3 -3
  108. package/src/approvals.ts +8 -1
  109. package/src/assets/README.md +8 -0
  110. package/src/assets/gmail.ico +0 -0
  111. package/src/assets/outlook.ico +0 -0
  112. package/src/capability-catalog-row.tsx +94 -0
  113. package/src/capability-logo-fallback.ts +22 -0
  114. package/src/client.ts +0 -9
  115. package/src/components/approval-surface.tsx +12 -2
  116. package/src/components/artifacts/document-editor.tsx +63 -6
  117. package/src/components/artifacts/presentation-editor.tsx +214 -9
  118. package/src/components/artifacts/spreadsheet-canvas.ts +3 -8
  119. package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
  120. package/src/components/artifacts/spreadsheet-grid.tsx +10 -11
  121. package/src/components/chat-composer.tsx +26 -3
  122. package/src/components/composer.tsx +10 -4
  123. package/src/components/human-input-form.tsx +12 -2
  124. package/src/components/markdown.tsx +133 -9
  125. package/src/components/message-timeline.tsx +104 -36
  126. package/src/components/model-picker.tsx +11 -3
  127. package/src/components/model-policy-picker-menu.tsx +10 -3
  128. package/src/components/preview-loading.tsx +154 -0
  129. package/src/components/sandbox-workspace.tsx +20 -36
  130. package/src/components/session-capability-frame.tsx +163 -0
  131. package/src/components/session-chrome.tsx +46 -77
  132. package/src/components/session-commands.tsx +18 -0
  133. package/src/components/session-connection-request.tsx +97 -0
  134. package/src/components/session-conversation.tsx +10 -5
  135. package/src/components/session-mcp-capability-card.tsx +532 -0
  136. package/src/components/session-status.tsx +2 -2
  137. package/src/components/timeline-anchor.tsx +9 -8
  138. package/src/components/timeline-search.tsx +168 -0
  139. package/src/components/user-message-body.tsx +7 -0
  140. package/src/connect-account-identity.tsx +34 -0
  141. package/src/connect-accounts.tsx +114 -52
  142. package/src/connect-chooser.tsx +171 -39
  143. package/src/connect-panel.tsx +73 -9
  144. package/src/connect-setup.tsx +72 -25
  145. package/src/connect.ts +13 -22
  146. package/src/connection-assets.d.ts +4 -0
  147. package/src/connection-catalog.tsx +61 -39
  148. package/src/connection-discovery.tsx +235 -0
  149. package/src/connection-installed.tsx +2 -0
  150. package/src/connection-logo.tsx +18 -10
  151. package/src/connection-service-logo.tsx +55 -0
  152. package/src/connection-service-presentation.ts +46 -0
  153. package/src/connection-skeleton.tsx +16 -0
  154. package/src/conversation-timeline.ts +1 -0
  155. package/src/discovery-cache.ts +42 -0
  156. package/src/hooks/use-codex-accounts.ts +33 -14
  157. package/src/hooks/use-composer.ts +4 -5
  158. package/src/hooks/use-connect.ts +23 -0
  159. package/src/hooks/use-session-events.ts +114 -1
  160. package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
  161. package/src/hooks/use-workspace-sessions.ts +10 -0
  162. package/src/index.ts +22 -2
  163. package/src/mcp-connection-status.ts +35 -0
  164. package/src/model-policy.ts +21 -0
  165. package/src/plugin-details.tsx +8 -5
  166. package/src/plugin-discovery.tsx +92 -72
  167. package/src/realtime/realtime-control.tsx +6 -8
  168. package/src/session-auth-recommendation.ts +48 -0
  169. package/src/session-capability-policy.ts +83 -0
  170. package/src/session-ui.ts +2 -0
  171. package/src/session.ts +1 -0
  172. package/src/skill-discovery.tsx +101 -56
  173. package/src/timeline/compaction-copy.ts +40 -0
  174. package/src/timeline/platform-activity-row.tsx +8 -3
  175. package/src/timeline/projection.ts +78 -2
  176. package/src/timeline/rolling-activity.tsx +4 -2
  177. package/src/timeline/shared.tsx +6 -1
  178. package/src/timeline/startup-timings.tsx +1 -1
  179. package/src/timeline/tool-display-name.ts +8 -6
  180. package/src/timeline/tool-renderers.tsx +5 -3
  181. package/src/timeline/turn-summary.tsx +17 -3
  182. package/src/timeline/types.ts +24 -2
  183. package/styles/compiled.css +325 -27
  184. package/styles/connect.css +90 -15
  185. package/styles/index.css +46 -0
  186. package/styles/session-capability.css +42 -0
  187. package/dist/chunk-45XEUVTK.js.map +0 -1
  188. package/dist/chunk-HQV2I5HV.js +0 -124
  189. package/dist/chunk-HQV2I5HV.js.map +0 -1
  190. package/dist/chunk-HUIKIDM5.js.map +0 -1
  191. package/dist/chunk-ICA6R6TW.js.map +0 -1
  192. package/dist/chunk-IHQII5WO.js +0 -886
  193. package/dist/chunk-IHQII5WO.js.map +0 -1
  194. package/dist/chunk-KANFU34B.js.map +0 -1
  195. package/dist/chunk-L2NBTKRX.js.map +0 -1
  196. package/dist/chunk-NYESIADM.js.map +0 -1
  197. package/dist/chunk-PEI6RANI.js.map +0 -1
  198. package/dist/chunk-TDSEILUH.js.map +0 -1
  199. package/dist/chunk-UMECRJRV.js.map +0 -1
  200. package/dist/hooks/use-packs.d.ts +0 -32
  201. package/dist/platform-activity-row-DUE2W74J.js.map +0 -1
  202. package/src/hooks/use-packs.ts +0 -157
  203. /package/dist/{browser-viewer-NTD6UIPR.js.map → browser-viewer-LGH4IP47.js.map} +0 -0
  204. /package/dist/{chunk-NOSYBS2D.js.map → chunk-2VHARTBL.js.map} +0 -0
  205. /package/dist/{chunk-5M6VTFJ5.js.map → chunk-GBPCZH3Y.js.map} +0 -0
  206. /package/dist/{chunk-YBM6CQRU.js.map → chunk-GEN54DU5.js.map} +0 -0
  207. /package/dist/{chunk-R4KRSFGA.js.map → chunk-IP4BUBKH.js.map} +0 -0
  208. /package/dist/{chunk-NLTS7JHI.js.map → chunk-JPHDWKZE.js.map} +0 -0
  209. /package/dist/{chunk-24M4YBCL.js.map → chunk-PNAVEK2U.js.map} +0 -0
  210. /package/dist/{model-policy-picker-menu-3R336DP2.js.map → model-policy-picker-menu-RVOQ4ZZG.js.map} +0 -0
  211. /package/dist/{queue-surface-implementation-LK3S4BIW.js.map → queue-surface-implementation-3RIFK2BS.js.map} +0 -0
  212. /package/dist/{timeline-annotation-markers-DRSTLEM6.js.map → timeline-annotation-markers-OY6OWR3V.js.map} +0 -0
  213. /package/dist/{timeline-annotation-selection-IHLUGVND.js.map → timeline-annotation-selection-BOXA2TIN.js.map} +0 -0
  214. /package/dist/{timeline-annotations-dialog-6Q53N5FG.js.map → timeline-annotations-dialog-RGY3MHL3.js.map} +0 -0
@@ -0,0 +1,40 @@
1
+ import type { ContextCompactionItem } from "./types";
2
+
3
+ /**
4
+ * Subtitle for a settled compaction landmark. A definitive provider rejection
5
+ * repeats deterministically for the same conversation, so it names the
6
+ * rejected field and withholds the generic retry promise; every other skip
7
+ * keeps its existing copy.
8
+ */
9
+ export function compactionSkipSubtitle(
10
+ reason: string | null,
11
+ providerRejection: ContextCompactionItem["providerRejection"] = null,
12
+ ): string {
13
+ switch (reason) {
14
+ case "no_history":
15
+ return "No active history to compact";
16
+ case "replacement_not_smaller":
17
+ return "Checkpoint would not reduce memory size";
18
+ case "replacement_unchanged":
19
+ return "Checkpoint made no progress";
20
+ case "summarization_failed":
21
+ return providerRejection
22
+ ? `The model provider rejected the compaction request (${describeCompactionProviderRejection(providerRejection)}). Chat history is unchanged. Repeating it fails the same way until the conversation changes; if a new message fails again, start a new session.`
23
+ : "Request it again to retry. Chat history is unchanged.";
24
+ default:
25
+ return "Compaction was not needed. Chat history is unchanged.";
26
+ }
27
+ }
28
+
29
+ /** `HTTP 400 invalid_request_error, param input[3].encrypted_content`; identifiers only. */
30
+ export function describeCompactionProviderRejection(
31
+ rejection: NonNullable<ContextCompactionItem["providerRejection"]>,
32
+ ): string {
33
+ const parts = [
34
+ `HTTP ${rejection.httpStatus}${rejection.type ? ` ${rejection.type}` : ""}${
35
+ rejection.code ? ` ${rejection.code}` : ""
36
+ }`,
37
+ ];
38
+ if (rejection.param) parts.push(`param ${rejection.param}`);
39
+ return parts.join(", ");
40
+ }
@@ -73,7 +73,7 @@ export default function PlatformActivityRow({
73
73
  : startupPhaseTitle(item.phase, item.status, item.outcome),
74
74
  preview:
75
75
  item.phase === "model_preparation"
76
- ? "Includes overlapping sandbox, rig, repository, and runtime setup shown below."
76
+ ? "Includes overlapping sandbox startup, custom environment setup, repository preparation, and runtime setup shown below."
77
77
  : undefined,
78
78
  running,
79
79
  failed,
@@ -140,7 +140,7 @@ function startupPhaseTitle(
140
140
  return `Sandbox ${outcome === "resumed" ? "reattached" : outcome}`;
141
141
  }
142
142
  if (status === "complete" && phase === "rig" && outcome === "skipped") {
143
- return "Rig already ready";
143
+ return "Sandbox Environment already ready";
144
144
  }
145
145
  const statusIndex =
146
146
  status === "running" ? 0 : status === "failed" ? 1 : status === "cancelled" ? 2 : 3;
@@ -163,7 +163,12 @@ const STARTUP_PHASE_TITLES: Record<
163
163
  "Sandbox startup interrupted",
164
164
  "Sandbox ready",
165
165
  ],
166
- rig: ["Setting up rig", "Rig setup failed", "Rig setup interrupted", "Rig ready"],
166
+ rig: [
167
+ "Setting up sandbox environment",
168
+ "Sandbox Environment setup failed",
169
+ "Sandbox Environment setup interrupted",
170
+ "Sandbox Environment ready",
171
+ ],
167
172
  repository: [
168
173
  "Preparing repository",
169
174
  "Repository preparation failed",
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  parseMediaGenerationResult,
3
+ parseToolDisplayMetadata,
3
4
  type HumanInputAnswer,
4
5
  type HumanInputQuestion,
5
6
  type HumanInputResponse,
@@ -129,10 +130,20 @@ function timelineAnnotationToolOutputText(output: unknown): string | null {
129
130
  return text.length > 0 ? text : null;
130
131
  }
131
132
 
132
- export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
133
+ export function buildTimeline(
134
+ events: SessionEvent[],
135
+ options: { partialStart?: boolean } = {},
136
+ ): TimelineItem[] {
133
137
  const items: TimelineItem[] = [];
134
138
  const prescan = prescanTurnAnchors(events);
135
139
  const ordered = orderTimelineEvents(events, prescan);
140
+ // A bounded replay can begin halfway through a message (including inside an
141
+ // interactive fence). Never parse that suffix as a complete Markdown source.
142
+ // Keep the raw events available for pagination; a completed receipt restores
143
+ // the authoritative message without requiring an unbounded history fetch.
144
+ let completeHistoryPrefix = options.partialStart !== true;
145
+ const knownMessagePrefixTurns = new Set<string | null>();
146
+ const incompleteMessageKeys = new Set<string>();
136
147
  const pendingWaitOutcomeByTurn = new Map<string | null, PendingWaitOutcome>();
137
148
  const latestAgentResponseByTurn = new Map<string | null, TrackedAgentResponse>();
138
149
  const identifiedMessages = new Map<string, AgentMessageItem>();
@@ -299,6 +310,18 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
299
310
  for (const event of ordered) {
300
311
  const payload = asRecord(event.payload);
301
312
  const turnId = event.turnId ?? null;
313
+ if (event.type === "session.created") {
314
+ completeHistoryPrefix = true;
315
+ } else if (
316
+ event.type === "turn.started" ||
317
+ (event.type === "user.message" &&
318
+ payload.delivery !== "steer" &&
319
+ payload.routing !== "accepted_for_steering")
320
+ ) {
321
+ // Accepted Steer is visible before its replacement turn starts. It says
322
+ // nothing about the prefix of a still-streaming message from the old turn.
323
+ knownMessagePrefixTurns.add(turnId);
324
+ }
302
325
  startupEvent = event;
303
326
  startupTurnId = turnId;
304
327
  startupAttemptId =
@@ -415,6 +438,13 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
415
438
  }
416
439
  const messageId = stringValue(payload.messageId);
417
440
  const messageKey = messageId ? JSON.stringify([turnId, messageId]) : null;
441
+ if (
442
+ (!completeHistoryPrefix && !knownMessagePrefixTurns.has(turnId)) ||
443
+ (messageKey && incompleteMessageKeys.has(messageKey))
444
+ ) {
445
+ if (messageKey) incompleteMessageKeys.add(messageKey);
446
+ break;
447
+ }
418
448
  const identified = messageKey ? identifiedMessages.get(messageKey) : undefined;
419
449
  if (identified) {
420
450
  if (identified.annotationSource?.eventType !== "agent.message.completed") {
@@ -470,6 +500,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
470
500
  }
471
501
 
472
502
  case "agent.message.completed": {
503
+ knownMessagePrefixTurns.add(turnId);
473
504
  const text = stringValue(payload.text);
474
505
  const messageId = stringValue(payload.messageId);
475
506
  const messageKey = messageId ? JSON.stringify([turnId, messageId]) : null;
@@ -580,6 +611,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
580
611
 
581
612
  case "agent.toolCall.created": {
582
613
  const name = typeof payload.name === "string" ? payload.name : "tool";
614
+ const display = parseToolDisplayMetadata(payload.display);
583
615
  const callId = typeof payload.id === "string" ? payload.id : null;
584
616
  const args = payload.arguments ?? null;
585
617
  closeStreamingTail();
@@ -621,6 +653,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
621
653
  (item): item is ToolCallItem => item.kind === "tool-call" && item.callId === callId,
622
654
  );
623
655
  if (existing) {
656
+ if (display) existing.display = display;
624
657
  if (args != null) {
625
658
  existing.arguments = args;
626
659
  }
@@ -637,6 +670,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
637
670
  turnId,
638
671
  callId,
639
672
  name,
673
+ ...(display ? { display } : {}),
640
674
  arguments: args,
641
675
  output: undefined,
642
676
  truncation: null,
@@ -915,6 +949,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
915
949
  estimatedTokensBefore: numberOrNull(payload.estimatedTokensBefore),
916
950
  estimatedTokensAfter: null,
917
951
  skipReason: null,
952
+ providerRejection: null,
918
953
  implementation:
919
954
  typeof payload.implementation === "string" ? payload.implementation : null,
920
955
  occurredAt: event.occurredAt,
@@ -932,6 +967,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
932
967
  estimatedTokensBefore: numberOrNull(payload.estimatedTokensBefore),
933
968
  estimatedTokensAfter: numberOrNull(payload.estimatedTokensAfter),
934
969
  skipReason: null,
970
+ providerRejection: null,
935
971
  implementation:
936
972
  typeof payload.implementation === "string" ? payload.implementation : null,
937
973
  occurredAt: event.occurredAt,
@@ -949,6 +985,7 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
949
985
  estimatedTokensBefore: numberOrNull(payload.estimatedTokensBefore),
950
986
  estimatedTokensAfter: null,
951
987
  skipReason: typeof payload.reason === "string" ? payload.reason : null,
988
+ providerRejection: compactionProviderRejection(payload),
952
989
  implementation:
953
990
  typeof payload.implementation === "string" ? payload.implementation : null,
954
991
  occurredAt: event.occurredAt,
@@ -1001,6 +1038,13 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
1001
1038
  id: event.id,
1002
1039
  turnId,
1003
1040
  serverId: typeof payload.serverId === "string" ? payload.serverId : null,
1041
+ canonicalServerId:
1042
+ typeof payload.canonicalServerId === "string" ? payload.canonicalServerId : null,
1043
+ connectionSubjectScope:
1044
+ payload.connectionSubjectScope === "subject" ||
1045
+ payload.connectionSubjectScope === "workspace"
1046
+ ? payload.connectionSubjectScope
1047
+ : null,
1004
1048
  source: capability
1005
1049
  ? "capability"
1006
1050
  : event.type === "tool.auth_needed"
@@ -1277,7 +1321,16 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
1277
1321
  }
1278
1322
  }
1279
1323
 
1324
+ const sourceEventsById = new Map(events.map((event) => [event.id, event]));
1280
1325
  for (const item of items) {
1326
+ const source = sourceEventsById.get(item.id);
1327
+ const canonical = "annotationSource" in item ? item.annotationSource : undefined;
1328
+ item.sourceEvents = [
1329
+ ...(source ? [{ eventId: source.id, sequence: source.sequence }] : []),
1330
+ ...(canonical && canonical.eventId !== source?.id
1331
+ ? [{ eventId: canonical.eventId, sequence: canonical.sequence }]
1332
+ : []),
1333
+ ];
1281
1334
  if (item.kind === "agent-message") {
1282
1335
  item.text = stripOpaqueCitationTokens(item.text);
1283
1336
  }
@@ -2096,6 +2149,29 @@ function numberOrNull(value: unknown): number | null {
2096
2149
  return typeof value === "number" && Number.isFinite(value) ? value : null;
2097
2150
  }
2098
2151
 
2152
+ /**
2153
+ * Read the closed provider-rejection record a `summarization_failed` skip
2154
+ * carries. Only bounded identifiers are accepted; a provider message is never
2155
+ * part of the payload and would be ignored here anyway.
2156
+ */
2157
+ function compactionProviderRejection(
2158
+ payload: Record<string, unknown>,
2159
+ ): ContextCompactionItem["providerRejection"] {
2160
+ const record = asRecord(payload.providerRejection);
2161
+ if (typeof record.httpStatus !== "number" || !Number.isFinite(record.httpStatus)) {
2162
+ return null;
2163
+ }
2164
+ const text = (value: unknown): string | null =>
2165
+ typeof value === "string" && value.trim() ? value : null;
2166
+ return {
2167
+ httpStatus: record.httpStatus,
2168
+ type: text(record.type),
2169
+ code: text(record.code),
2170
+ param: text(record.param),
2171
+ requestId: text(record.requestId),
2172
+ };
2173
+ }
2174
+
2099
2175
  function compactionTrigger(payload: Record<string, unknown>): ContextCompactionItem["trigger"] {
2100
2176
  const trigger = payload.trigger;
2101
2177
  return trigger === "auto" ||
@@ -2527,7 +2603,7 @@ function capabilityAuthorizationRequest(
2527
2603
  if (
2528
2604
  typeof record.id !== "string" ||
2529
2605
  typeof record.name !== "string" ||
2530
- !["pack", "mcp", "api", "skill", "plugin"].includes(String(kind)) ||
2606
+ !["mcp", "api", "skill", "plugin"].includes(String(kind)) ||
2531
2607
  !["built_in", "library", "configured", "public_registry", "registry", "manual"].includes(
2532
2608
  String(source),
2533
2609
  ) ||
@@ -36,7 +36,9 @@ export function RollingActivity({
36
36
  const fallback = (
37
37
  <span className="og-rolling-label">
38
38
  <WrenchIcon className="size-3.5" />
39
- <span>{item.kind === "tool-call" ? toolDisplayName(item.name) : "Working"}</span>
39
+ <span>
40
+ {item.kind === "tool-call" ? toolDisplayName(item.name, item.display) : "Working"}
41
+ </span>
40
42
  </span>
41
43
  );
42
44
  return (
@@ -46,7 +48,7 @@ export function RollingActivity({
46
48
  >
47
49
  <span className="sr-only">
48
50
  {item.kind === "tool-call"
49
- ? toolDisplayName(item.name)
51
+ ? toolDisplayName(item.name, item.display)
50
52
  : item.kind === "reasoning"
51
53
  ? "Thinking"
52
54
  : "Working"}
@@ -1,5 +1,6 @@
1
1
  import { CameraIcon, CameraOffIcon, ChevronRightIcon } from "lucide-react";
2
- import { createContext, useContext, useState, type ReactNode } from "react";
2
+ import { createContext, useContext, useEffect, useState, type ReactNode } from "react";
3
+ import { useTimelineSearchReveal } from "../components/timeline-search";
3
4
  import { cn } from "../lib/cn";
4
5
  import { stringifyPayload } from "../lib/format";
5
6
  import { useForcedDefaultOpen } from "./disclosure-context";
@@ -154,6 +155,10 @@ export function ActivityDisclosure({
154
155
  // absent in normal app usage, where the row starts collapsed.
155
156
  const forcedDefaultOpen = useForcedDefaultOpen();
156
157
  const [open, setOpen] = useState(defaultOpen ?? forcedDefaultOpen ?? false);
158
+ const searchReveal = useTimelineSearchReveal();
159
+ useEffect(() => {
160
+ if (searchReveal) setOpen(true);
161
+ }, [searchReveal]);
157
162
  const truncation = useContext(ToolCallTruncationContext);
158
163
  const compact = useContext(CompactActivityContext);
159
164
  if (compact)
@@ -3,7 +3,7 @@ import type { StartupPhaseItem } from "./types";
3
3
  const LABELS: Record<StartupPhaseItem["phase"], string> = {
4
4
  queue: "Worker queue",
5
5
  sandbox: "Sandbox",
6
- rig: "Rig",
6
+ rig: "Sandbox Environment",
7
7
  repository: "Repository",
8
8
  files: "Files",
9
9
  tools: "Tools",
@@ -7,6 +7,8 @@
7
7
  * from argument JSON.
8
8
  */
9
9
 
10
+ import type { ToolDisplayMetadata } from "@opengeni/sdk";
11
+
10
12
  /** Leaf tool name after the first `__` server boundary (or the whole name). */
11
13
  export function mcpToolLeaf(name: string): string {
12
14
  const boundary = name.indexOf("__");
@@ -26,10 +28,10 @@ export function toolMatchesLeaf(wireName: string, leaf: string): boolean {
26
28
  * Readable label for a tool call ("session_create" / "opengeni__session_create"
27
29
  * → "Session create"). Title-cases the first character of the leaf phrase.
28
30
  */
29
- export function toolDisplayName(name: string): string {
30
- const phrase = mcpToolLeaf(name).replace(/[_-]+/g, " ").trim();
31
- if (!phrase) {
32
- return name;
33
- }
34
- return phrase.charAt(0).toUpperCase() + phrase.slice(1);
31
+ export function toolDisplayName(name: string, display?: ToolDisplayMetadata): string {
32
+ if (!display && /^[a-f0-9]{64}$/.test(name)) return "Tool call";
33
+ const phrase = (display?.toolName ?? mcpToolLeaf(name)).replace(/[_-]+/g, " ").trim();
34
+ const title =
35
+ display?.title ?? (phrase ? phrase.charAt(0).toUpperCase() + phrase.slice(1) : name);
36
+ return display?.accountLabel ? `${title} — ${display.accountLabel}` : title;
35
37
  }
@@ -1786,7 +1786,9 @@ function ToolSearchRenderer({ item }: ToolRendererProps) {
1786
1786
  function DocsSearchRenderer({ item }: ToolRendererProps) {
1787
1787
  const args = parseToolArgs(item.arguments);
1788
1788
  const query = typeof args.query === "string" ? args.query.trim() : "";
1789
- const title = query ? `Search “${truncatePreview(query, 48)}”` : toolDisplayName(item.name);
1789
+ const title = query
1790
+ ? `Search “${truncatePreview(query, 48)}”`
1791
+ : toolDisplayName(item.name, item.display);
1790
1792
  const running = item.status === "running";
1791
1793
 
1792
1794
  if (running) {
@@ -1860,7 +1862,7 @@ function DocsSearchRenderer({ item }: ToolRendererProps) {
1860
1862
  function SetSessionTitleRenderer({ item }: ToolRendererProps) {
1861
1863
  const args = parseToolArgs(item.arguments);
1862
1864
  const titleArg = typeof args.title === "string" ? args.title.trim() : "";
1863
- const display = toolDisplayName(item.name);
1865
+ const display = toolDisplayName(item.name, item.display);
1864
1866
  const previewTitle = titleArg ? truncatePreview(titleArg, 72) : "";
1865
1867
  const icon = <MessagesSquareIcon className={ICON_SIZE} />;
1866
1868
 
@@ -2198,7 +2200,7 @@ function RunOnRenderer({ item }: ToolRendererProps) {
2198
2200
  function GenericRenderer({ item }: ToolRendererProps) {
2199
2201
  const running = item.status === "running";
2200
2202
  const args = parseToolArgs(item.arguments);
2201
- const display = toolDisplayName(item.name);
2203
+ const display = toolDisplayName(item.name, item.display);
2202
2204
  const icon = <GenericToolIcon name={item.name} />;
2203
2205
  // Goal tools: surface the objective text on the collapsed row so the in-cluster
2204
2206
  // tool replaces the old breakaway GoalRow pill without losing the gist.
@@ -14,6 +14,7 @@ import { CopyButton } from "../components/copy-button";
14
14
  import { cn } from "../lib/cn";
15
15
  import { MOTION_INSPECT_SCALE } from "../lib/motion-inspect";
16
16
  import { useForcedDefaultOpen } from "./disclosure-context";
17
+ import { useTimelineSearchReveal } from "../components/timeline-search";
17
18
  import { useEntranceAnimation } from "./entrance";
18
19
  import { useFoldMemory, type FoldRestingState } from "./fold-memory";
19
20
  import {
@@ -125,8 +126,8 @@ export type TurnSummaryProps = {
125
126
  items: ActivityItem[];
126
127
  /**
127
128
  * The settled verdict — or absent for a completed CLUSTER of a still-running
128
- * turn, which folds neutrally: no verdict glyph (the turn has none yet), a
129
- * quiet pulse dot in its place so alignment and the running feel both hold.
129
+ * turn, which folds neutrally. Only unfinished activity inside this summary
130
+ * animates; the parent turn may still be composing a response elsewhere.
130
131
  */
131
132
  outcome?: TurnOutcome | undefined;
132
133
  /** A short failure reason shown inline on a failed chip (never hidden). */
@@ -202,6 +203,7 @@ export function TurnSummary({
202
203
  // An explicit `defaultOpen` always wins; otherwise an ancestor may seed it
203
204
  // (screenshot instrumentation); otherwise the turn starts folded.
204
205
  const forcedDefaultOpen = useForcedDefaultOpen();
206
+ const searchReveal = useTimelineSearchReveal();
205
207
  const foldMemory = useFoldMemory();
206
208
  // A remembered resting state outranks author defaults: a fold that already
207
209
  // finished its settle collapse (or that the reader closed) mounts closed
@@ -315,6 +317,18 @@ export function TurnSummary({
315
317
  }
316
318
  // oxlint-disable-next-line react-hooks/exhaustive-deps
317
319
  }, [settleFold]);
320
+ useEffect(() => {
321
+ if (!searchReveal) return;
322
+ clearSettleTimers();
323
+ settleArmedRef.current = false;
324
+ setSettling(false);
325
+ setSettlePhase(false);
326
+ setNestSuppressLatch(false);
327
+ setOpen(true);
328
+ rememberResting("open");
329
+ // Search is an explicit, persistent reader action, not a new fold default.
330
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
331
+ }, [searchReveal]);
318
332
  const onOpenChange = (next: boolean) => {
319
333
  // The reader took over — cancel the pending auto-collapse for good.
320
334
  // Clear settle CSS phase immediately (fast collapse) but keep nest latch
@@ -447,7 +461,7 @@ export function TurnSummary({
447
461
  />
448
462
  {/* Completion is the quiet default and needs no repeated glyph. Failed,
449
463
  cancelled, and still-running folds retain a visible state marker. */}
450
- {outcome === "complete" || (liveHeader && !outcome) ? null : (
464
+ {outcome === "complete" || (!outcome && (liveHeader || context.settled)) ? null : (
451
465
  <span
452
466
  className={cn(
453
467
  "inline-flex shrink-0 items-center justify-center",
@@ -8,6 +8,7 @@ import type {
8
8
  TimelineAnnotationSource,
9
9
  ToolAuthNeededPayload,
10
10
  ToolRef,
11
+ ToolDisplayMetadata,
11
12
  } from "@opengeni/sdk";
12
13
 
13
14
  /* ----------------------------------------------------------------------------
@@ -129,6 +130,7 @@ export type ToolCallItem = {
129
130
  turnId: string | null;
130
131
  callId: string | null;
131
132
  name: string;
133
+ display?: ToolDisplayMetadata;
132
134
  arguments: unknown;
133
135
  output: unknown;
134
136
  truncation?: ToolCallTruncation | null;
@@ -383,11 +385,24 @@ export type ContextCompactionItem = {
383
385
  estimatedTokensBefore: number | null;
384
386
  estimatedTokensAfter: number | null;
385
387
  skipReason: string | null;
388
+ /**
389
+ * Present only for a `summarization_failed` skip where the provider
390
+ * definitively rejected the compaction request. Content-free identifiers.
391
+ */
392
+ providerRejection: ContextCompactionProviderRejection | null;
386
393
  /** Provider implementation id for debug disclosure only. */
387
394
  implementation: string | null;
388
395
  occurredAt: string;
389
396
  };
390
397
 
398
+ export type ContextCompactionProviderRejection = {
399
+ httpStatus: number;
400
+ type: string | null;
401
+ code: string | null;
402
+ param: string | null;
403
+ requestId: string | null;
404
+ };
405
+
391
406
  export type MachineInputMember = {
392
407
  id: string;
393
408
  kind:
@@ -438,6 +453,9 @@ export type AuthNeededItem = {
438
453
  turnId: string | null;
439
454
  /** The runtime surface that requested recovery, when the event is an MCP auth signal. */
440
455
  serverId: string | null;
456
+ /** Explicit recovery identity; never inferred from an opaque execution alias. */
457
+ canonicalServerId?: string | null;
458
+ connectionSubjectScope?: "workspace" | "subject" | null;
441
459
  /** Durable event family that produced this notice. */
442
460
  source?: "tool" | "credential" | "capability" | undefined;
443
461
  /** The connection's registrable domain, e.g. "linear.app". */
@@ -473,7 +491,7 @@ export type TurnEndItem = {
473
491
  occurredAt: string;
474
492
  };
475
493
 
476
- export type TimelineItem =
494
+ export type TimelineItem = (
477
495
  | UserMessageItem
478
496
  | HumanInputItem
479
497
  | AgentMessageItem
@@ -492,7 +510,11 @@ export type TimelineItem =
492
510
  | MemoryItem
493
511
  | KnowledgeItem
494
512
  | FleetDecisionItem
495
- | TurnEndItem;
513
+ | TurnEndItem
514
+ ) & {
515
+ /** Durable identities, independent of renderer/reconciliation keys. */
516
+ sourceEvents?: readonly { eventId: string; sequence: number }[] | undefined;
517
+ };
496
518
 
497
519
  /** Activity items cluster between chat messages (reasoning, tools, workers, sandbox, memory). */
498
520
  export type ActivityItem =