@opengeni/react 0.13.0 → 0.20.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 (113) hide show
  1. package/README.md +129 -23
  2. package/dist/chunk-6BXBGJ3B.js +1956 -0
  3. package/dist/chunk-6BXBGJ3B.js.map +1 -0
  4. package/dist/chunk-6UT5OC3P.js +2133 -0
  5. package/dist/chunk-6UT5OC3P.js.map +1 -0
  6. package/dist/chunk-EBTT3MYN.js +92 -0
  7. package/dist/chunk-EBTT3MYN.js.map +1 -0
  8. package/dist/chunk-HHFA4AFX.js +425 -0
  9. package/dist/chunk-HHFA4AFX.js.map +1 -0
  10. package/dist/chunk-LAZ2A743.js +2393 -0
  11. package/dist/chunk-LAZ2A743.js.map +1 -0
  12. package/dist/chunk-MRSECXRP.js +563 -0
  13. package/dist/chunk-MRSECXRP.js.map +1 -0
  14. package/dist/chunk-TK7G6XLT.js +18 -0
  15. package/dist/chunk-TK7G6XLT.js.map +1 -0
  16. package/dist/composer-DvUaa5ki.d.ts +585 -0
  17. package/dist/composer.d.ts +6 -0
  18. package/dist/composer.js +56 -0
  19. package/dist/composer.js.map +1 -0
  20. package/dist/index.d.ts +642 -1080
  21. package/dist/index.js +7672 -8005
  22. package/dist/index.js.map +1 -1
  23. package/dist/machines.d.ts +412 -3
  24. package/dist/machines.js +25 -1
  25. package/dist/noto-sans-arabic-loader-IA2T4X2A.js +21 -0
  26. package/dist/noto-sans-arabic-loader-IA2T4X2A.js.map +1 -0
  27. package/dist/noto-sans-jp-loader.generated-HFGLYBR3.js +292 -0
  28. package/dist/noto-sans-jp-loader.generated-HFGLYBR3.js.map +1 -0
  29. package/dist/queue-surface-implementation-NQMV2ML3.js +890 -0
  30. package/dist/queue-surface-implementation-NQMV2ML3.js.map +1 -0
  31. package/dist/session-Gd4iVPYw.d.ts +425 -0
  32. package/dist/session-context-DIFFlXKc.d.ts +52 -0
  33. package/dist/session.d.ts +4 -0
  34. package/dist/session.js +50 -0
  35. package/dist/session.js.map +1 -0
  36. package/dist/use-composer-BCfm4mzX.d.ts +112 -0
  37. package/package.json +23 -4
  38. package/src/approvals.ts +5 -3
  39. package/src/client.ts +50 -1
  40. package/src/components/approval-surface.tsx +198 -0
  41. package/src/components/chat-composer.tsx +104 -751
  42. package/src/components/code-editor.tsx +104 -26
  43. package/src/components/command-palette.tsx +8 -2
  44. package/src/components/composer-transcription-control.tsx +211 -0
  45. package/src/components/composer.tsx +1536 -0
  46. package/src/components/desktop-viewer.tsx +3 -3
  47. package/src/components/enrollment-consent.tsx +2 -2
  48. package/src/components/file-browser.tsx +367 -29
  49. package/src/components/human-input-form.tsx +417 -0
  50. package/src/components/machine-card.tsx +82 -16
  51. package/src/components/machine-health-pill.tsx +68 -0
  52. package/src/components/machine-metrics.tsx +10 -24
  53. package/src/components/machines/health.ts +146 -0
  54. package/src/components/machines/machine-detail.tsx +220 -0
  55. package/src/components/machines/metric-history-chart.tsx +298 -0
  56. package/src/components/machines/metric-sparkline.tsx +76 -0
  57. package/src/components/machines/series.ts +113 -0
  58. package/src/components/machines-dashboard.tsx +16 -4
  59. package/src/components/message-timeline.tsx +15 -7
  60. package/src/components/model-picker.tsx +12 -3
  61. package/src/components/pierre-diff.tsx +32 -6
  62. package/src/components/queue-surface-implementation.tsx +1041 -0
  63. package/src/components/queue-surface-state.tsx +94 -0
  64. package/src/components/queue-surface.tsx +60 -0
  65. package/src/components/sandbox-files.tsx +230 -21
  66. package/src/components/sandbox-terminal.tsx +8 -2
  67. package/src/components/sandbox-workspace.tsx +489 -135
  68. package/src/components/session-status.tsx +0 -6
  69. package/src/components/workbench-changes.tsx +145 -50
  70. package/src/components/workspace-dock.tsx +329 -68
  71. package/src/composer.ts +60 -0
  72. package/src/hooks/internal.ts +115 -34
  73. package/src/hooks/use-composer.ts +635 -74
  74. package/src/hooks/use-human-input.ts +131 -0
  75. package/src/hooks/use-machine-chip.ts +2 -2
  76. package/src/hooks/use-machines.ts +27 -11
  77. package/src/hooks/use-sandbox-files.ts +310 -62
  78. package/src/hooks/use-sandbox-git.ts +154 -40
  79. package/src/hooks/use-sandbox-terminal.ts +28 -6
  80. package/src/hooks/use-session-capabilities.ts +38 -9
  81. package/src/hooks/use-session-control.ts +43 -15
  82. package/src/hooks/use-session-events.ts +523 -48
  83. package/src/hooks/use-session-lineage.ts +15 -6
  84. package/src/hooks/use-session.ts +10 -2
  85. package/src/hooks/use-slash-commands.ts +38 -38
  86. package/src/hooks/use-transcription.ts +757 -0
  87. package/src/hooks/use-turn-queue.ts +273 -77
  88. package/src/hooks/use-windowed-sections.ts +2 -2
  89. package/src/hooks/use-workspace-capture.ts +146 -40
  90. package/src/hooks/use-workspace-edit.ts +50 -14
  91. package/src/hooks/use-workspace-sessions.ts +3 -0
  92. package/src/human-input.ts +72 -0
  93. package/src/index.ts +88 -12
  94. package/src/lib/noto-sans-arabic-loader.ts +21 -0
  95. package/src/lib/noto-sans-jp-loader.generated.ts +295 -0
  96. package/src/lib/use-portal-token-style.ts +51 -0
  97. package/src/lib/use-unicode-fonts.ts +57 -0
  98. package/src/machines.ts +16 -0
  99. package/src/provider.tsx +163 -41
  100. package/src/session-context.ts +135 -0
  101. package/src/session.ts +79 -0
  102. package/src/timeline/parsers.ts +78 -6
  103. package/src/timeline/projection.ts +36 -6
  104. package/src/timeline/tool-renderers.tsx +41 -0
  105. package/src/timeline/turn-summary.tsx +2 -2
  106. package/src/timeline/types.ts +16 -8
  107. package/styles/index.css +78 -0
  108. package/styles/index.d.ts +2 -0
  109. package/styles/tokens.css +11 -6
  110. package/styles/tokens.d.ts +2 -0
  111. package/dist/chunk-NFYVQWIB.js +0 -1377
  112. package/dist/chunk-NFYVQWIB.js.map +0 -1
  113. package/dist/machines-CnlMb7E-.d.ts +0 -329
