@opengeni/react 1.2.1-canary.37222965366001 → 1.4.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 (75) hide show
  1. package/README.md +52 -1
  2. package/dist/artifacts.js +2 -2
  3. package/dist/artifacts.js.map +1 -1
  4. package/dist/{chunk-ERGYJIBB.js → chunk-AWZLIMKX.js} +2 -2
  5. package/dist/{chunk-ERGYJIBB.js.map → chunk-AWZLIMKX.js.map} +1 -1
  6. package/dist/{chunk-FZCP527Y.js → chunk-CJUO7J5Z.js} +2 -2
  7. package/dist/{chunk-742CZ3L3.js → chunk-H5X55XH7.js} +16 -200
  8. package/dist/chunk-H5X55XH7.js.map +1 -0
  9. package/dist/{chunk-4OTO7KBK.js → chunk-LJ2UTJJE.js} +2737 -1580
  10. package/dist/chunk-LJ2UTJJE.js.map +1 -0
  11. package/dist/{chunk-CY7WK5FD.js → chunk-LN6TCXD3.js} +22 -1
  12. package/dist/chunk-LN6TCXD3.js.map +1 -0
  13. package/dist/{chunk-TMYGL6X5.js → chunk-MBMPHOMA.js} +71 -6
  14. package/dist/chunk-MBMPHOMA.js.map +1 -0
  15. package/dist/{chunk-RC6BZ44Q.js → chunk-OA6HFRQP.js} +2 -2
  16. package/dist/{chunk-X34BSY2R.js → chunk-WZMYFJD3.js} +242 -63
  17. package/dist/chunk-WZMYFJD3.js.map +1 -0
  18. package/dist/components/approval-surface.d.ts +11 -13
  19. package/dist/components/composer-transcription-control.d.ts +3 -0
  20. package/dist/components/open-geni-chat.d.ts +26 -7
  21. package/dist/components/session-conversation.d.ts +26 -3
  22. package/dist/components/session-list.d.ts +4 -1
  23. package/dist/components/session-proxy-scope.d.ts +16 -2
  24. package/dist/components/tool-action-review.d.ts +47 -0
  25. package/dist/components/tool-review-history.d.ts +25 -0
  26. package/dist/composer.js +1 -1
  27. package/dist/connect.js +1 -1
  28. package/dist/hooks/use-client-config-flags.d.ts +37 -0
  29. package/dist/index.d.ts +7 -4
  30. package/dist/index.js +27 -11
  31. package/dist/index.js.map +1 -1
  32. package/dist/{latest-question-YTOBHCWR.js → latest-question-GPYM2JNU.js} +3 -3
  33. package/dist/realtime/realtime-control.d.ts +2 -0
  34. package/dist/realtime.js +25 -4
  35. package/dist/realtime.js.map +1 -1
  36. package/dist/session-capability-policy.d.ts +20 -1
  37. package/dist/session-ui.d.ts +4 -1
  38. package/dist/session-ui.js +12 -6
  39. package/dist/session-ui.js.map +1 -1
  40. package/dist/session.js +6 -6
  41. package/dist/timeline/index.d.ts +2 -0
  42. package/dist/timeline/retained-loaders.d.ts +27 -0
  43. package/package.json +3 -3
  44. package/src/components/approval-surface.tsx +368 -239
  45. package/src/components/artifacts/session-artifact-viewer.tsx +4 -2
  46. package/src/components/composer-transcription-control.tsx +14 -0
  47. package/src/components/composer.tsx +1 -0
  48. package/src/components/open-geni-chat.tsx +245 -72
  49. package/src/components/session-conversation.tsx +243 -58
  50. package/src/components/session-list.tsx +9 -2
  51. package/src/components/session-proxy-scope.tsx +47 -7
  52. package/src/components/tool-action-review.tsx +649 -0
  53. package/src/components/tool-review-history.tsx +88 -0
  54. package/src/hooks/use-client-config-flags.ts +102 -0
  55. package/src/hooks/use-session-events.ts +19 -16
  56. package/src/hooks/use-transcription.ts +6 -0
  57. package/src/hooks/use-voice-input.ts +6 -0
  58. package/src/index.ts +18 -1
  59. package/src/realtime/realtime-control.tsx +28 -1
  60. package/src/session-capability-policy.ts +119 -6
  61. package/src/session-ui.ts +9 -1
  62. package/src/timeline/index.ts +10 -0
  63. package/src/timeline/retained-loaders.ts +86 -0
  64. package/src/timeline/tool-display-name.ts +5 -1
  65. package/src/timeline/tool-renderers.tsx +148 -8
  66. package/styles/compiled.css +79 -15
  67. package/styles/tokens.css +1 -1
  68. package/dist/chunk-4OTO7KBK.js.map +0 -1
  69. package/dist/chunk-742CZ3L3.js.map +0 -1
  70. package/dist/chunk-CY7WK5FD.js.map +0 -1
  71. package/dist/chunk-TMYGL6X5.js.map +0 -1
  72. package/dist/chunk-X34BSY2R.js.map +0 -1
  73. /package/dist/{chunk-FZCP527Y.js.map → chunk-CJUO7J5Z.js.map} +0 -0
  74. /package/dist/{chunk-RC6BZ44Q.js.map → chunk-OA6HFRQP.js.map} +0 -0
  75. /package/dist/{latest-question-YTOBHCWR.js.map → latest-question-GPYM2JNU.js.map} +0 -0
