@opengeni/react 5.2.0-canary.0 → 5.2.0-canary.1

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 (49) hide show
  1. package/README.md +12 -0
  2. package/dist/{chunk-5PQJOCX5.js → chunk-KANFU34B.js} +6 -4
  3. package/dist/chunk-KANFU34B.js.map +1 -0
  4. package/dist/{chunk-QXJCNVSD.js → chunk-O4NQNMPG.js} +1534 -1315
  5. package/dist/chunk-O4NQNMPG.js.map +1 -0
  6. package/dist/{chunk-IYCR4343.js → chunk-PZ27MCZP.js} +36 -1
  7. package/dist/chunk-PZ27MCZP.js.map +1 -0
  8. package/dist/{chunk-T5FRXMC3.js → chunk-YS24CFDI.js} +24 -9
  9. package/dist/chunk-YS24CFDI.js.map +1 -0
  10. package/dist/components/session-chrome.d.ts +6 -1
  11. package/dist/{computer-viewer-AA4JH2AP.js → computer-viewer-CTFCJVS7.js} +2 -2
  12. package/dist/hooks/use-file-attachments.d.ts +2 -0
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +12 -4
  15. package/dist/index.js.map +1 -1
  16. package/dist/interaction.js +1 -1
  17. package/dist/{platform-activity-row-UW4UVVM4.js → platform-activity-row-DUE2W74J.js} +1 -1
  18. package/dist/platform-activity-row-DUE2W74J.js.map +1 -0
  19. package/dist/session-ui.d.ts +2 -0
  20. package/dist/session-ui.js +5 -106
  21. package/dist/session-ui.js.map +1 -1
  22. package/dist/session.js +2 -2
  23. package/dist/timeline/genie-loading.d.ts +9 -1
  24. package/dist/timeline/index.d.ts +3 -1
  25. package/dist/timeline/knowledge-receipt.d.ts +17 -0
  26. package/dist/timeline/platform-activity-row.d.ts +0 -1
  27. package/dist/timeline/types.d.ts +13 -2
  28. package/package.json +3 -3
  29. package/src/components/computer-viewer.tsx +11 -3
  30. package/src/components/session-chrome.tsx +14 -2
  31. package/src/hooks/use-computer-frame-stream.ts +17 -5
  32. package/src/hooks/use-file-attachments.ts +4 -1
  33. package/src/hooks/use-goal.ts +3 -1
  34. package/src/index.ts +6 -0
  35. package/src/session-ui.ts +3 -0
  36. package/src/timeline/activity-rail.tsx +11 -1
  37. package/src/timeline/genie-loading.tsx +18 -4
  38. package/src/timeline/index.ts +4 -0
  39. package/src/timeline/knowledge-receipt.tsx +100 -0
  40. package/src/timeline/platform-activity-row.tsx +0 -1
  41. package/src/timeline/projection.ts +40 -0
  42. package/src/timeline/tool-renderers.tsx +48 -0
  43. package/src/timeline/types.ts +14 -0
  44. package/dist/chunk-5PQJOCX5.js.map +0 -1
  45. package/dist/chunk-IYCR4343.js.map +0 -1
  46. package/dist/chunk-QXJCNVSD.js.map +0 -1
  47. package/dist/chunk-T5FRXMC3.js.map +0 -1
  48. package/dist/platform-activity-row-UW4UVVM4.js.map +0 -1
  49. /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-O4NQNMPG.js";
20
22
  import "./chunk-YBM6CQRU.js";
21
23
  import "./chunk-5M6VTFJ5.js";
22
24
  import "./chunk-ZYRGEKWS.js";