package/README.md CHANGED
@@ -4,16 +4,17 @@ React hooks and styled components for OpenGeni, built on
4
4
  [`@opengeni/sdk`](../sdk): live session streaming, a chat composer, a message
5
5
  timeline that renders streaming deltas / tool calls / spawned-worker status,
6
6
  session status badges, and fleet tiles for workspace overviews. Two opt-in
7
- surfaces layer on top: a **sandbox-surfacing** workbench (files, terminal, diff,
7
+ surfaces layer on top: a **sandbox workspace** workbench (files, terminal, diff,
8
8
  and an optional desktop stream) and, at the
9
9
  [`@opengeni/react/machines`](#connected-machines-opengenireactmachines) subpath,
10
10
  the **Connected Machines** dashboard + enrollment flow.
11
11
 
12
12
  The default root import (`@opengeni/react`) is the clean sandbox-agnostic
13
- surface — the chat/timeline hooks and components plus the sandbox-surfacing
14
- suite. Connected-Machine UI lives under the `@opengeni/react/machines` subpath so
15
- consumers that never surface machines don't pull it in. (The root barrel still
16
- re-exports the machines island for back-compat, deprecated per #144.)
13
+ surface — the chat/timeline hooks and components plus the sandbox workspace
14
+ suite. Advanced chat-composer composition lives under
15
+ `@opengeni/react/composer`; Connected-Machine UI lives under
16
+ `@opengeni/react/machines`. (The root barrel still re-exports the machines
17
+ island for back-compat, deprecated per #144.)
17
18
 
18
19
  Design-system-first: every visual decision routes through CSS-variable tokens
19
20
  (`styles/tokens.css`) — color, typography, radius, shadow, motion. Dark mode is
@@ -24,6 +25,27 @@ animation. Override the tokens to rebrand everything.
24
25
 
25
26
  ## Install & styles
26
27
 
28
+ Hosts that render their own UI should import the session-only surface:
29
+
30
+ ```tsx
31
+ import {
32
+ useComposer,
33
+ useSessionControl,
34
+ useSessionEvents,
35
+ useTurnQueue,
36
+ } from "@opengeni/react/session";
37
+ ```
38
+
39
+ That subpath contains session hooks, approval helpers, and the pure timeline
40
+ projection only. It does not load the styled composer, timeline, workbench,
41
+ CSS, or their optional editor/terminal peers. Pass `{ client, workspaceId }` to
42
+ each hook when the host intentionally does not mount `OpenGeniProvider`. The
43
+ exported `SessionClientLike` is deliberately narrow: a tenant-safe proxy needs
44
+ only session events, composer draft/send, queue, pause/resume, and approval
45
+ operations. Workspace-level Resume is an optional authority.
46
+
47
+ The styled root surface uses Tailwind v4 and the package CSS entries:
48
+
27
49
  The package ships TypeScript source plus two CSS entries. In your Tailwind v4
28
50
  entry CSS:
29
51
 
@@ -45,16 +67,19 @@ import {
45
67
  ChatComposer,
46
68
  MessageTimeline,
47
69
  OpenGeniProvider,
70
+ QueueSurface,
48
71
  SessionStatus,
49
72
  useComposer,
50
73
  useSessionEvents,
74
+ useTurnQueue,
51
75
  } from "@opengeni/react";
52
76
 
53
77
  const client = new OpenGeniClient({ baseUrl: "/api/opengeni" }); // proxy through your API
54
78
 
55
79
  function OpsChannel({ sessionId }: { sessionId: string }) {
56
80
  const { timeline, sessionStatus, hasOlder, loadingOlder, loadOlder } = useSessionEvents(sessionId);
57
- const composer = useComposer(sessionId);
81
+ const queue = useTurnQueue(sessionId);
82
+ const composer = useComposer(sessionId, { effectiveControl: queue.effectiveControl });
58
83
  return (
59
84
  <div className="flex h-full flex-col">
60
85
  {sessionStatus ? <SessionStatus status={sessionStatus} /> : null}
@@ -66,7 +91,8 @@ function OpsChannel({ sessionId }: { sessionId: string }) {
66
91
  onLoadOlder={() => void loadOlder()}
67
92
  className="min-h-0 flex-1"
68
93
  />
69
- <ChatComposer composer={composer} status={sessionStatus} />
94
+ <QueueSurface queue={queue} composer={composer} />
95
+ <ChatComposer composer={composer} effectiveControl={queue.effectiveControl} />
70
96
  </div>
71
97
  );
72
98
  }
@@ -80,6 +106,82 @@ export function App() {
80
106
  }
81
107
  ```
82
108
 
109
+ ## Composer customization (`@opengeni/react/composer`)
110
+
111
+ Use `ChatComposer` for the standard layout and its `controlsStart`, `header`,
112
+ and `messages` props for small additions. For a different layout, import the
113
+ headless controller and compound primitives as a namespace. The controller is
114
+ the one behavior path for keyboard routing, guarded queue/steer submission,
115
+ attachments, commands, pause/resume, focus, confirmations, and feedback.
116
+
117
+ ```tsx
118
+ import * as Composer from "@opengeni/react/composer";
119
+
120
+ function InsertTranscript() {
121
+ const composer = Composer.useChatComposer();
122
+ return (
123
+ <button
124
+ type="button"
125
+ onClick={() => {
126
+ const separator = composer.value.trim().length > 0 ? " " : "";
127
+ composer.setValue(`${composer.value}${separator}Transcribed text`);
128
+ composer.focusInput();
129
+ }}
130
+ >
131
+ Insert transcript
132
+ </button>
133
+ );
134
+ }
135
+
136
+ function CustomComposer({ sessionComposer, attachments, effectiveControl }) {
137
+ const controller = Composer.useChatComposerController({
138
+ delivery: sessionComposer,
139
+ draft: sessionComposer,
140
+ control: sessionComposer,
141
+ attachments,
142
+ effectiveControl,
143
+ });
144
+
145
+ return (
146
+ <Composer.Root controller={controller}>
147
+ <Composer.Frame>
148
+ <Composer.CommandPalette />
149
+ <Composer.Surface>
150
+ <Composer.PausedState />
151
+ <Composer.RestoredResources />
152
+ <Composer.Attachments />
153
+ <Composer.Input />
154
+ {controller.confirmState ? (
155
+ <Composer.Confirmation />
156
+ ) : (
157
+ <Composer.Footer>
158
+ <Composer.Controls>
159
+ <Composer.AttachButton />
160
+ <InsertTranscript />
161
+ </Composer.Controls>
162
+ <Composer.Actions>
163
+ <Composer.PauseButton />
164
+ <Composer.SendButton />
165
+ </Composer.Actions>
166
+ </Composer.Footer>
167
+ )}
168
+ </Composer.Surface>
169
+ </Composer.Frame>
170
+ <Composer.Help />
171
+ <Composer.Status />
172
+ </Composer.Root>
173
+ );
174
+ }
175
+ ```
176
+
177
+ For a pre-session or otherwise limited composer, pass only `delivery`; `draft`
178
+ and `control` are optional capabilities rather than no-op requirements. Custom
179
+ controls should call `controller.submit("queue" | "steer")` (or read it through
180
+ `useChatComposer`) instead of calling a delivery adapter directly, so upload,
181
+ disabled, in-flight, and slash-command guards stay intact. Accessory-local UI
182
+ state remains application-owned; durable draft and session state remain in
183
+ `useComposer`.
184
+
83
185
  ## Hooks
84
186
 
85
187
  - `useSessionEvents(sessionId)` — loads a compact, bounded tail window by
@@ -90,27 +192,30 @@ export function App() {
90
192
  older-history controls (`hasOlder`, `loadingOlder`, `loadOlder`). Pass
91
193
  `replay: "full"` to opt back into full replay; a nonzero `after` keeps the
92
194
  previous resume semantics.
93
- - `useComposer(sessionId, { sendExtras, defaultMode })` — draft/send/interrupt
94
- state plus the compose-time **queue-vs-steer** choice (`mode`/`setMode`,
95
- default `"queue"`): queue stacks the message behind the running turn, steer
96
- interrupts and injects it now. Drafts survive failed sends; each draft
97
- reuses one `clientEventId` across retries so the server dedupes.
195
+ - `useComposer(sessionId, { sendExtras, effectiveControl })` — revisioned private
196
+ draft, Send, Steer, and workstream Pause/Resume state. `send()` appends in
197
+ visible queue order; `steer()` supersedes the current direction. Drafts
198
+ autosave with optimistic concurrency, survive failed sends, and reuse one
199
+ `clientEventId` across retries so the server dedupes.
98
200
  `sendExtras` (object or function evaluated at send time) merges
99
201
  resources/tools/model/reasoningEffort into every message. All human input is
100
202
  plain chat text by design; approvals flow as control events
101
203
  (`useSessionControl`), not bespoke widgets.
102
- - `useTurnQueue(sessionId, { events })` — the live turn queue: `queue` (queued
103
- turns in execution order), `activeTurn`, and optimistic `editTurn` /
104
- `reorderTurns` / `removeTurn` that reconcile with the server (failed
105
- mutations roll back via refetch). Live-updates on `turn.*` events — pass the
204
+ - `useTurnQueue(sessionId, { events })` — the one server-authoritative human
205
+ prompt queue with `moveTurn`, crash-safe `editTurn`, identity-preserving
206
+ `steerTurn`, and `removeTurn`. Mutations carry observed revisions and conflicts
207
+ refetch server truth. Live-updates on `turn.*` and `session.queue.*` events — pass the
106
208
  `events` log from `useSessionEvents` to reuse its stream, or let it tail the
107
- session itself.
209
+ session itself. Providerless self-streams reconcile authoritative queue/draft
210
+ state after the SSE connection opens, closing the initial-read handoff race.
108
211
  - `useGoal(sessionId, { events })` — goal state + autonomy counters
109
212
  (`autoContinuations`, `noProgressStreak`) with `pause(rationale?)` /
110
213
  `resume()`. Goal-less sessions yield `goal: null`. Live-updates on `goal.*`
111
214
  events.
112
- - `useSessionControl(sessionId)` — `interrupt(reason?)` and
113
- `approve`/`reject(approvalId, message?)` for `requires_action` approvals.
215
+ - `useSessionControl(sessionId)` — durable `pause(reason?)` / `resume(reason?)`
216
+ workstream controls and `approve`/`reject(approvalId, message?)` for
217
+ `requires_action` approvals. Pause is recursive control state, not lifecycle
218
+ status or queue work; Resume creates no message.
114
219
  - `useSession(sessionId)` — fetch one session (optional polling) with
115
220
  `updateTitle(title)` (rename) and live title-patching on `session.title_set`.
116
221
  - `useFileAttachments()` — the composer's attach flow: stages files, drives the
@@ -159,11 +264,12 @@ intentional changes should regenerate those snapshots and review the diff.
159
264
 
160
265
  ## Components
161
266
 
162
- - `ChatComposer` — auto-growing textarea, Enter-to-send (IME-safe), stop
163
- control while a turn runs, inline error recovery. Slots for app chrome:
267
+ - `ChatComposer` — auto-growing textarea, Enter-to-send (IME-safe), pause/resume
268
+ controls, inline error recovery. Slots for app chrome:
164
269
  `controlsStart` (footer controls like model pickers / attach buttons),
165
270
  `header` (e.g. attachment chips above the field), and `onPaste`
166
- (paste-image-to-attach).
271
+ (paste-image-to-attach). Its advanced controller and compound primitives are
272
+ exported from `@opengeni/react/composer`.
167
273
  - `MessageTimeline` — the session timeline with stick-to-bottom scrolling, a
168
274
  "jump to latest" affordance, streaming caret, collapsible activity clusters,
169
275
  and worker cards (wire `onOpenSession` to drill into a worker). Pass
@@ -247,7 +353,7 @@ end-to-end embedder story (create-on-machine, discover, swap, enroll, revoke).
247
353
 
248
354
  ## Optional peer dependencies
249
355
 
250
- The chat/timeline surface has none. The sandbox-surfacing and diff surfaces pull
356
+ The chat/timeline surface has none. The sandbox workspace and diff surfaces pull
251
357
  their heavy libraries from **optional** `peerDependencies`, so you install only
252
358
  what the surfaces you mount need:
253
359