@@ -0,0 +1,86 @@
1
+ import type { OpenGeniClient, RetainedArtifactReference } from "@opengeni/sdk";
2
+ import type {
3
+ RetainedArtifactLoader,
4
+ RetainedScreenshotLoader,
5
+ VideoArtifactPlaybackLoader,
6
+ } from "./registry";
7
+
8
+ /** SDK methods the workspace retained-artifact loader needs. */
9
+ export type RetainedArtifactLoaderClient = Pick<
10
+ OpenGeniClient,
11
+ "createRetainedArtifactDownloadUrl" | "downloadRetainedArtifact"
12
+ >;
13
+
14
+ /** SDK method the session retained-screenshot loader needs. */
15
+ export type RetainedScreenshotLoaderClient = Pick<OpenGeniClient, "downloadRetainedScreenshot">;
16
+
17
+ /** SDK method the generated-video playback loader needs. */
18
+ export type RetainedVideoLoaderClient = Pick<OpenGeniClient, "createVideoArtifactPlaybackSource">;
19
+
20
+ /**
21
+ * Bind permanent retained-artifact retrieval (generated images, published
22
+ * files) to one authenticated workspace, for `MessageTimeline`'s
23
+ * `loadRetainedArtifact`. Images get a short-lived URL; files are assembled
24
+ * from verified byte ranges.
25
+ */
26
+ export function createWorkspaceRetainedArtifactLoader(
27
+ client: RetainedArtifactLoaderClient,
28
+ workspaceId: string,
29
+ ): RetainedArtifactLoader {
30
+ return async (artifact: RetainedArtifactReference, signal: AbortSignal) => {
31
+ if (artifact.kind === "file") {
32
+ const download = await client.downloadRetainedArtifact(workspaceId, artifact, { signal });
33
+ return download.bytes;
34
+ }
35
+ const download = await client.createRetainedArtifactDownloadUrl(workspaceId, artifact, {
36
+ signal,
37
+ });
38
+ return { url: download.url };
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Bind the authenticated screenshot downloader to one workspace and session,
44
+ * for `MessageTimeline`'s `loadRetainedScreenshot`. Fetched metadata must match
45
+ * the timeline receipt before bytes are handed to React; errors deliberately
46
+ * contain no storage locator or content.
47
+ */
48
+ export function createSessionRetainedScreenshotLoader(
49
+ client: RetainedScreenshotLoaderClient,
50
+ workspaceId: string,
51
+ sessionId: string,
52
+ ): RetainedScreenshotLoader {
53
+ return async (artifact: RetainedArtifactReference, signal: AbortSignal) => {
54
+ const download = await client.downloadRetainedScreenshot(
55
+ workspaceId,
56
+ sessionId,
57
+ artifact.artifactId,
58
+ { signal },
59
+ );
60
+ if (!download.metadata.available || !download.bytes) return null;
61
+ if (
62
+ download.metadata.artifactId !== artifact.artifactId ||
63
+ download.metadata.kind !== artifact.kind ||
64
+ download.metadata.contentType !== artifact.contentType ||
65
+ download.metadata.originalBytes !== artifact.originalBytes ||
66
+ download.metadata.sha256 !== artifact.sha256 ||
67
+ download.metadata.dimensions?.width !== artifact.dimensions?.width ||
68
+ download.metadata.dimensions?.height !== artifact.dimensions?.height
69
+ ) {
70
+ throw new Error("Retained screenshot receipt verification failed");
71
+ }
72
+ return download.bytes;
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Bind expiring generated-video playback sources to one authenticated
78
+ * workspace, for `MessageTimeline`'s `loadVideoArtifactPlayback`.
79
+ */
80
+ export function createWorkspaceRetainedVideoLoader(
81
+ client: RetainedVideoLoaderClient,
82
+ workspaceId: string,
83
+ ): VideoArtifactPlaybackLoader {
84
+ return async (artifactId: string, signal: AbortSignal) =>
85
+ await client.createVideoArtifactPlaybackSource(workspaceId, artifactId, { signal });
86
+ }
@@ -30,7 +30,11 @@ export function toolMatchesLeaf(wireName: string, leaf: string): boolean {
30
30
  */
31
31
  export function toolDisplayName(name: string, display?: ToolDisplayMetadata): string {
32
32
  if (!display && /^[a-f0-9]{64}$/.test(name)) return "Tool call";
33
- const phrase = (display?.toolName ?? mcpToolLeaf(name)).replace(/[_-]+/g, " ").trim();
33
+ // "batch modify messages" → "Modify messages": batching is transport, not the action.
34
+ const phrase = (display?.toolName ?? mcpToolLeaf(name))
35
+ .replace(/[_-]+/g, " ")
36
+ .trim()
37
+ .replace(/^batch\s+(?=\S)/i, "");
34
38
  const title =
35
39
  display?.title ?? (phrase ? phrase.charAt(0).toUpperCase() + phrase.slice(1) : name);
36
40
  return display?.accountLabel ? `${title} — ${display.accountLabel}` : title;
@@ -1,3 +1,6 @@
1
+ import { useHasToolReview, useRecordedToolReview } from "../components/tool-review-history";
2
+ import { ToolActionReviewCard } from "../components/tool-action-review";
3
+ import type { ToolReviewStatus } from "@opengeni/sdk";
1
4
  import { KnowledgeReceiptRow } from "./knowledge-receipt";
2
5
  import { defaultUrlTransform } from "react-markdown";
3
6
  import { isRetainedImageContentType, useRetainedImageObjectUrl } from "./retained-image";
@@ -587,7 +590,10 @@ function ComputerCallRenderer({ item, loadRetainedScreenshot }: ToolRendererProp
587
590
  // every transport.
588
591
  const functionAction: ComputerAction | undefined =
589
592
  !raw.action && item.name.startsWith("computer_") && item.name !== "computer_call"
590
- ? { type: item.name.slice("computer_".length), ...asComputerArgs(item.arguments) }
593
+ ? {
594
+ type: item.name.slice("computer_".length),
595
+ ...asComputerArgs(item.arguments),
596
+ }
591
597
  : undefined;
592
598
  const action = raw.action ?? functionAction;
593
599
  const actions = raw.actions ?? (action ? [action] : []);
@@ -2333,6 +2339,76 @@ function RunOnRenderer({ item }: ToolRendererProps) {
2333
2339
  * JSON stays in the expandable body only.
2334
2340
  */
2335
2341
  function GenericRenderer({ item }: ToolRendererProps) {
2342
+ const reviewed = useHasToolReview(item.callId);
2343
+ if (reviewed && item.callId) return <ReviewedGenericRenderer item={item} />;
2344
+ return <UnreviewedGenericRenderer item={item} />;
2345
+ }
2346
+
2347
+ /** Settled review states earn one quiet gutter word; success and waiting stay chip-free. */
2348
+ const REVIEW_CHIP: Partial<Record<ToolReviewStatus, DisclosureChip>> = {
2349
+ rejected: { tone: "interrupted", text: "declined" },
2350
+ cancelled: { tone: "interrupted", text: "not run" },
2351
+ expired: { tone: "interrupted", text: "expired" },
2352
+ stale: { tone: "interrupted", text: "not run" },
2353
+ revoked: { tone: "interrupted", text: "not run" },
2354
+ blocked: { tone: "interrupted", text: "blocked" },
2355
+ unknown: { tone: "bad", text: "outcome unknown" },
2356
+ partial: { tone: "bad", text: "partly done" },
2357
+ failed: { tone: "bad", text: "failed" },
2358
+ };
2359
+
2360
+ /**
2361
+ * A call that went through approval keeps the ordinary row shape, titled with
2362
+ * what was approved. The expanded body is the saved review plus the result.
2363
+ */
2364
+ function ReviewedGenericRenderer({ item }: ToolRendererProps) {
2365
+ const { review, onViewDetails } = useRecordedToolReview(item.callId);
2366
+ if (!review) return <UnreviewedGenericRenderer item={item} />;
2367
+ const icon = <GenericToolIcon name={item.name} />;
2368
+ const waiting = review.status === "pending";
2369
+ const running =
2370
+ !waiting &&
2371
+ (review.status === "executing" || review.status === "approved") &&
2372
+ item.status === "running";
2373
+ const { text: outText, isError } = unwrapMcpOutput(item.output);
2374
+ const chip =
2375
+ REVIEW_CHIP[review.status] ??
2376
+ (isError && !running && !waiting ? ({ tone: "bad", text: "error" } as const) : undefined);
2377
+ return (
2378
+ <ActivityDisclosure
2379
+ icon={icon}
2380
+ iconTone={chip?.tone === "bad" ? "failed" : waiting ? "accent" : "muted"}
2381
+ title={review.title}
2382
+ running={running}
2383
+ chip={chip}
2384
+ preview={
2385
+ waiting ? (
2386
+ "Waiting for your approval"
2387
+ ) : running ? (
2388
+ <RunningPreview>Running…</RunningPreview>
2389
+ ) : (
2390
+ (review.accountLabel ?? undefined)
2391
+ )
2392
+ }
2393
+ >
2394
+ <div className="py-1" data-approval-id={item.callId} data-review-origin="history">
2395
+ <ToolActionReviewCard
2396
+ bare
2397
+ review={{ ...review, availableActions: [] }}
2398
+ onViewDetails={onViewDetails}
2399
+ />
2400
+ </div>
2401
+ {outText ? <PayloadBlock label="Result" value={outText} failed={isError} /> : null}
2402
+ </ActivityDisclosure>
2403
+ );
2404
+ }
2405
+
2406
+ /** The runtime's exact refusal for a tool whose effective permission is Block. */
2407
+ const BLOCKED_OUTPUT = /Connector action was not executed: blocked\b/;
2408
+ /** The runtime's refusal to guess whether an approved action ran. */
2409
+ const UNCERTAIN_OUTPUT = /Connector action outcome is uncertain\b/;
2410
+
2411
+ function UnreviewedGenericRenderer({ item }: ToolRendererProps) {
2336
2412
  const running = item.status === "running";
2337
2413
  const args = parseToolArgs(item.arguments);
2338
2414
  const display = toolDisplayName(item.name, item.display);
@@ -2356,6 +2432,42 @@ function GenericRenderer({ item }: ToolRendererProps) {
2356
2432
  }
2357
2433
 
2358
2434
  const { text: outText, isError } = unwrapMcpOutput(item.output);
2435
+ // A permission Block is a decision, not a tool failure: say so plainly instead
2436
+ // of the generic "error occurred, please try again" wrapper.
2437
+ if (isError && BLOCKED_OUTPUT.test(outText)) {
2438
+ return (
2439
+ <ActivityDisclosure
2440
+ icon={icon}
2441
+ iconTone="muted"
2442
+ title={display}
2443
+ chip={{ tone: "interrupted", text: "blocked" }}
2444
+ preview="Blocked by your permission settings"
2445
+ >
2446
+ <p className="m-0 py-1 text-og-sm text-og-fg-muted">
2447
+ Your permission settings block this action, so it did not run. You can change this in the
2448
+ integration's tool permissions.
2449
+ </p>
2450
+ <PayloadBlock label="Arguments" value={args} />
2451
+ </ActivityDisclosure>
2452
+ );
2453
+ }
2454
+ // An interrupted approved action may have run. Never invite a blind retry.
2455
+ if (isError && UNCERTAIN_OUTPUT.test(outText)) {
2456
+ return (
2457
+ <ActivityDisclosure
2458
+ icon={icon}
2459
+ iconTone="failed"
2460
+ title={display}
2461
+ chip={{ tone: "bad", text: "outcome unknown" }}
2462
+ preview="It may have run"
2463
+ >
2464
+ <p className="m-0 py-1 text-og-sm text-og-fg-muted">
2465
+ This action may have run. Check the result in the connected app before trying again.
2466
+ </p>
2467
+ <PayloadBlock label="Arguments" value={args} />
2468
+ </ActivityDisclosure>
2469
+ );
2470
+ }
2359
2471
  // Cancelled is NOT an error — a user-cancelled tool should not surface the red
2360
2472
  // error chip even if the output payload carries an isError flag (the error may be
2361
2473
  // a consequence of the cancellation, not the tool's own failure).
@@ -2536,25 +2648,41 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
2536
2648
  { match: "name", name: "apply_patch_call", render: ApplyPatchRenderer },
2537
2649
  { match: "name", name: "apply_patch", render: ApplyPatchRenderer },
2538
2650
  { match: "name", name: "computer_call", render: ComputerCallRenderer },
2539
- { match: "name", name: "browser_screenshot", render: BrowserScreenshotRenderer },
2651
+ {
2652
+ match: "name",
2653
+ name: "browser_screenshot",
2654
+ render: BrowserScreenshotRenderer,
2655
+ },
2540
2656
  { match: "name", name: "browser_observe", render: BrowserScreenshotRenderer },
2541
2657
  { match: "name", name: "browser_act", render: BrowserScreenshotRenderer },
2542
2658
  // Function-mode computer tools (codex / chat-wire transports).
2543
2659
  { match: "name", name: "computer_screenshot", render: ComputerCallRenderer },
2544
2660
  { match: "name", name: "computer_click", render: ComputerCallRenderer },
2545
- { match: "name", name: "computer_double_click", render: ComputerCallRenderer },
2661
+ {
2662
+ match: "name",
2663
+ name: "computer_double_click",
2664
+ render: ComputerCallRenderer,
2665
+ },
2546
2666
  { match: "name", name: "computer_move", render: ComputerCallRenderer },
2547
2667
  { match: "name", name: "computer_scroll", render: ComputerCallRenderer },
2548
2668
  { match: "name", name: "computer_type", render: ComputerCallRenderer },
2549
2669
  { match: "name", name: "computer_keypress", render: ComputerCallRenderer },
2550
2670
  { match: "name", name: "computer_drag", render: ComputerCallRenderer },
2551
2671
  { match: "name", name: "web_search_call", render: WebSearchRenderer },
2552
- { match: "name", name: "image_generation_call", render: GeneratedImageRenderer },
2672
+ {
2673
+ match: "name",
2674
+ name: "image_generation_call",
2675
+ render: GeneratedImageRenderer,
2676
+ },
2553
2677
  { match: "name", name: "generate_image", render: GeneratedImageRenderer },
2554
2678
  { match: "name", name: "generate_video", render: GeneratedVideoRenderer },
2555
2679
  { match: "name", name: "tool_search", render: ToolSearchRenderer },
2556
2680
  { match: "name", name: "view_image", render: ViewImageRenderer },
2557
- { match: "name", name: "sandbox_file_publish", render: SandboxFilePublishRenderer },
2681
+ {
2682
+ match: "name",
2683
+ name: "sandbox_file_publish",
2684
+ render: SandboxFilePublishRenderer,
2685
+ },
2558
2686
  {
2559
2687
  match: "name",
2560
2688
  name: "artifacts_create",
@@ -2579,13 +2707,25 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
2579
2707
  render: SiteArtifactRenderer,
2580
2708
  matchPrefixedLeaf: false,
2581
2709
  },
2582
- { match: "name", name: "environment_set_variable", render: SecretSetRenderer },
2583
- { match: "name", name: "variable_set_set_variable", render: SecretSetRenderer },
2710
+ {
2711
+ match: "name",
2712
+ name: "environment_set_variable",
2713
+ render: SecretSetRenderer,
2714
+ },
2715
+ {
2716
+ match: "name",
2717
+ name: "variable_set_set_variable",
2718
+ render: SecretSetRenderer,
2719
+ },
2584
2720
  { match: "name", name: "search_documents", render: DocsSearchRenderer },
2585
2721
  { match: "name", name: "knowledge_search", render: DocsSearchRenderer },
2586
2722
  { match: "name", name: "memory_propose", render: MemoryProposeRenderer },
2587
2723
  { match: "name", name: "set_session_title", render: SetSessionTitleRenderer },
2588
- { match: "name", name: "set_other_session_title", render: SetSessionTitleRenderer },
2724
+ {
2725
+ match: "name",
2726
+ name: "set_other_session_title",
2727
+ render: SetSessionTitleRenderer,
2728
+ },
2589
2729
  ];
2590
2730
 
2591
2731
  /** The built-in tool renderer registry: every first-party tool plus a fallback. */
@@ -698,7 +698,7 @@
698
698
  --_og-color-primary-hover: var(--og-color-primary-hover, var(--og-color-primary));
699
699
  --_og-color-diff-add-bg: var(--og-color-diff-add-bg, var(--og-color-status-idle));
700
700
  --_og-color-diff-del-bg: var(--og-color-diff-del-bg, var(--og-color-status-failed));
701
- --_og-shadow-glow: var(--og-shadow-glow, 0 0 24px var(--og-color-accent));
701
+ --_og-shadow-glow: var(--og-shadow-glow, 0 0 24px color-mix(in oklch, var(--og-color-accent) 10%, transparent));
702
702
  --_og-session-chrome-surface: var(--og-session-chrome-surface, var(--og-color-surface-2));
703
703
  --_og-session-chrome-surface-open: var(--og-session-chrome-surface-open, var(--og-color-surface-2));
704
704
  --_og-session-chrome-border: var(--og-session-chrome-border, var(--og-color-border));
@@ -1786,6 +1786,9 @@
1786
1786
  :where(.og-root).mt-5,:where(.og-root) .mt-5 {
1787
1787
  margin-top: calc(var(--spacing) * 5);
1788
1788
  }
1789
+ :where(.og-root).mt-\[0\.55em\],:where(.og-root) .mt-\[0\.55em\] {
1790
+ margin-top: 0.55em;
1791
+ }
1789
1792
  :where(.og-root).mt-auto,:where(.og-root) .mt-auto {
1790
1793
  margin-top: auto;
1791
1794
  }
@@ -1828,6 +1831,9 @@
1828
1831
  :where(.og-root).mb-3,:where(.og-root) .mb-3 {
1829
1832
  margin-bottom: calc(var(--spacing) * 3);
1830
1833
  }
1834
+ :where(.og-root).mb-4,:where(.og-root) .mb-4 {
1835
+ margin-bottom: calc(var(--spacing) * 4);
1836
+ }
1831
1837
  :where(.og-root).ml-0\.5,:where(.og-root) .ml-0\.5 {
1832
1838
  margin-left: calc(var(--spacing) * 0.5);
1833
1839
  }
@@ -1993,6 +1999,9 @@
1993
1999
  :where(.og-root).h-2\.5,:where(.og-root) .h-2\.5 {
1994
2000
  height: calc(var(--spacing) * 2.5);
1995
2001
  }
2002
+ :where(.og-root).h-3,:where(.og-root) .h-3 {
2003
+ height: calc(var(--spacing) * 3);
2004
+ }
1996
2005
  :where(.og-root).h-3\.5,:where(.og-root) .h-3\.5 {
1997
2006
  height: calc(var(--spacing) * 3.5);
1998
2007
  }
@@ -2065,9 +2074,6 @@
2065
2074
  :where(.og-root).max-h-40,:where(.og-root) .max-h-40 {
2066
2075
  max-height: calc(var(--spacing) * 40);
2067
2076
  }
2068
- :where(.og-root).max-h-48,:where(.og-root) .max-h-48 {
2069
- max-height: calc(var(--spacing) * 48);
2070
- }
2071
2077
  :where(.og-root).max-h-56,:where(.og-root) .max-h-56 {
2072
2078
  max-height: calc(var(--spacing) * 56);
2073
2079
  }
@@ -2173,9 +2179,15 @@
2173
2179
  :where(.og-root).w-1\.5,:where(.og-root) .w-1\.5 {
2174
2180
  width: calc(var(--spacing) * 1.5);
2175
2181
  }
2182
+ :where(.og-root).w-1\/2,:where(.og-root) .w-1\/2 {
2183
+ width: calc(1 / 2 * 100%);
2184
+ }
2176
2185
  :where(.og-root).w-3,:where(.og-root) .w-3 {
2177
2186
  width: calc(var(--spacing) * 3);
2178
2187
  }
2188
+ :where(.og-root).w-3\/4,:where(.og-root) .w-3\/4 {
2189
+ width: calc(3 / 4 * 100%);
2190
+ }
2179
2191
  :where(.og-root).w-5,:where(.og-root) .w-5 {
2180
2192
  width: calc(var(--spacing) * 5);
2181
2193
  }
@@ -2356,6 +2368,9 @@
2356
2368
  :where(.og-root).min-w-4,:where(.og-root) .min-w-4 {
2357
2369
  min-width: calc(var(--spacing) * 4);
2358
2370
  }
2371
+ :where(.og-root).min-w-8,:where(.og-root) .min-w-8 {
2372
+ min-width: calc(var(--spacing) * 8);
2373
+ }
2359
2374
  :where(.og-root).min-w-10,:where(.og-root) .min-w-10 {
2360
2375
  min-width: calc(var(--spacing) * 10);
2361
2376
  }
@@ -2407,6 +2422,9 @@
2407
2422
  :where(.og-root).grow,:where(.og-root) .grow {
2408
2423
  flex-grow: 1;
2409
2424
  }
2425
+ :where(.og-root).basis-48,:where(.og-root) .basis-48 {
2426
+ flex-basis: calc(var(--spacing) * 48);
2427
+ }
2410
2428
  :where(.og-root).border-collapse,:where(.og-root) .border-collapse {
2411
2429
  border-collapse: collapse;
2412
2430
  }
@@ -2554,9 +2572,6 @@
2554
2572
  :where(.og-root).grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)\],:where(.og-root) .grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)\] {
2555
2573
  grid-template-columns: minmax(0,1fr) minmax(0,1fr);
2556
2574
  }
2557
- :where(.og-root).grid-cols-\[minmax\(5\.5rem\,max-content\)_minmax\(0\,1fr\)\],:where(.og-root) .grid-cols-\[minmax\(5\.5rem\,max-content\)_minmax\(0\,1fr\)\] {
2558
- grid-template-columns: minmax(5.5rem,max-content) minmax(0,1fr);
2559
- }
2560
2575
  :where(.og-root).flex-col,:where(.og-root) .flex-col {
2561
2576
  flex-direction: column;
2562
2577
  }
@@ -2731,14 +2746,6 @@
2731
2746
  }
2732
2747
  }
2733
2748
  }
2734
- :where(.og-root).divide-og-status-waiting\/20,:where(.og-root) .divide-og-status-waiting\/20 {
2735
- :where(& > :not(:last-child)) {
2736
- border-color: var(--og-color-status-waiting);
2737
- @supports (color: color-mix(in lab, red, red)) {
2738
- border-color: color-mix(in oklab, var(--og-color-status-waiting) 20%, transparent);
2739
- }
2740
- }
2741
- }
2742
2749
  :where(.og-root).self-center,:where(.og-root) .self-center {
2743
2750
  align-self: center;
2744
2751
  }
@@ -2858,6 +2865,10 @@
2858
2865
  border-style: var(--tw-border-style);
2859
2866
  border-width: 2px;
2860
2867
  }