@@ -31,122 +33,19 @@ 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeW,cAkBP,YAlBO;AAbX,IAAM,SAAoD;AAAA,EACxD,OAAO;AAAA,EACP,SAAS;AAAA,EACT,KAAK;AAAA,EACL,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,mBAAmB;AAAA,EACnB,qBAAqB;AACvB;AAEO,SAAS,eAAe,EAAE,OAAO,GAAmC;AACzE,MAAI,CAAC,OAAO;AACV,WAAO,oBAAC,OAAE,WAAU,gCAA+B,8CAAgC;AACrF,QAAM,SAAS,oBAAI,IAAuC;AAC1D,aAAW,SAAS,QAAQ;AAC1B,UAAM,QAAQ,OAAO,IAAI,MAAM,MAAM,KAAK,CAAC;AAC3C,UAAM,KAAK,KAAK;AAChB,WAAO,IAAI,MAAM,QAAQ,KAAK;AAAA,EAChC;AACA,QAAM,QAAQ,CAAC,GAAG,OAAO,QAAQ,CAAC,EAC/B,IAAI,CAAC,CAAC,QAAQ,UAAU,OAAO;AAAA,IAC9B;AAAA,IACA,QAAQ;AAAA,IACR,WAAW,WAAW;AAAA,MACpB,CAAC,UAAU,UAAW,MAAM,YAAY,WAAW,MAAM,YAAY;AAAA,MACrE,WAAW,CAAC,EAAG;AAAA,IACjB;AAAA,EACF,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AACxD,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,wBAAC,OAAE,WAAU,gCAA+B,4FAE5C;AAAA,IACC,MAAM,IAAI,CAAC,MAAM,UAChB;AAAA,MAAC;AAAA;AAAA,QAEE,GAAG;AAAA,QACJ,QAAQ,UAAU,KAAK,KAAK,WAAW;AAAA;AAAA,MAFlC,KAAK,UAAU;AAAA,IAGtB,CACD;AAAA,KACH;AAEJ;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,SAAS,OAAO,KAAK,CAAC,UAAU,MAAM,WAAW,QAAQ,IAC3D,WACA,OAAO,KAAK,CAAC,UAAU,MAAM,WAAW,SAAS,IAC/C,gBACA,OAAO,KAAK,CAAC,UAAU,MAAM,WAAW,WAAW,IACjD,gBACA;AACR,SACE,qBAAC,aAAQ,MAAM,QAAQ,WAAU,wCAC/B;AAAA,yBAAC,aAAQ,WAAU,mHACjB;AAAA,0BAAC,UAAK,WAAU,eACb,qBAAW,OAAO,sBAAsB,SAAS,gBAAgB,gBACpE;AAAA,MACA,oBAAC,UAAK,WAAU,qCACb,cAAI,KAAK,SAAS,EAAE,mBAAmB,CAAC,GAAG;AAAA,QAC1C,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC,GACH;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,WACE,WAAW,WACP,0CACA;AAAA,UAGL;AAAA;AAAA,MACH;AAAA,MACA,oBAAC,UAAK,WAAU,uEACb,oBAAU,uBACb;AAAA,OACF;AAAA,IACA,qBAAC,SAAI,WAAU,QACb;AAAA,2BAAC,OAAE,WAAU,gCAA+B;AAAA;AAAA,QAClC,oBAAC,UAAK,UAAU,WAAY,cAAI,KAAK,SAAS,EAAE,eAAe,GAAE;AAAA,SAC3E;AAAA,MACA,oBAAC,SAAI,WAAU,mBACb,+BAAC,WAAM,WAAU,+BACf;AAAA,6BAAC,aAAQ,WAAU,WAAU;AAAA;AAAA,UACP,UAAU;AAAA,WAChC;AAAA,QACA,oBAAC,WACC,+BAAC,QAAG,WAAU,+CACZ;AAAA,8BAAC,QAAG,OAAM,OAAM,WAAU,oBAAmB,mBAE7C;AAAA,UACA,oBAAC,QAAG,OAAM,OAAM,WAAU,yBAAwB,oBAElD;AAAA,UACA,oBAAC,QAAG,OAAM,OAAM,WAAU,+BAA8B,sBAExD;AAAA,WACF,GACF;AAAA,QACA,oBAAC,WACE,iBAAO,IAAI,CAAC,UACX;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YACV,OAAO,SAAS,MAAM,UAAU,SAAS,kBAAe,MAAM,SAAS;AAAA,YAEvE;AAAA,kCAAC,QAAG,OAAM,OAAM,WAAU,uCACvB,iBAAO,MAAM,KAAK,GACrB;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,eAAe,MAAM,WAAW,WAAW,0BAA0B,mBAAmB;AAAA,kBAElG,gBAAM,WAAW,YAAY,gBAAgB,MAAM;AAAA;AAAA,cACtD;AAAA,cACA,oBAAC,QAAG,WAAU,gEACX,gBAAM,eAAe,OAClB,WACA,MAAM,aAAa,MACjB,GAAG,KAAK,MAAM,MAAM,UAAU,CAAC,QAC/B,IAAI,MAAM,aAAa,KAAM,QAAQ,CAAC,CAAC,MAC/C;AAAA;AAAA;AAAA,UAlBK,MAAM;AAAA,QAmBb,CACD,GACH;AAAA,SACF,GACF;AAAA,OACF;AAAA,KACF;AAEJ;","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>>;
@@ -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": "5.2.0-canary.1",
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.8",
137
+ "@opengeni/sdk": "^5.1.0-canary.2",
138
138
  "clsx": "^2.1.1",
139
139
  "dequal": "2.0.3",
140
140
  "lucide-react": "^1.8.0",
@@ -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
@@ -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
  );
