@opengeni/react 5.2.0-canary.0 → 6.0.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 (62) hide show
  1. package/README.md +12 -0
  2. package/dist/artifacts.d.ts +1 -1
  3. package/dist/artifacts.js +3 -1
  4. package/dist/artifacts.js.map +1 -1
  5. package/dist/{chunk-QXJCNVSD.js → chunk-CC7AVRIJ.js} +1769 -1493
  6. package/dist/chunk-CC7AVRIJ.js.map +1 -0
  7. package/dist/{chunk-5PQJOCX5.js → chunk-KANFU34B.js} +6 -4
  8. package/dist/chunk-KANFU34B.js.map +1 -0
  9. package/dist/{chunk-IYCR4343.js → chunk-PZ27MCZP.js} +36 -1
  10. package/dist/chunk-PZ27MCZP.js.map +1 -0
  11. package/dist/{chunk-2TKI3WEG.js → chunk-WYWRYUNQ.js} +12 -1
  12. package/dist/chunk-WYWRYUNQ.js.map +1 -0
  13. package/dist/{chunk-T5FRXMC3.js → chunk-YS24CFDI.js} +24 -9
  14. package/dist/chunk-YS24CFDI.js.map +1 -0
  15. package/dist/components/session-chrome.d.ts +6 -1
  16. package/dist/{computer-viewer-AA4JH2AP.js → computer-viewer-CTFCJVS7.js} +2 -2
  17. package/dist/connect.js +11 -19
  18. package/dist/connect.js.map +1 -1
  19. package/dist/hooks/use-file-attachments.d.ts +2 -0
  20. package/dist/index.d.ts +4 -0
  21. package/dist/index.js +13 -5
  22. package/dist/index.js.map +1 -1
  23. package/dist/interaction.js +1 -1
  24. package/dist/{platform-activity-row-UW4UVVM4.js → platform-activity-row-DUE2W74J.js} +1 -1
  25. package/dist/platform-activity-row-DUE2W74J.js.map +1 -0
  26. package/dist/session-ui.d.ts +2 -0
  27. package/dist/session-ui.js +6 -107
  28. package/dist/session-ui.js.map +1 -1
  29. package/dist/session.js +2 -2
  30. package/dist/timeline/genie-loading.d.ts +9 -1
  31. package/dist/timeline/index.d.ts +3 -1
  32. package/dist/timeline/knowledge-receipt.d.ts +17 -0
  33. package/dist/timeline/platform-activity-row.d.ts +0 -1
  34. package/dist/timeline/retained-image.d.ts +2 -0
  35. package/dist/timeline/types.d.ts +13 -2
  36. package/package.json +3 -3
  37. package/src/artifacts.ts +1 -1
  38. package/src/components/computer-viewer.tsx +11 -3
  39. package/src/components/message-timeline.tsx +42 -12
  40. package/src/components/session-chrome.tsx +14 -2
  41. package/src/connection-catalog.tsx +8 -21
  42. package/src/hooks/use-computer-frame-stream.ts +17 -5
  43. package/src/hooks/use-file-attachments.ts +4 -1
  44. package/src/hooks/use-goal.ts +3 -1
  45. package/src/index.ts +6 -0
  46. package/src/session-ui.ts +3 -0
  47. package/src/timeline/activity-rail.tsx +11 -1
  48. package/src/timeline/genie-loading.tsx +18 -4
  49. package/src/timeline/index.ts +4 -0
  50. package/src/timeline/knowledge-receipt.tsx +100 -0
  51. package/src/timeline/platform-activity-row.tsx +0 -1
  52. package/src/timeline/projection.ts +40 -0
  53. package/src/timeline/retained-image.ts +12 -0
  54. package/src/timeline/tool-renderers.tsx +115 -16
  55. package/src/timeline/types.ts +14 -0
  56. package/dist/chunk-2TKI3WEG.js.map +0 -1
  57. package/dist/chunk-5PQJOCX5.js.map +0 -1
  58. package/dist/chunk-IYCR4343.js.map +0 -1
  59. package/dist/chunk-QXJCNVSD.js.map +0 -1
  60. package/dist/chunk-T5FRXMC3.js.map +0 -1
  61. package/dist/platform-activity-row-UW4UVVM4.js.map +0 -1
  62. /package/dist/{computer-viewer-AA4JH2AP.js.map → computer-viewer-CTFCJVS7.js.map} +0 -0
