@opengeni/react 3.5.1-canary.0 → 3.7.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 (87) hide show
  1. package/dist/artifacts.d.ts +1 -1
  2. package/dist/artifacts.js +248 -6
  3. package/dist/artifacts.js.map +1 -1
  4. package/dist/{browser-viewer-E5DDEFQ4.js → browser-viewer-NTD6UIPR.js} +3 -3
  5. package/dist/{chunk-W2RGYBCV.js → chunk-24M4YBCL.js} +4 -4
  6. package/dist/{chunk-WY3MELVJ.js → chunk-5IXTJTK3.js} +1438 -397
  7. package/dist/chunk-5IXTJTK3.js.map +1 -0
  8. package/dist/chunk-5PQJOCX5.js +902 -0
  9. package/dist/chunk-5PQJOCX5.js.map +1 -0
  10. package/dist/{chunk-UNCXXIQR.js → chunk-INGB2N5R.js} +4310 -3982
  11. package/dist/chunk-INGB2N5R.js.map +1 -0
  12. package/dist/{chunk-TJFMMDQU.js → chunk-MOWYEBCQ.js} +1839 -17
  13. package/dist/chunk-MOWYEBCQ.js.map +1 -0
  14. package/dist/chunk-PAJU5KKL.js +331 -0
  15. package/dist/chunk-PAJU5KKL.js.map +1 -0
  16. package/dist/{chunk-VTOREEXF.js → chunk-PLYRL5ER.js} +24 -2
  17. package/dist/{chunk-VTOREEXF.js.map → chunk-PLYRL5ER.js.map} +1 -1
  18. package/dist/{chunk-YVCHAQZY.js → chunk-ZFOFY5ST.js} +27 -349
  19. package/dist/chunk-ZFOFY5ST.js.map +1 -0
  20. package/dist/client.d.ts +1 -1
  21. package/dist/components/artifacts/index.d.ts +1 -1
  22. package/dist/components/artifacts/published-html-artifact-frame.d.ts +46 -3
  23. package/dist/components/composer.d.ts +2 -0
  24. package/dist/components/session-chrome.d.ts +38 -5
  25. package/dist/components/session-commands-panel.d.ts +6 -0
  26. package/dist/components/session-conversation.d.ts +14 -0
  27. package/dist/components/timeline-anchor.d.ts +21 -0
  28. package/dist/composer.js +2 -3
  29. package/dist/conversation-timeline.d.ts +5 -0
  30. package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
  31. package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
  32. package/dist/hooks/use-file-attachments.d.ts +6 -0
  33. package/dist/hooks/use-sandbox-files.d.ts +4 -1
  34. package/dist/hooks/use-workspace-edit.d.ts +4 -0
  35. package/dist/index.d.ts +4 -1
  36. package/dist/index.js +823 -965
  37. package/dist/index.js.map +1 -1
  38. package/dist/interaction.js +2 -2
  39. package/dist/lib/format.d.ts +5 -0
  40. package/dist/machines.js +3 -2
  41. package/dist/session-ui.d.ts +3 -0
  42. package/dist/session-ui.js +14 -4
  43. package/dist/session.js +19 -19
  44. package/dist/timeline/registry.d.ts +2 -0
  45. package/dist/timeline/types.d.ts +4 -2
  46. package/package.json +2 -2
  47. package/src/artifacts.ts +3 -0
  48. package/src/client.ts +2 -1
  49. package/src/components/artifacts/index.ts +3 -0
  50. package/src/components/artifacts/published-html-artifact-frame.tsx +307 -4
  51. package/src/components/composer.tsx +89 -25
  52. package/src/components/machine-input-display.ts +6 -0
  53. package/src/components/message-timeline.tsx +351 -204
  54. package/src/components/sandbox-workspace.tsx +11 -1
  55. package/src/components/session-chrome.tsx +501 -128
  56. package/src/components/session-commands-panel.tsx +113 -0
  57. package/src/components/session-conversation.tsx +141 -0
  58. package/src/components/timeline-anchor.tsx +91 -0
  59. package/src/conversation-timeline.ts +83 -0
  60. package/src/hooks/use-file-attachments.ts +34 -0
  61. package/src/hooks/use-sandbox-files.ts +68 -20
  62. package/src/hooks/use-session-background-commands.ts +21 -10
  63. package/src/hooks/use-session-events.ts +56 -39
  64. package/src/hooks/use-session.ts +23 -2
  65. package/src/hooks/use-workspace-edit.ts +23 -5
  66. package/src/index.ts +4 -0
  67. package/src/lib/format.ts +32 -0
  68. package/src/session-ui.ts +3 -0
  69. package/src/timeline/fleet-decision-projection.ts +2 -1
  70. package/src/timeline/fleet-decision-row.tsx +1 -0
  71. package/src/timeline/projection.ts +157 -19
  72. package/src/timeline/registry.ts +15 -3
  73. package/src/timeline/tool-renderers.tsx +117 -1
  74. package/src/timeline/types.ts +12 -1
  75. package/styles/compiled.css +495 -411
  76. package/styles/index.css +23 -0
  77. package/dist/chunk-7EAFGICR.js +0 -302
  78. package/dist/chunk-7EAFGICR.js.map +0 -1
  79. package/dist/chunk-IB27C53Y.js +0 -2582
  80. package/dist/chunk-IB27C53Y.js.map +0 -1
  81. package/dist/chunk-TJFMMDQU.js.map +0 -1
  82. package/dist/chunk-UNCXXIQR.js.map +0 -1
  83. package/dist/chunk-WY3MELVJ.js.map +0 -1
  84. package/dist/chunk-YVCHAQZY.js.map +0 -1
  85. package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
  86. /package/dist/{browser-viewer-E5DDEFQ4.js.map → browser-viewer-NTD6UIPR.js.map} +0 -0
  87. /package/dist/{chunk-W2RGYBCV.js.map → chunk-24M4YBCL.js.map} +0 -0
@@ -8,21 +8,52 @@ import {
8
8
  tableElementToTsv
9
9
  } from "./chunk-JVYQRRC4.js";
10
10
  import {
11
+ Actions,
12
+ AttachButton,
13
+ Attachments,
14
+ CommandPalette2 as CommandPalette,
15
+ ComposerTranscriptionControl,
16
+ Confirmation,
17
+ Controls,
18
+ Footer,
19
+ Frame,
20
+ Help,
21
+ Hint,
22
+ Input,
11
23
  LightboxProvider,
24
+ ModelPicker2 as ModelPicker,
25
+ PauseButton,
26
+ PausedState,
27
+ RestoredResources,
28
+ Root,
29
+ SendButton,
30
+ Status,
31
+ Surface,
12
32
  Tooltip,
13
33
  TooltipContent,
14
34
  TooltipProvider,
15
35
  TooltipTrigger,
36
+ useChatComposerController,
16
37
  useLightboxOptional
17
- } from "./chunk-7EAFGICR.js";
38
+ } from "./chunk-INGB2N5R.js";
39
+ import {
40
+ ModelPolicyPicker
41
+ } from "./chunk-4JFUT22W.js";
18
42
  import {
19
43
  buildTimeline,
20
44
  groupTimeline,
21
45
  invokeOlderHistoryLoaderWithReceiptCapture,
22
46
  isActionableHumanInputRequest,
23
47
  mcpToolLeaf,
24
- toolDisplayName
25
- } from "./chunk-TJFMMDQU.js";
48
+ toolDisplayName,
49
+ useHumanInputRequests,
50
+ useSession,
51
+ useSessionEvents,
52
+ useTurnQueue
53
+ } from "./chunk-MOWYEBCQ.js";
54
+ import {
55
+ useComposer
56
+ } from "./chunk-IOLVN74D.js";
26
57
  import {
27
58
  formatBytes,
28
59
  formatClockTime,
@@ -30,7 +61,18 @@ import {
30
61
  stringifyPayload,
31
62
  truncate,
32
63
  tryParseJson
33
- } from "./chunk-VTOREEXF.js";
64
+ } from "./chunk-PLYRL5ER.js";
65
+ import {
66
+ usePolledValue
67
+ } from "./chunk-KZ73RL76.js";
68
+ import {
69
+ useOpenGeni,
70
+ useOpenGeniClient
71
+ } from "./chunk-NEXLLTP4.js";
72
+ import {
73
+ projectPickerRows,
74
+ sortPickerRows
75
+ } from "./chunk-WMGF4Z7X.js";
34
76
  import {
35
77
  cn
36
78
  } from "./chunk-22KP6LR5.js";