@@ -159,9 +159,19 @@ export function useComputerFrameStream(
159
159
  pendingFrame = null;
160
160
  };
161
161
 
162
+ const clearRecoveryTimers = () => {
163
+ if (reconnectTimer) clearTimeout(reconnectTimer);
164
+ if (expiryTimer) clearTimeout(expiryTimer);
165
+ reconnectTimer = null;
166
+ expiryTimer = null;
167
+ };
168
+
162
169
  const scheduleReconnect = () => {
163
170
  if (disposed || reconnectTimer) return;
164
- if (failures >= MAX_AUTOMATIC_RECONNECTS_WITHOUT_A_FRAME) return;
171
+ if (failures >= MAX_AUTOMATIC_RECONNECTS_WITHOUT_A_FRAME) {
172
+ clearRecoveryTimers();
173
+ return;
174
+ }
165
175
  const delay = Math.min(5_000, 250 * 2 ** Math.min(failures, 5));
166
176
  failures += 1;
167
177
  setResult((current) => ({ ...current, state: "reconnecting" }));
@@ -177,6 +187,7 @@ export function useComputerFrameStream(
177
187
  setResult((current) => ({ ...current, state: "error", error }));
178
188
  clearSocket();
179
189
  if (reconnectAutomatically) scheduleReconnect();
190
+ else clearRecoveryTimers();
180
191
  };
181
192
 
182
193
  const onOpen = (source: ComputerFrameWebSocket) => {
@@ -295,8 +306,7 @@ export function useComputerFrameStream(
295
306
 
296
307
  const onClose = (source: ComputerFrameWebSocket) => {
297
308
  if (disposed || source !== socket) return;
298
- clearSocket();
299
- scheduleReconnect();
309
+ fail(new Error("Desktop view lost connection."));
300
310
  };
301
311
 
302
312
  const connectSocket = () => {
@@ -366,6 +376,9 @@ export function useComputerFrameStream(
366
376
  throw new Error("desktop attachment does not match the requested resource");
367
377
  }
368
378
  controllerGeneration = attachment.controllerGeneration;
379
+ // A fresh attachment owns a new producer whose sequence can restart.
380
+ // Transport reconnects reuse the attachment and retain their sequence fence.
381
+ latestRef.current = { key: "", sequence: -1 };
369
382
  activeAttachment = attachment;
370
383
  activeStream = attachment.stream;
371
384
  attachmentExpiresAt = Date.parse(attachment.expiresAt);
@@ -406,8 +419,7 @@ export function useComputerFrameStream(
406
419
  disposed = true;
407
420
  pendingFrame = null;
408
421
  attachmentAbort.abort();
409
- if (reconnectTimer) clearTimeout(reconnectTimer);
410
- if (expiryTimer) clearTimeout(expiryTimer);
422
+ clearRecoveryTimers();
411
423
  clearSocket(true);
412
424
  };
413
425
  }, [client, enabled, nonce, options.computerSessionId, options.targetId, workspaceId]);
@@ -13,6 +13,8 @@ export type UseFileAttachmentsOptions = EmbeddedFileAttachmentClientOverride & {
13
13
  * UseFileAttachmentsResult.addFiles} (the explicit picker / drop path)
14
14
  * bypasses it.
15
15
  */
16
+ /** Retain original uploads in the chat owner’s personal scope when private. */
17
+ scope?: "workspace" | "personal";
16
18
  pasteFilter?: ((file: File) => boolean) | undefined;
17
19
  };
18
20
 
@@ -212,6 +214,7 @@ export function useFileAttachments(
212
214
  filename: file.name || "file",
213
215
  contentType: file.type || "application/octet-stream",
214
216
  data: file,
217
+ ...(options.scope ? { scope: options.scope } : {}),
215
218
  })
216
219
  .then((asset) => {
217
220
  if (scopeGeneration.current !== generation) return;
@@ -252,7 +255,7 @@ export function useFileAttachments(
252
255
  );
253
256
  });
254
257
  },
255
- [client, workspaceId],
258
+ [client, workspaceId, options.scope],
256
259
  );
257
260
 
