@opengeni/react 0.12.0 → 0.13.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.
- package/README.md +1 -1
- package/dist/{chunk-5TIXRCSI.js → chunk-NFYVQWIB.js} +150 -64
- package/dist/chunk-NFYVQWIB.js.map +1 -0
- package/dist/index.d.ts +760 -142
- package/dist/index.js +5345 -2146
- package/dist/index.js.map +1 -1
- package/dist/{machines-BeZ3bD3t.d.ts → machines-CnlMb7E-.d.ts} +5 -5
- package/dist/machines.d.ts +1 -1
- package/dist/machines.js +1 -1
- package/package.json +17 -12
- package/src/approvals.ts +16 -4
- package/src/client.ts +32 -5
- package/src/commands/index.ts +1 -7
- package/src/commands/registry.ts +46 -12
- package/src/components/chat-composer.tsx +135 -39
- package/src/components/code-editor.tsx +28 -36
- package/src/components/command-palette.tsx +26 -5
- package/src/components/desktop-viewer.tsx +29 -16
- package/src/components/diff-view.tsx +27 -189
- package/src/components/enrollment-consent.tsx +28 -10
- package/src/components/enrollment-device-flow.tsx +8 -5
- package/src/components/file-browser.tsx +190 -56
- package/src/components/fleet-tile.tsx +13 -4
- package/src/components/machine-card.tsx +16 -4
- package/src/components/machine-dock-bar.tsx +20 -8
- package/src/components/machine-metrics.tsx +31 -8
- package/src/components/machine-status-pill.tsx +26 -5
- package/src/components/machines-dashboard.tsx +8 -2
- package/src/components/markdown.tsx +39 -9
- package/src/components/message-timeline.tsx +633 -109
- package/src/components/pierre-diff.tsx +83 -15
- package/src/components/pierre-file.tsx +10 -9
- package/src/components/sandbox-files.tsx +110 -227
- package/src/components/sandbox-terminal.tsx +256 -88
- package/src/components/sandbox-workspace.tsx +823 -0
- package/src/components/session-status.tsx +28 -2
- package/src/components/workbench-changes.tsx +541 -0
- package/src/components/workspace-dock.tsx +85 -22
- package/src/hooks/internal.ts +5 -2
- package/src/hooks/use-available-models.ts +7 -2
- package/src/hooks/use-billing-usage.ts +4 -1
- package/src/hooks/use-codex-accounts.ts +74 -44
- package/src/hooks/use-composer.ts +57 -36
- package/src/hooks/use-environments.ts +92 -47
- package/src/hooks/use-file-attachments.ts +101 -55
- package/src/hooks/use-goal.ts +52 -16
- package/src/hooks/use-machine-chip.ts +134 -0
- package/src/hooks/use-machines.ts +34 -16
- package/src/hooks/use-packs.ts +24 -19
- package/src/hooks/use-relay-frame-stream.ts +5 -2
- package/src/hooks/use-rigs.ts +335 -0
- package/src/hooks/use-sandbox-files.ts +213 -39
- package/src/hooks/use-sandbox-git.ts +188 -11
- package/src/hooks/use-sandbox-terminal.ts +18 -14
- package/src/hooks/use-scheduled-tasks.ts +10 -2
- package/src/hooks/use-session-capabilities.ts +77 -20
- package/src/hooks/use-session-control.ts +49 -21
- package/src/hooks/use-session-events.ts +48 -20
- package/src/hooks/use-session-lineage.ts +119 -0
- package/src/hooks/use-session.ts +43 -28
- package/src/hooks/use-slash-commands.ts +6 -4
- package/src/hooks/use-turn-queue.ts +74 -147
- package/src/hooks/use-windowed-sections.ts +204 -0
- package/src/hooks/use-workspace-capture.ts +233 -0
- package/src/hooks/use-workspace-edit.ts +231 -0
- package/src/hooks/use-workspace-sessions.ts +48 -5
- package/src/hooks/use-workspaces.ts +18 -15
- package/src/index.ts +127 -23
- package/src/lib/format.ts +3 -3
- package/src/lib/xterm-renderer.ts +65 -0
- package/src/lib/xterm-theme.ts +224 -18
- package/src/machines.ts +13 -3
- package/src/provider.tsx +3 -1
- package/src/timeline/activity-rail.tsx +213 -54
- package/src/timeline/disclosure-context.tsx +12 -2
- package/src/timeline/index.ts +21 -2
- package/src/timeline/parsers.ts +44 -10
- package/src/timeline/projection.ts +388 -85
- package/src/timeline/shared.tsx +111 -24
- package/src/timeline/tool-diff.tsx +24 -20
- package/src/timeline/tool-renderers.tsx +98 -21
- package/src/timeline/turn-summary.tsx +76 -23
- package/src/timeline/types.ts +96 -12
- package/styles/tokens.css +2 -2
- package/dist/chunk-5TIXRCSI.js.map +0 -1
package/src/index.ts
CHANGED
|
@@ -12,31 +12,71 @@ export type { ClientOverride, OpenGeniContextValue, OpenGeniProviderProps } from
|
|
|
12
12
|
export { useSession, isTitleEvent } from "./hooks/use-session";
|
|
13
13
|
export type { UseSessionOptions, UseSessionResult } from "./hooks/use-session";
|
|
14
14
|
export { useSessionEvents } from "./hooks/use-session-events";
|
|
15
|
-
export type {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
export type {
|
|
16
|
+
SessionEventsConnectionState,
|
|
17
|
+
UseSessionEventsOptions,
|
|
18
|
+
UseSessionEventsResult,
|
|
19
|
+
} from "./hooks/use-session-events";
|
|
20
20
|
export {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
useComposer,
|
|
22
|
+
composeSendInput,
|
|
23
|
+
shouldSubmitOnKey,
|
|
24
|
+
FILE_ONLY_MESSAGE_TEXT,
|
|
25
|
+
} from "./hooks/use-composer";
|
|
26
|
+
export type {
|
|
27
|
+
ComposerMode,
|
|
28
|
+
ComposerSendExtras,
|
|
29
|
+
ComposerState,
|
|
30
|
+
UseComposerOptions,
|
|
31
|
+
} from "./hooks/use-composer";
|
|
32
|
+
export { useFileAttachments } from "./hooks/use-file-attachments";
|
|
33
|
+
export type {
|
|
34
|
+
FileAttachment,
|
|
35
|
+
UseFileAttachmentsOptions,
|
|
36
|
+
UseFileAttachmentsResult,
|
|
37
|
+
} from "./hooks/use-file-attachments";
|
|
38
|
+
export { useTurnQueue, isTurnQueueEvent } from "./hooks/use-turn-queue";
|
|
29
39
|
export type { UseTurnQueueOptions, UseTurnQueueResult } from "./hooks/use-turn-queue";
|
|
30
40
|
export { useGoal, isGoalEvent } from "./hooks/use-goal";
|
|
31
41
|
export type { UseGoalOptions, UseGoalResult } from "./hooks/use-goal";
|
|
32
42
|
export { useSessionControl } from "./hooks/use-session-control";
|
|
33
|
-
export type {
|
|
43
|
+
export type {
|
|
44
|
+
UseSessionControlOptions,
|
|
45
|
+
UseSessionControlResult,
|
|
46
|
+
} from "./hooks/use-session-control";
|
|
34
47
|
export { useScheduledTasks } from "./hooks/use-scheduled-tasks";
|
|
35
|
-
export type {
|
|
48
|
+
export type {
|
|
49
|
+
UseScheduledTasksOptions,
|
|
50
|
+
UseScheduledTasksResult,
|
|
51
|
+
} from "./hooks/use-scheduled-tasks";
|
|
36
52
|
export { useWorkspaceSessions } from "./hooks/use-workspace-sessions";
|
|
37
|
-
export type {
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
export type {
|
|
54
|
+
UseWorkspaceSessionsOptions,
|
|
55
|
+
UseWorkspaceSessionsResult,
|
|
56
|
+
} from "./hooks/use-workspace-sessions";
|
|
57
|
+
export { useSessionLineage, isLineageRefreshEvent } from "./hooks/use-session-lineage";
|
|
58
|
+
export type {
|
|
59
|
+
UseSessionLineageOptions,
|
|
60
|
+
UseSessionLineageResult,
|
|
61
|
+
} from "./hooks/use-session-lineage";
|
|
62
|
+
export { useVariableSets, useEnvironments } from "./hooks/use-environments";
|
|
63
|
+
export type {
|
|
64
|
+
UseVariableSetsOptions,
|
|
65
|
+
UseVariableSetsResult,
|
|
66
|
+
UseEnvironmentsOptions,
|
|
67
|
+
UseEnvironmentsResult,
|
|
68
|
+
} from "./hooks/use-environments";
|
|
69
|
+
export { useRigs, useRig, useRigVersions, useRigChanges } from "./hooks/use-rigs";
|
|
70
|
+
export type {
|
|
71
|
+
UseRigsOptions,
|
|
72
|
+
UseRigsResult,
|
|
73
|
+
UseRigOptions,
|
|
74
|
+
UseRigResult,
|
|
75
|
+
UseRigVersionsOptions,
|
|
76
|
+
UseRigVersionsResult,
|
|
77
|
+
UseRigChangesOptions,
|
|
78
|
+
UseRigChangesResult,
|
|
79
|
+
} from "./hooks/use-rigs";
|
|
40
80
|
export { usePacks } from "./hooks/use-packs";
|
|
41
81
|
export type { UsePacksOptions, UsePacksResult } from "./hooks/use-packs";
|
|
42
82
|
export { useWorkspaces } from "./hooks/use-workspaces";
|
|
@@ -44,7 +84,10 @@ export type { UseWorkspacesOptions, UseWorkspacesResult } from "./hooks/use-work
|
|
|
44
84
|
export { useBillingUsage } from "./hooks/use-billing-usage";
|
|
45
85
|
export type { UseBillingUsageOptions, UseBillingUsageResult } from "./hooks/use-billing-usage";
|
|
46
86
|
export { useAvailableModels } from "./hooks/use-available-models";
|
|
47
|
-
export type {
|
|
87
|
+
export type {
|
|
88
|
+
UseAvailableModelsOptions,
|
|
89
|
+
UseAvailableModelsResult,
|
|
90
|
+
} from "./hooks/use-available-models";
|
|
48
91
|
|
|
49
92
|
// Sandbox surfacing (Phase 5): capability negotiation + terminal/files/diff/desktop
|
|
50
93
|
export { useSessionCapabilities } from "./hooks/use-session-capabilities";
|
|
@@ -84,6 +127,27 @@ export type {
|
|
|
84
127
|
export { useSandboxGit } from "./hooks/use-sandbox-git";
|
|
85
128
|
export type { UseSandboxGitOptions, UseSandboxGitResult } from "./hooks/use-sandbox-git";
|
|
86
129
|
|
|
130
|
+
// Workbench v2 turn-end capture (the cold-paint data layer)
|
|
131
|
+
export { useWorkspaceCapture } from "./hooks/use-workspace-capture";
|
|
132
|
+
export type {
|
|
133
|
+
UseWorkspaceCaptureOptions,
|
|
134
|
+
UseWorkspaceCaptureResult,
|
|
135
|
+
} from "./hooks/use-workspace-capture";
|
|
136
|
+
export { useWorkspaceEdit } from "./hooks/use-workspace-edit";
|
|
137
|
+
export type {
|
|
138
|
+
UseWorkspaceEditOptions,
|
|
139
|
+
UseWorkspaceEditResult,
|
|
140
|
+
WorkspaceEditConflict,
|
|
141
|
+
WorkspaceEditState,
|
|
142
|
+
} from "./hooks/use-workspace-edit";
|
|
143
|
+
export { deriveMachineChip, formatAsOf, useMachineChip } from "./hooks/use-machine-chip";
|
|
144
|
+
export type {
|
|
145
|
+
DeriveMachineChipInput,
|
|
146
|
+
MachineChip,
|
|
147
|
+
MachineChipState,
|
|
148
|
+
UseMachineChipOptions,
|
|
149
|
+
} from "./hooks/use-machine-chip";
|
|
150
|
+
|
|
87
151
|
// Pending-approvals projection
|
|
88
152
|
export { approvalsFromRequiresAction, projectPendingApprovals } from "./approvals";
|
|
89
153
|
export type { PendingApproval } from "./approvals";
|
|
@@ -100,6 +164,7 @@ export {
|
|
|
100
164
|
export type {
|
|
101
165
|
ActivityItem,
|
|
102
166
|
AgentMessageItem,
|
|
167
|
+
AuthNeededItem,
|
|
103
168
|
GoalItem,
|
|
104
169
|
NoticeItem,
|
|
105
170
|
ReasoningItem,
|
|
@@ -114,7 +179,12 @@ export type {
|
|
|
114
179
|
} from "./timeline";
|
|
115
180
|
|
|
116
181
|
// Tool-renderer registry + the per-tool renderers (the timeline's extension API)
|
|
117
|
-
export {
|
|
182
|
+
export {
|
|
183
|
+
createDefaultToolRegistry,
|
|
184
|
+
createToolRegistry,
|
|
185
|
+
defaultToolRegistry,
|
|
186
|
+
rawTypeOf,
|
|
187
|
+
} from "./timeline";
|
|
118
188
|
export type {
|
|
119
189
|
CreateToolRegistryOptions,
|
|
120
190
|
ToolRegistry,
|
|
@@ -206,7 +276,11 @@ export type { MessageTimelineProps } from "./components/message-timeline";
|
|
|
206
276
|
export { Markdown } from "./components/markdown";
|
|
207
277
|
export type { MarkdownProps } from "./components/markdown";
|
|
208
278
|
export { SessionStatus, StatusDot, SESSION_STATUS_META } from "./components/session-status";
|
|
209
|
-
export type {
|
|
279
|
+
export type {
|
|
280
|
+
SessionStatusProps,
|
|
281
|
+
StatusDotProps,
|
|
282
|
+
SessionStatusMeta,
|
|
283
|
+
} from "./components/session-status";
|
|
210
284
|
export { FleetTile, sessionDisplayTitle } from "./components/fleet-tile";
|
|
211
285
|
export type { FleetTileProps } from "./components/fleet-tile";
|
|
212
286
|
|
|
@@ -230,12 +304,33 @@ export type { DesktopViewerProps } from "./components/desktop-viewer";
|
|
|
230
304
|
export { WorkspaceDock } from "./components/workspace-dock";
|
|
231
305
|
export type { WorkspaceDockProps, WorkspaceTab } from "./components/workspace-dock";
|
|
232
306
|
|
|
307
|
+
// The embeddable dock "brain" (Workbench v2, M4): the whole session workspace as
|
|
308
|
+
// one component + the tab-building hook + the pre-paint default-tab helper.
|
|
309
|
+
export {
|
|
310
|
+
SandboxWorkspace,
|
|
311
|
+
useSandboxWorkspaceTabs,
|
|
312
|
+
initialWorkspaceTab,
|
|
313
|
+
WORKBENCH_TAB_CHANGES,
|
|
314
|
+
WORKBENCH_TAB_FILES,
|
|
315
|
+
} from "./components/sandbox-workspace";
|
|
316
|
+
export type {
|
|
317
|
+
SandboxWorkspaceProps,
|
|
318
|
+
UseSandboxWorkspaceTabsOptions,
|
|
319
|
+
UseSandboxWorkspaceTabsResult,
|
|
320
|
+
WorkspaceMachine,
|
|
321
|
+
WorkspaceNotification,
|
|
322
|
+
} from "./components/sandbox-workspace";
|
|
323
|
+
|
|
233
324
|
// Connected-machine UI moved to the "@opengeni/react/machines" subpath; re-exported
|
|
234
325
|
// here for back-compat (#144).
|
|
235
326
|
export * from "./machines";
|
|
236
327
|
// Multi-account Codex (P1): accounts list + active-switch hook.
|
|
237
328
|
export { useCodexAccounts, isCodexAccountEvent } from "./hooks/use-codex-accounts";
|
|
238
|
-
export type {
|
|
329
|
+
export type {
|
|
330
|
+
CodexAccountsClientLike,
|
|
331
|
+
UseCodexAccountsOptions,
|
|
332
|
+
UseCodexAccountsResult,
|
|
333
|
+
} from "./hooks/use-codex-accounts";
|
|
239
334
|
|
|
240
335
|
// Sandbox helpers
|
|
241
336
|
export { gitFileDiffToPatch } from "./lib/git-patch";
|
|
@@ -243,4 +338,13 @@ export { xtermThemeFromTokens } from "./lib/xterm-theme";
|
|
|
243
338
|
|
|
244
339
|
// Utilities
|
|
245
340
|
export { cn } from "./lib/cn";
|
|
246
|
-
export {
|
|
341
|
+
export {
|
|
342
|
+
CREDIT_EXHAUSTION_MESSAGE,
|
|
343
|
+
formatBytes,
|
|
344
|
+
formatRelativeTime,
|
|
345
|
+
humanizeFailureReason,
|
|
346
|
+
isCreditExhaustion,
|
|
347
|
+
stringifyPayload,
|
|
348
|
+
truncate,
|
|
349
|
+
tryParseJson,
|
|
350
|
+
} from "./lib/format";
|
package/src/lib/format.ts
CHANGED
|
@@ -140,13 +140,13 @@ export function humanizeFailureReason(reason: string | null): string | null {
|
|
|
140
140
|
normalized.includes("invalid api key") ||
|
|
141
141
|
normalized.includes("invalid_api_key") ||
|
|
142
142
|
normalized.includes("platform.openai.com/account/api-keys") ||
|
|
143
|
-
(normalized.includes("401") &&
|
|
143
|
+
(normalized.includes("401") &&
|
|
144
|
+
(normalized.includes("api key") || normalized.includes("unauthorized")));
|
|
144
145
|
if (authFailure) {
|
|
145
146
|
return "The model provider rejected this deployment's engine credentials. Sending messages won't help until the deployment's engine configuration is fixed.";
|
|
146
147
|
}
|
|
147
148
|
const quotaFailure =
|
|
148
|
-
normalized.includes("insufficient_quota") ||
|
|
149
|
-
normalized.includes("exceeded your current quota");
|
|
149
|
+
normalized.includes("insufficient_quota") || normalized.includes("exceeded your current quota");
|
|
150
150
|
if (quotaFailure) {
|
|
151
151
|
return "The model provider refused the request: this deployment's provider quota is exhausted.";
|
|
152
152
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* ----------------------------------------------------------------------------
|
|
2
|
+
xterm renderer selection ladder: WebGL → 2D canvas → DOM.
|
|
3
|
+
|
|
4
|
+
WebGL is the fast path (GPU-composited cells — the whole point of the burst
|
|
5
|
+
responsiveness win). But a WebGL context can fail to init (headless / no GPU /
|
|
6
|
+
blocklisted driver) or be LOST at runtime (GPU reset, tab backgrounded). On
|
|
7
|
+
either, we dispose the addon and step down one tier so the terminal keeps
|
|
8
|
+
painting via the 2D canvas addon, and failing that xterm's built-in DOM
|
|
9
|
+
renderer (no addon).
|
|
10
|
+
|
|
11
|
+
`attachRenderer` is pure over its `loaders` (each closes over the xterm
|
|
12
|
+
instance and constructs+loads its addon, throwing on failure), so the ladder
|
|
13
|
+
+ context-loss downgrade unit-test without a real WebGL context.
|
|
14
|
+
-------------------------------------------------------------------------- */
|
|
15
|
+
|
|
16
|
+
export type RendererTier = "webgl" | "canvas" | "dom";
|
|
17
|
+
|
|
18
|
+
export type RendererAddon = { dispose: () => void };
|
|
19
|
+
|
|
20
|
+
/** A loader constructs + `loadAddon`s its renderer, wiring `onLoss` to the
|
|
21
|
+
* addon's context-loss event, and throws if the renderer can't initialize. */
|
|
22
|
+
export type RendererLoaders = {
|
|
23
|
+
webgl?: ((onLoss: () => void) => Promise<RendererAddon>) | undefined;
|
|
24
|
+
canvas?: (() => Promise<RendererAddon>) | undefined;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const ORDER: RendererTier[] = ["webgl", "canvas", "dom"];
|
|
28
|
+
|
|
29
|
+
/** The next lower renderer tier, or null at the bottom (DOM). Pure. */
|
|
30
|
+
export function nextRendererTier(tier: RendererTier): RendererTier | null {
|
|
31
|
+
const i = ORDER.indexOf(tier);
|
|
32
|
+
return i >= 0 && i < ORDER.length - 1 ? ORDER[i + 1]! : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Attach the highest renderer tier at or below `prefer` that initializes,
|
|
37
|
+
* reporting the settled tier via `onTier`. On a WebGL/canvas context loss the
|
|
38
|
+
* loader's `onLoss` re-enters at the next tier down, so `onTier` is called again
|
|
39
|
+
* with the downgraded tier. Returns the tier chosen on this pass.
|
|
40
|
+
*/
|
|
41
|
+
export async function attachRenderer(
|
|
42
|
+
prefer: RendererTier,
|
|
43
|
+
loaders: RendererLoaders,
|
|
44
|
+
onTier: (tier: RendererTier) => void,
|
|
45
|
+
): Promise<RendererTier> {
|
|
46
|
+
const start = Math.max(0, ORDER.indexOf(prefer));
|
|
47
|
+
for (let i = start; i < ORDER.length; i++) {
|
|
48
|
+
const tier = ORDER[i]!;
|
|
49
|
+
if (tier === "dom") break;
|
|
50
|
+
const loader = tier === "webgl" ? loaders.webgl : loaders.canvas;
|
|
51
|
+
if (!loader) continue;
|
|
52
|
+
try {
|
|
53
|
+
const downgrade = nextRendererTier(tier) ?? "dom";
|
|
54
|
+
await loader(() => {
|
|
55
|
+
void attachRenderer(downgrade, loaders, onTier);
|
|
56
|
+
});
|
|
57
|
+
onTier(tier);
|
|
58
|
+
return tier;
|
|
59
|
+
} catch {
|
|
60
|
+
// Initialization failed — fall through to the next tier down.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
onTier("dom");
|
|
64
|
+
return "dom";
|
|
65
|
+
}
|
package/src/lib/xterm-theme.ts
CHANGED
|
@@ -1,31 +1,237 @@
|
|
|
1
1
|
import type { XtermTheme } from "../components/sandbox-terminal";
|
|
2
2
|
|
|
3
|
+
/* ----------------------------------------------------------------------------
|
|
4
|
+
xterm theming + font resolution from the `--og-*` token system.
|
|
5
|
+
|
|
6
|
+
xterm paints glyphs into a canvas (WebGL / 2D) and builds its font strings by
|
|
7
|
+
hand, so it can consume NEITHER CSS custom properties (`var(--og-font-mono)`
|
|
8
|
+
never resolves in a canvas font string) NOR a partial palette (an unset ANSI
|
|
9
|
+
slot falls back to xterm's stock VGA color). This module resolves both to
|
|
10
|
+
concrete values: a full 16-color ANSI ITheme designed against the og palette
|
|
11
|
+
for BOTH themes, and a concrete monospace family + px size.
|
|
12
|
+
|
|
13
|
+
The color-building + font-resolution cores are pure over a token `read`
|
|
14
|
+
function so they unit-test without a DOM; thin `*FromTokens` / `resolve*`
|
|
15
|
+
wrappers do the `getComputedStyle` read on the client.
|
|
16
|
+
-------------------------------------------------------------------------- */
|
|
17
|
+
|
|
18
|
+
export type ThemeMode = "dark" | "light";
|
|
19
|
+
|
|
20
|
+
/** Reads a resolved token value (already `getComputedStyle`-flattened). */
|
|
21
|
+
export type TokenReader = (name: string) => string | undefined;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The 16 ANSI colors + selection/cursor treatment, designed against the og
|
|
25
|
+
* OKLCH palette. Hues are borrowed from the og status ramp so terminal color
|
|
26
|
+
* reads as part of the same system: red≈status-failed(22), green≈status-idle
|
|
27
|
+
* (155), yellow≈status-running(80), blue≈accent(255), magenta≈status-waiting
|
|
28
|
+
* (305), cyan≈200. Dark uses lifted lightness on the dark slate ground; light
|
|
29
|
+
* uses deeper, more saturated inks on the near-white ground. Bright variants
|
|
30
|
+
* add lightness + a touch of chroma. `black`/`white` are neutral slate ramp
|
|
31
|
+
* stops (never pure #000/#fff — that clashes with the calm neutral ground).
|
|
32
|
+
*/
|
|
33
|
+
export type AnsiPalette = {
|
|
34
|
+
black: string;
|
|
35
|
+
red: string;
|
|
36
|
+
green: string;
|
|
37
|
+
yellow: string;
|
|
38
|
+
blue: string;
|
|
39
|
+
magenta: string;
|
|
40
|
+
cyan: string;
|
|
41
|
+
white: string;
|
|
42
|
+
brightBlack: string;
|
|
43
|
+
brightRed: string;
|
|
44
|
+
brightGreen: string;
|
|
45
|
+
brightYellow: string;
|
|
46
|
+
brightBlue: string;
|
|
47
|
+
brightMagenta: string;
|
|
48
|
+
brightCyan: string;
|
|
49
|
+
brightWhite: string;
|
|
50
|
+
/** Selection wash + its foreground; sits over the terminal ground. */
|
|
51
|
+
selectionBackground: string;
|
|
52
|
+
selectionForeground: string;
|
|
53
|
+
selectionInactiveBackground: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const DARK_ANSI: AnsiPalette = {
|
|
57
|
+
black: "oklch(0.3 0.014 260)",
|
|
58
|
+
red: "oklch(0.68 0.17 22)",
|
|
59
|
+
green: "oklch(0.75 0.13 155)",
|
|
60
|
+
yellow: "oklch(0.8 0.11 80)",
|
|
61
|
+
blue: "oklch(0.7 0.14 255)",
|
|
62
|
+
magenta: "oklch(0.72 0.13 305)",
|
|
63
|
+
cyan: "oklch(0.75 0.1 210)",
|
|
64
|
+
white: "oklch(0.8 0.01 260)",
|
|
65
|
+
brightBlack: "oklch(0.45 0.014 260)",
|
|
66
|
+
brightRed: "oklch(0.76 0.17 22)",
|
|
67
|
+
brightGreen: "oklch(0.82 0.14 155)",
|
|
68
|
+
brightYellow: "oklch(0.86 0.12 85)",
|
|
69
|
+
brightBlue: "oklch(0.78 0.13 255)",
|
|
70
|
+
brightMagenta: "oklch(0.8 0.13 305)",
|
|
71
|
+
brightCyan: "oklch(0.83 0.1 200)",
|
|
72
|
+
brightWhite: "oklch(0.97 0.005 260)",
|
|
73
|
+
selectionBackground: "oklch(0.72 0.15 255 / 0.34)",
|
|
74
|
+
selectionForeground: "oklch(0.985 0.005 260)",
|
|
75
|
+
selectionInactiveBackground: "oklch(0.72 0.02 260 / 0.22)",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const LIGHT_ANSI: AnsiPalette = {
|
|
79
|
+
black: "oklch(0.35 0.015 260)",
|
|
80
|
+
red: "oklch(0.52 0.19 22)",
|
|
81
|
+
green: "oklch(0.5 0.13 155)",
|
|
82
|
+
yellow: "oklch(0.56 0.13 80)",
|
|
83
|
+
blue: "oklch(0.52 0.18 255)",
|
|
84
|
+
magenta: "oklch(0.52 0.16 305)",
|
|
85
|
+
cyan: "oklch(0.52 0.1 210)",
|
|
86
|
+
white: "oklch(0.7 0.01 260)",
|
|
87
|
+
brightBlack: "oklch(0.5 0.014 260)",
|
|
88
|
+
brightRed: "oklch(0.55 0.2 22)",
|
|
89
|
+
brightGreen: "oklch(0.54 0.14 155)",
|
|
90
|
+
brightYellow: "oklch(0.6 0.14 80)",
|
|
91
|
+
brightBlue: "oklch(0.48 0.19 255)",
|
|
92
|
+
brightMagenta: "oklch(0.54 0.17 305)",
|
|
93
|
+
brightCyan: "oklch(0.54 0.11 210)",
|
|
94
|
+
brightWhite: "oklch(0.3 0.015 260)",
|
|
95
|
+
selectionBackground: "oklch(0.55 0.18 255 / 0.24)",
|
|
96
|
+
selectionForeground: "oklch(0.21 0.015 260)",
|
|
97
|
+
selectionInactiveBackground: "oklch(0.6 0.02 260 / 0.16)",
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** The designed ANSI-16 palette for a theme mode. Pure. */
|
|
101
|
+
export function ogAnsiPalette(mode: ThemeMode): AnsiPalette {
|
|
102
|
+
return mode === "light" ? LIGHT_ANSI : DARK_ANSI;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Build a COMPLETE xterm ITheme from token values. Background/foreground/cursor
|
|
107
|
+
* come from the live `--og-*` tokens (so an embedder's rebrand flows through);
|
|
108
|
+
* the ANSI-16 + selection come from the designed palette for `mode`. Every ANSI
|
|
109
|
+
* slot is always set — xterm never falls back to its stock VGA colors. Pure.
|
|
110
|
+
*/
|
|
111
|
+
export function buildXtermTheme(read: TokenReader, mode: ThemeMode): XtermTheme {
|
|
112
|
+
const ansi = ogAnsiPalette(mode);
|
|
113
|
+
const bgFallback = mode === "light" ? "oklch(0.978 0.003 260)" : "oklch(0.155 0.012 260)";
|
|
114
|
+
const fgFallback = mode === "light" ? "oklch(0.21 0.015 260)" : "oklch(0.955 0.005 260)";
|
|
115
|
+
const bg = read("--og-color-bg") ?? bgFallback;
|
|
116
|
+
const fg = read("--og-color-fg") ?? fgFallback;
|
|
117
|
+
const accent = read("--og-color-accent") ?? ansi.brightBlue;
|
|
118
|
+
return {
|
|
119
|
+
// Match the dock surface the terminal paints on (`--og-color-bg`).
|
|
120
|
+
background: bg,
|
|
121
|
+
foreground: fg,
|
|
122
|
+
cursor: accent,
|
|
123
|
+
cursorAccent: bg,
|
|
124
|
+
selectionBackground: ansi.selectionBackground,
|
|
125
|
+
selectionForeground: ansi.selectionForeground,
|
|
126
|
+
selectionInactiveBackground: ansi.selectionInactiveBackground,
|
|
127
|
+
black: ansi.black,
|
|
128
|
+
red: ansi.red,
|
|
129
|
+
green: ansi.green,
|
|
130
|
+
yellow: ansi.yellow,
|
|
131
|
+
blue: ansi.blue,
|
|
132
|
+
magenta: ansi.magenta,
|
|
133
|
+
cyan: ansi.cyan,
|
|
134
|
+
white: ansi.white,
|
|
135
|
+
brightBlack: ansi.brightBlack,
|
|
136
|
+
brightRed: ansi.brightRed,
|
|
137
|
+
brightGreen: ansi.brightGreen,
|
|
138
|
+
brightYellow: ansi.brightYellow,
|
|
139
|
+
brightBlue: ansi.brightBlue,
|
|
140
|
+
brightMagenta: ansi.brightMagenta,
|
|
141
|
+
brightCyan: ansi.brightCyan,
|
|
142
|
+
brightWhite: ansi.brightWhite,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Which og theme is active for `el`, matching the `use-theme-type` convention
|
|
147
|
+
* (nearest `data-og-theme` / `.og-light` ancestor; else the computed
|
|
148
|
+
* `color-scheme`; else dark, the first-class default). */
|
|
149
|
+
function detectMode(el: Element, style: CSSStyleDeclaration): ThemeMode {
|
|
150
|
+
const closest = el.closest?.bind(el);
|
|
151
|
+
if (closest) {
|
|
152
|
+
if (closest('[data-og-theme="light"]') || closest(".og-light")) return "light";
|
|
153
|
+
const explicit = closest("[data-og-theme]");
|
|
154
|
+
if (explicit) return explicit.getAttribute("data-og-theme") === "light" ? "light" : "dark";
|
|
155
|
+
}
|
|
156
|
+
const scheme = (
|
|
157
|
+
style.getPropertyValue("color-scheme").trim() ||
|
|
158
|
+
style.colorScheme ||
|
|
159
|
+
""
|
|
160
|
+
).toLowerCase();
|
|
161
|
+
if (scheme.includes("light") && !scheme.includes("dark")) return "light";
|
|
162
|
+
return "dark";
|
|
163
|
+
}
|
|
164
|
+
|
|
3
165
|
/**
|
|
4
|
-
* Derive
|
|
5
|
-
* Reads the COMPUTED values so xterm
|
|
6
|
-
*
|
|
7
|
-
*
|
|
166
|
+
* Derive a COMPLETE xterm `ITheme` from the live `--og-*` token system on the
|
|
167
|
+
* DOM. Reads the COMPUTED values so xterm gets concrete colors, detects the
|
|
168
|
+
* active theme mode, and fills every ANSI slot. Call on mount + re-derive on a
|
|
169
|
+
* `data-og-theme` flip. SSR-safe: returns undefined off the DOM.
|
|
8
170
|
*
|
|
9
|
-
*
|
|
171
|
+
* `root` should be an element INSIDE the themed subtree (e.g. the terminal
|
|
172
|
+
* container) so nested `[data-og-theme]` themes resolve correctly; when omitted
|
|
173
|
+
* it falls back to the nearest `[data-og-theme]` element, then documentElement.
|
|
10
174
|
*/
|
|
11
175
|
export function xtermThemeFromTokens(root?: HTMLElement | null): XtermTheme | undefined {
|
|
12
176
|
if (typeof window === "undefined" || typeof getComputedStyle === "undefined") return undefined;
|
|
13
|
-
const el =
|
|
177
|
+
const el =
|
|
178
|
+
root ??
|
|
179
|
+
(typeof document !== "undefined"
|
|
180
|
+
? ((document.querySelector("[data-og-theme]") as HTMLElement | null) ??
|
|
181
|
+
document.documentElement)
|
|
182
|
+
: null);
|
|
183
|
+
if (!el) return undefined;
|
|
14
184
|
const style = getComputedStyle(el);
|
|
15
|
-
const read = (name
|
|
185
|
+
const read: TokenReader = (name) => {
|
|
16
186
|
const value = style.getPropertyValue(name).trim();
|
|
17
187
|
return value || undefined;
|
|
18
188
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
189
|
+
return buildXtermTheme(read, detectMode(el, style));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── Font resolution ──────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
export type ResolvedTerminalFont = { fontFamily: string; fontSize: number; lineHeight: number };
|
|
195
|
+
|
|
196
|
+
/** Concrete fallback if the token is unset or (defensively) still a `var()`. */
|
|
197
|
+
const FALLBACK_MONO = "ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace";
|
|
198
|
+
|
|
199
|
+
export type FontOverrides = { fontFamily?: string | undefined; fontSize?: number | undefined };
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Resolve xterm's font from token values. The critical bug this fixes:
|
|
203
|
+
* `fontFamily: "var(--og-font-mono)"` is measured by xterm via a canvas font
|
|
204
|
+
* string where `var()` does NOT resolve, so xterm silently mis-measures every
|
|
205
|
+
* glyph. Here the family is a CONCRETE stack; a `var(` in the input is treated
|
|
206
|
+
* as unresolved and replaced with the fallback. Pure over a token `read`.
|
|
207
|
+
*/
|
|
208
|
+
export function resolveTerminalFontFromReader(
|
|
209
|
+
read: TokenReader,
|
|
210
|
+
overrides?: FontOverrides,
|
|
211
|
+
): ResolvedTerminalFont {
|
|
212
|
+
const rawFamily = overrides?.fontFamily ?? read("--og-font-mono");
|
|
213
|
+
const fontFamily =
|
|
214
|
+
rawFamily && rawFamily.trim() && !rawFamily.includes("var(") ? rawFamily.trim() : FALLBACK_MONO;
|
|
215
|
+
|
|
216
|
+
let fontSize = overrides?.fontSize;
|
|
217
|
+
if (fontSize == null) {
|
|
218
|
+
const raw = read("--og-code-font-size");
|
|
219
|
+
const parsed = raw ? Number.parseFloat(raw) : Number.NaN;
|
|
220
|
+
fontSize = Number.isFinite(parsed) && parsed > 0 ? parsed : 13;
|
|
28
221
|
}
|
|
29
|
-
|
|
30
|
-
return
|
|
222
|
+
|
|
223
|
+
return { fontFamily, fontSize, lineHeight: 1.3 };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** DOM wrapper: resolve the terminal font from an element's computed tokens. */
|
|
227
|
+
export function resolveTerminalFont(
|
|
228
|
+
el: HTMLElement,
|
|
229
|
+
overrides?: FontOverrides,
|
|
230
|
+
): ResolvedTerminalFont {
|
|
231
|
+
const style = getComputedStyle(el);
|
|
232
|
+
const read: TokenReader = (name) => {
|
|
233
|
+
const value = style.getPropertyValue(name).trim();
|
|
234
|
+
return value || undefined;
|
|
235
|
+
};
|
|
236
|
+
return resolveTerminalFontFromReader(read, overrides);
|
|
31
237
|
}
|
package/src/machines.ts
CHANGED
|
@@ -37,9 +37,15 @@ export type { MachineCardProps } from "./components/machine-card";
|
|
|
37
37
|
export { MachinesDashboard } from "./components/machines-dashboard";
|
|
38
38
|
export type { MachinesDashboardProps } from "./components/machines-dashboard";
|
|
39
39
|
export { MachineDockBar, SharedMachineDisclosure } from "./components/machine-dock-bar";
|
|
40
|
-
export type {
|
|
40
|
+
export type {
|
|
41
|
+
MachineDockBarProps,
|
|
42
|
+
SharedMachineDisclosureProps,
|
|
43
|
+
} from "./components/machine-dock-bar";
|
|
41
44
|
export { EnrollmentDeviceFlow } from "./components/enrollment-device-flow";
|
|
42
|
-
export type {
|
|
45
|
+
export type {
|
|
46
|
+
DeviceFlowPhase,
|
|
47
|
+
EnrollmentDeviceFlowProps,
|
|
48
|
+
} from "./components/enrollment-device-flow";
|
|
43
49
|
export { EnrollmentConsent } from "./components/enrollment-consent";
|
|
44
50
|
export type {
|
|
45
51
|
EnrollmentConsentMachine,
|
|
@@ -47,4 +53,8 @@ export type {
|
|
|
47
53
|
EnrollmentConsentProps,
|
|
48
54
|
} from "./components/enrollment-consent";
|
|
49
55
|
export { useMachines } from "./hooks/use-machines";
|
|
50
|
-
export type {
|
|
56
|
+
export type {
|
|
57
|
+
MachinesClientLike,
|
|
58
|
+
UseMachinesOptions,
|
|
59
|
+
UseMachinesResult,
|
|
60
|
+
} from "./hooks/use-machines";
|
package/src/provider.tsx
CHANGED
|
@@ -45,7 +45,9 @@ export function useOpenGeni(override: ClientOverride = {}): OpenGeniContextValue
|
|
|
45
45
|
* Resolve the client only — for hooks that are not workspace-scoped
|
|
46
46
|
* (`useWorkspaces`, `useBillingUsage`).
|
|
47
47
|
*/
|
|
48
|
-
export function useOpenGeniClient(
|
|
48
|
+
export function useOpenGeniClient(
|
|
49
|
+
override: Pick<ClientOverride, "client"> = {},
|
|
50
|
+
): SessionClientLike {
|
|
49
51
|
const context = useContext(OpenGeniContext);
|
|
50
52
|
const client = override.client ?? context?.client;
|
|
51
53
|
if (!client) {
|