2868
+ :where(.og-root).border-y,:where(.og-root) .border-y {
2869
+ border-block-style: var(--tw-border-style);
2870
+ border-block-width: 1px;
2871
+ }
2861
2872
  :where(.og-root).border-t,:where(.og-root) .border-t {
2862
2873
  border-top-style: var(--tw-border-style);
2863
2874
  border-top-width: 1px;
@@ -3283,6 +3294,12 @@
3283
3294
  background-color: color-mix(in oklab, var(--og-color-fg) 5%, transparent);
3284
3295
  }
3285
3296
  }
3297
+ :where(.og-root).bg-og-fg\/8,:where(.og-root) .bg-og-fg\/8 {
3298
+ background-color: var(--og-color-fg);
3299
+ @supports (color: color-mix(in lab, red, red)) {
3300
+ background-color: color-mix(in oklab, var(--og-color-fg) 8%, transparent);
3301
+ }
3302
+ }
3286
3303
  :where(.og-root).bg-og-primary,:where(.og-root) .bg-og-primary {
3287
3304
  background-color: var(--og-color-primary);
3288
3305
  }
@@ -3750,6 +3767,9 @@
3750
3767
  :where(.og-root).pr-1,:where(.og-root) .pr-1 {
3751
3768
  padding-right: calc(var(--spacing) * 1);
3752
3769
  }