258
261
  const addFiles = useCallback(
@@ -138,7 +138,9 @@ export function useGoal(
138
138
  return;
139
139
  }
140
140
  if (sharedFeed) {
141
- setLoading(false);
141
+ // A shared log supplies invalidations, not the authoritative goal snapshot.
142
+ setLoading(true);
143
+ void load();
142
144
  return () => {
143
145
  retireLoads();
144
146
  };
package/src/index.ts CHANGED
@@ -617,3 +617,9 @@ export {
617
617
  tryParseJson,
618
618
  } from "./lib/format";
619
619
  export { SessionCommandsPanel } from "./components/session-commands-panel";
620
+
621
+ export { KnowledgeActivityProvider } from "./timeline/knowledge-receipt";
622
+ export type { KnowledgeActivityActions } from "./timeline/knowledge-receipt";
623
+
624
+ export { StartupTimings } from "./timeline/startup-timings";
625
+ export { setStartupDetails, useStartupDetails } from "./timeline/startup-preference";
package/src/session-ui.ts CHANGED
@@ -46,6 +46,9 @@ export type {
46
46
  SessionChromeSignalTone,
47
47
  } from "./components/session-chrome";
48
48
  export { SessionCommandsPanel } from "./components/session-commands-panel";
49
+
50
+ export { KnowledgeActivityProvider } from "./timeline/knowledge-receipt";
51
+ export type { KnowledgeActivityActions } from "./timeline/knowledge-receipt";
49
52
  export { StartupTimings } from "./timeline/startup-timings";
50
53
  export { useStartupDetails, setStartupDetails } from "./timeline/startup-preference";
51
54
  export type { GenieLoadingOptions } from "./timeline/genie-loading";
@@ -1,3 +1,4 @@
1
+ import { KnowledgeReceiptRow } from "./knowledge-receipt";
1
2
  import { AnimatePresence, motion, useReducedMotion } from "motion/react";
2
3
  import { GenieLoading } from "./genie-loading";
3
4
  import { useStartupDetails } from "./startup-preference";
@@ -241,7 +242,6 @@ export function renderActivity(
241
242
  t={toolDisplayName}
242
243
  b={BotIcon}
243
244
  m={Markdown}
244
- r={truncate}
245
245
  j={rowJsx}
246
246
  s={rowJsxs}
247
247
  />
@@ -261,6 +261,16 @@ export function renderActivity(
261
261
  }
262
262
  case "worker":
263
263
  return <WorkerRow item={item} onOpenSession={onOpenSession} />;
264
+ case "knowledge":
265
+ return (
266
+ <KnowledgeReceiptRow
267
+ outcome={item.outcome}
268
+ entryId={item.entryId}
269
+ fileId={item.fileId}
270
+ title={item.filename}
271
+ source={Boolean(item.fileId)}
272
+ />
273
+ );
264
274
  case "memory":
265
275
  return <MemoryRow item={item} onMemoryClick={onMemoryClick} />;
266
276
  case "fleet-decision":
@@ -12,7 +12,15 @@ export type GenieLoadingOptions = {
12
12
  /** Replace the visual while preserving SDK loading visibility and transitions. */
13
13
  render?: (props: GenieLoadingRenderProps) => ReactNode;
14
14
  phrases?: readonly string[];
15
- /** Public options stay independent of the renderer's declaration layout. */
15
+ /** Native copy overrides. Omitted messages retain the default English copy. */
16
+ messages?: {
17
+ status?: string;
18
+ slowStatus?: string;
19
+ slowText?: string;
20
+ showDetails?: string;
21
+ hideDetails?: string;
22
+ };
23
+ /** Public adapter options; the renderer dependency's declarations stay private. */
16
24
  orb?: {
17
25
  state?:
18
26
  | "working"
@@ -90,10 +98,14 @@ export function GenieLoading({
90
98
  </div>
91
99
  <div className="og-genie-copy">
92
100
  <span className="sr-only" role="status">
93
- {slow ? "Preparing your task. Taking longer than usual." : "Preparing your task."}
101
+ {slow
102
+ ? (options?.messages?.slowStatus ?? "Preparing your task. Taking longer than usual.")
103
+ : (options?.messages?.status ?? "Preparing your task.")}
94
104
  </span>
95
105
  <span key={slow ? "slow" : phrase} className="og-genie-phrase" aria-hidden="true">
96
- {slow ? "A little longer than usual…" : phrases[phrase % phrases.length]}
106
+ {slow
107
+ ? (options?.messages?.slowText ?? "A little longer than usual…")
108
+ : phrases[phrase % phrases.length]}
97
109
  </span>
98
110
  {showDetails || detailsOpen ? (
99
111
  <button
@@ -102,7 +114,9 @@ export function GenieLoading({
102
114
  aria-expanded={detailsOpen}
103
115
  onClick={onShowDetails}
104
116
  >
105
- {detailsOpen ? "Hide details" : "Behind the magic"}
117
+ {detailsOpen
118
+ ? (options?.messages?.hideDetails ?? "Hide details")
119
+ : (options?.messages?.showDetails ?? "Behind the magic")}
106
120
  <span aria-hidden="true"> ↗</span>
107
121
  </button>
108
122
  ) : null}