@@ -13,7 +13,7 @@ import {
13
13
  useComputerFrameStream,
14
14
  useComputerSession,
15
15
  useComputerSessions
16
- } from "./chunk-T5FRXMC3.js";
16
+ } from "./chunk-YS24CFDI.js";
17
17
  import {
18
18
  useInteractionInterventions,
19
19
  useInteractionInvalidation
@@ -169,4 +169,4 @@ function startupDuration(durationMs) {
169
169
  export {
170
170
  PlatformActivityRow as default
171
171
  };
172
- //# sourceMappingURL=platform-activity-row-UW4UVVM4.js.map
172
+ //# sourceMappingURL=platform-activity-row-DUE2W74J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/timeline/platform-activity-row.tsx"],"sourcesContent":["import type { ReasoningItem, SandboxItem, StartupPhaseItem } from \"./types\";\n\ntype RowJsx = typeof import(\"react/jsx-runtime\").jsx;\ntype RowJsxs = typeof import(\"react/jsx-runtime\").jsxs;\n\nexport default function PlatformActivityRow({\n item,\n d: ActivityDisclosure,\n p: PayloadBlock,\n t: displayName,\n b: BotIcon,\n m: Markdown,\n j,\n s,\n}: {\n item: ReasoningItem | SandboxItem | StartupPhaseItem;\n d: typeof import(\"./shared\").ActivityDisclosure;\n p: typeof import(\"./shared\").PayloadBlock;\n t: (name: string) => string;\n b: typeof import(\"lucide-react\").BotIcon;\n m: typeof import(\"../components/markdown\").Markdown;\n j: RowJsx;\n s: RowJsxs;\n}) {\n if (item.kind === \"reasoning\") {\n return j(ActivityDisclosure, {\n icon: brainIcon(j, s),\n iconTone: \"muted\",\n title: item.streaming\n ? \"Thinking\"\n : j(\"span\", {\n className: \"font-normal italic text-og-fg-subtle\",\n children: \"Thought\",\n }),\n running: item.streaming,\n compactPreview: item.text.replace(/\\*\\*|__|`/g, \"\").replace(/\\s+/g, \" \"),\n preview: j(\"span\", {\n className: \"og-reasoning-preview\",\n children: j(Markdown, { streaming: item.streaming, children: item.text }),\n }),\n children: j(\"div\", {\n className: \"text-og-base leading-6 text-og-fg-muted [&_strong]:text-og-fg-muted\",\n children: j(Markdown, { streaming: item.streaming, children: item.text }),\n }),\n });\n }\n if (item.kind === \"sandbox\") {\n return s(ActivityDisclosure, {\n icon: terminalIcon(j, s),\n iconTone:\n item.status === \"failed\" ? \"failed\" : item.status === \"running\" ? \"running\" : \"muted\",\n title: sandboxRowTitle(item, displayName),\n running: item.status === \"running\",\n failed: item.status === \"failed\",\n cancelled: item.status === \"cancelled\",\n preview: item.command ?? undefined,\n children: [\n item.command ? j(PayloadBlock, { label: \"Command\", value: item.command }, \"command\") : null,\n item.output ? j(PayloadBlock, { label: \"Output\", value: item.output }, \"output\") : null,\n ],\n });\n }\n\n const failed = item.status === \"failed\";\n const running = item.status === \"running\";\n const duration = startupDuration(item.durationMs);\n return j(ActivityDisclosure, {\n icon: j(BotIcon, { className: \"size-3.5\" }),\n iconTone: failed ? \"failed\" : running ? \"running\" : \"muted\",\n title:\n item.blockedReason === \"rotation_in_progress\"\n ? \"Waiting for sandbox rotation\"\n : startupPhaseTitle(item.phase, item.status, item.outcome),\n preview:\n item.phase === \"model_preparation\"\n ? \"Includes overlapping sandbox, rig, repository, and runtime setup shown below.\"\n : undefined,\n running,\n failed,\n cancelled: item.status === \"cancelled\",\n chip: duration ? { tone: failed ? \"bad\" : \"muted\", text: duration } : undefined,\n expandable: false,\n });\n}\n\nfunction brainIcon(j: RowJsx, s: RowJsxs) {\n return lucideIcon(j, s, \"brain\", [\n j(\"path\", { d: \"M 12 18V5\" }, \"spine\"),\n j(\"path\", { d: \"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4\" }, \"center\"),\n j(\"path\", { d: \"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5\" }, \"top\"),\n j(\"path\", { d: \"M17.997 5.125a4 4 0 0 1 2.526 5.77\" }, \"upper-right\"),\n j(\"path\", { d: \"M18 18a4 4 0 0 0 2-7.464\" }, \"right\"),\n j(\"path\", { d: \"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517\" }, \"base\"),\n j(\"path\", { d: \"M6 18a4 4 0 0 1-2-7.464\" }, \"left\"),\n j(\"path\", { d: \"M6.003 5.125a4 4 0 0 0-2.526 5.77\" }, \"upper-left\"),\n ]);\n}\n\nfunction terminalIcon(j: RowJsx, s: RowJsxs) {\n return lucideIcon(j, s, \"square-terminal\", [\n j(\"path\", { d: \"m7 11 2-2-2-2\" }, \"prompt\"),\n j(\"path\", { d: \"M11 13h4\" }, \"cursor\"),\n j(\"rect\", { width: 18, height: 18, x: 3, y: 3, rx: 2, ry: 2 }, \"frame\"),\n ]);\n}\n\nfunction lucideIcon(j: RowJsx, s: RowJsxs, name: string, children: ReturnType<RowJsx>[]) {\n return s(\"svg\", {\n \"aria-hidden\": \"true\",\n className: `lucide lucide-${name} size-3.5`,\n fill: \"none\",\n height: 24,\n stroke: \"currentColor\",\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n viewBox: \"0 0 24 24\",\n width: 24,\n children,\n });\n}\n\nfunction sandboxRowTitle(item: SandboxItem, displayName: (name: string) => string): string {\n if (item.name === \"sandbox.provision\") {\n return startupPhaseTitle(\n \"sandbox\",\n item.status === \"cancelled\" ? \"complete\" : item.status,\n item.origin ?? null,\n );\n }\n return displayName(item.name);\n}\n\nfunction startupPhaseTitle(\n phase: StartupPhaseItem[\"phase\"],\n status: StartupPhaseItem[\"status\"],\n outcome: StartupPhaseItem[\"outcome\"],\n): string {\n if (status === \"complete\" && phase === \"sandbox\" && outcome && outcome !== \"skipped\") {\n return `Sandbox ${outcome === \"resumed\" ? \"reattached\" : outcome}`;\n }\n if (status === \"complete\" && phase === \"rig\" && outcome === \"skipped\") {\n return \"Rig already ready\";\n }\n const statusIndex =\n status === \"running\" ? 0 : status === \"failed\" ? 1 : status === \"cancelled\" ? 2 : 3;\n return STARTUP_PHASE_TITLES[phase][statusIndex];\n}\n\nconst STARTUP_PHASE_TITLES: Record<\n StartupPhaseItem[\"phase\"],\n readonly [string, string, string, string]\n> = {\n queue: [\n \"Waiting for a worker\",\n \"Worker startup failed\",\n \"Worker wait interrupted\",\n \"Worker started\",\n ],\n sandbox: [\n \"Starting sandbox\",\n \"Sandbox didn’t start\",\n \"Sandbox startup interrupted\",\n \"Sandbox ready\",\n ],\n rig: [\"Setting up rig\", \"Rig setup failed\", \"Rig setup interrupted\", \"Rig ready\"],\n repository: [\n \"Preparing repository\",\n \"Repository preparation failed\",\n \"Repository preparation interrupted\",\n \"Repository ready\",\n ],\n files: [\n \"Preparing files\",\n \"File preparation failed\",\n \"File preparation interrupted\",\n \"Files ready\",\n ],\n tools: [\n \"Connecting tools\",\n \"Tool connection failed\",\n \"Tool connection interrupted\",\n \"Tools ready\",\n ],\n model_preparation: [\n \"Preparing runtime and model request\",\n \"Runtime/model preparation failed\",\n \"Runtime/model preparation interrupted\",\n \"Model request dispatched\",\n ],\n provider_first_byte: [\n \"Waiting for model\",\n \"Model didn’t respond\",\n \"Model wait interrupted\",\n \"Model started responding\",\n ],\n};\n\nfunction startupDuration(durationMs: number | null): string | null {\n if (durationMs === null || !Number.isFinite(durationMs) || durationMs < 0) return null;\n if (durationMs < 1_000) return `${Math.round(durationMs)}ms`;\n if (durationMs < 60_000) return `${(durationMs / 1_000).toFixed(1)}s`;\n const minutes = Math.floor(durationMs / 60_000);\n const seconds = Math.round((durationMs % 60_000) / 1_000);\n return `${minutes}m ${String(seconds).padStart(2, \"0\")}s`;\n}\n"],"mappings":"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","names":[]}
@@ -19,6 +19,8 @@ export type { QueueSurfaceProps } from "./components/queue-surface.js";
19
19
  export { SessionChrome, sessionChromeGoalPillExplanation, sessionChromeGoalPillLabel, sessionChromeGoalPillState, } from "./components/session-chrome.js";
20
20
  export type { SessionChromeAgentsSignal, SessionChromeProps, SessionChromeSignalId, SessionChromeSignalTone, } from "./components/session-chrome.js";
21
21
  export { SessionCommandsPanel } from "./components/session-commands-panel.js";
22
+ export { KnowledgeActivityProvider } from "./timeline/knowledge-receipt.js";
23
+ export type { KnowledgeActivityActions } from "./timeline/knowledge-receipt.js";
22
24
  export { StartupTimings } from "./timeline/startup-timings.js";
23
25
  export { useStartupDetails, setStartupDetails } from "./timeline/startup-preference.js";
24
26
  export type { GenieLoadingOptions } from "./timeline/genie-loading.js";
@@ -3,11 +3,13 @@ import {
3
3
  BUILT_IN_TURN_SUMMARY_FACET_IDS,
4
4
  HumanInputForm,
5
5
  HumanInputSurface,
6
+ KnowledgeActivityProvider,
6
7
  MessageTimeline,
7
8
  QueueSurface,
8
9
  SessionChrome,
9
10
  SessionCommandsPanel,
10
11
  SessionConversation,
12
+ StartupTimings,
11
13
  TimelineRow,
12
14
  UserMessageBody,
13
15
  sessionChromeGoalPillExplanation,
@@ -16,7 +18,7 @@ import {
16
18
  setStartupDetails,
17
19
  useStartupDetails,
18
20
  userMessageLikelyNeedsDisclosure
19
- } from "./chunk-QXJCNVSD.js";
21
+ } from "./chunk-CC7AVRIJ.js";
20
22
  import "./chunk-YBM6CQRU.js";
21
23
  import "./chunk-5M6VTFJ5.js";
22
24
  import "./chunk-ZYRGEKWS.js";
@@ -26,127 +28,24 @@ import "./chunk-IHQII5WO.js";
26
28
  import "./chunk-JVYQRRC4.js";
27
29
  import "./chunk-45XEUVTK.js";
28
30
  import "./chunk-HQV2I5HV.js";
29
- import "./chunk-2TKI3WEG.js";
31
+ import "./chunk-WYWRYUNQ.js";
30
32
  import "./chunk-R4KRSFGA.js";
31
33
  import "./chunk-VZTQ73XT.js";
32
34
  import {
33
35
  createOlderHistoryLoadReceipt
34
- } from "./chunk-IYCR4343.js";
36
+ } from "./chunk-PZ27MCZP.js";
35
37
  import "./chunk-NYESIADM.js";
36
38
  import "./chunk-PLYRL5ER.js";
37
39
  import "./chunk-KZ73RL76.js";
38
40
  import "./chunk-NEXLLTP4.js";
39
41
  import "./chunk-VRBL3F5E.js";
40
42
  import "./chunk-22KP6LR5.js";
41
-
42
- // src/timeline/startup-timings.tsx
43
- import { jsx, jsxs } from "react/jsx-runtime";
44
- var LABELS = {
45
- queue: "Worker queue",
46
- sandbox: "Sandbox",
47
- rig: "Rig",
48
- repository: "Repository",
49
- files: "Files",
50
- tools: "Tools",
51
- model_preparation: "Runtime & model request",
52
- provider_first_byte: "First model response"
53
- };
54
- function StartupTimings({ phases }) {
55
- if (!phases.length)
56
- return /* @__PURE__ */ jsx("p", { className: "text-og-sm text-og-fg-subtle", children: "No startup timings recorded yet." });
57
- const byTurn = /* @__PURE__ */ new Map();
58
- for (const phase of phases) {
59
- const group = byTurn.get(phase.turnId) ?? [];
60
- group.push(phase);
61
- byTurn.set(phase.turnId, group);
62
- }
63
- const turns = [...byTurn.entries()].map(([turnId, turnPhases]) => ({
64
- turnId,
65
- phases: turnPhases,
66
- startedAt: turnPhases.reduce(
67
- (earliest, phase) => phase.startedAt < earliest ? phase.startedAt : earliest,
68
- turnPhases[0].startedAt
69
- )
70
- })).sort((a, b) => b.startedAt.localeCompare(a.startedAt));
71
- return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
72
- /* @__PURE__ */ jsx("p", { className: "text-og-xs text-og-fg-subtle", children: "Each turn has its own startup. Phases can overlap; durations are not additive." }),
73
- turns.map((turn, index) => /* @__PURE__ */ jsx(
74
- StartupTurn,
75
- {
76
- ...turn,
77
- latest: index === 0 && turn.turnId !== null
78
- },
79
- turn.turnId ?? "unassigned"
80
- ))
81
- ] });
82
- }
83
- function StartupTurn({
84
- turnId,
85
- phases,
86
- startedAt,
87
- latest
88
- }) {
89
- const status = phases.some((phase) => phase.status === "failed") ? "Failed" : phases.some((phase) => phase.status === "running") ? "In progress" : phases.some((phase) => phase.status === "cancelled") ? "Interrupted" : "Ready";
90
- return /* @__PURE__ */ jsxs("details", { open: latest, className: "group border-b border-og-border pb-3", children: [
91
- /* @__PURE__ */ jsxs("summary", { className: "cursor-pointer rounded py-3 text-og-sm text-og-fg-muted focus-visible:outline-2 focus-visible:outline-og-accent", children: [
92
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: turnId === null ? "Unassigned events" : latest ? "Latest turn" : "Earlier turn" }),
93
- /* @__PURE__ */ jsx("span", { className: "ml-2 text-og-xs text-og-fg-subtle", children: new Date(startedAt).toLocaleTimeString([], {
94
- hour: "2-digit",
95
- minute: "2-digit",
96
- second: "2-digit"
97
- }) }),
98
- /* @__PURE__ */ jsx(
99
- "span",
100
- {
101
- className: status === "Failed" ? "ml-2 text-og-xs text-og-status-failed" : "ml-2 text-og-xs text-og-fg-subtle",
102
- children: status
103
- }
104
- ),
105
- /* @__PURE__ */ jsx("span", { className: "mt-1 block break-all pl-4 font-og-mono text-og-xs text-og-fg-subtle", children: turnId ?? "No turn ID recorded" })
106
- ] }),
107
- /* @__PURE__ */ jsxs("div", { className: "pb-2", children: [
108
- /* @__PURE__ */ jsxs("p", { className: "text-og-xs text-og-fg-subtle", children: [
109
- "Started ",
110
- /* @__PURE__ */ jsx("time", { dateTime: startedAt, children: new Date(startedAt).toLocaleString() })
111
- ] }),
112
- /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-left text-og-xs", children: [
113
- /* @__PURE__ */ jsxs("caption", { className: "sr-only", children: [
114
- "Startup phases for ",
115
- turnId ?? "unassigned events"
116
- ] }),
117
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-og-border text-og-fg-subtle", children: [
118
- /* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-medium", children: "Phase" }),
119
- /* @__PURE__ */ jsx("th", { scope: "col", className: "px-3 py-2 font-medium", children: "Status" }),
120
- /* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 text-right font-medium", children: "Duration" })
121
- ] }) }),
122
- /* @__PURE__ */ jsx("tbody", { children: phases.map((phase) => /* @__PURE__ */ jsxs(
123
- "tr",
124
- {
125
- className: "border-b border-og-border/40",
126
- title: `Turn: ${phase.turnId ?? "unknown"} \xB7 Started: ${phase.startedAt}`,
127
- children: [
128
- /* @__PURE__ */ jsx("th", { scope: "row", className: "py-2.5 font-normal text-og-fg-muted", children: LABELS[phase.phase] }),
129
- /* @__PURE__ */ jsx(
130
- "td",
131
- {
132
- className: `px-3 py-2.5 ${phase.status === "failed" ? "text-og-status-failed" : "text-og-fg-subtle"}`,
133
- children: phase.status === "running" ? "In progress" : phase.status
134
- }
135
- ),
136
- /* @__PURE__ */ jsx("td", { className: "py-2.5 text-right font-og-mono tabular-nums text-og-fg-muted", children: phase.durationMs === null ? "\u2014" : phase.durationMs < 1e3 ? `${Math.round(phase.durationMs)} ms` : `${(phase.durationMs / 1e3).toFixed(1)} s` })
137
- ]
138
- },
139
- phase.id
140
- )) })
141
- ] }) })
142
- ] })
143
- ] });
144
- }
145
43
  export {
146
44
  ApprovalSurface,
147
45
  BUILT_IN_TURN_SUMMARY_FACET_IDS,
148
46
  HumanInputForm,
149
47
  HumanInputSurface,
48
+ KnowledgeActivityProvider,
150
49
  MessageTimeline,
151
50
  QueueSurface,
152
51
  SessionChrome,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/timeline/startup-timings.tsx"],"sourcesContent":["import type { StartupPhaseItem } from \"./types\";\n\nconst LABELS: Record<StartupPhaseItem[\"phase\"], string> = {\n queue: \"Worker queue\",\n sandbox: \"Sandbox\",\n rig: \"Rig\",\n repository: \"Repository\",\n files: \"Files\",\n tools: \"Tools\",\n model_preparation: \"Runtime & model request\",\n provider_first_byte: \"First model response\",\n};\n\nexport function StartupTimings({ phases }: { phases: StartupPhaseItem[] }) {\n if (!phases.length)\n return <p className=\"text-og-sm text-og-fg-subtle\">No startup timings recorded yet.</p>;\n const byTurn = new Map<string | null, StartupPhaseItem[]>();\n for (const phase of phases) {\n const group = byTurn.get(phase.turnId) ?? [];\n group.push(phase);\n byTurn.set(phase.turnId, group);\n }\n const turns = [...byTurn.entries()]\n .map(([turnId, turnPhases]) => ({\n turnId,\n phases: turnPhases,\n startedAt: turnPhases.reduce(\n (earliest, phase) => (phase.startedAt < earliest ? phase.startedAt : earliest),\n turnPhases[0]!.startedAt,\n ),\n }))\n .sort((a, b) => b.startedAt.localeCompare(a.startedAt));\n return (\n <div className=\"space-y-3\">\n <p className=\"text-og-xs text-og-fg-subtle\">\n Each turn has its own startup. Phases can overlap; durations are not additive.\n </p>\n {turns.map((turn, index) => (\n <StartupTurn\n key={turn.turnId ?? \"unassigned\"}\n {...turn}\n latest={index === 0 && turn.turnId !== null}\n />\n ))}\n </div>\n );\n}\n\nfunction StartupTurn({\n turnId,\n phases,\n startedAt,\n latest,\n}: {\n turnId: string | null;\n phases: StartupPhaseItem[];\n startedAt: string;\n latest: boolean;\n}) {\n const status = phases.some((phase) => phase.status === \"failed\")\n ? \"Failed\"\n : phases.some((phase) => phase.status === \"running\")\n ? \"In progress\"\n : phases.some((phase) => phase.status === \"cancelled\")\n ? \"Interrupted\"\n : \"Ready\";\n return (\n <details open={latest} className=\"group border-b border-og-border pb-3\">\n <summary className=\"cursor-pointer rounded py-3 text-og-sm text-og-fg-muted focus-visible:outline-2 focus-visible:outline-og-accent\">\n <span className=\"font-medium\">\n {turnId === null ? \"Unassigned events\" : latest ? \"Latest turn\" : \"Earlier turn\"}\n </span>\n <span className=\"ml-2 text-og-xs text-og-fg-subtle\">\n {new Date(startedAt).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n })}\n </span>\n <span\n className={\n status === \"Failed\"\n ? \"ml-2 text-og-xs text-og-status-failed\"\n : \"ml-2 text-og-xs text-og-fg-subtle\"\n }\n >\n {status}\n </span>\n <span className=\"mt-1 block break-all pl-4 font-og-mono text-og-xs text-og-fg-subtle\">\n {turnId ?? \"No turn ID recorded\"}\n </span>\n </summary>\n <div className=\"pb-2\">\n <p className=\"text-og-xs text-og-fg-subtle\">\n Started <time dateTime={startedAt}>{new Date(startedAt).toLocaleString()}</time>\n </p>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-left text-og-xs\">\n <caption className=\"sr-only\">\n Startup phases for {turnId ?? \"unassigned events\"}\n </caption>\n <thead>\n <tr className=\"border-b border-og-border text-og-fg-subtle\">\n <th scope=\"col\" className=\"py-2 font-medium\">\n Phase\n </th>\n <th scope=\"col\" className=\"px-3 py-2 font-medium\">\n Status\n </th>\n <th scope=\"col\" className=\"py-2 text-right font-medium\">\n Duration\n </th>\n </tr>\n </thead>\n <tbody>\n {phases.map((phase) => (\n <tr\n key={phase.id}\n className=\"border-b border-og-border/40\"\n title={`Turn: ${phase.turnId ?? \"unknown\"} · Started: ${phase.startedAt}`}\n >\n <th scope=\"row\" className=\"py-2.5 font-normal text-og-fg-muted\">\n {LABELS[phase.phase]}\n </th>\n <td\n className={`px-3 py-2.5 ${phase.status === \"failed\" ? \"text-og-status-failed\" : \"text-og-fg-subtle\"}`}\n >\n {phase.status === \"running\" ? \"In progress\" : phase.status}\n </td>\n <td className=\"py-2.5 text-right font-og-mono tabular-nums text-og-fg-muted\">\n {phase.durationMs === null\n ? \"—\"\n : phase.durationMs < 1000\n ? `${Math.round(phase.durationMs)} ms`\n : `${(phase.durationMs / 1000).toFixed(1)} s`}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </details>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/session.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  useSessionControl,
11
11
  useSessionLineage,
12
12
  useSessionMcpApprovalPolicy
13
- } from "./chunk-5PQJOCX5.js";
13
+ } from "./chunk-KANFU34B.js";
14
14
  import {
15
15
  buildTimeline,
16
16
  createOlderHistoryLoadReceipt,
@@ -28,7 +28,7 @@ import {
28
28
  useSession,
29
29
  useSessionEvents,
30
30
  useTurnQueue
31
- } from "./chunk-IYCR4343.js";
31
+ } from "./chunk-PZ27MCZP.js";
32
32
  import {
33
33
  FILE_ONLY_MESSAGE_TEXT,
34
34
  composeSendInput,
@@ -8,7 +8,15 @@ export type GenieLoadingOptions = {
8
8
  /** Replace the visual while preserving SDK loading visibility and transitions. */
9
9
  render?: (props: GenieLoadingRenderProps) => ReactNode;
10
10
  phrases?: readonly string[];
11
- /** Public options stay independent of the renderer's declaration layout. */
11
+ /** Native copy overrides. Omitted messages retain the default English copy. */
12
+ messages?: {
13
+ status?: string;
14
+ slowStatus?: string;
15
+ slowText?: string;
16
+ showDetails?: string;
17
+ hideDetails?: string;
18
+ };
19
+ /** Public adapter options; the renderer dependency's declarations stay private. */
12
20
  orb?: {
13
21
  state?: "working" | "searching" | "solving" | "listening" | "connecting" | "weaving" | "composing" | "breathing" | "shaping";
14
22
  size?: 64 | 20;
@@ -1,5 +1,5 @@
1
1
  export { buildTimeline, creditExhaustedFromEvents, extractSessionRef, groupTimeline, sessionStatusFromEvents, mcpToolLeaf, toolDisplayName, toolMatchesLeaf, } from "./projection.js";
2
- export type { ActivityItem, AgentMessageItem, AuthNeededItem, ContextCompactionItem, FleetDecisionItem, FleetDecisionScoreItem, GoalItem, HumanInputAnswerSummary, HumanInputItem, MachineInputBatchItem, MachineInputMember, MemoryItem, NoticeItem, ReasoningItem, SandboxItem, StartupPhase, StartupPhaseItem, SessionStatusItem, TimelineGroup, TimelineItem, TimelineAnnotationSourceDescriptor, TurnEndItem, ToolCallItem, UserMessageItem, WorkerCompletionItem, WorkerItem, } from "./types.js";
2
+ export type { ActivityItem, AgentMessageItem, AuthNeededItem, ContextCompactionItem, FleetDecisionItem, FleetDecisionScoreItem, GoalItem, HumanInputAnswerSummary, HumanInputItem, MachineInputBatchItem, MachineInputMember, MemoryItem, KnowledgeItem, NoticeItem, ReasoningItem, SandboxItem, StartupPhase, StartupPhaseItem, SessionStatusItem, TimelineGroup, TimelineItem, TimelineAnnotationSourceDescriptor, TurnEndItem, ToolCallItem, UserMessageItem, WorkerCompletionItem, WorkerItem, } from "./types.js";
3
3
  export { createToolRegistry, rawTypeOf } from "./registry.js";
4
4
  export type { CreateToolRegistryOptions, RetainedArtifactLoader, RetainedScreenshotLoader, VideoArtifactPlaybackLoader, ToolRegistry, ToolRegistryEntry, ToolRenderer, ToolRendererProps, } from "./registry.js";
5
5
  export { createDefaultToolRegistry, defaultToolRegistry } from "./tool-renderers.js";
@@ -18,3 +18,5 @@ export { BUILT_IN_TURN_SUMMARY_FACET_IDS, TurnSummary, useTurnSettleOpen } from
18
18
  export type { BuiltInTurnSummaryFacetId, TurnOutcome, TurnSummaryContext, TurnSummaryFacet, TurnSummaryFacetConfiguration, TurnSummaryFacetResult, TurnSummaryOptions, TurnSummaryProps, } from "./turn-summary.js";
19
19
  export { applyPatchOps, applyPatchOpsFromToolItem, parseFreeformApplyPatch, controlCaret, execTruncated, isApplyPatch, isExecSessionLostBanner, looksBinary, parseExecBannerSessionId, parseToolArgs, sandboxCommandExitCode, stripExecBanner, tailPeek, unwrapMcpOutput, v4aToGitFileDiff, } from "./parsers.js";
20
20
  export type { ApplyPatchOperation } from "./parsers.js";
21
+ export { KnowledgeActivityProvider } from "./knowledge-receipt.js";
22
+ export type { KnowledgeActivityActions } from "./knowledge-receipt.js";
@@ -0,0 +1,17 @@
1
+ import { type ReactNode } from "react";
2
+ export type KnowledgeActivityActions = {
3
+ onInspect?: ((entryId: string) => void) | undefined;
4
+ onRetryFile?: ((fileId: string) => Promise<boolean | void>) | undefined;
5
+ retryDisabled?: boolean | undefined;
6
+ };
7
+ export declare function KnowledgeActivityProvider({ children, ...actions }: KnowledgeActivityActions & {
8
+ children: ReactNode;
9
+ }): import("react").JSX.Element;
10
+ /** A saved/pending result never opens or blocks the human-input surface. */
11
+ export declare function KnowledgeReceiptRow(props: {
12
+ outcome: "published" | "pending" | "rejected" | "archived" | "failed";
13
+ entryId?: string | undefined;
14
+ fileId?: string | undefined;
15
+ title?: string | undefined;
16
+ source?: boolean | undefined;
17
+ }): import("react").JSX.Element;
@@ -8,7 +8,6 @@ export default function PlatformActivityRow({ item, d: ActivityDisclosure, p: Pa
8
8
  t: (name: string) => string;
9
9
  b: typeof import("lucide-react").BotIcon;
10
10
  m: typeof import("../components/markdown.js").Markdown;
11
- r: typeof import("../lib/format.js").truncate;
12
11
  j: RowJsx;
13
12
  s: RowJsxs;
14
13
  }): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -12,5 +12,7 @@ type RetainedImageState = {
12
12
  kind: "error";
13
13
  message: string;
14
14
  };
15
+ /** Shared browser preview allowlist; other published files remain downloads. */
16
+ export declare function isRetainedImageContentType(contentType: string): boolean;
15
17
  export declare function useRetainedImageObjectUrl(artifact: RetainedArtifactReference, load: ToolRendererProps["loadRetainedArtifact"]): RetainedImageState;
16
18
  export {};
@@ -185,6 +185,17 @@ export type StartupPhaseItem = {
185
185
  * `onMemoryClick` handler the row also deep-links to the record in its memory
186
186
  * pane; without one it is non-interactive rich content.
187
187
  */
188
+ export type KnowledgeItem = {
189
+ kind: "knowledge";
190
+ id: string;
191
+ turnId: string | null;
192
+ status: "complete" | "failed";
193
+ outcome: "published" | "pending" | "rejected" | "archived" | "failed";
194
+ fileId?: string | undefined;
195
+ filename?: string | undefined;
196
+ entryId?: string | undefined;
197
+ occurredAt: string;
198
+ };
188
199
  export type MemoryItem = {
189
200
  kind: "memory";
190
201
  id: string;
@@ -361,9 +372,9 @@ export type TurnEndItem = {
361
372
  failureText: string | null;
362
373
  occurredAt: string;
363
374
  };
364
- export type TimelineItem = UserMessageItem | HumanInputItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | StartupPhaseItem | SessionStatusItem | GoalItem | NoticeItem | ContextCompactionItem | MachineInputBatchItem | AuthNeededItem | MemoryItem | FleetDecisionItem | TurnEndItem;
375
+ export type TimelineItem = UserMessageItem | HumanInputItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | StartupPhaseItem | SessionStatusItem | GoalItem | NoticeItem | ContextCompactionItem | MachineInputBatchItem | AuthNeededItem | MemoryItem | KnowledgeItem | FleetDecisionItem | TurnEndItem;
365
376
  /** Activity items cluster between chat messages (reasoning, tools, workers, sandbox, memory). */
366
- export type ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem | StartupPhaseItem | MemoryItem | FleetDecisionItem;
377
+ export type ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem | StartupPhaseItem | MemoryItem | KnowledgeItem | FleetDecisionItem;
367
378
  export type TimelineGroup = {
368
379
  kind: "item";
369
380
  item: TimelineItem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/react",
3
- "version": "5.2.0-canary.0",
3
+ "version": "6.0.0-canary.0",
4
4
  "description": "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views — token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -133,8 +133,8 @@
133
133
  "@dnd-kit/utilities": "3.2.2",
134
134
  "@fontsource-variable/noto-sans-arabic": "5.2.10",
135
135
  "@fontsource-variable/noto-sans-jp": "5.2.10",
136
- "@opengeni/connect": "^0.2.0-canary.7",
137
- "@opengeni/sdk": "^5.1.0-canary.1",
136
+ "@opengeni/connect": "^0.2.0-canary.9",
137
+ "@opengeni/sdk": "^6.0.0-canary.0",
138
138
  "clsx": "^2.1.1",
139
139
  "dequal": "2.0.3",
140
140
  "lucide-react": "^1.8.0",
package/src/artifacts.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { inlineHtmlDocument } from "./components/artifacts/inline-html-document";
2
- export { useRetainedImageObjectUrl } from "./timeline/retained-image";
2
+ export { isRetainedImageContentType, useRetainedImageObjectUrl } from "./timeline/retained-image";
3
3
  /** Public artifact surfaces. Import from `@opengeni/react/artifacts`. */
4
4
  export {
5
5
  ArtifactSurface,
@@ -567,7 +567,12 @@ export function ComputerViewer({
567
567
  if (relevant[0]) selectComputerSession({ sessionId: relevant[0].id, pinned: false });
568
568
  }}
569
569
  onCreate={hideGenericCreate ? undefined : createComputer}
570
- onRefresh={() => void Promise.all([refreshRegistry(), refreshComputer()])}
570
+ onRefresh={() => {
571
+ if (frames.state === "error" && !generationLossSelected && !generationLossFrames) {
572
+ frames.reconnect();
573
+ }
574
+ void Promise.all([refreshRegistry(), refreshComputer()]);
575
+ }}
571
576
  />
572
577
  <InteractionInterventionBanner
573
578
  interventions={selectedInterventions}
@@ -1031,8 +1036,11 @@ function ComputerViewport(props: {
1031
1036
  actionRef.current = props.onAction;
1032
1037
  readClipboardRef.current = props.onReadClipboard;
1033
1038
  errorRef.current = props.onError;
1039
+ const streamFailed = props.connectionState === "error";
1034
1040
  const rawInputEnabled =
1035
- !props.backgroundActions || props.target?.kind === "screen" || props.target?.focused === true;
1041
+ !streamFailed &&
1042
+ !props.machineLocked &&
1043
+ (!props.backgroundActions || props.target?.kind === "screen" || props.target?.focused === true);
1036
1044
 
1037
1045
  const paintQueuedFrames = useCallback(() => {
1038
1046
  if (decodingFrameRef.current) return;
@@ -1346,7 +1354,7 @@ function ComputerViewport(props: {
1346
1354
  if (inputRef.current) inputRef.current.value = "";
1347
1355
  };
1348
1356
 
1349
- const showCanvas = props.frame !== null && !props.machineLocked;
1357
+ const showCanvas = props.frame !== null && !props.machineLocked && !streamFailed;
1350
1358
  return (
1351
1359
  <div className="relative min-h-0 flex-1 overflow-hidden bg-black">
1352
1360
  <canvas
@@ -2,6 +2,10 @@ import { RollingActivity } from "../timeline/rolling-activity";
2
2
  import { GenieLoadingOptionsContext, type GenieLoadingOptions } from "../timeline/genie-loading";
3
3
  import { ChildSessionLink } from "./child-session-link";
4
4
  import { useStartupDetails } from "../timeline/startup-preference";
5
+ import { parseSandboxFileArtifactReceipt } from "@opengeni/sdk";
6
+ import { unwrapMcpOutput } from "../timeline/parsers";
7
+ import { isRetainedImageContentType } from "../timeline/retained-image";
8
+ import { mcpToolLeaf } from "../timeline/tool-display-name";
5
9
  import type {
6
10
  DraftTimelineAnnotation,
7
11
  MediaGenerationResult,
@@ -2537,9 +2541,15 @@ const TimelineGroupView = memo(function TimelineGroupView({
2537
2541
  // Settled (or live-fold) activity clusters get a chip. Inside an expanded
2538
2542
  // turn that is the second layer — quiet nested chips under the outer turn
2539
2543
  // summary when contiguous activity naturally clusters (≥2 only).
2544
+ const containsPresentedImage = timelineGroupContainsPresentedImage(group);
2545
+ const hasRememberedImageFold =
2546
+ group.kind === "activity" && containsPresentedImage && foldMemory?.has(group.id);
2547
+ // Primary images stay visible through live narration and the turn wrap.
2548
+ // Manual collapse still belongs to TurnSummary's existing fold memory.
2540
2549
  const activityShouldFold =
2541
- group.kind === "activity" && !!(group.outcome || (foldLiveCluster && clusterIsSettled(group)));
2542
- const containsGeneratedImage = timelineGroupContainsGeneratedImage(group);
2550
+ group.kind === "activity" &&
2551
+ !containsPresentedImage &&
2552
+ !!(group.outcome || (foldLiveCluster && clusterIsSettled(group)));
2543
2553
  // Latch live→folded so a top-level shell that was already mounted open can
2544
2554
  // start the settle beat without remounting bare rail → wrapper.
2545
2555
  const liveActivitySettle = useLiveSettleFold(activityShouldFold && !insideTurn);
@@ -2548,7 +2558,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
2548
2558
  group.kind === "turn" &&
2549
2559
  (group.outcome === "failed" ||
2550
2560
  timelineGroupContainsAuthNeeded(group) ||
2551
- containsGeneratedImage);
2561
+ containsPresentedImage);
2552
2562
  // activity-* → turn-* remount: carry resting state so settleFold does not
2553
2563
  // re-open a chip the reader already watched collapse.
2554
2564
  if (group.kind === "turn" && foldMemory && !insideTurn) {
@@ -2589,6 +2599,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
2589
2599
  if (
2590
2600
  turnSummary?.rolling &&
2591
2601
  !startupDetails &&
2602
+ !hasRememberedImageFold &&
2592
2603
  group.items.filter((item) => item.kind !== "startup-phase").length === 1
2593
2604
  ) {
2594
2605
  return (
@@ -2620,8 +2631,12 @@ const TimelineGroupView = memo(function TimelineGroupView({
2620
2631
  !startupDetails &&
2621
2632
  visibleActivity.length === 1 &&
2622
2633
  visibleActivity[0]?.kind === "reasoning";
2634
+ // Untouched images stay primary output, but a reader-owned image fold
2635
+ // must keep its shell across a multi-cluster wrap. A bare rail would
2636
+ // bypass the remembered choice; retaining either state also lets the
2637
+ // reader reopen and close the same chip after settlement.
2623
2638
  const useNestedChip =
2624
- nestClusterChips && activityShouldFold && !containsGeneratedImage && !singleThought;
2639
+ nestClusterChips && (activityShouldFold || hasRememberedImageFold) && !singleThought;
2625
2640
  if (!useNestedChip) {
2626
2641
  return (
2627
2642
  <ActivityRail
@@ -2663,16 +2678,24 @@ const TimelineGroupView = memo(function TimelineGroupView({
2663
2678
  // flips settleFold (collapse) instead of remounting bare rail → wrapper.
2664
2679
  return (
2665
2680
  <TurnSummary
2681
+ // Apply the primary-output default when a rolling activity first
2682
+ // produces an image; the stable foldKey still preserves user choices.
2683
+ key={containsPresentedImage ? "primary-image" : "activity"}
2666
2684
  items={group.items}
2667
2685
  outcome={group.outcome}
2668
2686
  failureText={group.failureText}
2669
2687
  defaultOpen={
2670
- group.outcome === "failed" || (!turnSummary?.rolling && !activityShouldFold)
2688
+ group.outcome === "failed" ||
2689
+ containsPresentedImage ||
2690
+ (!turnSummary?.rolling && !activityShouldFold)
2671
2691
  ? true
2672
2692
  : undefined
2673
2693
  }
2674
2694
  liveHeader={
2675
- turnSummary?.rolling && !group.outcome && !foldLiveCluster ? (
2695
+ turnSummary?.rolling &&
2696
+ !containsPresentedImage &&
2697
+ !group.outcome &&
2698
+ !foldLiveCluster ? (
2676
2699
  <RollingActivity
2677
2700
  items={group.items}
2678
2701
  toolRegistry={toolRegistry}
@@ -2862,17 +2885,24 @@ function timelineGroupContainsAuthNeeded(group: TimelineGroup): boolean {
2862
2885
  }
2863
2886
  }
2864
2887
 
2865
- /** Generated images are primary user-visible output, not incidental activity. */
2866
- function timelineGroupContainsGeneratedImage(group: TimelineGroup): boolean {
2888
+ /** Deliberately published images are primary output, not incidental screenshots. */
2889
+ function timelineGroupContainsPresentedImage(group: TimelineGroup): boolean {
2867
2890
  switch (group.kind) {
2868
2891
  case "item":
2869
2892
  return false;
2870
2893
  case "activity":
2871
- return group.items.some(
2872
- (item) => item.kind === "tool-call" && item.name === "generate_image",
2873
- );
2894
+ return group.items.some((item) => {
2895
+ if (item.kind !== "tool-call") return false;
2896
+ const name = mcpToolLeaf(item.name);
2897
+ if (name === "generate_image" || name === "image_generation_call") return true;
2898
+ if (item.status !== "complete" || name !== "sandbox_file_publish") return false;
2899
+ const output = unwrapMcpOutput(item.output);
2900
+ if (output.isError) return false;
2901
+ const receipt = parseSandboxFileArtifactReceipt(output.text);
2902
+ return receipt !== null && isRetainedImageContentType(receipt.artifact.contentType);
2903
+ });
2874
2904
  case "turn":
2875
- return group.groups.some(timelineGroupContainsGeneratedImage);
2905
+ return group.groups.some(timelineGroupContainsPresentedImage);
2876
2906
  }
2877
2907
  }
2878
2908
 
@@ -100,6 +100,11 @@ export type SessionChromeProps = {
100
100
  queue: UseTurnQueueResult;
101
101
  /** Needed for queue edit → composer checkout. Omit with `readOnly`. */
102
102
  composer?: ComposerState | undefined;
103
+ /** Focus the composer after a successful queue checkout has applied its draft.
104
+ * Connect to the composer controller's `focusInput`, or a custom input ref.
105
+ * Never called for failed checkout or while replacement awaits confirmation.
106
+ */
107
+ onComposerFocus?: (() => void) | undefined;
103
108
  goal?: UseGoalResult | null | undefined;
104
109
  /** Expanded agents body (host supplies tree / list). */
105
110
  agentsPanel?: ReactNode;
@@ -431,6 +436,7 @@ export function SessionChrome({
431
436
  sessionStatus,
432
437
  queue,
433
438
  composer,
439
+ onComposerFocus,
434
440
  goal,
435
441
  agentsPanel,
436
442
  commandsPanel,
@@ -802,7 +808,10 @@ export function SessionChrome({
802
808
  expectedDraftRevision: composer.draftRevision,
803
809
  replaceDraft: true,
804
810
  });
805
- if (checkedOut) composer.applyDraft(checkedOut);
811
+ if (checkedOut) {
812
+ composer.applyDraft(checkedOut);
813
+ onComposerFocus?.();
814
+ }
806
815
  })();
807
816
  }
808
817
  : undefined
@@ -819,7 +828,10 @@ export function SessionChrome({
819
828
  expectedDraftRevision: composer.draftRevision,
820
829
  replaceDraft: false,
821
830
  });
822
- if (checkedOut) composer.applyDraft(checkedOut);
831
+ if (checkedOut) {
832
+ composer.applyDraft(checkedOut);
833
+ onComposerFocus?.();
834
+ }
823
835
  })();
824
836
  },
825
837
  );
@@ -26,22 +26,11 @@ export type ConnectionCatalogProps = {
26
26
  emptyMessage?: string;
27
27
  };
28
28
 
29
- function ConnectionDetailsAction({
30
- option,
31
- name = option.name,
32
- }: {
33
- option: ConnectionCatalogOption;
34
- name?: string;
35
- }) {
29
+ function ConnectionDetailsIndicator() {
36
30
  return (
37
- <button
38
- type="button"
39
- className="og-connection-details-action"
40
- aria-label={`View ${name} details`}
41
- onClick={option.onOpen}
42
- >
43
- <span aria-hidden>{option.connected ? "›" : "+"}</span>
44
- </button>
31
+ <span aria-hidden className="og-connection-group-chevron">
32
+
33
+ </span>
45
34
  );
46
35
  }
47
36
 
@@ -54,10 +43,9 @@ export function ConnectionOptionRow({ option }: { option: ConnectionCatalogOptio
54
43
  <span>{option.description}</span>
55
44
  </span>
56
45
  <span className="og-connection-catalog-status">{option.status}</span>
46
+ {!option.action ? <ConnectionDetailsIndicator /> : null}
57
47
  </button>
58
- <span className="og-connection-option-action">
59
- {option.action ?? <ConnectionDetailsAction option={option} />}
60
- </span>
48
+ {option.action ? <span className="og-connection-option-action">{option.action}</span> : null}
61
49
  </div>
62
50
  );
63
51
  }
@@ -91,10 +79,9 @@ export function ConnectionServiceRow({ service }: { service: ConnectionCatalogSe
91
79
  onClick={service.options[0]!.onOpen}
92
80
  >
93
81
  {identity}
82
+ {!service.options[0]?.action ? <ConnectionDetailsIndicator /> : null}
94
83
  </button>
95
- {service.options[0]?.action ?? (
96
- <ConnectionDetailsAction option={service.options[0]!} name={service.name} />
97
- )}
84
+ {service.options[0]?.action}
98
85
  </div>
99
86
  ) : (
100
87
  <details className="og-connection-catalog-service">