@@ -1851,6 +1893,7 @@ function createToolRegistry(baseEntries, baseFallback, options = {}) {
1851
1893
  const fallback = options.fallback ?? baseFallback;
1852
1894
  const byRawType = /* @__PURE__ */ new Map();
1853
1895
  const byName = /* @__PURE__ */ new Map();
1896
+ const byPrefixedLeaf = /* @__PURE__ */ new Map();
1854
1897
  for (const entry of entries) {
1855
1898
  if (entry.match === "rawType") {
1856
1899
  if (!byRawType.has(entry.type)) {
@@ -1859,6 +1902,11 @@ function createToolRegistry(baseEntries, baseFallback, options = {}) {
1859
1902
  } else if (!byName.has(entry.name)) {
1860
1903
  byName.set(entry.name, entry.render);
1861
1904
  }
1905
+ if (entry.match === "name" && entry.matchPrefixedLeaf !== false) {
1906
+ if (!byPrefixedLeaf.has(entry.name)) {
1907
+ byPrefixedLeaf.set(entry.name, entry.render);
1908
+ }
1909
+ }
1862
1910
  }
1863
1911
  const resolve = (item) => {
1864
1912
  const rawType = rawTypeOf(item);
@@ -1874,7 +1922,7 @@ function createToolRegistry(baseEntries, baseFallback, options = {}) {
1874
1922
  }
1875
1923
  const leaf = mcpToolLeaf(item.name);
1876
1924
  if (leaf !== item.name) {
1877
- const byLeaf = byName.get(leaf);
1925
+ const byLeaf = byPrefixedLeaf.get(leaf);
1878
1926
  if (byLeaf) {
1879
1927
  return byLeaf;
1880
1928
  }
@@ -3740,6 +3788,76 @@ function SandboxFilePublishRenderer({ item, loadRetainedArtifact }) {
3740
3788
  }
3741
3789
  );
3742
3790
  }
3791
+ function publishedSiteReceipt(output) {
3792
+ const { text, isError } = unwrapMcpOutput(output);
3793
+ if (isError) return null;
3794
+ const parsed = tryParseJson(text);
3795
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
3796
+ const artifact = parsed.artifact;
3797
+ const version = parsed.version;
3798
+ if (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || !version || typeof version !== "object" || Array.isArray(version)) {
3799
+ return null;
3800
+ }
3801
+ const artifactRecord = artifact;
3802
+ const versionRecord = version;
3803
+ if (typeof artifactRecord.workspaceId !== "string" || typeof artifactRecord.id !== "string" || typeof artifactRecord.title !== "string" || typeof versionRecord.revision !== "number" || !Number.isInteger(versionRecord.revision) || versionRecord.revision < 1) {
3804
+ return null;
3805
+ }
3806
+ return {
3807
+ workspaceId: artifactRecord.workspaceId,
3808
+ artifactId: artifactRecord.id,
3809
+ title: artifactRecord.title,
3810
+ revision: versionRecord.revision,
3811
+ replayed: parsed.replayed === true
3812
+ };
3813
+ }
3814
+ function SiteOpenLink({ receipt }) {
3815
+ const href = `/workspaces/${encodeURIComponent(receipt.workspaceId)}/artifacts/${encodeURIComponent(receipt.artifactId)}`;
3816
+ return /* @__PURE__ */ jsx10(
3817
+ "a",
3818
+ {
3819
+ href,
3820
+ "aria-label": `Open ${receipt.title}`,
3821
+ className: "inline-flex min-h-7 items-center rounded-og-sm px-2 text-og-sm font-medium text-og-accent-strong hover:bg-og-surface-2 hover:underline focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-10",
3822
+ onClick: (event) => event.stopPropagation(),
3823
+ onKeyDown: (event) => event.stopPropagation(),
3824
+ children: "Open"
3825
+ }
3826
+ );
3827
+ }
3828
+ function SiteArtifactRenderer({ item }) {
3829
+ const leaf = mcpToolLeaf(item.name);
3830
+ const publishingExisting = leaf === "artifacts_publish";
3831
+ if (item.status === "running") {
3832
+ return /* @__PURE__ */ jsx10(
3833
+ ActivityDisclosure,
3834
+ {
3835
+ icon: /* @__PURE__ */ jsx10(PanelsTopLeftIcon, { className: ICON_SIZE }),
3836
+ iconTone: "running",
3837
+ title: publishingExisting ? "Publishing Site update" : "Publishing Site",
3838
+ running: true,
3839
+ preview: /* @__PURE__ */ jsx10(RunningPreview, { children: "retaining source and compiled HTML\u2026" })
3840
+ }
3841
+ );
3842
+ }
3843
+ const receipt = publishedSiteReceipt(item.output);
3844
+ if (!receipt || item.status === "failed") return /* @__PURE__ */ jsx10(GenericRenderer, { item });
3845
+ return /* @__PURE__ */ jsx10(
3846
+ ActivityDisclosure,
3847
+ {
3848
+ icon: /* @__PURE__ */ jsx10(PanelsTopLeftIcon, { className: ICON_SIZE }),
3849
+ iconTone: "accent",
3850
+ title: publishingExisting ? `Updated ${receipt.title}` : `Published ${receipt.title}`,
3851
+ media: /* @__PURE__ */ jsx10(SiteOpenLink, { receipt }),
3852
+ children: /* @__PURE__ */ jsxs7(BodyNote, { children: [
3853
+ "Version ",
3854
+ receipt.revision,
3855
+ " is live",
3856
+ receipt.replayed ? " (replayed from the original publication)." : "."
3857
+ ] })
3858
+ }
3859
+ );
3860
+ }
3743
3861
  function GeneratedImageDisclosure({
3744
3862
  receipt,
3745
3863
  load,
@@ -4632,7 +4750,7 @@ function GenericRenderer({ item }) {
4632
4750
  }
4633
4751
  function goalToolPreview(name, args) {
4634
4752
  const leaf = mcpToolLeaf(name);
4635
- if (leaf !== "goal_set" && leaf !== "goal_update" && leaf !== "goal_complete" && leaf !== "goal_pause" && leaf !== "goal_wait") {
4753
+ if (leaf !== "goal_set" && leaf !== "goal_update" && leaf !== "goal_complete" && leaf !== "goal_pause" && leaf !== "wait_for_input") {
4636
4754
  return null;
4637
4755
  }
4638
4756
  const record = args && typeof args === "object" ? args : null;
@@ -4684,6 +4802,30 @@ var BASE_ENTRIES = [
4684
4802
  { match: "name", name: "tool_search", render: ToolSearchRenderer },
4685
4803
  { match: "name", name: "view_image", render: ViewImageRenderer },
4686
4804
  { match: "name", name: "sandbox_file_publish", render: SandboxFilePublishRenderer },
4805
+ {
4806
+ match: "name",
4807
+ name: "artifacts_create",
4808
+ render: SiteArtifactRenderer,
4809
+ matchPrefixedLeaf: false
4810
+ },
4811
+ {
4812
+ match: "name",
4813
+ name: "artifacts_publish",
4814
+ render: SiteArtifactRenderer,
4815
+ matchPrefixedLeaf: false
4816
+ },
4817
+ {
4818
+ match: "name",
4819
+ name: "opengeni__artifacts_create",
4820
+ render: SiteArtifactRenderer,
4821
+ matchPrefixedLeaf: false
4822
+ },
4823
+ {
4824
+ match: "name",
4825
+ name: "opengeni__artifacts_publish",
4826
+ render: SiteArtifactRenderer,
4827
+ matchPrefixedLeaf: false
4828
+ },
4687
4829
  { match: "name", name: "environment_set_variable", render: SecretSetRenderer },
4688
4830
  { match: "name", name: "variable_set_set_variable", render: SecretSetRenderer },
4689
4831
  { match: "name", name: "search_documents", render: DocsSearchRenderer },
@@ -4734,7 +4876,7 @@ function useSeenActivityIds() {
4734
4876
 
4735
4877
  // src/timeline/activity-rail.tsx
4736
4878
  import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
4737
- var LazyFleetDecisionRow = lazy2(() => import("./fleet-decision-row-GGCAT4E4.js"));
4879
+ var LazyFleetDecisionRow = lazy2(() => import("./fleet-decision-row-YZ3ZKWMM.js"));
4738
4880
  var LazyPlatformActivityRow = lazy2(() => import("./platform-activity-row-BJHUHXAT.js"));
4739
4881
  function familyOf(item) {
4740
4882
  if (item.kind === "tool-call") {
@@ -5635,7 +5777,7 @@ import {
5635
5777
  import { AnimatePresence, motion } from "motion/react";
5636
5778
  import { Collapsible as Collapsible2 } from "radix-ui";
5637
5779
  import {
5638
- Component as Component2,
5780
+ Component as Component3,
5639
5781
  Suspense as Suspense3,
5640
5782
  lazy as lazy3,
5641
5783
  memo as memo2,
@@ -5647,6 +5789,73 @@ import {
5647
5789
  useState as useState12
5648
5790
  } from "react";
5649
5791
 
5792
+ // src/components/timeline-anchor.tsx
5793
+ import { Component as Component2 } from "react";
5794
+ var TimelineBeforeLayout = class extends Component2 {
5795
+ getSnapshotBeforeUpdate() {
5796
+ this.props.capture();
5797
+ return null;
5798
+ }
5799
+ componentDidUpdate() {
5800
+ }
5801
+ render() {
5802
+ return this.props.children;
5803
+ }
5804
+ };
5805
+ function captureTimelineAnchor(scroller) {
5806
+ const viewport = scroller.getBoundingClientRect();
5807
+ if (viewport.height <= 0) return null;
5808
+ const groups = Array.from(scroller.querySelectorAll("[data-og-group-key]")).filter(
5809
+ (group) => group.getBoundingClientRect().height > 0
5810
+ );
5811
+ const anchors = [];
5812
+ const focused = scroller.ownerDocument.activeElement;
5813
+ if (focused instanceof HTMLElement && scroller.contains(focused) && focused.matches("button[aria-expanded]")) {
5814
+ const box = focused.getBoundingClientRect();
5815
+ if (box.bottom > viewport.top && box.top < viewport.bottom) {
5816
+ anchors.push({ element: focused, key: null, text: null, top: box.top });
5817
+ }
5818
+ }
5819
+ for (const group of groups) {
5820
+ const rect = group.getBoundingClientRect();
5821
+ if (rect.bottom <= viewport.top || rect.top >= viewport.bottom) continue;
5822
+ for (const element of group.querySelectorAll("p, li, pre, h1, h2, h3, h4")) {
5823
+ const box = element.getBoundingClientRect();
5824
+ const text = element.textContent;
5825
+ if (box.bottom > viewport.top && box.top < viewport.bottom && text && text.length >= 12) {
5826
+ anchors.push({ element, key: null, text, top: box.top });
5827
+ }
5828
+ }
5829
+ }
5830
+ const rows = groups.map((element) => ({
5831
+ element,
5832
+ key: element.getAttribute("data-og-group-key"),
5833
+ text: null,
5834
+ top: element.getBoundingClientRect().top
5835
+ }));
5836
+ anchors.push(...rows.filter((row) => row.top >= viewport.top));
5837
+ anchors.push(...rows.filter((row) => row.top < viewport.top).reverse());
5838
+ return anchors;
5839
+ }
5840
+ function timelineAnchorCorrection(scroller, anchors) {
5841
+ let blocks;
5842
+ const groups = Array.from(scroller.querySelectorAll("[data-og-group-key]"));
5843
+ for (const anchor of anchors) {
5844
+ let element;
5845
+ if (scroller.contains(anchor.element) && (!anchor.text || anchor.element.textContent === anchor.text)) {
5846
+ element = anchor.element;
5847
+ } else if (anchor.key) {
5848
+ element = groups.find((group) => group.getAttribute("data-og-group-key") === anchor.key);
5849
+ } else if (anchor.text) {
5850
+ blocks ??= Array.from(scroller.querySelectorAll("p, li, pre, h1, h2, h3, h4"));
5851
+ const matches = blocks.filter((block) => block.textContent === anchor.text);
5852
+ if (matches.length === 1) element = matches[0];
5853
+ }
5854
+ if (element) return element.getBoundingClientRect().top - anchor.top;
5855
+ }
5856
+ return null;
5857
+ }
5858
+
5650
5859
  // src/components/tip-follow.ts
5651
5860
  var _t = (ms) => ms * MOTION_INSPECT_SCALE;
5652
5861
  var _s = (pxPerSec) => pxPerSec / MOTION_INSPECT_SCALE;
@@ -5946,6 +6155,8 @@ function tipFollowStep(state, input) {
5946
6155
  var MACHINE_INPUT_META = {
5947
6156
  scheduled_occurrence: "Scheduled update",
5948
6157
  goal_continuation: "Goal continued",
6158
+ background_command_result: "Command result received",
6159
+ session_wait_timeout: "Wait ended",
5949
6160
  agent_message: "Agent update",
5950
6161
  agent_steer_instruction: "Agent direction",
5951
6162
  child_terminal_result: "Agent finished",
@@ -5966,6 +6177,10 @@ function machineInputBatchLabel(members) {
5966
6177
  const kind = members[0].kind;
5967
6178
  const n = members.length;
5968
6179
  switch (kind) {
6180
+ case "background_command_result":
6181
+ return n === 1 ? "Command result received" : `${n} command results received`;
6182
+ case "session_wait_timeout":
6183
+ return n === 1 ? "Wait ended" : `${n} waits ended`;
5969
6184
  case "child_terminal_result":
5970
6185
  return n === 1 ? "Agent finished" : `${n} agents finished`;
5971
6186
  case "goal_continuation":
@@ -6130,8 +6345,13 @@ function MessageTimeline({
6130
6345
  (item) => item.kind !== "auth-needed" || shouldRenderAuthNeeded(item)
6131
6346
  );
6132
6347
  }, [items, events, shouldRenderAuthNeeded]);
6133
- const sourceItems = items || events;
6348
+ const sourceItems = events ?? items;
6134
6349
  const olderBoundaryKey = sourceItems?.[0]?.id;
6350
+ const previousSourceIdsRef = useRef10(/* @__PURE__ */ new Set());
6351
+ const previousSourceBoundaryRef = useRef10(void 0);
6352
+ const readingAnchorRef = useRef10(null);
6353
+ const olderPageBudgetRef = useRef10(0);
6354
+ const [olderDemand, setOlderDemand] = useState12(0);
6135
6355
  const allGroups = useMemo4(() => groupTimeline(resolvedItems), [resolvedItems]);
6136
6356
  const annotationSources = useMemo4(() => {
6137
6357
  const sources = /* @__PURE__ */ new Map();
@@ -6260,28 +6480,22 @@ function MessageTimeline({
6260
6480
  followFrameRef.current = null;
6261
6481
  }
6262
6482
  }, []);
6263
- const releasePinFromReader = useCallback2(
6264
- (node) => {
6265
- if (!autoFollow || !pinnedRef.current || hasNewerRef.current) {
6266
- return;
6267
- }
6268
- if (node && maxScrollOf(node) <= 1) {
6269
- return;
6270
- }
6271
- clearReaderIntent();
6272
- clearPendingReaderLeave();
6273
- stopFollow();
6274
- applyPinned(false);
6275
- if (wantPinRef.current) {
6276
- wantPinRef.current = false;
6277
- }
6278
- if (!olderPrefetchArmedRef.current) {
6279
- olderPrefetchArmedRef.current = true;
6280
- setOlderPrefetchArmed(true);
6281
- }
6282
- },
6283
- [autoFollow, applyPinned, clearPendingReaderLeave, clearReaderIntent, stopFollow]
6284
- );
6483
+ const releasePinFromReader = useCallback2(() => {
6484
+ if (!autoFollow || !pinnedRef.current || hasNewerRef.current) {
6485
+ return;
6486
+ }
6487
+ clearReaderIntent();
6488
+ clearPendingReaderLeave();
6489
+ stopFollow();
6490
+ applyPinned(false);
6491
+ if (wantPinRef.current) {
6492
+ wantPinRef.current = false;
6493
+ }
6494
+ if (!olderPrefetchArmedRef.current) {
6495
+ olderPrefetchArmedRef.current = true;
6496
+ setOlderPrefetchArmed(true);
6497
+ }
6498
+ }, [autoFollow, applyPinned, clearPendingReaderLeave, clearReaderIntent, stopFollow]);
6285
6499
  const releasePinAfterScrollSettled = useCallback2(
6286
6500
  (node) => {
6287
6501
  if (!autoFollow || !pinnedRef.current || hasNewerRef.current) {
@@ -6297,7 +6511,7 @@ function MessageTimeline({
6297
6511
  clearPendingReaderLeave();
6298
6512
  return;
6299
6513
  }
6300
- releasePinFromReader(node);
6514
+ releasePinFromReader();
6301
6515
  rearmOlderPrefetchAfterLeavingTop(node);
6302
6516
  },
6303
6517
  [autoFollow, clearPendingReaderLeave, rearmOlderPrefetchAfterLeavingTop, releasePinFromReader]
@@ -6315,6 +6529,16 @@ function MessageTimeline({
6315
6529
  }
6316
6530
  });
6317
6531
  }, [cancelLeaveFallback, releasePinAfterScrollSettled]);
6532
+ const requestEarlierFromReader = () => {
6533
+ releasePinFromReader();
6534
+ wantPinRef.current = false;
6535
+ olderPageBudgetRef.current = 8;
6536
+ if (olderLoadAttemptRef.current?.[1] === 2) {
6537
+ olderLoadAttemptRef.current = null;
6538
+ setOlderDemand((value) => value + 1);
6539
+ }
6540
+ };
6541
+ const touchPositionRef = useRef10(null);
6318
6542
  const onWheel = (event) => {
6319
6543
  if (Math.abs(event.deltaY) <= Math.abs(event.deltaX)) {
6320
6544
  return;
@@ -6323,11 +6547,11 @@ function MessageTimeline({
6323
6547
  return;
6324
6548
  }
6325
6549
  disclosureKeepsUnpinnedRef.current = false;
6550
+ programmaticScrollRef.current = 0;
6326
6551
  if (event.deltaY >= 0) {
6327
6552
  return;
6328
6553
  }
6329
- const node = event.currentTarget instanceof HTMLElement ? event.currentTarget : scrollRef.current;
6330
- releasePinFromReader(node);
6554
+ requestEarlierFromReader();
6331
6555
  };
6332
6556
  const onPointerDown = (event) => {
6333
6557
  if (event.button && event.pointerType === "mouse") {
@@ -6348,8 +6572,8 @@ function MessageTimeline({
6348
6572
  if (event.key !== "ArrowUp" && event.key !== "PageUp" && event.key !== "Home") {
6349
6573
  return;
6350
6574
  }
6351
- const node = event.currentTarget instanceof HTMLElement ? event.currentTarget : scrollRef.current;
6352
- releasePinFromReader(node);
6575
+ programmaticScrollRef.current = 0;
6576
+ requestEarlierFromReader();
6353
6577
  };
6354
6578
  const snapToBottom = useCallback2(
6355
6579
  (node) => {
@@ -6597,10 +6821,21 @@ function MessageTimeline({
6597
6821
  const previousMaxScroll = lastMaxScrollRef.current;
6598
6822
  const wasAtLiveTailBeforeCommit = previousMaxScroll <= 1 || previousMaxScroll - previousScrollTop < Math.min(PIN_THRESHOLD_PX, previousMaxScroll);
6599
6823
  const firstItemChanged = !!previousFirstItemId && firstItemId !== previousFirstItemId;
6600
- const prepended = firstItemChanged && resolvedItems.some((item) => item.id === previousFirstItemId);
6824
+ const sourceChanged = olderBoundaryKey !== previousSourceBoundaryRef.current;
6825
+ const retainedSource = sourceItems?.some((item) => previousSourceIdsRef.current.has(item.id)) ?? false;
6826
+ const prepended = sourceChanged && retainedSource;
6827
+ previousSourceBoundaryRef.current = olderBoundaryKey;
6828
+ previousSourceIdsRef.current = new Set(sourceItems?.map((item) => item.id));
6829
+ const readingAnchor = readingAnchorRef.current;
6830
+ readingAnchorRef.current = null;
6601
6831
  const attempt = olderLoadAttemptRef.current;
6602
- const committedZeroOverlapOlderReplacement = !!(attempt?.[2]?.committed && firstItemChanged && !prepended);
6832
+ const committedZeroOverlapOlderReplacement = !!(attempt?.[2]?.committed && sourceChanged && !retainedSource);
6603
6833
  const restorePrependAnchor = () => {
6834
+ const correction = readingAnchor && timelineAnchorCorrection(node, readingAnchor);
6835
+ if (correction != null) {
6836
+ if (Math.abs(correction) > 1) writeScrollTop(node, node.scrollTop + correction);
6837
+ return;
6838
+ }
6604
6839
  let delta = null;
6605
6840
  if (previousFirstItemId && previousItemContentTop != null) {
6606
6841
  const itemEl = node.querySelector(
@@ -6651,7 +6886,9 @@ function MessageTimeline({
6651
6886
  applyPinned(false);
6652
6887
  }
6653
6888
  } else if (prepended) {
6654
- if (autoFollow && pinnedRef.current && !hasNewer && !pendingReaderLeaveRef.current && (wasAtLiveTailBeforeCommit || olderLoadAttemptRef.current)) {
6889
+ const olderAttemptState = olderLoadAttemptRef.current?.[1];
6890
+ const underfillOwned = !!olderLoadAttemptRef.current && olderAttemptState !== 1 && olderAttemptState !== 2 && olderAttemptState !== 3;
6891
+ if (autoFollow && pinnedRef.current && !hasNewer && !pendingReaderLeaveRef.current && (wasAtLiveTailBeforeCommit || underfillOwned)) {
6655
6892
  clearPendingReaderLeave();
6656
6893
  snapToBottom(node);
6657
6894
  } else {
@@ -6704,6 +6941,11 @@ function MessageTimeline({
6704
6941
  return;
6705
6942
  }
6706
6943
  olderLoadAttemptRef.current = [olderBoundaryKey, 2];
6944
+ if (attempt[2]?.committed && !pinnedRef.current && hasOlder && node.scrollTop <= OLDER_PREFETCH_MARGIN_PX && olderPageBudgetRef.current > 0) {
6945
+ olderPageBudgetRef.current -= 1;
6946
+ olderLoadAttemptRef.current = null;
6947
+ setOlderDemand((value) => value + 1);
6948
+ }
6707
6949
  rearmOlderPrefetchAfterLeavingTop(node);
6708
6950
  requestOlderIfUnderfilled(node);
6709
6951
  });
@@ -6833,6 +7075,7 @@ function MessageTimeline({
6833
7075
  loadingOlder,
6834
7076
  olderBoundaryKey,
6835
7077
  olderPrefetchArmed,
7078
+ olderDemand,
6836
7079
  onLoadOlder,
6837
7080
  requestOlderIfUnderfilled
6838
7081
  ]);
@@ -6943,6 +7186,13 @@ function MessageTimeline({
6943
7186
  syncScrollBaseline(node);
6944
7187
  return;
6945
7188
  }
7189
+ if (programmatic && !pinnedRef.current) {
7190
+ syncScrollBaseline(node);
7191
+ if (wantPinRef.current && !isNearBottom(node)) {
7192
+ wantPinRef.current = false;
7193
+ }
7194
+ return;
7195
+ }
6946
7196
  if (autoFollow && pinnedRef.current && !hasNewer) {
6947
7197
  const previousClient = followRef.current.lastClientHeight;
6948
7198
  const viewportShrunk = previousClient > 0 && node.clientHeight < previousClient - TIP_FOLLOW_SHRINK_EPS_PX;
@@ -6963,7 +7213,7 @@ function MessageTimeline({
6963
7213
  }
6964
7214
  if (readerArmed && cumulativeReaderUp > TIP_FOLLOW_READER_UP_EPS_PX && !nearBottomPinned) {
6965
7215
  clearReaderIntent();
6966
- releasePinFromReader(node);
7216
+ requestEarlierFromReader();
6967
7217
  rearmOlderPrefetchAfterLeavingTop(node);
6968
7218
  return;
6969
7219
  }
@@ -6978,8 +7228,13 @@ function MessageTimeline({
6978
7228
  return;
6979
7229
  }
6980
7230
  syncScrollBaseline(node);
7231
+ if (programmatic) {
7232
+ return;
7233
+ }
6981
7234
  const nearBottom = isNearBottom(node);
6982
- const nextPinned = !hasNewer && nearBottom && nextTop >= previousTop - TIP_FOLLOW_READER_UP_EPS_PX;
7235
+ const inserted = Math.max(0, nextMaxScroll - previousMaxScroll);
7236
+ const towardTip = nextTop - previousTop - inserted;
7237
+ const nextPinned = !hasNewer && nearBottom && towardTip > 0.5 && inserted <= 1;
6983
7238
  if (!nextPinned) {
6984
7239
  stopFollow();
6985
7240
  }
@@ -7035,118 +7290,163 @@ function MessageTimeline({
7035
7290
  onScroll,
7036
7291
  onScrollEnd,
7037
7292
  onWheel,
7293
+ onTouchStart: (event) => {
7294
+ const touch = event.touches.length === 1 ? event.touches[0] : void 0;
7295
+ touchPositionRef.current = touch ? { x: touch.clientX, y: touch.clientY } : null;
7296
+ },
7297
+ onTouchMove: (event) => {
7298
+ const touch = event.touches[0];
7299
+ const previous = touchPositionRef.current;
7300
+ if (!touch || !previous || event.touches.length !== 1) {
7301
+ touchPositionRef.current = null;
7302
+ return;
7303
+ }
7304
+ const deltaX = previous.x - touch.clientX;
7305
+ const deltaY = previous.y - touch.clientY;
7306
+ if (Math.max(Math.abs(deltaX), Math.abs(deltaY)) < 4) return;
7307
+ touchPositionRef.current = { x: touch.clientX, y: touch.clientY };
7308
+ onWheel({
7309
+ deltaX,
7310
+ deltaY,
7311
+ target: event.target,
7312
+ currentTarget: event.currentTarget
7313
+ });
7314
+ },
7315
+ onTouchEnd: () => {
7316
+ touchPositionRef.current = null;
7317
+ },
7318
+ onTouchCancel: () => {
7319
+ touchPositionRef.current = null;
7320
+ },
7321
+ onClickCapture: (event) => {
7322
+ const target = event.target instanceof Element ? event.target.closest("button[aria-expanded]") : null;
7323
+ if (target) {
7324
+ releasePinFromReader();
7325
+ disclosureKeepsUnpinnedRef.current = true;
7326
+ }
7327
+ },
7038
7328
  onPointerDown,
7039
7329
  onKeyDown,
7040
7330
  style: groups.length > 0 && !revealed ? { visibility: "hidden" } : void 0,
7041
7331
  className: cn(
7042
7332
  // tabIndex=-1 is programmatic only — never paint a focus ring on
7043
7333
  // the whole scroller (click + Shift used to flash a blue outline).
7044
- "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 sm:px-6 outline-hidden",
7334
+ "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 pt-16 pb-6 sm:px-6 outline-hidden",
7045
7335
  autoFollow && pinned && !hasNewer ? "[overflow-anchor:none]" : "[overflow-anchor:auto]"
7046
7336
  ),
7047
- children: /* @__PURE__ */ jsxs11("div", { className: "relative mx-auto flex w-full max-w-3xl flex-col gap-5", children: [
7048
- !groups.length ? emptyState ?? /* @__PURE__ */ jsx16("p", { className: "py-10 text-center text-og-menu text-og-fg-subtle", children: "No activity yet." }) : null,
7049
- hasOlder && olderPrefetchArmed ? (
7050
- // Overlaid, not a layout row: mounting/unmounting the sentinel
7051
- // must never shift content (that shift was itself a wobble).
7052
- /* @__PURE__ */ jsx16(
7053
- "div",
7054
- {
7055
- ref: topSentinelRef,
7056
- "data-og-top-sentinel": "",
7057
- "data-og-timeline-chrome": "",
7058
- "aria-hidden": "true",
7059
- className: "pointer-events-none absolute inset-x-0 top-0 h-px"
7060
- }
7061
- )
7062
- ) : null,
7063
- groups.map(({ group, key, entranceEnabled }, index) => {
7064
- return /* @__PURE__ */ jsx16(
7065
- TimelineGroupEntry,
7066
- {
7067
- groupKey: key,
7068
- group,
7069
- nextGroup: groups[index + 1]?.group,
7070
- entranceEnabled,
7071
- liveEntranceEnabled: group.kind === "activity" ? !bulkRender : void 0,
7072
- context: timelineGroupEntryContext
7073
- },
7074
- key
7075
- );
7076
- }),
7077
- groups.length > 0 && trailingState ? /* @__PURE__ */ jsx16("div", { "data-og-timeline-trailing-state": "", children: trailingState }) : null,
7078
- hasNewer ? /* @__PURE__ */ jsx16(
7079
- "div",
7080
- {
7081
- ref: bottomSentinelRef,
7082
- "data-og-bottom-sentinel": "",
7083
- "data-og-timeline-chrome": "",
7084
- "aria-hidden": "true",
7085
- className: "h-px w-full"
7086
- }
7087
- ) : null
7088
- ] })
7337
+ children: /* @__PURE__ */ jsx16(
7338
+ TimelineBeforeLayout,
7339
+ {
7340
+ capture: () => {
7341
+ readingAnchorRef.current = !pinnedRef.current && scrollRef.current ? captureTimelineAnchor(scrollRef.current) : null;
7342
+ },
7343
+ children: /* @__PURE__ */ jsxs11("div", { className: "relative mx-auto flex w-full max-w-3xl flex-col gap-5", children: [
7344
+ /* @__PURE__ */ jsx16(AnimatePresence, { children: loadingOlder || loadingOldest || hasOlder && onJumpToStart && olderPrefetchArmed || underfillRetryReady ? (
7345
+ // Reserved top gutter: controls scroll with history and cannot
7346
+ // cover a disclosure. Visibility never changes content height.
7347
+ /* @__PURE__ */ jsxs11(
7348
+ motion.div,
7349
+ {
7350
+ initial: { opacity: 0, y: -6 },
7351
+ animate: { opacity: 1, y: 0 },
7352
+ exit: { opacity: 0, y: -6 },
7353
+ transition: { duration: 0.15, ease: "easeOut" },
7354
+ "data-og-loading-older": "",
7355
+ "aria-live": "polite",
7356
+ className: "pointer-events-none absolute inset-x-0 -top-11 z-10 flex justify-center",
7357
+ children: [
7358
+ loadingOlder || loadingOldest ? /* @__PURE__ */ jsx16("span", { className: LOADING_CHIP_CLASS, children: /* @__PURE__ */ jsx16("span", { className: "og-shimmer-text", children: loadingOldest ? "Jumping to start\u2026" : "Loading earlier activity\u2026" }) }) : null,
7359
+ hasOlder && !loadingOlder && !loadingOldest && (underfillRetryReady || onJumpToStart) ? /* @__PURE__ */ jsx16(
7360
+ "button",
7361
+ {
7362
+ type: "button",
7363
+ "data-og-retry": underfillRetryReady || void 0,
7364
+ "data-og-jump-to-start": !underfillRetryReady || void 0,
7365
+ onClick: () => {
7366
+ const node = scrollRef.current;
7367
+ if (underfillRetryReady) {
7368
+ if (node && underfillRetryReadyRef.current) {
7369
+ requestOlderIfUnderfilled(node, underfillSettledAttempt);
7370
+ }
7371
+ return;
7372
+ }
7373
+ applyPinned(false);
7374
+ pendingJumpToStartRef.current = true;
7375
+ const seq = ++jumpToStartSeqRef.current;
7376
+ void Promise.resolve(onJumpToStart()).then(
7377
+ () => {
7378
+ const scroller = scrollRef.current ?? node;
7379
+ if (scroller) {
7380
+ scroller.scrollTop = 0;
7381
+ }
7382
+ requestFrame(() => {
7383
+ if (jumpToStartSeqRef.current === seq) {
7384
+ pendingJumpToStartRef.current = false;
7385
+ }
7386
+ });
7387
+ },
7388
+ () => {
7389
+ if (jumpToStartSeqRef.current === seq) {
7390
+ pendingJumpToStartRef.current = false;
7391
+ }
7392
+ }
7393
+ );
7394
+ },
7395
+ className: "pointer-events-auto rounded-full border border-og-border px-3 py-1.5 text-og-control",
7396
+ children: underfillRetryReady ? "Retry earlier activity" : "Jump to start"
7397
+ }
7398
+ ) : null
7399
+ ]
7400
+ }
7401
+ )
7402
+ ) : null }),
7403
+ !groups.length ? emptyState ?? /* @__PURE__ */ jsx16("p", { className: "py-10 text-center text-og-menu text-og-fg-subtle", children: "No activity yet." }) : null,
7404
+ hasOlder && olderPrefetchArmed ? (
7405
+ // Overlaid, not a layout row: mounting/unmounting the sentinel
7406
+ // must never shift content (that shift was itself a wobble).
7407
+ // End at the scroll origin above the pt-16 gutter so the
7408
+ // observer and scrollTop cooldown share the same 400px band.
7409
+ /* @__PURE__ */ jsx16(
7410
+ "div",
7411
+ {
7412
+ ref: topSentinelRef,
7413
+ "data-og-top-sentinel": "",
7414
+ "data-og-timeline-chrome": "",
7415
+ "aria-hidden": "true",
7416
+ className: "pointer-events-none absolute inset-x-0 -top-16 h-px -translate-y-full"
7417
+ }
7418
+ )
7419
+ ) : null,
7420
+ groups.map(({ group, key, entranceEnabled }, index) => {
7421
+ return /* @__PURE__ */ jsx16(
7422
+ TimelineGroupEntry,
7423
+ {
7424
+ groupKey: key,
7425
+ group,
7426
+ nextGroup: groups[index + 1]?.group,
7427
+ entranceEnabled,
7428
+ liveEntranceEnabled: group.kind === "activity" ? !bulkRender : void 0,
7429
+ context: timelineGroupEntryContext
7430
+ },
7431
+ key
7432
+ );
7433
+ }),
7434
+ groups.length > 0 && trailingState ? /* @__PURE__ */ jsx16("div", { "data-og-timeline-trailing-state": "", children: trailingState }) : null,
7435
+ hasNewer ? /* @__PURE__ */ jsx16(
7436
+ "div",
7437
+ {
7438
+ ref: bottomSentinelRef,
7439
+ "data-og-bottom-sentinel": "",
7440
+ "data-og-timeline-chrome": "",
7441
+ "aria-hidden": "true",
7442
+ className: "h-px w-full"
7443
+ }
7444
+ ) : null
7445
+ ] })
7446
+ }
7447
+ )
7089
7448
  }
7090
7449
  ),
7091
- /* @__PURE__ */ jsx16(AnimatePresence, { children: loadingOlder || loadingOldest || hasOlder && onJumpToStart && olderPrefetchArmed || underfillRetryReady ? (
7092
- // Floating over the scroller (not a timeline row) so showing and
7093
- // hiding it never reflows history under the reader.
7094
- /* @__PURE__ */ jsxs11(
7095
- motion.div,
7096
- {
7097
- initial: { opacity: 0, y: -6 },
7098
- animate: { opacity: 1, y: 0 },
7099
- exit: { opacity: 0, y: -6 },
7100
- transition: { duration: 0.15, ease: "easeOut" },
7101
- "data-og-loading-older": "",
7102
- "aria-live": "polite",
7103
- className: "absolute inset-x-0 top-3 z-10 flex justify-center",
7104
- children: [
7105
- loadingOlder || loadingOldest ? /* @__PURE__ */ jsx16("span", { className: LOADING_CHIP_CLASS, children: /* @__PURE__ */ jsx16("span", { className: "og-shimmer-text", children: loadingOldest ? "Jumping to start\u2026" : "Loading earlier activity\u2026" }) }) : null,
7106
- hasOlder && !loadingOlder && !loadingOldest && (underfillRetryReady || onJumpToStart) ? /* @__PURE__ */ jsx16(
7107
- "button",
7108
- {
7109
- type: "button",
7110
- "data-og-retry": underfillRetryReady || void 0,
7111
- "data-og-jump-to-start": !underfillRetryReady || void 0,
7112
- onClick: () => {
7113
- const node = scrollRef.current;
7114
- if (underfillRetryReady) {
7115
- if (node && underfillRetryReadyRef.current) {
7116
- requestOlderIfUnderfilled(node, underfillSettledAttempt);
7117
- }
7118
- return;
7119
- }
7120
- applyPinned(false);
7121
- pendingJumpToStartRef.current = true;
7122
- const seq = ++jumpToStartSeqRef.current;
7123
- void Promise.resolve(onJumpToStart()).then(
7124
- () => {
7125
- const scroller = scrollRef.current ?? node;
7126
- if (scroller) {
7127
- scroller.scrollTop = 0;
7128
- }
7129
- requestFrame(() => {
7130
- if (jumpToStartSeqRef.current === seq) {
7131
- pendingJumpToStartRef.current = false;
7132
- }
7133
- });
7134
- },
7135
- () => {
7136
- if (jumpToStartSeqRef.current === seq) {
7137
- pendingJumpToStartRef.current = false;
7138
- }
7139
- }
7140
- );
7141
- },
7142
- className: "rounded-full border border-og-border px-3 py-1.5 text-og-control",
7143
- children: underfillRetryReady ? "Retry earlier activity" : "Jump to start"
7144
- }
7145
- ) : null
7146
- ]
7147
- }
7148
- )
7149
- ) : null }),
7150
7450
  /* @__PURE__ */ jsx16(AnimatePresence, { children: loadingNewer ? /* @__PURE__ */ jsx16(
7151
7451
  motion.div,
7152
7452
  {
@@ -7276,7 +7576,7 @@ function cancelFrame(id) {
7276
7576
  function timelineRenderResetKeysChanged(previous, next) {
7277
7577
  return previous.length !== next.length || previous.some((key, index) => !Object.is(key, next[index]));
7278
7578
  }
7279
- var TimelineGroupRenderBoundary = class extends Component2 {
7579
+ var TimelineGroupRenderBoundary = class extends Component3 {
7280
7580
  state = {
7281
7581
  failed: false,
7282
7582
  resetKeys: this.props.resetKeys
@@ -7737,7 +8037,7 @@ function CompactionRow({ item }) {
7737
8037
  const after = item.estimatedTokensAfter != null ? Math.round(item.estimatedTokensAfter).toLocaleString("en-US") : null;
7738
8038
  const title = item.phase === "started" ? "Compacting conversation history\u2026" : item.phase === "compacted" ? before && after ? `Conversation history compacted \xB7 ~${before} \u2192 ~${after} estimated history tokens` : "Conversation history compacted" : "Couldn\u2019t compact conversation history";
7739
8039
  const subtitle = item.phase === "compacted" ? "Chat history above is unchanged" : item.phase === "skipped" ? compactionSkipSubtitle(item.skipReason) : null;
7740
- const pill = item.phase === "skipped" && item.skipReason === "summarization_failed" ? "border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed" : item.phase === "started" ? WAITING_PILL_CLASS : "border-og-border bg-og-surface-1 text-og-fg-muted";
8040
+ const pill = item.phase === "skipped" && item.skipReason === "summarization_failed" ? "border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed" : item.phase === "started" ? WAITING_PILL_CLASS : NEUTRAL_PILL;
7741
8041
  return /* @__PURE__ */ jsx16("div", { className: cn(enter && "animate-og-enter", "flex justify-center"), children: /* @__PURE__ */ jsxs11(
7742
8042
  "div",
7743
8043
  {
@@ -8083,35 +8383,38 @@ function SessionStatusRow({ item }) {
8083
8383
  );
8084
8384
  }
8085
8385
  var NEUTRAL_PILL = "border-og-border bg-og-surface-1 text-og-fg-muted";
8086
- var GOAL_META = {
8087
- set: {
8088
- label: "Goal set",
8089
- pill: "border-og-accent/30 bg-og-accent/10 text-og-accent",
8090
- icon: TargetIcon2
8091
- },
8092
- updated: { label: "Goal updated", pill: NEUTRAL_PILL, icon: PencilLineIcon },
8093
- completed: {
8094
- label: "Goal completed",
8095
- pill: "border-og-status-idle/30 bg-og-status-idle/10 text-og-status-idle",
8096
- icon: CheckIcon2
8097
- },
8098
- paused: {
8099
- label: "Goal paused",
8100
- pill: WAITING_PILL_CLASS,
8101
- icon: PauseIcon
8102
- },
8103
- resumed: { label: "Goal resumed", pill: NEUTRAL_PILL, icon: PlayIcon },
8104
- cleared: { label: "Goal cleared", pill: NEUTRAL_PILL, icon: Trash2Icon },
8105
- held: {
8106
- label: "Goal held",
8107
- pill: WAITING_PILL_CLASS,
8108
- icon: PauseCircleIcon
8109
- },
8110
- continuation: { label: "Continuing toward the goal", pill: NEUTRAL_PILL, icon: ArrowRightIcon2 }
8111
- };
8386
+ function goalMeta(action) {
8387
+ const metadata = {
8388
+ set: {
8389
+ label: "Goal set",
8390
+ pill: "border-og-accent/30 bg-og-accent/10 text-og-accent",
8391
+ icon: TargetIcon2
8392
+ },
8393
+ updated: { label: "Goal updated", pill: NEUTRAL_PILL, icon: PencilLineIcon },
8394
+ completed: {
8395
+ label: "Goal completed",
8396
+ pill: "border-og-status-idle/30 bg-og-status-idle/10 text-og-status-idle",
8397
+ icon: CheckIcon2
8398
+ },
8399
+ paused: {
8400
+ label: "Goal paused",
8401
+ pill: WAITING_PILL_CLASS,
8402
+ icon: PauseIcon
8403
+ },
8404
+ resumed: { label: "Goal resumed", pill: NEUTRAL_PILL, icon: PlayIcon },
8405
+ cleared: { label: "Goal cleared", pill: NEUTRAL_PILL, icon: Trash2Icon },
8406
+ held: {
8407
+ label: "Goal held",
8408
+ pill: WAITING_PILL_CLASS,
8409
+ icon: PauseCircleIcon
8410
+ },
8411
+ continuation: { label: "Continuing toward the goal", pill: NEUTRAL_PILL, icon: ArrowRightIcon2 }
8412
+ };
8413
+ return metadata[action];
8414
+ }
8112
8415
  function GoalRow({ item }) {
8113
8416
  const enter = useEntranceAnimation();
8114
- const { label, pill, icon: Icon } = GOAL_META[item.action];
8417
+ const { label, pill, icon: Icon } = goalMeta(item.action);
8115
8418
  return /* @__PURE__ */ jsx16("div", { className: cn(enter && "animate-og-enter", "flex justify-center"), children: /* @__PURE__ */ jsxs11(
8116
8419
  "span",
8117
8420
  {
@@ -8148,35 +8451,49 @@ function MachineInputBatchRow({
8148
8451
  const singleSummary = single ? cleanMachineInputSummary(single.summary) : "";
8149
8452
  const showCollapsedSummary = single != null && machineInputSummaryIsUseful(single.kind, singleSummary);
8150
8453
  return /* @__PURE__ */ jsxs11("div", { className: cn(enter && "animate-og-enter", "flex flex-col items-center gap-1.5"), children: [
8151
- /* @__PURE__ */ jsxs11("details", { className: "group w-full max-w-full", "data-og-machine-input-batch": "", children: [
8152
- /* @__PURE__ */ jsx16("summary", { className: "flex cursor-pointer list-none justify-center [&::-webkit-details-marker]:hidden", children: /* @__PURE__ */ jsxs11(
8153
- "span",
8154
- {
8155
- className: cn(
8156
- "inline-flex max-w-full items-center gap-1.5 rounded-full border px-3 py-1 text-og-sm",
8157
- NEUTRAL_PILL
8158
- ),
8159
- children: [
8160
- /* @__PURE__ */ jsx16(
8161
- ChevronRightIcon3,
8454
+ /* @__PURE__ */ jsxs11(
8455
+ "details",
8456
+ {
8457
+ className: "group w-full max-w-full",
8458
+ "data-og-machine-input-batch": "",
8459
+ title: `Received ${formatClockTime(item.occurredAt)}`,
8460
+ children: [
8461
+ /* @__PURE__ */ jsx16("summary", { className: "flex cursor-pointer list-none justify-center [&::-webkit-details-marker]:hidden", children: /* @__PURE__ */ jsxs11(
8462
+ "span",
8463
+ {
8464
+ className: cn(
8465
+ "inline-flex max-w-full items-center gap-1.5 rounded-full border px-3 py-1 text-og-sm",
8466
+ NEUTRAL_PILL
8467
+ ),
8468
+ children: [
8469
+ /* @__PURE__ */ jsx16(
8470
+ ChevronRightIcon3,
8471
+ {
8472
+ "aria-hidden": true,
8473
+ className: "size-3.5 shrink-0 transition-transform group-open:rotate-90"
8474
+ }
8475
+ ),
8476
+ /* @__PURE__ */ jsx16("span", { className: "truncate", children: label })
8477
+ ]
8478
+ }
8479
+ ) }),
8480
+ /* @__PURE__ */ jsxs11("div", { className: "mx-auto mt-2 w-full max-w-lg space-y-2 border-t border-og-border/50 pt-2", children: [
8481
+ /* @__PURE__ */ jsxs11("p", { className: "text-og-xs text-og-fg-subtle", children: [
8482
+ "Received ",
8483
+ /* @__PURE__ */ jsx16("time", { dateTime: item.occurredAt, children: formatClockTime(item.occurredAt) })
8484
+ ] }),
8485
+ item.members.map((member) => /* @__PURE__ */ jsx16(
8486
+ MachineInputRow,
8162
8487
  {
8163
- "aria-hidden": true,
8164
- className: "size-3.5 shrink-0 transition-transform group-open:rotate-90"
8165
- }
8166
- ),
8167
- /* @__PURE__ */ jsx16("span", { className: "truncate", children: label })
8168
- ]
8169
- }
8170
- ) }),
8171
- /* @__PURE__ */ jsx16("div", { className: "mx-auto mt-2 w-full max-w-lg space-y-2 border-t border-og-border/50 pt-2", children: item.members.map((member) => /* @__PURE__ */ jsx16(
8172
- MachineInputRow,
8173
- {
8174
- member,
8175
- loadVideoArtifactPlayback
8176
- },
8177
- member.id
8178
- )) })
8179
- ] }),
8488
+ member,
8489
+ loadVideoArtifactPlayback
8490
+ },
8491
+ member.id
8492
+ ))
8493
+ ] })
8494
+ ]
8495
+ }
8496
+ ),
8180
8497
  showCollapsedSummary ? /* @__PURE__ */ jsx16("p", { className: "max-w-lg px-3 text-center text-og-xs leading-4 text-og-fg-subtle", children: truncate(singleSummary, 160) }) : null
8181
8498
  ] });
8182
8499
  }
@@ -8275,7 +8592,7 @@ function formatVideoDuration(seconds) {
8275
8592
  }
8276
8593
  function NoticeRow({ item }) {
8277
8594
  const enter = useEntranceAnimation();
8278
- const tone = item.tone === "failed" ? "border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed" : item.tone === "waiting" ? WAITING_PILL_CLASS : "border-og-border bg-og-surface-1 text-og-fg-muted";
8595
+ const tone = item.tone === "failed" ? "border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed" : item.tone === "waiting" ? WAITING_PILL_CLASS : NEUTRAL_PILL;
8279
8596
  return /* @__PURE__ */ jsxs11(
8280
8597
  "div",
8281
8598
  {
@@ -8284,7 +8601,8 @@ function NoticeRow({ item }) {
8284
8601
  "flex items-start gap-2.5 rounded-og-md border px-3.5 py-2.5 text-og-menu",
8285
8602
  tone
8286
8603
  ),
8287
- role: "status",
8604
+ role: item.recordedOutcome ? "note" : "status",
8605
+ "data-og-recorded-outcome": item.recordedOutcome ? "wait" : void 0,
8288
8606
  children: [
8289
8607
  /* @__PURE__ */ jsx16(
8290
8608
  TriangleAlertIcon2,
@@ -8293,6 +8611,14 @@ function NoticeRow({ item }) {
8293
8611
  }
8294
8612
  ),
8295
8613
  /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
8614
+ item.recordedOutcome ? /* @__PURE__ */ jsxs11("p", { className: "mb-1 text-og-control font-medium", children: [
8615
+ "Wait recorded",
8616
+ " ",
8617
+ /* @__PURE__ */ jsx16("time", { dateTime: item.occurredAt, children: new Date(item.occurredAt).toLocaleString(void 0, {
8618
+ dateStyle: "medium",
8619
+ timeStyle: "short"
8620
+ }) })
8621
+ ] }) : null,
8296
8622
  /* @__PURE__ */ jsx16("span", { className: "whitespace-pre-wrap break-words", children: item.text }),
8297
8623
  item.details ? /* @__PURE__ */ jsxs11("details", { className: "mt-2 text-og-control", children: [
8298
8624
  /* @__PURE__ */ jsx16("summary", { className: "cursor-pointer font-medium", children: item.details.label }),
@@ -8525,8 +8851,377 @@ function QueueSurfaceFallback() {
8525
8851
  );
8526
8852
  }
8527
8853
 
8854
+ // src/hooks/use-available-models.ts
8855
+ import { useCallback as useCallback3 } from "react";
8856
+ function useAvailableModels(options = {}) {
8857
+ const client = useOpenGeniClient(options);
8858
+ const load = useCallback3(
8859
+ async (signal) => await client.getClientConfig({ signal }),
8860
+ [client]
8861
+ );
8862
+ const state = usePolledValue(load, {
8863
+ pollIntervalMs: options.pollIntervalMs,
8864
+ enabled: options.enabled
8865
+ });
8866
+ return {
8867
+ models: state.data?.models ?? [],
8868
+ defaultModel: state.data?.defaultModel ?? null,
8869
+ loading: state.loading,
8870
+ error: state.error,
8871
+ refresh: state.refresh
8872
+ };
8873
+ }
8874
+ function useWorkspaceModelCatalog(options) {
8875
+ const client = useOpenGeniClient(options);
8876
+ const load = useCallback3(
8877
+ async (signal) => {
8878
+ if (!options.workspaceId) {
8879
+ return { models: [], defaultModel: null };
8880
+ }
8881
+ const [catalog, config] = await Promise.all([
8882
+ client.getWorkspaceModelCatalog(options.workspaceId, { signal }),
8883
+ client.getClientConfig({ signal })
8884
+ ]);
8885
+ return {
8886
+ models: catalog.models,
8887
+ defaultModel: config.defaultModel
8888
+ };
8889
+ },
8890
+ [client, options.workspaceId]
8891
+ );
8892
+ const state = usePolledValue(load, {
8893
+ pollIntervalMs: options.pollIntervalMs,
8894
+ enabled: options.enabled !== false && Boolean(options.workspaceId)
8895
+ });
8896
+ const rows = sortPickerRows(projectPickerRows(state.data?.models ?? []));
8897
+ return {
8898
+ models: state.data?.models ?? [],
8899
+ rows,
8900
+ defaultModel: state.data?.defaultModel ?? null,
8901
+ loading: state.loading,
8902
+ error: state.error,
8903
+ refresh: state.refresh
8904
+ };
8905
+ }
8906
+
8907
+ // src/components/chat-composer.tsx
8908
+ import { LayoutGroup, motion as motion2 } from "motion/react";
8909
+ import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
8910
+ function ChatComposer({
8911
+ composer,
8912
+ responsiveBasis,
8913
+ effectiveControl,
8914
+ queuedAheadCount,
8915
+ canControlWorkspace,
8916
+ controlLinks,
8917
+ placeholder,
8918
+ disabled,
8919
+ autoFocus,
8920
+ hint,
8921
+ controlsLeading,
8922
+ controlsStart,
8923
+ actionsStart,
8924
+ attachButtonClassName,
8925
+ transcription,
8926
+ transcriptionClassName,
8927
+ transcriptionSuppressed = false,
8928
+ header,
8929
+ onPaste,
8930
+ attachments,
8931
+ models,
8932
+ selectedModel,
8933
+ onSelectModel,
8934
+ className,
8935
+ commands,
8936
+ commandContext,
8937
+ onClearView,
8938
+ messages
8939
+ }) {
8940
+ const controller = useChatComposerController({
8941
+ delivery: composer,
8942
+ draft: composer,
8943
+ control: composer,
8944
+ effectiveControl,
8945
+ queuedAheadCount,
8946
+ canControlWorkspace,
8947
+ controlLinks,
8948
+ disabled,
8949
+ attachments,
8950
+ commands,
8951
+ commandContext,
8952
+ onClearView,
8953
+ onPaste,
8954
+ messages
8955
+ });
8956
+ const hasControls = Boolean(
8957
+ attachments || models || controlsLeading || controlsStart || transcription
8958
+ );
8959
+ const stackActions = hasControls && Boolean(actionsStart);
8960
+ return /* @__PURE__ */ jsx18(Fragment6, { children: /* @__PURE__ */ jsxs13(Root, { controller, responsiveBasis, className, children: [
8961
+ /* @__PURE__ */ jsxs13(Frame, { children: [
8962
+ /* @__PURE__ */ jsx18(CommandPalette, {}),
8963
+ /* @__PURE__ */ jsxs13(Surface, { children: [
8964
+ /* @__PURE__ */ jsx18(PausedState, {}),
8965
+ /* @__PURE__ */ jsx18(RestoredResources, {}),
8966
+ /* @__PURE__ */ jsx18(Attachments, {}),
8967
+ header,
8968
+ composer.annotations && composer.annotations.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "px-3 pt-2 sm:px-4", children: /* @__PURE__ */ jsx18(
8969
+ TimelineAnnotationsChip,
8970
+ {
8971
+ annotations: composer.annotations,
8972
+ editable: true,
8973
+ focusAnnotationId: composer.annotationReviewTargetId,
8974
+ onFocusConsumed: composer.clearAnnotationReviewTarget,
8975
+ onUpdate: composer.updateAnnotation,
8976
+ onRemove: composer.removeAnnotation
8977
+ }
8978
+ ) }) : null,
8979
+ /* @__PURE__ */ jsx18(Input, { placeholder, autoFocus }),
8980
+ controller.confirmState ? /* @__PURE__ */ jsx18(Confirmation, {}) : /* @__PURE__ */ jsx18(
8981
+ Footer,
8982
+ {
8983
+ "data-og-stack-actions": stackActions ? "" : void 0,
8984
+ className: stackActions ? "max-sm:flex-nowrap sm:flex-wrap" : void 0,
8985
+ children: /* @__PURE__ */ jsxs13(LayoutGroup, { id: "og-composer-footer", children: [
8986
+ hasControls ? /* @__PURE__ */ jsxs13(
8987
+ Controls,
8988
+ {
8989
+ className: stackActions ? "min-w-0 max-sm:flex-1 sm:w-auto" : void 0,
8990
+ children: [
8991
+ controlsLeading,
8992
+ /* @__PURE__ */ jsx18(AttachButton, { className: attachButtonClassName }),
8993
+ transcription ? /* @__PURE__ */ jsx18(
8994
+ ComposerTranscriptionControl,
8995
+ {
8996
+ ...transcription,
8997
+ suppressed: transcriptionSuppressed,
8998
+ className: [transcription.className, transcriptionClassName].filter(Boolean).join(" ")
8999
+ }
9000
+ ) : null,
9001
+ models ? /* @__PURE__ */ jsx18(
9002
+ motion2.span,
9003
+ {
9004
+ layout: true,
9005
+ transition: { duration: 0.36, ease: [0.22, 1, 0.36, 1] },
9006
+ className: "inline-flex min-w-0",
9007
+ children: /* @__PURE__ */ jsx18(
9008
+ ModelPicker,
9009
+ {
9010
+ models,
9011
+ value: selectedModel,
9012
+ onChange: onSelectModel
9013
+ }
9014
+ )
9015
+ }
9016
+ ) : null,
9017
+ controlsStart ? /* @__PURE__ */ jsx18(
9018
+ motion2.span,
9019
+ {
9020
+ layout: true,
9021
+ transition: { duration: 0.36, ease: [0.22, 1, 0.36, 1] },
9022
+ className: "inline-flex min-w-0 flex-1 items-center gap-1.5",
9023
+ children: controlsStart
9024
+ }
9025
+ ) : null
9026
+ ]
9027
+ }
9028
+ ) : /* @__PURE__ */ jsx18(Hint, { children: hint }),
9029
+ /* @__PURE__ */ jsxs13(
9030
+ Actions,
9031
+ {
9032
+ className: stackActions ? "max-sm:shrink-0 sm:w-auto sm:justify-end" : void 0,
9033
+ children: [
9034
+ actionsStart,
9035
+ /* @__PURE__ */ jsx18(PauseButton, {}),
9036
+ /* @__PURE__ */ jsx18(SendButton, {})
9037
+ ]
9038
+ }
9039
+ )
9040
+ ] })
9041
+ }
9042
+ )
9043
+ ] })
9044
+ ] }),
9045
+ /* @__PURE__ */ jsx18(Help, {}),
9046
+ /* @__PURE__ */ jsx18(Status, {})
9047
+ ] }) });
9048
+ }
9049
+
9050
+ // src/components/session-conversation.tsx
9051
+ import { useRef as useRef11 } from "react";
9052
+
9053
+ // src/conversation-timeline.ts
9054
+ function conversationTimeline(items, queue, composer) {
9055
+ const queued = new Set(
9056
+ queue.queue.filter((turn) => turn.metadata.delivery !== "steer").map((turn) => turn.triggerEventId)
9057
+ );
9058
+ const pending = composer.optimisticMessages ?? [];
9059
+ const pendingQueue = new Set(
9060
+ pending.filter(
9061
+ (message) => message.destination === "queue" && !(message.turnId && message.appliedQueueVersion != null && queue.snapshot && queue.snapshot.version >= message.appliedQueueVersion && !queue.queue.some((turn) => turn.id === message.turnId))
9062
+ ).map((message) => `user-message:${message.clientEventId}`)
9063
+ );
9064
+ const visible = items.filter(
9065
+ (item) => item.kind !== "user-message" || !queued.has(item.id) && !pendingQueue.has(item.reconciliationKey ?? "")
9066
+ );
9067
+ const keys = new Set(
9068
+ visible.flatMap((item) => item.kind === "user-message" ? [item.reconciliationKey] : [])
9069
+ );
9070
+ const optimistic = pending.filter(
9071
+ (message) => !keys.has(`user-message:${message.clientEventId}`) && !queue.queue.some((turn) => turn.id === message.turnId)
9072
+ ).map((message) => ({
9073
+ kind: "user-message",
9074
+ id: `optimistic:${message.clientEventId}`,
9075
+ reconciliationKey: `user-message:${message.clientEventId}`,
9076
+ text: message.text,
9077
+ annotations: message.annotations.map((annotation, ordinal) => ({ ...annotation, ordinal })),
9078
+ resources: message.resources,
9079
+ tools: [],
9080
+ occurredAt: message.occurredAt,
9081
+ delivery: {
9082
+ state: message.state,
9083
+ ...message.error ? { error: message.error } : {},
9084
+ ...message.state === "failed" ? {
9085
+ onRetry: () => composer.retryOptimisticMessage?.(message.clientEventId),
9086
+ onRemove: () => composer.removeOptimisticMessage?.(message.clientEventId)
9087
+ } : {}
9088
+ }
9089
+ }));
9090
+ const ids = new Set(visible.map((item) => item.id));
9091
+ const steers = (queue.acceptedSteers ?? []).filter((steer) => !ids.has(steer.triggerEventId)).map((steer) => ({
9092
+ kind: "user-message",
9093
+ id: steer.triggerEventId,
9094
+ text: steer.text,
9095
+ annotations: steer.annotations,
9096
+ resources: steer.resources,
9097
+ tools: steer.tools,
9098
+ occurredAt: steer.occurredAt,
9099
+ delivery: { state: steer.state }
9100
+ }));
9101
+ return [...visible, ...optimistic, ...steers];
9102
+ }
9103
+
9104
+ // src/components/session-conversation.tsx
9105
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
9106
+ function SessionConversation(props) {
9107
+ return /* @__PURE__ */ jsx19(Conversation, { ...props }, `${props.workspaceId ?? ""}:${props.sessionId}`);
9108
+ }
9109
+ function Conversation({
9110
+ sessionId,
9111
+ client,
9112
+ workspaceId,
9113
+ className,
9114
+ height = "100%",
9115
+ composerProps
9116
+ }) {
9117
+ const scope = { client, workspaceId };
9118
+ const context = useOpenGeni(scope);
9119
+ const catalog = useWorkspaceModelCatalog({
9120
+ client: context.client,
9121
+ workspaceId: context.workspaceId
9122
+ });
9123
+ const feed = useSessionEvents(sessionId, scope);
9124
+ const options = { ...scope, events: feed.events };
9125
+ const detail = useSession(sessionId, options);
9126
+ const queue = useTurnQueue(sessionId, options);
9127
+ const human = useHumanInputRequests(sessionId, options);
9128
+ const status = feed.sessionStatus ?? detail.session?.status;
9129
+ const terminal = status === "cancelled";
9130
+ const composer = useComposer(sessionId, {
9131
+ ...options,
9132
+ effectiveControl: queue.effectiveControl ?? detail.session?.effectiveControl,
9133
+ sendDestination: () => queue.queue.length > 0 || status === "running" ? "queue" : "chat"
9134
+ });
9135
+ const region = useRef11(null);
9136
+ const error = detail.error ?? feed.error ?? human.error;
9137
+ return /* @__PURE__ */ jsxs14(
9138
+ "div",
9139
+ {
9140
+ className: cn("og-root flex min-h-0 min-w-0 flex-col gap-2 overflow-hidden", className),
9141
+ ref: region,
9142
+ style: { height },
9143
+ "data-og-conversation": "",
9144
+ children: [
9145
+ error && /* @__PURE__ */ jsx19("p", { role: "alert", children: error.message }),
9146
+ /* @__PURE__ */ jsx19(
9147
+ MessageTimeline,
9148
+ {
9149
+ className: "min-h-0 flex-1",
9150
+ items: conversationTimeline(feed.timeline, queue, composer),
9151
+ status,
9152
+ hasOlder: feed.hasOlder,
9153
+ loadingOlder: feed.loadingOlder,
9154
+ onLoadOlder: feed.loadOlder,
9155
+ hasNewer: feed.hasNewer,
9156
+ loadingNewer: feed.loadingNewer,
9157
+ onLoadNewer: () => {
9158
+ void feed.loadNewer();
9159
+ },
9160
+ onJumpToStart: async () => {
9161
+ await feed.loadOldest();
9162
+ },
9163
+ loadingOldest: feed.loadingOldest,
9164
+ onJumpToLatest: feed.jumpToLatest,
9165
+ onAnnotate: composer.addAnnotation
9166
+ }
9167
+ ),
9168
+ /* @__PURE__ */ jsxs14("div", { className: "min-h-0 max-h-[40%] shrink-0 overflow-y-auto", "data-og-conversation-inputs": "", children: [
9169
+ /* @__PURE__ */ jsx19(
9170
+ HumanInputSurface,
9171
+ {
9172
+ requests: human.requests,
9173
+ onSubmit: async (id, response) => {
9174
+ await human.respond(id, response);
9175
+ },
9176
+ respondingRequestId: human.respondingRequestId,
9177
+ error: human.mutationError?.message,
9178
+ autoFocus: false
9179
+ }
9180
+ ),
9181
+ terminal ? /* @__PURE__ */ jsx19(QueueSurface, { queue, readOnly: true }) : /* @__PURE__ */ jsx19(
9182
+ QueueSurface,
9183
+ {
9184
+ queue,
9185
+ composer,
9186
+ onRequestComposerFocus: () => region.current?.querySelector("textarea")?.focus()
9187
+ }
9188
+ )
9189
+ ] }),
9190
+ /* @__PURE__ */ jsx19("div", { className: "shrink-0", "data-og-conversation-composer": "", children: /* @__PURE__ */ jsx19(
9191
+ ChatComposer,
9192
+ {
9193
+ ...composerProps,
9194
+ composer,
9195
+ disabled: terminal || composerProps?.disabled,
9196
+ controlsStart: composerProps?.controlsStart ?? (composer.policy && /* @__PURE__ */ jsx19(
9197
+ ModelPolicyPicker,
9198
+ {
9199
+ rows: catalog.rows,
9200
+ model: composer.policy.model,
9201
+ effort: composer.policy.reasoningEffort,
9202
+ latencyMode: composer.policy.latencyMode,
9203
+ loading: catalog.loading,
9204
+ error: catalog.error?.message,
9205
+ disabled: terminal,
9206
+ sessionKey: sessionId,
9207
+ onModelChange: (model) => composer.setModel?.(model),
9208
+ onEffortChange: (effort) => composer.setReasoningEffort?.(effort),
9209
+ onLatencyModeChange: (mode) => composer.setLatencyMode?.(mode)
9210
+ }
9211
+ )),
9212
+ responsiveBasis: composerProps?.responsiveBasis ?? "container",
9213
+ effectiveControl: composer.effectiveControl ?? queue.effectiveControl ?? detail.session?.effectiveControl,
9214
+ queuedAheadCount: queue.queue.length
9215
+ }
9216
+ ) })
9217
+ ]
9218
+ }
9219
+ );
9220
+ }
9221
+
8528
9222
  // src/components/session-chrome.tsx
8529
9223
  import {
9224
+ ActivityIcon,
8530
9225
  AudioLinesIcon,
8531
9226
  ArrowDownIcon as ArrowDownIcon2,
8532
9227
  ArrowUpIcon,
@@ -8539,17 +9234,19 @@ import {
8539
9234
  PencilIcon,
8540
9235
  PlayIcon as PlayIcon2,
8541
9236
  Trash2Icon as Trash2Icon2,
9237
+ TerminalIcon as TerminalIcon2,
8542
9238
  TriangleAlertIcon as TriangleAlertIcon3,
8543
9239
  XIcon,
8544
- ZapIcon
9240
+ CornerDownRightIcon,
9241
+ TargetIcon as TargetIcon3
8545
9242
  } from "lucide-react";
8546
- import { AnimatePresence as AnimatePresence2, motion as motion2, useReducedMotion } from "motion/react";
8547
- import { useEffect as useEffect11, useId as useId3, useMemo as useMemo5, useRef as useRef11, useState as useState13 } from "react";
8548
- import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
9243
+ import { AnimatePresence as AnimatePresence2, motion as motion3, useReducedMotion } from "motion/react";
9244
+ import { useEffect as useEffect11, useId as useId3, useMemo as useMemo5, useRef as useRef12, useState as useState13 } from "react";
9245
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
8549
9246
  var GOAL_LABEL = {
8550
9247
  pursuing: "Pursuing",
8551
9248
  waiting: "Waiting",
8552
- scheduled: "Scheduled",
9249
+ scheduled: "Waiting",
8553
9250
  blocked: "Blocked",
8554
9251
  held: "Held",
8555
9252
  paused: "Paused",
@@ -8580,13 +9277,13 @@ function sessionChromeGoalPillExplanation(state, record) {
8580
9277
  if (state === "paused") {
8581
9278
  return record?.pausedReason ? GOAL_PAUSED_REASON_EXPLANATION[record.pausedReason] ?? null : null;
8582
9279
  }
8583
- if (state === "scheduled" && continuation?.reason === "backoff_pending") {
8584
- return continuation.nextAttemptAt ? `Next goal check at ${formatClockTime(continuation.nextAttemptAt)}.` : "Next goal check is scheduled.";
9280
+ if (state === "scheduled") {
9281
+ return continuation?.nextAttemptAt ? `Continues at ${formatClockTime(continuation.nextAttemptAt)}.` : "Waiting to continue automatically.";
8585
9282
  }
8586
9283
  if (state === "held" && continuation?.reason === "held_for_input") {
8587
9284
  const reason = continuation.holdReason?.trim();
8588
9285
  const until = continuation.nextAttemptAt ? ` until ${formatClockTime(continuation.nextAttemptAt)}` : "";
8589
- return `Waiting for input${reason ? `: ${reason}` : ""}${until}. A child result, an agent message, or your prompt wakes it sooner.`;
9286
+ return `Waiting for input${reason ? `: ${reason}` : ""}${until}. Relevant session input\u2014including a child result, background-command result, agent message, schedule, or your prompt\u2014wakes it sooner.`;
8590
9287
  }
8591
9288
  return null;
8592
9289
  }
@@ -8604,6 +9301,27 @@ function queuedTurnPresentation(turn) {
8604
9301
  function isSteeringTurn(turn) {
8605
9302
  return turn.metadata.delivery === "steer";
8606
9303
  }
9304
+ function isAuthoritativeQueuedTurn(turn, mutationFor) {
9305
+ return !isSteeringTurn(turn) && mutationFor(turn.id) !== "steer";
9306
+ }
9307
+ function countAuthoritativeQueuedTurns(turns, mutationFor) {
9308
+ return turns.filter((turn) => isAuthoritativeQueuedTurn(turn, mutationFor)).length;
9309
+ }
9310
+ function isOptimisticQueuedMessage(message, queuedTurnIds, snapshot) {
9311
+ return message.delivery === "send" && message.destination === "queue" && (!message.turnId || !queuedTurnIds.has(message.turnId)) && !(message.turnId && message.appliedQueueVersion !== null && message.appliedQueueVersion !== void 0 && snapshot && snapshot.version >= message.appliedQueueVersion);
9312
+ }
9313
+ function countOptimisticQueuedMessages(messages, queuedTurnIds, snapshot) {
9314
+ return (messages ?? []).filter(
9315
+ (message) => isOptimisticQueuedMessage(message, queuedTurnIds, snapshot)
9316
+ ).length;
9317
+ }
9318
+ function sessionChromeInitialActive(input) {
9319
+ if (input.defaultActive != null) return input.defaultActive;
9320
+ return input.authoritativeQueuedCount >= 1 ? "queue" : null;
9321
+ }
9322
+ function sessionChromeShouldOfferQueue(input) {
9323
+ return !input.controlled && input.active === null && !input.activityOpen && input.authoritativeQueuedCount >= 1 && !input.suppressed;
9324
+ }
8607
9325
  function objectValue(value) {
8608
9326
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
8609
9327
  }
@@ -8616,6 +9334,7 @@ function sessionChromeGoalPillState(goalStatus, continuation) {
8616
9334
  }
8617
9335
  if (continuation.state === "scheduled") return "scheduled";
8618
9336
  if (continuation.state === "blocked") {
9337
+ if (continuation.reason === "human_turn_running") return "waiting";
8619
9338
  return continuation.reason === "workstream_paused" || continuation.reason === "held_for_input" ? "held" : "blocked";
8620
9339
  }
8621
9340
  return "invariant_broken";
@@ -8665,6 +9384,12 @@ function pendingKindLabel(kind) {
8665
9384
  return "Goal wake";
8666
9385
  case "agent_message":
8667
9386
  return "Update";
9387
+ case "background_command_result":
9388
+ return "Command result";
9389
+ case "session_wait_timeout":
9390
+ return "Wait ended";
9391
+ case "media_generation_result":
9392
+ return "Video result";
8668
9393
  default:
8669
9394
  return "Incoming";
8670
9395
  }
@@ -8682,10 +9407,13 @@ function toneClass(tone, selected) {
8682
9407
  }
8683
9408
  }
8684
9409
  function SessionChrome({
9410
+ compact = false,
8685
9411
  queue,
8686
9412
  composer,
8687
9413
  goal,
8688
9414
  agentsPanel,
9415
+ commandsPanel,
9416
+ commandsCount = 0,
8689
9417
  agentsSignal,
8690
9418
  onDismissIncoming,
8691
9419
  readOnly = false,
@@ -8694,6 +9422,9 @@ function SessionChrome({
8694
9422
  defaultActive = null,
8695
9423
  onActiveChange
8696
9424
  }) {
9425
+ const [activityRequested, setActivityOpen] = useState13(
9426
+ Boolean(compact && defaultActive && ["incoming", "agents", "commands"].includes(defaultActive))
9427
+ );
8697
9428
  const reactId = useId3();
8698
9429
  const panelId = `og-session-chrome-panel-${reactId}`;
8699
9430
  const reduceMotion = useReducedMotion();
@@ -8702,26 +9433,52 @@ function SessionChrome({
8702
9433
  const turns = queue.queue;
8703
9434
  const queueMutationFor = queue.mutationFor;
8704
9435
  const queuedTurns = useMemo5(
8705
- () => turns.filter((turn) => !isSteeringTurn(turn) && queueMutationFor(turn.id) !== "steer"),
9436
+ () => turns.filter((turn) => isAuthoritativeQueuedTurn(turn, queueMutationFor)),
8706
9437
  [queueMutationFor, turns]
8707
9438
  );
8708
9439
  const queuedTurnIds = useMemo5(() => new Set(queuedTurns.map((turn) => turn.id)), [queuedTurns]);
8709
9440
  const optimisticQueued = useMemo5(
8710
9441
  () => (composer?.optimisticMessages ?? []).filter(
8711
- (message) => message.delivery === "send" && message.destination === "queue" && (!message.turnId || !queuedTurnIds.has(message.turnId)) && !(message.turnId && message.appliedQueueVersion !== null && message.appliedQueueVersion !== void 0 && queue.snapshot && queue.snapshot.version >= message.appliedQueueVersion)
9442
+ (message) => isOptimisticQueuedMessage(message, queuedTurnIds, queue.snapshot)
8712
9443
  ),
8713
9444
  [composer?.optimisticMessages, queue.snapshot, queuedTurnIds]
8714
9445
  );
8715
9446
  const stoppingKind = composer?.stoppingAttempt ?? (queue.stoppingPreviousAttempt ? queue.effectiveControl?.state === "paused" ? "current" : "previous" : null);
8716
9447
  const stopping = stoppingKind !== null;
8717
9448
  const canMutateQueue = !readOnly && composer !== void 0;
8718
- const liveGoal = record?.status === "active";
8719
- const elapsed = useLiveElapsed(
8720
- record?.createdAt,
8721
- Boolean(liveGoal),
8722
- !liveGoal ? record?.updatedAt : null
8723
- );
9449
+ const elapsed = useLiveElapsed(record?.createdAt, Boolean(record));
8724
9450
  const goalState = record ? sessionChromeGoalPillState(record.status, record.continuation) : null;
9451
+ const initialAuthoritativeQueuedCount = countAuthoritativeQueuedTurns(
9452
+ queue.queue,
9453
+ queue.mutationFor
9454
+ );
9455
+ const [activeUncontrolled, setActiveUncontrolled] = useState13(
9456
+ () => sessionChromeInitialActive({
9457
+ defaultActive,
9458
+ authoritativeQueuedCount: initialAuthoritativeQueuedCount
9459
+ })
9460
+ );
9461
+ const active = activeControlled !== void 0 ? activeControlled : activeUncontrolled;
9462
+ const activityOpen = activityRequested || Boolean(compact && active && ["incoming", "agents", "commands"].includes(active));
9463
+ const activityVisibleRef = useRef12(activityOpen);
9464
+ activityVisibleRef.current = activityOpen;
9465
+ const queueOfferAdmissionSuppressedRef = useRef12(
9466
+ defaultActive == null && initialAuthoritativeQueuedCount === 0 && countOptimisticQueuedMessages(composer?.optimisticMessages, queuedTurnIds, queue.snapshot) > 0
9467
+ );
9468
+ const queueOfferDismissedSessionIdsRef = useRef12(/* @__PURE__ */ new Set());
9469
+ const occupancySessionId = queuedTurns[0]?.sessionId ?? null;
9470
+ const setActive = (next) => {
9471
+ if (active === "queue" && next === null) {
9472
+ if (occupancySessionId) {
9473
+ queueOfferDismissedSessionIdsRef.current.add(occupancySessionId);
9474
+ } else {
9475
+ queueOfferAdmissionSuppressedRef.current = true;
9476
+ }
9477
+ }
9478
+ if (activeControlled === void 0) setActiveUncontrolled(next);
9479
+ onActiveChange?.(next);
9480
+ };
9481
+ const hasCommandsPanel = commandsPanel != null;
8725
9482
  const signals = useMemo5(() => {
8726
9483
  const rows = [];
8727
9484
  if (incoming.length > 0) {
@@ -8733,7 +9490,7 @@ function SessionChrome({
8733
9490
  tone: incoming.some(
8734
9491
  (item) => item.classification === "action_required" || item.classification === "failure"
8735
9492
  ) ? "waiting" : "neutral",
8736
- icon: /* @__PURE__ */ jsx18(InboxIcon, { className: "size-3" })
9493
+ icon: /* @__PURE__ */ jsx20(InboxIcon, { className: "size-3" })
8737
9494
  });
8738
9495
  }
8739
9496
  const queuedCount = queuedTurns.length + optimisticQueued.length;
@@ -8750,7 +9507,7 @@ function SessionChrome({
8750
9507
  label: queueProblem ? queuedCount > 0 ? `${queuedCount} queued \xB7 needs attention` : "Queue needs attention" : allVoiceRequests ? queuedCount === 1 ? "Voice request queued" : `${queuedCount} voice requests queued` : onlyVoiceHandoff ? "Voice handoff queued" : `${queuedCount} queued prompt${queuedCount === 1 ? "" : "s"}`,
8751
9508
  ...detail ? { detail } : {},
8752
9509
  tone: queueProblem ? "waiting" : "neutral",
8753
- icon: queueProblem ? /* @__PURE__ */ jsx18(TriangleAlertIcon3, { className: "size-3" }) : voiceOnly ? /* @__PURE__ */ jsx18(AudioLinesIcon, { className: "size-3" }) : /* @__PURE__ */ jsx18(ListOrderedIcon, { className: "size-3" })
9510
+ icon: queueProblem ? /* @__PURE__ */ jsx20(TriangleAlertIcon3, { className: "size-3" }) : voiceOnly ? /* @__PURE__ */ jsx20(AudioLinesIcon, { className: "size-3" }) : /* @__PURE__ */ jsx20(ListOrderedIcon, { className: "size-3" })
8754
9511
  });
8755
9512
  }
8756
9513
  if (record && goalState) {
@@ -8762,7 +9519,7 @@ function SessionChrome({
8762
9519
  detail: elapsed ? `${elapsed} \xB7 ${record.text}` : record.text,
8763
9520
  ...explanation ? { title: explanation } : {},
8764
9521
  tone: waiting ? "waiting" : goalState === "pursuing" || goalState === "scheduled" ? "accent" : "neutral",
8765
- icon: goalState === "blocked" || goalState === "invariant_broken" ? /* @__PURE__ */ jsx18(TriangleAlertIcon3, { className: "size-3" }) : goalState === "waiting" ? /* @__PURE__ */ jsx18(Loader2Icon2, { className: "size-3 animate-og-spin" }) : goalState === "paused" || goalState === "held" ? /* @__PURE__ */ jsx18(PauseIcon2, { className: "size-3" }) : /* @__PURE__ */ jsx18(ZapIcon, { className: "size-3" })
9522
+ icon: /* @__PURE__ */ jsx20(TargetIcon3, { className: "size-3" })
8766
9523
  });
8767
9524
  }
8768
9525
  if (agentsSignal && agentsSignal.count > 0) {
@@ -8772,11 +9529,22 @@ function SessionChrome({
8772
9529
  label: `${agentsSignal.count} agent${agentsSignal.count === 1 ? "" : "s"}`,
8773
9530
  ...detail ? { detail } : {},
8774
9531
  tone: agentsSignal.tone ?? "neutral",
8775
- icon: /* @__PURE__ */ jsx18(BotIcon3, { className: "size-3" })
9532
+ icon: /* @__PURE__ */ jsx20(BotIcon3, { className: "size-3" })
9533
+ });
9534
+ }
9535
+ if (commandsCount > 0 || active === "commands" && hasCommandsPanel) {
9536
+ rows.push({
9537
+ id: "commands",
9538
+ label: commandsCount > 0 ? `${commandsCount} command${commandsCount === 1 ? "" : "s"}` : "Commands",
9539
+ tone: commandsCount > 0 ? "running" : "neutral",
9540
+ icon: /* @__PURE__ */ jsx20(TerminalIcon2, { className: "size-3" })
8776
9541
  });
8777
9542
  }
8778
9543
  return rows;
8779
9544
  }, [
9545
+ commandsCount,
9546
+ hasCommandsPanel,
9547
+ active,
8780
9548
  agentsSignal,
8781
9549
  elapsed,
8782
9550
  goalState,
@@ -8787,16 +9555,8 @@ function SessionChrome({
8787
9555
  queuedTurns,
8788
9556
  record
8789
9557
  ]);
8790
- const [activeUncontrolled, setActiveUncontrolled] = useState13(
8791
- defaultActive
8792
- );
8793
- const active = activeControlled !== void 0 ? activeControlled : activeUncontrolled;
8794
- const setActive = (next) => {
8795
- if (activeControlled === void 0) setActiveUncontrolled(next);
8796
- onActiveChange?.(next);
8797
- };
8798
9558
  const optimisticQueueKeys = optimisticQueued.map((message) => message.clientEventId).join(",");
8799
- const previousOptimisticQueueKeys = useRef11(optimisticQueueKeys);
9559
+ const previousOptimisticQueueKeys = useRef12(optimisticQueueKeys);
8800
9560
  const [queueArrivalNonce, setQueueArrivalNonce] = useState13(0);
8801
9561
  useEffect11(() => {
8802
9562
  const previous = new Set(previousOptimisticQueueKeys.current.split(",").filter(Boolean));
@@ -8804,12 +9564,47 @@ function SessionChrome({
8804
9564
  previousOptimisticQueueKeys.current = optimisticQueueKeys;
8805
9565
  if (!arrived) return;
8806
9566
  setQueueArrivalNonce((current) => current + 1);
8807
- }, [optimisticQueueKeys, optimisticQueued]);
9567
+ if (activeControlled === void 0 && active === null) {
9568
+ queueOfferAdmissionSuppressedRef.current = true;
9569
+ }
9570
+ }, [active, activeControlled, optimisticQueueKeys, optimisticQueued]);
9571
+ const queueOccupied = queuedTurns.length > 0 || optimisticQueued.length > 0;
9572
+ useEffect11(() => {
9573
+ if (queueOccupied) return;
9574
+ queueOfferAdmissionSuppressedRef.current = false;
9575
+ queueOfferDismissedSessionIdsRef.current.clear();
9576
+ }, [queueOccupied]);
9577
+ const queueOfferSuppressed = queueOfferAdmissionSuppressedRef.current || occupancySessionId != null && queueOfferDismissedSessionIdsRef.current.has(occupancySessionId);
9578
+ useEffect11(() => {
9579
+ if (!sessionChromeShouldOfferQueue({
9580
+ controlled: activeControlled !== void 0,
9581
+ active,
9582
+ activityOpen,
9583
+ authoritativeQueuedCount: queuedTurns.length,
9584
+ suppressed: queueOfferSuppressed
9585
+ })) {
9586
+ return;
9587
+ }
9588
+ if (activeControlled === void 0) setActiveUncontrolled("queue");
9589
+ onActiveChange?.("queue");
9590
+ }, [
9591
+ active,
9592
+ activeControlled,
9593
+ activityOpen,
9594
+ occupancySessionId,
9595
+ onActiveChange,
9596
+ queueOfferSuppressed,
9597
+ queuedTurns.length
9598
+ ]);
8808
9599
  const [replaceDraftFor, setReplaceDraftFor] = useState13(null);
8809
- const chipRefs = useRef11({});
8810
- const railRef = useRef11(null);
9600
+ const chipRefs = useRef12({});
9601
+ const railRef = useRef12(null);
8811
9602
  const [pill, setPill] = useState13({ left: 0, top: 0, width: 0, height: 0, opacity: 0 });
8812
9603
  const signalIds = signals.map((signal) => signal.id).join(",");
9604
+ useEffect11(() => {
9605
+ if (compact && !signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id)))
9606
+ setActivityOpen(false);
9607
+ }, [compact, signals]);
8813
9608
  useEffect11(() => {
8814
9609
  if (active && !signalIds.split(",").includes(active)) {
8815
9610
  if (activeControlled === void 0) setActiveUncontrolled(null);
@@ -8830,7 +9625,10 @@ function SessionChrome({
8830
9625
  return;
8831
9626
  }
8832
9627
  const chip = chipRefs.current[active];
8833
- if (!chip) return;
9628
+ if (!chip) {
9629
+ setPill((prev) => ({ ...prev, opacity: 0 }));
9630
+ return;
9631
+ }
8834
9632
  const railBox = rail.getBoundingClientRect();
8835
9633
  const chipBox = chip.getBoundingClientRect();
8836
9634
  setPill({
@@ -8859,7 +9657,7 @@ function SessionChrome({
8859
9657
  const shellDuration = reduceMotion ? 0 : 0.22;
8860
9658
  const crossfadeDuration = reduceMotion ? 0 : 0.18;
8861
9659
  const ease = [0.22, 1, 0.36, 1];
8862
- const panelBody = active === "incoming" ? /* @__PURE__ */ jsx18(IncomingPanel, { inputs: incoming, onDismiss: onDismissIncoming }) : active === "queue" ? /* @__PURE__ */ jsx18(
9660
+ const panelBody = active === "incoming" ? /* @__PURE__ */ jsx20(IncomingPanel, { inputs: incoming, onDismiss: onDismissIncoming }) : active === "queue" ? /* @__PURE__ */ jsx20(
8863
9661
  QueuePanel,
8864
9662
  {
8865
9663
  turns: queuedTurns,
@@ -8910,15 +9708,15 @@ function SessionChrome({
8910
9708
  void queue.moveTurn(turnId, beforeTurnId);
8911
9709
  } : void 0
8912
9710
  }
8913
- ) : active === "goal" && record && goalState && goal ? /* @__PURE__ */ jsx18(GoalPanel, { goal, state: goalState, elapsed, readOnly }) : active === "agents" ? /* @__PURE__ */ jsx18("div", { "data-og-session-chrome-panel": "agents", children: agentsPanel ?? /* @__PURE__ */ jsx18("p", { className: "text-og-xs text-og-fg-muted", children: "No agent details." }) }) : null;
8914
- return /* @__PURE__ */ jsx18(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsx18(
9711
+ ) : active === "goal" && record && goalState && goal ? /* @__PURE__ */ jsx20(GoalPanel, { goal, state: goalState, elapsed, readOnly }) : active === "commands" ? /* @__PURE__ */ jsx20("div", { "data-og-session-chrome-panel": "commands", children: commandsPanel }) : active === "agents" ? /* @__PURE__ */ jsx20("div", { "data-og-session-chrome-panel": "agents", children: agentsPanel ?? /* @__PURE__ */ jsx20("p", { className: "text-og-xs text-og-fg-muted", children: "No agent details." }) }) : null;
9712
+ return /* @__PURE__ */ jsx20(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsx20(
8915
9713
  "div",
8916
9714
  {
8917
9715
  className: cn("og-session-chrome og-root w-full", className),
8918
9716
  "data-testid": "session-chrome",
8919
9717
  "data-og-session-chrome": "",
8920
9718
  "data-og-session-chrome-open": open ? "true" : "false",
8921
- children: /* @__PURE__ */ jsxs13(
9719
+ children: /* @__PURE__ */ jsxs15(
8922
9720
  "div",
8923
9721
  {
8924
9722
  className: cn(
@@ -8927,14 +9725,14 @@ function SessionChrome({
8927
9725
  ),
8928
9726
  style: {
8929
9727
  borderRadius: "var(--_og-session-chrome-radius)",
8930
- background: open ? "var(--_og-session-chrome-surface-open)" : "var(--_og-session-chrome-surface)",
8931
- borderColor: open ? "var(--_og-session-chrome-border-open)" : "var(--_og-session-chrome-border)",
8932
- boxShadow: open ? "var(--og-session-chrome-shadow-open)" : "var(--og-session-chrome-shadow)",
9728
+ background: compact ? "transparent" : open ? "var(--_og-session-chrome-surface-open)" : "var(--_og-session-chrome-surface)",
9729
+ borderColor: compact ? "transparent" : open ? "var(--_og-session-chrome-border-open)" : "var(--_og-session-chrome-border)",
9730
+ boxShadow: compact ? "none" : open ? "var(--og-session-chrome-shadow-open)" : "var(--og-session-chrome-shadow)",
8933
9731
  transitionDuration: "var(--og-session-chrome-duration)",
8934
9732
  transitionTimingFunction: "var(--_og-session-chrome-ease)"
8935
9733
  },
8936
9734
  children: [
8937
- /* @__PURE__ */ jsx18(
9735
+ /* @__PURE__ */ jsx20(
8938
9736
  "div",
8939
9737
  {
8940
9738
  className: "relative",
@@ -8944,17 +9742,17 @@ function SessionChrome({
8944
9742
  paddingLeft: "var(--og-session-chrome-rail-pad)",
8945
9743
  paddingRight: "var(--og-session-chrome-rail-pad)"
8946
9744
  },
8947
- children: /* @__PURE__ */ jsxs13(
9745
+ children: /* @__PURE__ */ jsxs15(
8948
9746
  "div",
8949
9747
  {
8950
9748
  ref: railRef,
8951
- className: "relative flex flex-wrap items-center",
9749
+ className: cn("relative flex items-center", compact ? "flex-nowrap" : "flex-wrap"),
8952
9750
  style: {
8953
- gap: "var(--og-session-chrome-chip-gap)"
9751
+ gap: compact ? "10px" : "var(--og-session-chrome-chip-gap)"
8954
9752
  },
8955
9753
  children: [
8956
- /* @__PURE__ */ jsx18(
8957
- motion2.div,
9754
+ /* @__PURE__ */ jsx20(
9755
+ motion3.div,
8958
9756
  {
8959
9757
  "aria-hidden": true,
8960
9758
  className: "pointer-events-none absolute left-0 top-0 rounded-og-md",
@@ -8973,67 +9771,158 @@ function SessionChrome({
8973
9771
  transition: { duration: shellDuration, ease }
8974
9772
  }
8975
9773
  ),
8976
- signals.map((signal) => {
9774
+ signals.filter(
9775
+ (signal) => !compact || !["incoming", "agents", "commands"].includes(signal.id)
9776
+ ).map((signal) => {
8977
9777
  const selected = active === signal.id;
8978
- return /* @__PURE__ */ jsxs13(
8979
- "button",
9778
+ return /* @__PURE__ */ jsxs15(
9779
+ "div",
8980
9780
  {
8981
- type: "button",
8982
- ref: (node) => {
8983
- chipRefs.current[signal.id] = node;
8984
- },
8985
- "aria-expanded": selected,
8986
- "aria-controls": panelId,
8987
- "aria-label": selected ? `Close ${signal.label}` : void 0,
8988
- "data-testid": `session-chrome-${signal.id}`,
8989
- "data-og-session-chrome-signal": signal.id,
8990
- title: signal.title,
8991
- onClick: () => setActive(selected ? null : signal.id),
9781
+ role: "group",
9782
+ "aria-label": signal.id === "queue" ? "Queued messages and actions" : signal.id === "goal" ? "Goal and actions" : signal.label,
8992
9783
  className: cn(
8993
- "group relative z-[1] inline-flex min-h-[var(--og-session-chrome-chip-min-height)] max-w-full items-center gap-1 rounded-og-md py-1 text-left text-og-xs outline-hidden",
8994
- // Coarse pointers keep a 44px target (session-pins acceptance).
8995
- "pointer-coarse:min-h-11",
8996
- "transition-colors duration-150 motion-reduce:transition-none",
8997
- "hover:text-og-fg focus-visible:bg-og-surface-3/50",
8998
- selected ? "text-og-fg" : "text-og-fg-muted"
9784
+ "group/signal relative z-[1] inline-flex min-w-0 max-w-full items-center rounded-og-md",
9785
+ compact && "bg-og-surface-2/60 px-0.5",
9786
+ compact && selected && "bg-og-surface-3"
8999
9787
  ),
9000
- style: {
9001
- paddingInline: "var(--og-session-chrome-chip-pad-x)"
9002
- },
9003
9788
  children: [
9004
- signal.id === "queue" && queueArrivalNonce > 0 && !reduceMotion ? /* @__PURE__ */ jsx18(
9005
- motion2.span,
9789
+ /* @__PURE__ */ jsxs15(
9790
+ "button",
9006
9791
  {
9007
- "aria-hidden": "true",
9008
- "data-testid": "session-chrome-queue-arrival",
9009
- className: "pointer-events-none absolute inset-0 rounded-og-md bg-og-accent-soft",
9010
- initial: { opacity: 0 },
9011
- animate: { opacity: [0, 0.38, 0] },
9012
- transition: { duration: 0.72, times: [0, 0.18, 1], ease }
9013
- },
9014
- queueArrivalNonce
9015
- ) : null,
9016
- /* @__PURE__ */ jsx18("span", { className: cn("shrink-0", toneClass(signal.tone, selected)), children: signal.icon }),
9017
- /* @__PURE__ */ jsx18("span", { className: "shrink-0 font-medium text-og-fg", children: signal.label }),
9018
- signal.detail ? /* @__PURE__ */ jsxs13(Fragment6, { children: [
9019
- /* @__PURE__ */ jsx18("span", { "aria-hidden": true, className: "shrink-0 text-og-fg-subtle/60", children: "\xB7" }),
9020
- /* @__PURE__ */ jsx18("span", { className: "min-w-0 max-w-[8.5rem] truncate text-og-fg sm:max-w-[12rem]", children: signal.detail })
9021
- ] }) : null,
9022
- selected ? /* @__PURE__ */ jsx18(
9023
- "span",
9792
+ type: "button",
9793
+ ref: (node) => {
9794
+ chipRefs.current[signal.id] = node;
9795
+ },
9796
+ "aria-expanded": selected,
9797
+ "aria-controls": panelId,
9798
+ "aria-label": compact && signal.id === "goal" ? `Goal \xB7 ${goalState === "pursuing" ? "Running" : signal.label}` : selected ? `Close ${signal.label}` : void 0,
9799
+ "data-testid": `session-chrome-${signal.id}`,
9800
+ "data-og-session-chrome-signal": signal.id,
9801
+ title: signal.title ?? (compact ? signal.label : void 0),
9802
+ onClick: () => {
9803
+ if (compact) setActivityOpen(false);
9804
+ setActive(selected ? null : signal.id);
9805
+ },
9806
+ className: cn(
9807
+ "group relative z-[1] inline-flex min-w-0 min-h-[var(--og-session-chrome-chip-min-height)] max-w-full items-center gap-1 rounded-og-md py-1 text-left text-og-xs outline-hidden",
9808
+ // Coarse pointers keep a 44px target (session-pins acceptance).
9809
+ "pointer-coarse:min-h-11",
9810
+ "transition-colors duration-150 motion-reduce:transition-none",
9811
+ "hover:text-og-fg focus-visible:bg-og-surface-3/50",
9812
+ selected ? "text-og-fg" : "text-og-fg-muted"
9813
+ ),
9814
+ style: {
9815
+ paddingInline: "var(--og-session-chrome-chip-pad-x)"
9816
+ },
9817
+ children: [
9818
+ signal.id === "queue" && queueArrivalNonce > 0 && !reduceMotion ? /* @__PURE__ */ jsx20(
9819
+ motion3.span,
9820
+ {
9821
+ "aria-hidden": "true",
9822
+ "data-testid": "session-chrome-queue-arrival",
9823
+ className: "pointer-events-none absolute inset-0 rounded-og-md bg-og-accent-soft",
9824
+ initial: { opacity: 0 },
9825
+ animate: { opacity: [0, 0.38, 0] },
9826
+ transition: { duration: 0.72, times: [0, 0.18, 1], ease }
9827
+ },
9828
+ queueArrivalNonce
9829
+ ) : null,
9830
+ /* @__PURE__ */ jsx20("span", { className: cn("shrink-0", toneClass(signal.tone, selected)), children: signal.icon }),
9831
+ /* @__PURE__ */ jsxs15(
9832
+ "span",
9833
+ {
9834
+ className: cn(
9835
+ "font-medium text-og-fg",
9836
+ compact ? "min-w-0 truncate" : "shrink-0"
9837
+ ),
9838
+ children: [
9839
+ compact && signal.id === "goal" ? "Goal \xB7 " : null,
9840
+ compact && signal.id === "goal" ? goalState === "pursuing" ? "Running" : signal.label : compact && signal.id === "queue" ? `${queuedTurns.length + optimisticQueued.length} queued` : signal.label
9841
+ ]
9842
+ }
9843
+ ),
9844
+ signal.detail && !compact ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
9845
+ /* @__PURE__ */ jsx20("span", { "aria-hidden": true, className: "shrink-0 text-og-fg-subtle/60", children: "\xB7" }),
9846
+ /* @__PURE__ */ jsx20("span", { className: "min-w-0 max-w-[8.5rem] truncate text-og-fg sm:max-w-[12rem]", children: signal.detail })
9847
+ ] }) : null,
9848
+ selected && !compact ? /* @__PURE__ */ jsx20(
9849
+ "span",
9850
+ {
9851
+ "data-testid": "session-chrome-close",
9852
+ className: "ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-og-sm text-og-fg-subtle transition-colors group-hover:text-og-fg pointer-coarse:size-5",
9853
+ "aria-hidden": true,
9854
+ children: /* @__PURE__ */ jsx20(XIcon, { className: "size-3" })
9855
+ }
9856
+ ) : null
9857
+ ]
9858
+ }
9859
+ ),
9860
+ signal.id === "goal" && goal && record && !readOnly ? /* @__PURE__ */ jsxs15("div", { className: cn("flex shrink-0 items-center pr-1", compact && "pl-0.5"), children: [
9861
+ record.status === "active" || record.status === "paused" ? /* @__PURE__ */ jsx20(
9862
+ IconAction,
9863
+ {
9864
+ label: record.status === "paused" ? "Resume goal" : "Pause goal",
9865
+ tip: record.status === "paused" ? "Resume goal" : "Pause goal",
9866
+ disabled: goal.updating,
9867
+ onClick: () => void (record.status === "paused" ? goal.resume() : goal.pause("Paused from session chrome")),
9868
+ children: goal.updating ? /* @__PURE__ */ jsx20(Loader2Icon2, { className: "size-3 animate-og-spin" }) : record.status === "paused" ? /* @__PURE__ */ jsx20(PlayIcon2, { className: "size-3" }) : /* @__PURE__ */ jsx20(PauseIcon2, { className: "size-3" })
9869
+ }
9870
+ ) : null,
9871
+ /* @__PURE__ */ jsx20(
9872
+ IconAction,
9873
+ {
9874
+ label: "Clear goal",
9875
+ tip: "Clear goal",
9876
+ danger: true,
9877
+ disabled: goal.updating,
9878
+ onClick: () => void goal.deleteGoal(),
9879
+ children: /* @__PURE__ */ jsx20(Trash2Icon2, { className: "size-3" })
9880
+ }
9881
+ )
9882
+ ] }) : signal.id === "queue" && canMutateQueue && queuedTurns[0] ? /* @__PURE__ */ jsx20("div", { className: cn("flex shrink-0 items-center pr-1", compact && "pl-0.5"), children: /* @__PURE__ */ jsx20(
9883
+ IconAction,
9024
9884
  {
9025
- "data-testid": "session-chrome-close",
9026
- className: "ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-og-sm text-og-fg-subtle transition-colors group-hover:text-og-fg pointer-coarse:size-5",
9027
- "aria-hidden": true,
9028
- children: /* @__PURE__ */ jsx18(XIcon, { className: "size-3" })
9885
+ label: "Steer first queued message",
9886
+ text: "Steer",
9887
+ tip: QUEUE_STEER_TIP,
9888
+ disabled: queue.mutating || Boolean(queue.mutationFor(queuedTurns[0].id)),
9889
+ onClick: () => void queue.steerTurn(queuedTurns[0].id),
9890
+ children: /* @__PURE__ */ jsx20(CornerDownRightIcon, { className: "size-3" })
9029
9891
  }
9030
- ) : null
9892
+ ) }) : null
9031
9893
  ]
9032
9894
  },
9033
9895
  signal.id
9034
9896
  );
9035
9897
  }),
9036
- stopping ? /* @__PURE__ */ jsxs13(
9898
+ compact && signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id)) ? /* @__PURE__ */ jsxs15(
9899
+ "button",
9900
+ {
9901
+ type: "button",
9902
+ "aria-label": "Session activity",
9903
+ title: activityOpen ? "Close activity" : "Inbox, agents and commands",
9904
+ "aria-controls": panelId,
9905
+ "aria-expanded": activityOpen,
9906
+ onClick: () => {
9907
+ setActivityOpen(!activityOpen);
9908
+ setActive(
9909
+ activityOpen ? null : signals.find(
9910
+ (signal) => ["incoming", "agents", "commands"].includes(signal.id)
9911
+ )?.id ?? null
9912
+ );
9913
+ },
9914
+ className: cn(
9915
+ "ml-auto inline-flex min-h-8 shrink-0 items-center justify-center gap-1.5 rounded-og-md px-2 text-og-xs transition-colors outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/40 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
9916
+ activityOpen ? "bg-og-surface-3 text-og-fg" : "text-og-fg-muted hover:bg-og-surface-2 hover:text-og-fg"
9917
+ ),
9918
+ children: [
9919
+ /* @__PURE__ */ jsx20(ActivityIcon, { className: "size-3.5" }),
9920
+ /* @__PURE__ */ jsx20("span", { className: "sr-only", children: "Activity" }),
9921
+ incoming.length > 0 ? /* @__PURE__ */ jsx20("span", { className: "size-1.5 rounded-full bg-og-accent" }) : null
9922
+ ]
9923
+ }
9924
+ ) : null,
9925
+ stopping ? /* @__PURE__ */ jsxs15(
9037
9926
  "span",
9038
9927
  {
9039
9928
  role: "status",
@@ -9041,7 +9930,7 @@ function SessionChrome({
9041
9930
  className: "inline-flex min-h-[var(--og-session-chrome-chip-min-height)] items-center gap-1.5 px-1.5 text-og-xs text-og-fg-muted",
9042
9931
  "data-testid": "session-chrome-stopping",
9043
9932
  children: [
9044
- /* @__PURE__ */ jsx18(
9933
+ /* @__PURE__ */ jsx20(
9045
9934
  Loader2Icon2,
9046
9935
  {
9047
9936
  "aria-hidden": "true",
@@ -9057,7 +9946,41 @@ function SessionChrome({
9057
9946
  )
9058
9947
  }
9059
9948
  ),
9060
- /* @__PURE__ */ jsx18(
9949
+ /* @__PURE__ */ jsx20(AnimatePresence2, { initial: false, children: compact && activityOpen ? /* @__PURE__ */ jsx20(
9950
+ motion3.div,
9951
+ {
9952
+ initial: { height: 0, opacity: 0 },
9953
+ animate: { height: "auto", opacity: 1 },
9954
+ exit: { height: 0, opacity: 0 },
9955
+ transition: { duration: shellDuration, ease },
9956
+ style: { overflow: "hidden" },
9957
+ children: /* @__PURE__ */ jsx20("div", { className: "mt-1 flex items-center gap-1 rounded-t-og-lg bg-og-surface-2/50 px-2 py-1", children: signals.filter((signal) => ["incoming", "agents", "commands"].includes(signal.id)).map((signal) => /* @__PURE__ */ jsxs15(
9958
+ "button",
9959
+ {
9960
+ type: "button",
9961
+ "aria-expanded": active === signal.id,
9962
+ onClick: () => {
9963
+ if (activityVisibleRef.current) setActive(signal.id);
9964
+ },
9965
+ className: cn(
9966
+ "inline-flex min-h-9 items-center gap-1.5 rounded-og-md px-2 text-og-xs pointer-coarse:min-h-11",
9967
+ active === signal.id ? "bg-og-surface-3 text-og-fg" : "text-og-fg-muted hover:text-og-fg"
9968
+ ),
9969
+ children: [
9970
+ signal.icon,
9971
+ signal.id === "incoming" ? `${incoming.length} incoming` : signal.label
9972
+ ]
9973
+ },
9974
+ signal.id
9975
+ )) })
9976
+ },
9977
+ "activity-tabs"
9978
+ ) : null }),
9979
+ goal?.mutationError ? /* @__PURE__ */ jsxs15("p", { role: "alert", className: "px-3 pb-2 text-og-xs text-og-danger", children: [
9980
+ "Goal action not confirmed. ",
9981
+ goal.mutationError.message
9982
+ ] }) : null,
9983
+ /* @__PURE__ */ jsx20(
9061
9984
  "div",
9062
9985
  {
9063
9986
  id: panelId,
@@ -9073,33 +9996,48 @@ function SessionChrome({
9073
9996
  transitionDuration: "var(--og-session-chrome-duration)",
9074
9997
  transitionTimingFunction: "var(--_og-session-chrome-ease)"
9075
9998
  },
9076
- children: /* @__PURE__ */ jsx18("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx18(
9999
+ children: /* @__PURE__ */ jsx20("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxs15(
9077
10000
  "div",
9078
10001
  {
9079
- className: "relative overflow-y-auto overscroll-contain border-t border-og-border/50",
10002
+ className: cn(
10003
+ "relative overflow-y-auto overscroll-contain",
10004
+ compact ? activityOpen ? "rounded-b-og-lg bg-og-surface-2/50" : "mt-1 rounded-og-lg bg-og-surface-2/50" : "border-t border-og-border/50"
10005
+ ),
9080
10006
  style: {
9081
10007
  maxHeight: "var(--og-session-chrome-panel-max-height)",
9082
10008
  paddingInline: "var(--og-session-chrome-panel-pad-x)",
9083
10009
  paddingBlock: "var(--og-session-chrome-panel-pad-y)"
9084
10010
  },
9085
- children: /* @__PURE__ */ jsx18(AnimatePresence2, { initial: false, children: active && panelBody ? /* @__PURE__ */ jsx18(
9086
- motion2.div,
9087
- {
9088
- "data-og-session-chrome-panel-frame": active,
9089
- initial: reduceMotion ? false : { opacity: 0 },
9090
- animate: { opacity: 1, position: "relative" },
9091
- exit: reduceMotion ? { opacity: 1, position: "relative" } : {
9092
- opacity: 0,
9093
- position: "absolute",
9094
- top: 0,
9095
- left: 0,
9096
- right: 0
10011
+ children: [
10012
+ /* @__PURE__ */ jsx20(AnimatePresence2, { initial: false, children: active && active !== "commands" && panelBody ? /* @__PURE__ */ jsx20(
10013
+ motion3.div,
10014
+ {
10015
+ "data-og-session-chrome-panel-frame": active,
10016
+ initial: reduceMotion ? false : { opacity: 0 },
10017
+ animate: { opacity: 1, position: "relative" },
10018
+ exit: reduceMotion ? { opacity: 1, position: "relative" } : {
10019
+ opacity: 0,
10020
+ position: "absolute",
10021
+ top: 0,
10022
+ left: 0,
10023
+ right: 0
10024
+ },
10025
+ transition: { duration: crossfadeDuration, ease },
10026
+ children: panelBody
9097
10027
  },
9098
- transition: { duration: crossfadeDuration, ease },
9099
- children: panelBody
9100
- },
9101
- active
9102
- ) : null })
10028
+ active
10029
+ ) : null }),
10030
+ active === "commands" ? /* @__PURE__ */ jsx20(
10031
+ motion3.div,
10032
+ {
10033
+ initial: reduceMotion ? false : { opacity: 0 },
10034
+ animate: { opacity: 1 },
10035
+ transition: { duration: crossfadeDuration, ease },
10036
+ children: panelBody
10037
+ },
10038
+ "commands"
10039
+ ) : null
10040
+ ]
9103
10041
  }
9104
10042
  ) })
9105
10043
  }
@@ -9114,18 +10052,18 @@ function IncomingPanel({
9114
10052
  inputs,
9115
10053
  onDismiss
9116
10054
  }) {
9117
- return /* @__PURE__ */ jsx18(
10055
+ return /* @__PURE__ */ jsx20(
9118
10056
  "ul",
9119
10057
  {
9120
10058
  className: "flex flex-col gap-0.5",
9121
10059
  "aria-label": "Incoming updates",
9122
10060
  "data-og-session-chrome-panel": "incoming",
9123
- children: inputs.map((input) => /* @__PURE__ */ jsxs13(
10061
+ children: inputs.map((input) => /* @__PURE__ */ jsxs15(
9124
10062
  "li",
9125
10063
  {
9126
10064
  className: "group flex items-start gap-1.5 rounded-og-sm px-1.5 py-1 transition-colors hover:bg-[var(--_og-session-chrome-row-hover)]",
9127
10065
  children: [
9128
- /* @__PURE__ */ jsx18(
10066
+ /* @__PURE__ */ jsx20(
9129
10067
  "span",
9130
10068
  {
9131
10069
  className: cn(
@@ -9135,15 +10073,15 @@ function IncomingPanel({
9135
10073
  children: pendingKindLabel(input.kind)
9136
10074
  }
9137
10075
  ),
9138
- /* @__PURE__ */ jsx18("p", { className: "min-w-0 flex-1 text-og-xs leading-4 text-og-fg", children: input.summary }),
9139
- onDismiss ? /* @__PURE__ */ jsx18("div", { className: "flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100 max-sm:opacity-100", children: /* @__PURE__ */ jsx18(
10076
+ /* @__PURE__ */ jsx20("p", { className: "min-w-0 flex-1 text-og-xs leading-4 text-og-fg", children: input.summary }),
10077
+ onDismiss ? /* @__PURE__ */ jsx20("div", { className: "flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100 max-sm:opacity-100", children: /* @__PURE__ */ jsx20(
9140
10078
  IconAction,
9141
10079
  {
9142
10080
  label: `Dismiss incoming ${pendingKindLabel(input.kind)}`,
9143
10081
  tip: "Dismiss",
9144
10082
  onClick: () => onDismiss(input.id),
9145
10083
  danger: true,
9146
- children: /* @__PURE__ */ jsx18(Trash2Icon2, { className: "size-3" })
10084
+ children: /* @__PURE__ */ jsx20(Trash2Icon2, { className: "size-3" })
9147
10085
  }
9148
10086
  ) }) : null
9149
10087
  ]
@@ -9190,7 +10128,7 @@ function QueuePanel({
9190
10128
  );
9191
10129
  return () => clearTimeout(timer);
9192
10130
  }, [reduceMotion, turnIdsKey]);
9193
- return /* @__PURE__ */ jsxs13(
10131
+ return /* @__PURE__ */ jsxs15(
9194
10132
  "ol",
9195
10133
  {
9196
10134
  className: "flex flex-col gap-0.5",
@@ -9206,65 +10144,66 @@ function QueuePanel({
9206
10144
  const beforeDown = index < turns.length - 1 ? turns[index + 2]?.id ?? null : null;
9207
10145
  const showActions = !readOnly && (onEdit || onSteer || onRemove || onMove);
9208
10146
  const confirmingReplace = replaceDraftFor === turn.id;
9209
- return /* @__PURE__ */ jsxs13(
10147
+ return /* @__PURE__ */ jsxs15(
9210
10148
  "li",
9211
10149
  {
9212
10150
  "data-queue-turn-id": turn.id,
9213
10151
  className: "group flex flex-col gap-1 rounded-og-sm px-1.5 py-1 transition-colors hover:bg-[var(--_og-session-chrome-row-hover)]",
9214
10152
  children: [
9215
- /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-1.5", children: [
9216
- voice ? /* @__PURE__ */ jsx18(
10153
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-start gap-1.5", children: [
10154
+ voice ? /* @__PURE__ */ jsx20(
9217
10155
  AudioLinesIcon,
9218
10156
  {
9219
10157
  "aria-hidden": "true",
9220
10158
  className: "mt-0.5 size-3 shrink-0 text-og-accent"
9221
10159
  }
9222
- ) : /* @__PURE__ */ jsx18("span", { className: "mt-px shrink-0 font-og-mono text-[10px] leading-4 text-og-fg-subtle", children: index + 1 }),
9223
- /* @__PURE__ */ jsx18("p", { className: "min-w-0 flex-1 truncate text-og-xs leading-4 text-og-fg", children: presentation.text }),
9224
- showActions ? /* @__PURE__ */ jsxs13("div", { className: "flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100 max-sm:opacity-100", children: [
9225
- onMove && turns.length > 1 ? /* @__PURE__ */ jsxs13(Fragment6, { children: [
9226
- /* @__PURE__ */ jsx18(
10160
+ ) : /* @__PURE__ */ jsx20("span", { className: "mt-px shrink-0 font-og-mono text-[10px] leading-4 text-og-fg-subtle", children: index + 1 }),
10161
+ /* @__PURE__ */ jsx20("p", { className: "min-w-0 flex-1 truncate text-og-xs leading-4 text-og-fg", children: presentation.text }),
10162
+ showActions ? /* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100 max-sm:opacity-100", children: [
10163
+ onMove && turns.length > 1 ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
10164
+ /* @__PURE__ */ jsx20(
9227
10165
  IconAction,
9228
10166
  {
9229
10167
  label: `Move queued prompt ${index + 1} up`,
9230
10168
  tip: "Move up",
9231
10169
  disabled: settling || pending !== null || index === 0,
9232
10170
  onClick: () => onMove(turn.id, beforeUp),
9233
- children: /* @__PURE__ */ jsx18(ArrowUpIcon, { className: "size-3" })
10171
+ children: /* @__PURE__ */ jsx20(ArrowUpIcon, { className: "size-3" })
9234
10172
  }
9235
10173
  ),
9236
- /* @__PURE__ */ jsx18(
10174
+ /* @__PURE__ */ jsx20(
9237
10175
  IconAction,
9238
10176
  {
9239
10177
  label: `Move queued prompt ${index + 1} down`,
9240
10178
  tip: "Move down",
9241
10179
  disabled: settling || pending !== null || index >= turns.length - 1,
9242
10180
  onClick: () => onMove(turn.id, beforeDown),
9243
- children: /* @__PURE__ */ jsx18(ArrowDownIcon2, { className: "size-3" })
10181
+ children: /* @__PURE__ */ jsx20(ArrowDownIcon2, { className: "size-3" })
9244
10182
  }
9245
10183
  )
9246
10184
  ] }) : null,
9247
- onSteer ? /* @__PURE__ */ jsx18(
10185
+ onSteer ? /* @__PURE__ */ jsx20(
9248
10186
  IconAction,
9249
10187
  {
9250
10188
  label: `Steer queued prompt ${index + 1}`,
10189
+ text: "Steer",
9251
10190
  tip: QUEUE_STEER_TIP,
9252
10191
  disabled: settling || pending !== null,
9253
10192
  onClick: () => onSteer(turn.id),
9254
- children: pending === "steer" ? /* @__PURE__ */ jsx18(Loader2Icon2, { className: "size-3 animate-og-spin" }) : /* @__PURE__ */ jsx18(ZapIcon, { className: "size-3" })
10193
+ children: pending === "steer" ? /* @__PURE__ */ jsx20(Loader2Icon2, { className: "size-3 animate-og-spin" }) : /* @__PURE__ */ jsx20(CornerDownRightIcon, { className: "size-3" })
9255
10194
  }
9256
10195
  ) : null,
9257
- onEdit ? /* @__PURE__ */ jsx18(
10196
+ onEdit ? /* @__PURE__ */ jsx20(
9258
10197
  IconAction,
9259
10198
  {
9260
10199
  label: `Edit queued prompt ${index + 1}`,
9261
10200
  tip: QUEUE_EDIT_TIP,
9262
10201
  disabled: settling || pending !== null,
9263
10202
  onClick: () => onEdit(turn),
9264
- children: pending === "edit" ? /* @__PURE__ */ jsx18(Loader2Icon2, { className: "size-3 animate-og-spin" }) : /* @__PURE__ */ jsx18(PencilIcon, { className: "size-3" })
10203
+ children: pending === "edit" ? /* @__PURE__ */ jsx20(Loader2Icon2, { className: "size-3 animate-og-spin" }) : /* @__PURE__ */ jsx20(PencilIcon, { className: "size-3" })
9265
10204
  }
9266
10205
  ) : null,
9267
- onRemove ? /* @__PURE__ */ jsx18(
10206
+ onRemove ? /* @__PURE__ */ jsx20(
9268
10207
  IconAction,
9269
10208
  {
9270
10209
  label: `Remove queued prompt ${index + 1}`,
@@ -9272,16 +10211,16 @@ function QueuePanel({
9272
10211
  disabled: settling || pending !== null,
9273
10212
  onClick: () => onRemove(turn.id),
9274
10213
  danger: true,
9275
- children: pending === "delete" ? /* @__PURE__ */ jsx18(Loader2Icon2, { className: "size-3 animate-og-spin" }) : /* @__PURE__ */ jsx18(Trash2Icon2, { className: "size-3" })
10214
+ children: pending === "delete" ? /* @__PURE__ */ jsx20(Loader2Icon2, { className: "size-3 animate-og-spin" }) : /* @__PURE__ */ jsx20(Trash2Icon2, { className: "size-3" })
9276
10215
  }
9277
10216
  ) : null
9278
10217
  ] }) : null
9279
10218
  ] }),
9280
- confirmingReplace ? /* @__PURE__ */ jsxs13("div", { className: "rounded-og-sm border border-og-status-waiting/30 bg-og-status-waiting/10 p-2 text-og-xs text-og-fg", children: [
9281
- /* @__PURE__ */ jsx18("p", { children: "Your composer already has a draft. Replace it with this queued prompt?" }),
9282
- /* @__PURE__ */ jsx18("p", { className: "mt-0.5 text-og-fg-muted", children: "The current draft will be permanently discarded; this queued prompt is preserved until you confirm." }),
9283
- /* @__PURE__ */ jsxs13("div", { className: "mt-2 flex justify-end gap-1.5", children: [
9284
- /* @__PURE__ */ jsx18(
10219
+ confirmingReplace ? /* @__PURE__ */ jsxs15("div", { className: "rounded-og-sm border border-og-status-waiting/30 bg-og-status-waiting/10 p-2 text-og-xs text-og-fg", children: [
10220
+ /* @__PURE__ */ jsx20("p", { children: "Your composer already has a draft. Replace it with this queued prompt?" }),
10221
+ /* @__PURE__ */ jsx20("p", { className: "mt-0.5 text-og-fg-muted", children: "The current draft will be permanently discarded; this queued prompt is preserved until you confirm." }),
10222
+ /* @__PURE__ */ jsxs15("div", { className: "mt-2 flex justify-end gap-1.5", children: [
10223
+ /* @__PURE__ */ jsx20(
9285
10224
  "button",
9286
10225
  {
9287
10226
  type: "button",
@@ -9290,7 +10229,7 @@ function QueuePanel({
9290
10229
  children: "Keep current draft"
9291
10230
  }
9292
10231
  ),
9293
- /* @__PURE__ */ jsx18(
10232
+ /* @__PURE__ */ jsx20(
9294
10233
  "button",
9295
10234
  {
9296
10235
  type: "button",
@@ -9306,8 +10245,8 @@ function QueuePanel({
9306
10245
  turn.id
9307
10246
  );
9308
10247
  }),
9309
- /* @__PURE__ */ jsx18(AnimatePresence2, { initial: false, children: optimistic.map((message, index) => /* @__PURE__ */ jsxs13(
9310
- motion2.li,
10248
+ /* @__PURE__ */ jsx20(AnimatePresence2, { initial: false, children: optimistic.map((message, index) => /* @__PURE__ */ jsxs15(
10249
+ motion3.li,
9311
10250
  {
9312
10251
  "aria-live": "polite",
9313
10252
  "data-optimistic-queue-message": message.clientEventId,
@@ -9319,11 +10258,11 @@ function QueuePanel({
9319
10258
  message.state === "failed" ? "bg-og-danger/8 text-og-danger" : "bg-og-accent-soft/45"
9320
10259
  ),
9321
10260
  children: [
9322
- /* @__PURE__ */ jsx18("span", { className: "shrink-0 font-og-mono text-[10px] leading-4 text-og-fg-subtle", children: turns.length + index + 1 }),
9323
- /* @__PURE__ */ jsx18("p", { className: "min-w-0 flex-1 truncate text-og-xs leading-4 text-og-fg", children: message.text }),
9324
- /* @__PURE__ */ jsx18("span", { className: "sr-only", children: message.state === "failed" ? "Not confirmed" : message.state === "sending" ? "Placing in queue" : "Queued" }),
9325
- message.state === "failed" ? /* @__PURE__ */ jsxs13("div", { className: "flex shrink-0 items-center gap-1 text-[10px]", children: [
9326
- onRetryOptimistic ? /* @__PURE__ */ jsx18(
10261
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0 font-og-mono text-[10px] leading-4 text-og-fg-subtle", children: turns.length + index + 1 }),
10262
+ /* @__PURE__ */ jsx20("p", { className: "min-w-0 flex-1 truncate text-og-xs leading-4 text-og-fg", children: message.text }),
10263
+ /* @__PURE__ */ jsx20("span", { className: "sr-only", children: message.state === "failed" ? "Not confirmed" : message.state === "sending" ? "Placing in queue" : "Queued" }),
10264
+ message.state === "failed" ? /* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 items-center gap-1 text-[10px]", children: [
10265
+ onRetryOptimistic ? /* @__PURE__ */ jsx20(
9327
10266
  "button",
9328
10267
  {
9329
10268
  type: "button",
@@ -9332,36 +10271,36 @@ function QueuePanel({
9332
10271
  children: "Retry"
9333
10272
  }
9334
10273
  ) : null,
9335
- onRemoveOptimistic ? /* @__PURE__ */ jsx18(
10274
+ onRemoveOptimistic ? /* @__PURE__ */ jsx20(
9336
10275
  "button",
9337
10276
  {
9338
10277
  type: "button",
9339
10278
  "aria-label": "Dismiss unconfirmed queued prompt",
9340
10279
  className: "rounded-og-sm p-1 text-og-fg-muted hover:bg-og-surface-2 hover:text-og-fg pointer-coarse:min-h-11 pointer-coarse:min-w-11",
9341
10280
  onClick: () => onRemoveOptimistic(message.clientEventId),
9342
- children: /* @__PURE__ */ jsx18(XIcon, { className: "size-3" })
10281
+ children: /* @__PURE__ */ jsx20(XIcon, { className: "size-3" })
9343
10282
  }
9344
10283
  ) : null
9345
- ] }) : message.state === "sending" ? /* @__PURE__ */ jsx18(
10284
+ ] }) : message.state === "sending" ? /* @__PURE__ */ jsx20(
9346
10285
  Loader2Icon2,
9347
10286
  {
9348
10287
  "aria-hidden": "true",
9349
10288
  className: "size-3 shrink-0 animate-og-spin text-og-accent motion-reduce:animate-none"
9350
10289
  }
9351
- ) : /* @__PURE__ */ jsx18(CheckIcon3, { "aria-hidden": "true", className: "size-3 shrink-0 text-og-accent" })
10290
+ ) : /* @__PURE__ */ jsx20(CheckIcon3, { "aria-hidden": "true", className: "size-3 shrink-0 text-og-accent" })
9352
10291
  ]
9353
10292
  },
9354
10293
  message.clientEventId
9355
10294
  )) }),
9356
- loadError ? /* @__PURE__ */ jsxs13(
10295
+ loadError ? /* @__PURE__ */ jsxs15(
9357
10296
  "li",
9358
10297
  {
9359
10298
  role: "alert",
9360
10299
  className: "flex items-center gap-1.5 rounded-og-sm bg-og-danger/8 px-1.5 py-1 text-og-xs text-og-danger",
9361
10300
  children: [
9362
- /* @__PURE__ */ jsx18(TriangleAlertIcon3, { className: "size-3 shrink-0" }),
9363
- /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1", children: "Queue unavailable." }),
9364
- /* @__PURE__ */ jsx18(
10301
+ /* @__PURE__ */ jsx20(TriangleAlertIcon3, { className: "size-3 shrink-0" }),
10302
+ /* @__PURE__ */ jsx20("span", { className: "min-w-0 flex-1", children: "Queue unavailable." }),
10303
+ /* @__PURE__ */ jsx20(
9365
10304
  "button",
9366
10305
  {
9367
10306
  type: "button",
@@ -9373,15 +10312,15 @@ function QueuePanel({
9373
10312
  ]
9374
10313
  }
9375
10314
  ) : null,
9376
- mutationError ? /* @__PURE__ */ jsxs13(
10315
+ mutationError ? /* @__PURE__ */ jsxs15(
9377
10316
  "li",
9378
10317
  {
9379
10318
  role: "alert",
9380
10319
  className: "flex items-center gap-1.5 rounded-og-sm bg-og-danger/8 px-1.5 py-1 text-og-xs text-og-danger",
9381
10320
  children: [
9382
- /* @__PURE__ */ jsx18(TriangleAlertIcon3, { className: "size-3 shrink-0" }),
9383
- /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1", children: "Not confirmed. Check the queue before retrying." }),
9384
- /* @__PURE__ */ jsx18(
10321
+ /* @__PURE__ */ jsx20(TriangleAlertIcon3, { className: "size-3 shrink-0" }),
10322
+ /* @__PURE__ */ jsx20("span", { className: "min-w-0 flex-1", children: "Not confirmed. Check the queue before retrying." }),
10323
+ /* @__PURE__ */ jsx20(
9385
10324
  "button",
9386
10325
  {
9387
10326
  type: "button",
@@ -9407,25 +10346,26 @@ function GoalPanel({
9407
10346
  if (!record) return null;
9408
10347
  const canToggle = !readOnly && (record.status === "active" || record.status === "paused");
9409
10348
  const explanation = sessionChromeGoalPillExplanation(state, record);
9410
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-1.5", "data-og-session-chrome-panel": "goal", children: [
9411
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-1.5 text-[10px] font-medium uppercase tracking-wider text-og-fg-subtle", children: [
9412
- /* @__PURE__ */ jsx18("span", { children: sessionChromeGoalPillLabel(state, record) }),
9413
- elapsed ? /* @__PURE__ */ jsxs13("span", { className: "tabular-nums normal-case tracking-normal text-og-fg-muted", children: [
9414
- "\xB7 ",
9415
- elapsed
10349
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-1.5", "data-og-session-chrome-panel": "goal", children: [
10350
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center gap-1.5 text-[10px] font-medium uppercase tracking-wider text-og-fg-subtle", children: [
10351
+ /* @__PURE__ */ jsx20("span", { children: sessionChromeGoalPillLabel(state, record) }),
10352
+ elapsed ? /* @__PURE__ */ jsxs15("span", { className: "tabular-nums normal-case tracking-normal text-og-fg-muted", children: [
10353
+ "\xB7 Created ",
10354
+ elapsed,
10355
+ " ago"
9416
10356
  ] }) : null,
9417
- /* @__PURE__ */ jsxs13("span", { className: "normal-case tracking-normal text-og-fg-muted", children: [
10357
+ /* @__PURE__ */ jsxs15("span", { className: "normal-case tracking-normal text-og-fg-muted", children: [
9418
10358
  "\xB7 v",
9419
10359
  record.version
9420
10360
  ] })
9421
10361
  ] }),
9422
- /* @__PURE__ */ jsx18("p", { className: "text-og-sm leading-5 text-og-fg", children: record.text }),
9423
- record.successCriteria ? /* @__PURE__ */ jsxs13("p", { className: "text-og-xs leading-4 text-og-fg-muted", children: [
9424
- /* @__PURE__ */ jsx18("span", { className: "font-medium text-og-fg", children: "Done when" }),
10362
+ /* @__PURE__ */ jsx20("p", { className: "text-og-sm leading-5 text-og-fg", children: record.text }),
10363
+ record.successCriteria ? /* @__PURE__ */ jsxs15("p", { className: "text-og-xs leading-4 text-og-fg-muted", children: [
10364
+ /* @__PURE__ */ jsx20("span", { className: "font-medium text-og-fg", children: "Done when" }),
9425
10365
  " ",
9426
10366
  record.successCriteria
9427
10367
  ] }) : null,
9428
- explanation ? /* @__PURE__ */ jsx18(
10368
+ explanation ? /* @__PURE__ */ jsx20(
9429
10369
  "p",
9430
10370
  {
9431
10371
  "data-og-session-chrome-goal-explanation": true,
@@ -9433,20 +10373,20 @@ function GoalPanel({
9433
10373
  children: explanation
9434
10374
  }
9435
10375
  ) : null,
9436
- record.continuation?.lastError ? /* @__PURE__ */ jsx18("p", { className: "rounded-og-sm bg-og-status-waiting/10 px-1.5 py-1 text-og-xs leading-4 text-og-status-waiting", children: record.continuation.lastError }) : null,
9437
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center justify-between gap-1.5 pt-0.5", children: [
9438
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap gap-1 text-[10px] text-og-fg-muted", children: [
9439
- /* @__PURE__ */ jsxs13("span", { className: "rounded bg-og-surface-3/70 px-1 py-px", children: [
10376
+ record.continuation?.lastError ? /* @__PURE__ */ jsx20("p", { className: "rounded-og-sm bg-og-status-waiting/10 px-1.5 py-1 text-og-xs leading-4 text-og-status-waiting", children: record.continuation.lastError }) : null,
10377
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center justify-between gap-1.5 pt-0.5", children: [
10378
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap gap-1 text-[10px] text-og-fg-muted", children: [
10379
+ /* @__PURE__ */ jsxs15("span", { className: "rounded bg-og-surface-3/70 px-1 py-px", children: [
9440
10380
  record.autoContinuations,
9441
10381
  " consecutive unattended continues"
9442
10382
  ] }),
9443
- /* @__PURE__ */ jsxs13("span", { className: "rounded bg-og-surface-3/70 px-1 py-px", children: [
10383
+ /* @__PURE__ */ jsxs15("span", { className: "rounded bg-og-surface-3/70 px-1 py-px", children: [
9444
10384
  record.noProgressStreak,
9445
10385
  " stalled"
9446
10386
  ] })
9447
10387
  ] }),
9448
- !readOnly ? /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-0.5", children: [
9449
- canToggle ? /* @__PURE__ */ jsxs13(
10388
+ !readOnly ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-0.5", children: [
10389
+ canToggle ? /* @__PURE__ */ jsxs15(
9450
10390
  "button",
9451
10391
  {
9452
10392
  type: "button",
@@ -9454,12 +10394,12 @@ function GoalPanel({
9454
10394
  onClick: () => void (record.status === "paused" ? goal.resume() : goal.pause("Paused from session chrome")),
9455
10395
  className: "inline-flex h-6 items-center gap-1 rounded-og-sm px-1.5 text-og-xs font-medium text-og-fg-muted outline-hidden transition-colors hover:bg-og-surface-3/70 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:opacity-50",
9456
10396
  children: [
9457
- goal.updating ? /* @__PURE__ */ jsx18(Loader2Icon2, { className: "size-3 animate-og-spin" }) : record.status === "paused" ? /* @__PURE__ */ jsx18(PlayIcon2, { className: "size-3" }) : /* @__PURE__ */ jsx18(PauseIcon2, { className: "size-3" }),
10397
+ goal.updating ? /* @__PURE__ */ jsx20(Loader2Icon2, { className: "size-3 animate-og-spin" }) : record.status === "paused" ? /* @__PURE__ */ jsx20(PlayIcon2, { className: "size-3" }) : /* @__PURE__ */ jsx20(PauseIcon2, { className: "size-3" }),
9458
10398
  record.status === "paused" ? "Resume" : "Pause"
9459
10399
  ]
9460
10400
  }
9461
10401
  ) : null,
9462
- /* @__PURE__ */ jsxs13(
10402
+ /* @__PURE__ */ jsxs15(
9463
10403
  "button",
9464
10404
  {
9465
10405
  type: "button",
@@ -9467,7 +10407,7 @@ function GoalPanel({
9467
10407
  onClick: () => void goal.deleteGoal(),
9468
10408
  className: "inline-flex h-6 items-center gap-1 rounded-og-sm px-1.5 text-og-xs font-medium text-og-fg-subtle outline-hidden transition-colors hover:bg-og-surface-3/70 hover:text-og-danger focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:opacity-50",
9469
10409
  children: [
9470
- /* @__PURE__ */ jsx18(Trash2Icon2, { className: "size-3" }),
10410
+ /* @__PURE__ */ jsx20(Trash2Icon2, { className: "size-3" }),
9471
10411
  "Clear"
9472
10412
  ]
9473
10413
  }
@@ -9476,13 +10416,14 @@ function GoalPanel({
9476
10416
  ] })
9477
10417
  ] });
9478
10418
  }
9479
- var QUEUE_STEER_TIP = /* @__PURE__ */ jsxs13("span", { className: "flex flex-col gap-0.5 text-left", children: [
9480
- /* @__PURE__ */ jsx18("span", { className: "font-medium", children: "Steer" }),
9481
- /* @__PURE__ */ jsx18("span", { className: "opacity-80", children: "Interrupt the current turn and send this message now" })
10419
+ var QUEUE_STEER_TIP = /* @__PURE__ */ jsxs15("span", { className: "flex flex-col gap-0.5 text-left", children: [
10420
+ /* @__PURE__ */ jsx20("span", { className: "font-medium", children: "Steer" }),
10421
+ /* @__PURE__ */ jsx20("span", { className: "opacity-80", children: "Interrupt the current turn and send this message now" })
9482
10422
  ] });
9483
10423
  var QUEUE_EDIT_TIP = "Edit in composer";
9484
10424
  var QUEUE_DELETE_TIP = "Delete this queued prompt";
9485
10425
  function IconAction({
10426
+ text,
9486
10427
  label,
9487
10428
  tip,
9488
10429
  onClick,
@@ -9490,8 +10431,8 @@ function IconAction({
9490
10431
  danger,
9491
10432
  children
9492
10433
  }) {
9493
- return /* @__PURE__ */ jsxs13(Tooltip, { children: [
9494
- /* @__PURE__ */ jsx18(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx18(
10434
+ return /* @__PURE__ */ jsxs15(Tooltip, { children: [
10435
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs15(
9495
10436
  "button",
9496
10437
  {
9497
10438
  type: "button",
@@ -9499,15 +10440,110 @@ function IconAction({
9499
10440
  disabled,
9500
10441
  onClick,
9501
10442
  className: cn(
9502
- "inline-flex size-6 items-center justify-center rounded-og-sm text-og-fg-subtle outline-hidden transition-colors",
10443
+ "inline-flex size-6 items-center justify-center rounded-og-sm outline-hidden transition-colors",
9503
10444
  "hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40",
9504
10445
  "disabled:pointer-events-none disabled:opacity-40 pointer-coarse:size-9",
10446
+ text ? "text-og-fg" : "text-og-fg-subtle",
10447
+ text && "w-auto gap-1 px-1.5 text-og-xs pointer-coarse:w-auto",
9505
10448
  danger && "hover:text-og-danger"
9506
10449
  ),
9507
- children
10450
+ children: [
10451
+ children,
10452
+ text
10453
+ ]
9508
10454
  }
9509
10455
  ) }),
9510
- /* @__PURE__ */ jsx18(TooltipContent, { side: "top", children: tip })
10456
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "top", children: tip })
10457
+ ] });
10458
+ }
10459
+
10460
+ // src/components/session-commands-panel.tsx
10461
+ import { ChevronRightIcon as ChevronRightIcon4, Loader2Icon as Loader2Icon3, SquareIcon } from "lucide-react";
10462
+ import { useState as useState14 } from "react";
10463
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
10464
+ function SessionCommandsPanel({
10465
+ commands: state,
10466
+ readOnly = false
10467
+ }) {
10468
+ const [pending, setPending] = useState14(null);
10469
+ const [error, setError] = useState14(null);
10470
+ const active = state.commands.filter(
10471
+ (command) => command.state === "running" || command.state === "stopping"
10472
+ );
10473
+ const stop = async (id) => {
10474
+ setPending(id);
10475
+ setError(null);
10476
+ try {
10477
+ await state.cancel(id);
10478
+ } catch (cause) {
10479
+ setError(cause instanceof Error ? cause.message : "Stop was not confirmed. Try again.");
10480
+ } finally {
10481
+ setPending(null);
10482
+ }
10483
+ };
10484
+ return /* @__PURE__ */ jsxs16("div", { className: "space-y-2 text-og-xs", "data-og-session-commands": "", children: [
10485
+ state.loading && active.length === 0 ? /* @__PURE__ */ jsx21("p", { role: "status", className: "text-og-fg-muted", children: "Loading commands\u2026" }) : null,
10486
+ state.error ? /* @__PURE__ */ jsxs16("div", { role: "alert", className: "flex items-center justify-between gap-2 text-og-danger", children: [
10487
+ /* @__PURE__ */ jsx21("span", { children: "Commands unavailable." }),
10488
+ /* @__PURE__ */ jsx21(
10489
+ "button",
10490
+ {
10491
+ type: "button",
10492
+ className: "underline outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/40",
10493
+ onClick: () => void state.refresh(),
10494
+ children: "Retry"
10495
+ }
10496
+ )
10497
+ ] }) : null,
10498
+ !state.loading && !state.error && active.length === 0 ? /* @__PURE__ */ jsx21("p", { role: "status", className: "text-og-fg-muted", children: "No background commands running." }) : null,
10499
+ active.length > 0 ? /* @__PURE__ */ jsx21("ul", { className: "max-h-64 overflow-y-auto overscroll-contain divide-y divide-og-border/40", children: active.map((command) => /* @__PURE__ */ jsxs16("li", { className: "flex items-start gap-3 py-2 first:pt-0 last:pb-0", children: [
10500
+ /* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1", children: [
10501
+ /* @__PURE__ */ jsxs16("details", { className: "group/command", children: [
10502
+ /* @__PURE__ */ jsxs16(
10503
+ "summary",
10504
+ {
10505
+ className: "flex cursor-pointer list-none items-center gap-1.5 rounded-og-sm font-mono text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/40",
10506
+ title: "Expand command",
10507
+ children: [
10508
+ /* @__PURE__ */ jsx21(ChevronRightIcon4, { className: "size-3 shrink-0 text-og-fg-subtle transition-transform group-open/command:rotate-90" }),
10509
+ /* @__PURE__ */ jsx21("span", { className: "truncate", children: command.commandPreview || "Background command" })
10510
+ ]
10511
+ }
10512
+ ),
10513
+ /* @__PURE__ */ jsxs16("div", { className: "mt-2 space-y-1", children: [
10514
+ /* @__PURE__ */ jsx21("p", { className: "whitespace-pre-wrap break-all font-mono text-og-fg-muted", children: command.commandPreview || "Background command" }),
10515
+ /* @__PURE__ */ jsxs16(
10516
+ "time",
10517
+ {
10518
+ className: "block text-og-fg-subtle",
10519
+ dateTime: command.startedAt,
10520
+ title: new Date(command.startedAt).toLocaleString(),
10521
+ children: [
10522
+ "Started ",
10523
+ formatClockTime(command.startedAt)
10524
+ ]
10525
+ }
10526
+ )
10527
+ ] })
10528
+ ] }),
10529
+ /* @__PURE__ */ jsx21("p", { className: "mt-1 text-og-fg-subtle", children: command.state === "stopping" ? "Stopping\u2026" : "Running" })
10530
+ ] }),
10531
+ !readOnly ? /* @__PURE__ */ jsxs16(
10532
+ "button",
10533
+ {
10534
+ type: "button",
10535
+ "aria-label": `Stop ${command.commandPreview || "background command"}`,
10536
+ disabled: pending !== null || command.state === "stopping",
10537
+ onClick: () => void stop(command.id),
10538
+ className: "inline-flex min-h-7 shrink-0 items-center gap-1 rounded-og-sm px-2 text-og-fg-muted outline-hidden hover:bg-og-surface-3/70 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:opacity-50 pointer-coarse:min-h-11",
10539
+ children: [
10540
+ pending === command.id || command.state === "stopping" ? /* @__PURE__ */ jsx21(Loader2Icon3, { className: "size-3 animate-og-spin motion-reduce:animate-none" }) : /* @__PURE__ */ jsx21(SquareIcon, { className: "size-3" }),
10541
+ "Stop"
10542
+ ]
10543
+ }
10544
+ ) : null
10545
+ ] }, command.id)) }) : null,
10546
+ error ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "text-og-danger", children: error }) : null
9511
10547
  ] });
9512
10548
  }
9513
10549
 
@@ -9565,9 +10601,14 @@ export {
9565
10601
  MessageTimeline,
9566
10602
  TimelineRow,
9567
10603
  QueueSurface,
10604
+ useAvailableModels,
10605
+ useWorkspaceModelCatalog,
10606
+ ChatComposer,
10607
+ SessionConversation,
9568
10608
  sessionChromeGoalPillLabel,
9569
10609
  sessionChromeGoalPillExplanation,
9570
10610
  sessionChromeGoalPillState,
9571
- SessionChrome
10611
+ SessionChrome,
10612
+ SessionCommandsPanel
9572
10613
  };
9573
- //# sourceMappingURL=chunk-WY3MELVJ.js.map
10614
+ //# sourceMappingURL=chunk-5IXTJTK3.js.map