3770
+ :where(.og-root).pr-2,:where(.og-root) .pr-2 {
3771
+ padding-right: calc(var(--spacing) * 2);
3772
+ }
3753
3773
  :where(.og-root).pr-2\.5,:where(.og-root) .pr-2\.5 {
3754
3774
  padding-right: calc(var(--spacing) * 2.5);
3755
3775
  }
@@ -5288,6 +5308,13 @@
5288
5308
  }
5289
5309
  }
5290
5310
  }
5311
+ :where(.og-root).hover\:decoration-current,:where(.og-root) .hover\:decoration-current {
5312
+ &:hover {
5313
+ @media (hover: hover) {
5314
+ text-decoration-color: currentcolor;
5315
+ }
5316
+ }
5317
+ }
5291
5318
  :where(.og-root).hover\:opacity-80,:where(.og-root) .hover\:opacity-80 {
5292
5319
  &:hover {
5293
5320
  @media (hover: hover) {
@@ -5997,6 +6024,11 @@
5997
6024
  grid-template-columns: minmax(0,1.2fr) minmax(0,1fr) 11rem;
5998
6025
  }
5999
6026
  }
6027
+ :where(.og-root).sm\:grid-cols-\[minmax\(0\,9rem\)_minmax\(0\,1fr\)\],:where(.og-root) .sm\:grid-cols-\[minmax\(0\,9rem\)_minmax\(0\,1fr\)\] {
6028
+ @media (width >= 40rem) {
6029
+ grid-template-columns: minmax(0,9rem) minmax(0,1fr);
6030
+ }
6031
+ }
6000
6032
  :where(.og-root).sm\:flex-row,:where(.og-root) .sm\:flex-row {
6001
6033
  @media (width >= 40rem) {
6002
6034
  flex-direction: row;
@@ -6074,6 +6106,11 @@
6074
6106
  padding-block: calc(var(--spacing) * 2);
6075
6107
  }
6076
6108
  }
6109
+ :where(.og-root).sm\:pt-px,:where(.og-root) .sm\:pt-px {
6110
+ @media (width >= 40rem) {
6111
+ padding-top: 1px;
6112
+ }
6113
+ }
6077
6114
  :where(.og-root).sm\:pb-2\.5,:where(.og-root) .sm\:pb-2\.5 {
6078
6115
  @media (width >= 40rem) {
6079
6116
  padding-bottom: calc(var(--spacing) * 2.5);
@@ -6084,6 +6121,23 @@
6084
6121
  padding-left: calc(var(--spacing) * 4);
6085
6122
  }
6086
6123
  }
6124
+ :where(.og-root).sm\:pl-\[3\.75rem\],:where(.og-root) .sm\:pl-\[3\.75rem\] {
6125
+ @media (width >= 40rem) {
6126
+ padding-left: 3.75rem;
6127
+ }
6128
+ }
6129
+ :where(.og-root).sm\:text-og-sm,:where(.og-root) .sm\:text-og-sm {
6130
+ @media (width >= 40rem) {
6131
+ font-size: var(--og-font-size-sm);
6132
+ line-height: var(--tw-leading, var(--og-line-height-sm));
6133
+ }
6134
+ }
6135
+ :where(.og-root).sm\:text-og-sm,:where(.og-root) .sm\:text-og-sm {
6136
+ @media (width >= 40rem) {
6137
+ --og-component-font-size: var(--og-font-size-sm);
6138
+ --og-component-line-height: var(--og-line-height-sm);
6139
+ }
6140
+ }
6087
6141
  :where(.og-root).md\:px-4,:where(.og-root) .md\:px-4 {
6088
6142
  @media (width >= 48rem) {
6089
6143
  padding-inline: calc(var(--spacing) * 4);
@@ -6525,6 +6579,16 @@
6525
6579
  margin-block: calc(var(--spacing) * 1);
6526
6580
  }
6527
6581
  }
6582
+ :where(.og-root).\[\@media\(pointer\:coarse\)\]\:min-h-11,:where(.og-root) .\[\@media\(pointer\:coarse\)\]\:min-h-11 {
6583
+ @media (pointer:coarse) {
6584
+ min-height: calc(var(--spacing) * 11);
6585
+ }
6586
+ }
6587
+ :where(.og-root).\[\@media\(pointer\:coarse\)\]\:min-w-11,:where(.og-root) .\[\@media\(pointer\:coarse\)\]\:min-w-11 {
6588
+ @media (pointer:coarse) {
6589
+ min-width: calc(var(--spacing) * 11);
6590
+ }
6591
+ }
6528
6592
  :where(.og-root).\[tr\:last-child\>\&\]\:border-b-0,:where(.og-root) .\[tr\:last-child\>\&\]\:border-b-0 {
6529
6593
  tr:last-child>& {
6530
6594
  border-bottom-style: var(--tw-border-style);
package/styles/tokens.css CHANGED
@@ -165,7 +165,7 @@
165
165
  draws a crisp edge via `focus-within:border-og-accent/50`; the old
166
166
  `0 0 0 1px` ring sat flush against that border and read as a doubled
167
167
  hairline, so the glow is purely a faint diffuse grey halo. */
168
- --og-shadow-glow: 0 0 24px var(--og-color-accent);
168
+ --og-shadow-glow: 0 0 24px color-mix(in oklch, var(--og-color-accent) 10%, transparent);
169
169
 
170
170
  /* Session chrome — override on `.og-session-chrome` (or an ancestor) to rebrand.
171
171
  Defaults stay quiet: soft surface, short motion, no gold shout. */