@workerdeck/ui 0.23.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/build/{SessionPanel-DUt2VzXG.mjs → SessionPanel-DDgBkHsi.mjs} +2151 -3357
  2. package/build/SessionPanel-DDgBkHsi.mjs.map +1 -0
  3. package/build/SessionPanel-E_L_ldQ5.d.mts +207 -0
  4. package/build/format-B8ZM9LPy.d.mts +16 -0
  5. package/build/format.d.mts +8 -75
  6. package/build/format.mjs +2 -2
  7. package/build/index.d.mts +63 -1138
  8. package/build/index.mjs +4 -300
  9. package/build/index.mjs.map +1 -1
  10. package/build/scoped.css +15 -23
  11. package/build/{status-BE-zg88x.mjs → status-C0HSLZas.mjs} +14 -85
  12. package/build/status-C0HSLZas.mjs.map +1 -0
  13. package/build/workspace.d.mts +5 -126
  14. package/build/workspace.mjs +11 -143
  15. package/build/workspace.mjs.map +1 -1
  16. package/package.json +4 -4
  17. package/src/components/agent/CodeEditor.tsx +31 -103
  18. package/src/components/agent/Composer.tsx +114 -333
  19. package/src/components/agent/ContextDialog.tsx +20 -41
  20. package/src/components/agent/ContextRing.tsx +6 -28
  21. package/src/components/agent/Conversation.tsx +21 -33
  22. package/src/components/agent/EditorTabs.tsx +39 -67
  23. package/src/components/agent/EngineIcon.tsx +29 -72
  24. package/src/components/agent/EntryIcon.tsx +16 -0
  25. package/src/components/agent/FileCard.tsx +10 -16
  26. package/src/components/agent/FileTree.tsx +52 -125
  27. package/src/components/agent/FileViewer.tsx +30 -60
  28. package/src/components/agent/HostFilesDialog.tsx +40 -69
  29. package/src/components/agent/Loader.tsx +3 -24
  30. package/src/components/agent/McpDialog.tsx +64 -137
  31. package/src/components/agent/Message.tsx +2 -21
  32. package/src/components/agent/ModelSelect.tsx +33 -62
  33. package/src/components/agent/PermissionModeSelect.tsx +21 -79
  34. package/src/components/agent/PermissionPrompt.tsx +59 -63
  35. package/src/components/agent/ProjectIcon.tsx +228 -93
  36. package/src/components/agent/PromptTokenText.tsx +10 -16
  37. package/src/components/agent/QuestionPrompt.tsx +43 -64
  38. package/src/components/agent/Reasoning.tsx +13 -16
  39. package/src/components/agent/Response.tsx +3 -9
  40. package/src/components/agent/Scrubber.tsx +31 -80
  41. package/src/components/agent/SessionBrowser.tsx +64 -243
  42. package/src/components/agent/SessionEmptyState.tsx +10 -40
  43. package/src/components/agent/SessionInfoDialog.tsx +46 -78
  44. package/src/components/agent/SessionItem.tsx +53 -320
  45. package/src/components/agent/SessionList.tsx +23 -39
  46. package/src/components/agent/SessionPanel.tsx +315 -996
  47. package/src/components/agent/SessionStatusIcon.tsx +14 -28
  48. package/src/components/agent/SessionSteps.tsx +34 -187
  49. package/src/components/agent/SessionWorkspace.tsx +104 -219
  50. package/src/components/agent/SkillsDialog.tsx +35 -80
  51. package/src/components/agent/StatusBar.tsx +51 -136
  52. package/src/components/agent/SubagentStrip.tsx +12 -77
  53. package/src/components/agent/ToolCallCard.tsx +94 -135
  54. package/src/components/agent/Transcript.tsx +103 -1288
  55. package/src/components/agent/TranscriptItemView.tsx +155 -0
  56. package/src/components/agent/TranscriptRows.tsx +418 -0
  57. package/src/components/agent/UsageDialog.tsx +7 -29
  58. package/src/components/agent/UsageMeters.tsx +18 -73
  59. package/src/components/agent/pulse.tsx +9 -32
  60. package/src/components/agent/scrubber-marks.ts +33 -103
  61. package/src/components/agent/status.ts +1 -5
  62. package/src/components/agent/tool-result-fetch.tsx +3 -25
  63. package/src/components/agent/tool-result-image.tsx +32 -111
  64. package/src/components/agent/transcript-rows.ts +41 -118
  65. package/src/components/agent/transcript-variant.tsx +3 -80
  66. package/src/components/agent/use-height-epoch.ts +10 -24
  67. package/src/components/agent/use-path-links.ts +45 -63
  68. package/src/components/agent/use-subagent-frame.ts +106 -0
  69. package/src/components/agent/use-transcript-jumps.ts +49 -107
  70. package/src/components/prompt-area/animated-placeholder.tsx +6 -5
  71. package/src/components/prompt-area/clipboard-helpers.ts +26 -21
  72. package/src/components/prompt-area/cursor-helpers.ts +79 -37
  73. package/src/components/prompt-area/dom-helpers.ts +97 -69
  74. package/src/components/prompt-area/file-strip.tsx +90 -80
  75. package/src/components/prompt-area/html-to-markdown.ts +67 -46
  76. package/src/components/prompt-area/image-strip.tsx +8 -18
  77. package/src/components/prompt-area/index.ts +2 -15
  78. package/src/components/prompt-area/prompt-area-engine.ts +100 -115
  79. package/src/components/prompt-area/prompt-area-list-ops.ts +66 -59
  80. package/src/components/prompt-area/prompt-area.tsx +31 -38
  81. package/src/components/prompt-area/remove-button.tsx +3 -9
  82. package/src/components/prompt-area/segment-helpers.ts +4 -12
  83. package/src/components/prompt-area/trigger-popover.tsx +15 -27
  84. package/src/components/prompt-area/trigger-presets.ts +0 -10
  85. package/src/components/prompt-area/types.ts +3 -8
  86. package/src/components/prompt-area/use-chip-editing.ts +305 -0
  87. package/src/components/prompt-area/use-markdown-mode.ts +7 -17
  88. package/src/components/prompt-area/use-prompt-area-events.ts +80 -86
  89. package/src/components/prompt-area/use-prompt-area-keydown.ts +598 -0
  90. package/src/components/prompt-area/use-prompt-area-state.ts +5 -23
  91. package/src/components/prompt-area/use-prompt-area.ts +170 -896
  92. package/src/components/prompt-area/use-trigger-search.ts +21 -19
  93. package/src/components/terminal/PermissionPrompt.tsx +56 -59
  94. package/src/components/terminal/QuestionPrompt.tsx +28 -79
  95. package/src/components/terminal/StatusLine.tsx +13 -63
  96. package/src/components/terminal/TerminalTranscript.tsx +44 -160
  97. package/src/components/terminal/affordances.tsx +68 -98
  98. package/src/components/terminal/blocks.ts +20 -156
  99. package/src/components/terminal/diff.tsx +19 -67
  100. package/src/components/terminal/height.ts +163 -313
  101. package/src/components/terminal/image-box.ts +0 -44
  102. package/src/components/terminal/items.tsx +150 -305
  103. package/src/components/terminal/markdown.tsx +36 -95
  104. package/src/components/terminal/press.tsx +26 -53
  105. package/src/components/terminal/prompt.tsx +40 -170
  106. package/src/components/terminal/result-preview.ts +8 -56
  107. package/src/components/terminal/row.tsx +11 -98
  108. package/src/components/terminal/scrubber.tsx +108 -401
  109. package/src/components/terminal/surface.tsx +6 -54
  110. package/src/components/terminal/todos.ts +66 -0
  111. package/src/components/terminal/tool-run.ts +21 -192
  112. package/src/components/ui/AlertDialog.tsx +8 -23
  113. package/src/components/ui/Badge.tsx +18 -29
  114. package/src/components/ui/Button.tsx +7 -15
  115. package/src/components/ui/Card.tsx +2 -13
  116. package/src/components/ui/CodeBlock.tsx +10 -37
  117. package/src/components/ui/CopyButton.tsx +10 -23
  118. package/src/components/ui/Dialog.tsx +23 -36
  119. package/src/components/ui/Empty.tsx +6 -29
  120. package/src/components/ui/Input.tsx +14 -16
  121. package/src/components/ui/Menu.tsx +6 -18
  122. package/src/components/ui/PortalScope.tsx +1 -21
  123. package/src/components/ui/ProgressRing.tsx +8 -19
  124. package/src/components/ui/Select.tsx +18 -31
  125. package/src/components/ui/Sonner.tsx +1 -2
  126. package/src/components/ui/Spinner.tsx +1 -1
  127. package/src/components/ui/Splitter.tsx +30 -64
  128. package/src/components/ui/Textarea.tsx +2 -5
  129. package/src/components/ui/Tooltip.tsx +3 -13
  130. package/src/format.ts +0 -9
  131. package/src/index.ts +16 -113
  132. package/src/lib/clipboard.ts +8 -28
  133. package/src/lib/css.ts +8 -0
  134. package/src/lib/format.ts +101 -86
  135. package/src/lib/plan-request.ts +16 -0
  136. package/src/lib/status.ts +45 -95
  137. package/src/lib/tool-icon.ts +39 -47
  138. package/src/lib/utils.ts +1 -3
  139. package/src/styles/terminal.css +81 -49
  140. package/src/styles/theme.css +96 -32
  141. package/src/workspace.ts +1 -24
  142. package/build/SessionPanel-BobynUo4.d.mts +0 -669
  143. package/build/SessionPanel-DUt2VzXG.mjs.map +0 -1
  144. package/build/format-ljc3lKpA.d.mts +0 -59
  145. package/build/status-BE-zg88x.mjs.map +0 -1
package/build/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-ljc3lKpA.mjs";
2
- import { C as permissionModeChoices, S as PermissionModeSelectProps, _ as useAffordances, a as SessionVitals, b as PermissionModeMeta, c as TranscriptDensityProvider, d as TranscriptVariantProvider, f as useTranscriptDensity, g as WithActions, h as TerminalAffordances, i as SessionSurfacePanel, l as TranscriptFont, m as CopyAction, n as SessionPanel, o as TerminalMetrics, p as useTranscriptVariant, r as SessionPanelProps, s as TranscriptDensity, t as SessionControls, u as TranscriptVariant, v as PERMISSION_MODES, w as permissionModeMeta, x as PermissionModeSelect, y as PermissionModeChoice } from "./SessionPanel-BobynUo4.mjs";
1
+ import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-B8ZM9LPy.mjs";
2
+ import { C as permissionModeChoices, S as PermissionModeSelectProps, _ as useAffordances, a as SessionVitals, b as PermissionModeMeta, c as TranscriptDensityProvider, d as TranscriptVariantProvider, f as useTranscriptDensity, g as WithActions, h as TerminalAffordances, i as SessionSurfacePanel, l as TranscriptFont, m as CopyAction, n as SessionPanel, o as TerminalMetrics, p as useTranscriptVariant, r as SessionPanelProps, s as TranscriptDensity, t as SessionControls, u as TranscriptVariant, v as PERMISSION_MODES, w as permissionModeMeta, x as PermissionModeSelect, y as PermissionModeChoice } from "./SessionPanel-E_L_ldQ5.mjs";
3
3
  import * as _$react from "react";
4
4
  import { ButtonHTMLAttributes, FunctionComponent, HTMLAttributes, InputHTMLAttributes, ReactElement, ReactNode, Ref, RefObject, TextareaHTMLAttributes } from "react";
5
5
  import { VariantProps } from "class-variance-authority";
@@ -34,7 +34,6 @@ declare const badgeVariants: (props?: ({
34
34
  mono?: boolean | null | undefined;
35
35
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
36
36
  interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
37
- /** Render a leading status dot in the variant's color. */
38
37
  dot?: boolean;
39
38
  }
40
39
  declare function Badge({
@@ -99,25 +98,15 @@ declare const MenuSeparator: FunctionComponent<Menu$1.Separator.Props>;
99
98
  declare const Dialog: typeof Dialog$1.Root;
100
99
  declare const DialogTrigger: Dialog$1.Trigger;
101
100
  declare const DialogClose: _$react.ForwardRefExoticComponent<Omit<_$_base_ui_react_dialog0.DialogCloseProps, "ref"> & _$react.RefAttributes<HTMLButtonElement>>;
102
- /**
103
- * A dismissible panel, sized for reading rather than confirming — the web
104
- * counterpart of the iOS app's detail sheets (context, usage, session info, MCP).
105
- *
106
- * Taller than {@link AlertDialogContent} and scrollable inside, because these
107
- * carry lists whose length is the engine's business, not the layout's.
108
- */
109
101
  declare const DialogContent: FunctionComponent<Dialog$1.Popup.Props & {
110
102
  size?: 'sm' | 'md' | 'lg';
111
103
  }>;
112
- /** Title row with the close button, pinned above the scrolling body. */
113
104
  declare const DialogHeader: FunctionComponent<{
114
105
  title: string;
115
- description?: string; /** Rendered between the title and the close button. */
106
+ description?: string;
116
107
  actions?: React.ReactNode;
117
108
  }>;
118
- /** The scrolling region under the header. */
119
109
  declare const DialogBody: FunctionComponent<React.HTMLAttributes<HTMLDivElement>>;
120
- /** A label/value row — the shape every one of these panels is mostly made of. */
121
110
  declare const DialogRow: FunctionComponent<{
122
111
  label: string;
123
112
  children: React.ReactNode;
@@ -127,14 +116,6 @@ declare const DialogRow: FunctionComponent<{
127
116
  //#region src/components/ui/Tooltip.d.ts
128
117
  declare const TooltipProvider: _$react.FC<_$_base_ui_react_tooltip0.TooltipProviderProps>;
129
118
  declare const TooltipContent: FunctionComponent<Tooltip.Popup.Props & Pick<Tooltip.Positioner.Props, 'side' | 'sideOffset'>>;
130
- /**
131
- * Convenience wrapper: `<Tip content="..."><Button/></Tip>`.
132
- *
133
- * Pass `render` when the trigger must *be* an element you already have — a tab, a
134
- * row — rather than something wrapped in a span. The default span is fine beside
135
- * a button but would break any layout that styles its own children (a flex tab
136
- * strip gets an extra box between the container and its items).
137
- */
138
119
  declare function Tip({
139
120
  content,
140
121
  render,
@@ -148,14 +129,11 @@ declare function Tip({
148
129
  }): _$react.JSX.Element;
149
130
  //#endregion
150
131
  //#region src/components/ui/Sonner.d.ts
151
- /** Token-themed toaster; relies on the [data-theme] swap, so no `theme` prop needed. */
152
132
  declare function Toaster(): _$react.JSX.Element;
153
133
  //#endregion
154
134
  //#region src/components/ui/CopyButton.d.ts
155
135
  interface CopyButtonProps extends Omit<ButtonProps, 'onClick' | 'children'> {
156
136
  value: string;
157
- /** Draw the state as characters (`⧉` / `✓`) rather than line-art icons — for
158
- * terminal-styled surfaces, where an SVG reads as another app's button. */
159
137
  glyph?: boolean;
160
138
  }
161
139
  declare function CopyButton({
@@ -177,24 +155,11 @@ declare function Spinner({
177
155
  //#region src/components/ui/CodeBlock.d.ts
178
156
  interface CodeBlockProps {
179
157
  code: string;
180
- /** Header label, e.g. a language or "Parameters". */
181
158
  label?: ReactNode;
182
159
  copyable?: boolean;
183
- /**
184
- * `'panel'` (default) is the framed card: border, header strip, rounded.
185
- * `'plain'` is the terminal treatment — the label is a dim line, the code a
186
- * flat band, and copy is a character. For surfaces where a box around every
187
- * payload is more chrome than content (the transcript's `lines` variant).
188
- *
189
- * A prop rather than a read of the transcript's variant context: this is a
190
- * `ui/` primitive and has no business knowing what a transcript is. The agent
191
- * component that renders it does.
192
- */
193
160
  variant?: 'panel' | 'plain';
194
161
  className?: string;
195
162
  }
196
- /** Plain (unhighlighted) code panel for structured data like tool inputs. Markdown code
197
- * inside assistant responses is highlighted by <Response> instead. */
198
163
  declare function CodeBlock({
199
164
  code,
200
165
  label,
@@ -205,49 +170,17 @@ declare function CodeBlock({
205
170
  //#endregion
206
171
  //#region src/components/ui/Splitter.d.ts
207
172
  interface SplitterProps {
208
- /**
209
- * ARIA's sense of the word: a `vertical` splitter is a vertical bar between
210
- * two side-by-side panes, and it resizes a **width**. A `horizontal` one sits
211
- * between stacked panes and resizes a **height**.
212
- */
213
173
  orientation: 'vertical' | 'horizontal';
214
- /** Current size of the pane this splitter controls, in pixels. */
215
174
  value: number;
216
175
  onValueChange: (value: number) => void;
217
176
  min: number;
218
177
  max: number;
219
- /** Keyboard step. */
220
178
  step?: number;
221
- /**
222
- * Size to snap back to on a double-click — the convention every pane divider
223
- * that can be dragged is expected to honour. Omit and a double-click does
224
- * nothing, which is the honest behaviour when there is no default to mean.
225
- */
226
179
  defaultValue?: number;
227
- /** Set when dragging the splitter *away* from the origin should shrink the
228
- * controlled pane — i.e. the pane is on the right or the bottom. */
229
180
  inverted?: boolean;
230
- /** Required: "Resize" alone does not say which of two splitters this is. */
231
181
  'aria-label': string;
232
182
  className?: string;
233
183
  }
234
- /**
235
- * A draggable pane divider.
236
- *
237
- * Hand-rolled rather than depended on: `@base-ui/react` ships no splitter, the
238
- * behaviour is a hundred lines of pointer events, and this repo's instinct at
239
- * this layer is to own it (the composer is vendored for the same reason).
240
- *
241
- * Pointer capture is what makes it survive a fast drag — without it the pointer
242
- * leaves the 5px bar within a frame and the moves go to whatever is underneath,
243
- * which for this layout is an iframe-free but still selection-happy code pane.
244
- * The drag origin is captured on pointerdown and every move is measured against
245
- * it, so the pane cannot drift relative to the cursor over a long drag the way
246
- * per-move deltas do once clamping is involved.
247
- *
248
- * Keyboard-operable and announced as a separator, because a pane you can only
249
- * size by dragging is a pane some people cannot size.
250
- */
251
184
  declare function Splitter({
252
185
  orientation,
253
186
  value,
@@ -262,22 +195,6 @@ declare function Splitter({
262
195
  }: SplitterProps): _$react.JSX.Element;
263
196
  //#endregion
264
197
  //#region src/components/ui/Empty.d.ts
265
- /**
266
- * A view with nothing in it: icon, title, description, and at most one action.
267
- *
268
- * Centered and given room, because an empty view is the first thing a new
269
- * install shows and a flush-left sentence in the top corner reads like a bug
270
- * report. It lives here rather than in one client because every panel that can
271
- * be empty should be empty the same way — the extension's views and the
272
- * dashboard's four sidebars are the same shape of thing.
273
- *
274
- * **At most one action, and never one the view header already offers.** Creating
275
- * a session and adding a gateway are the `+` in the native title bar, exclusively
276
- * — so those empty states point at it in words rather than growing a second
277
- * button that does the same thing two inches lower. A button here is for the way
278
- * out of a state the header has no answer to: clearing a filter, widening a
279
- * scope.
280
- */
281
198
  declare function Empty({
282
199
  icon,
283
200
  title,
@@ -291,7 +208,6 @@ declare function Empty({
291
208
  action?: string;
292
209
  onAction?: () => void;
293
210
  }): _$react.JSX.Element;
294
- /** A key or icon named inline in an empty state's description — "use the + above". */
295
211
  declare function EmptyKey({
296
212
  children
297
213
  }: {
@@ -300,15 +216,11 @@ declare function EmptyKey({
300
216
  //#endregion
301
217
  //#region src/components/ui/ProgressRing.d.ts
302
218
  interface ProgressRingProps {
303
- /** Filled share, 0–100 (clamped). */
304
219
  value: number;
305
- /** Outer diameter in px. */
306
220
  size?: number;
307
221
  strokeWidth?: number;
308
222
  className?: string;
309
223
  }
310
- /** Tiny SVG progress circle; stroke color comes from `currentColor` so callers set it
311
- * via text color classes (e.g. warning/danger past thresholds). */
312
224
  declare function ProgressRing({
313
225
  value,
314
226
  size,
@@ -325,10 +237,8 @@ declare function ProgressRing({
325
237
  * - Immutable chips for resolved mentions/commands
326
238
  * - Configurable trigger behavior (dropdown vs callback)
327
239
  * - Simple inline markdown rendering
328
- */
329
- /**
330
- * A segment of content within the editable text.
331
- * The document model is an ordered array of these segments.
240
+ *
241
+ * The document model is an ordered array of {@link TextSegment}/{@link ChipSegment}.
332
242
  */
333
243
  type TextSegment = {
334
244
  type: 'text';
@@ -763,241 +673,36 @@ type ToolCallItem$1 = Extract<TranscriptItem, {
763
673
  kind: 'tool_call';
764
674
  }>;
765
675
  //#endregion
766
- //#region src/components/terminal/row.d.ts
767
- /**
768
- * The primitives every terminal row is built from.
769
- *
770
- * There are three, and that is the whole vocabulary: a {@link Row} (a gutter
771
- * cell and a body cell), a {@link Blank} (one empty line), and a {@link Band} (a
772
- * run of rows carrying a full-bleed background). Anything the theme draws — a
773
- * message, a tool call, a diff hunk, an approval prompt — is some arrangement of
774
- * those, which is what keeps the grid a property of the renderer rather than a
775
- * thing each component re-derives.
776
- *
777
- * Geometry is in `styles/terminal.css`. These components choose a class, a
778
- * marker and a tone; they never carry a measurement.
779
- */
780
- /** The palette, as a name. See the `[data-tone]` rules in `terminal.css`. */
781
- type Tone = 'fg' | 'bright' | 'dim' | 'faint' | 'mark' | 'blue' | 'green' | 'red' | 'yellow' | 'magenta';
782
- interface RowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
783
- /**
784
- * What sits in the gutter — `●`, `⎿`, `>`, a list bullet, or nothing. Kept to
785
- * the width of the gutter (`--term-cell`, two columns by default): a wider
786
- * marker would push its own body off the column every other row starts on.
787
- * Omitted, the gutter is still drawn as empty space, so an unmarked row's
788
- * text lines up with a marked one's.
789
- */
790
- glyph?: ReactNode;
791
- /** The marker's colour. Defaults to dim — the marker is structure, not content. */
792
- glyphTone?: Tone;
793
- /** The body's colour. */
794
- tone?: Tone;
795
- bold?: boolean;
796
- /** Indent levels, one character cell each. A child row's marker then sits
797
- * exactly under its parent row's first letter. */
798
- indent?: 0 | 1 | 2 | 3;
799
- /**
800
- * Gutter width in columns, when the marker needs other than two — an ordered
801
- * list's `10.` is four, a prompt's `❯ 1.` is five, and a framed payload wants
802
- * `0`. Changes only this row's split, so the body still starts on a whole
803
- * column.
804
- */
805
- columns?: number;
806
- children?: ReactNode;
807
- }
808
- declare function Row({
809
- glyph,
810
- glyphTone,
811
- tone,
812
- bold,
813
- indent,
814
- columns,
815
- className,
816
- children,
817
- style,
818
- ...props
819
- }: RowProps): _$react.JSX.Element;
820
- /**
821
- * One empty line — the theme's only vertical spacing.
822
- *
823
- * A terminal separates blocks with a blank line, not with padding, and saying it
824
- * that way has a practical payoff: spacing is part of the row list, so it can be
825
- * decided by whoever knows whether two blocks belong together (a tool call and
826
- * its output do not get one; two assistant turns do), instead of by a margin
827
- * rule that cannot tell them apart.
828
- */
829
- declare function Blank(): _$react.JSX.Element;
830
- /**
831
- * A run of rows under a background: a code block, a command's output, a diff
832
- * hunk. Full-bleed — the wash reaches the scroller's edges, because in a
833
- * terminal the line is the full width of the screen. See `--term-bleed` on
834
- * {@link TerminalSurface}.
835
- */
836
- declare function Band({
837
- className,
838
- ...props
839
- }: HTMLAttributes<HTMLDivElement>): _$react.JSX.Element;
840
- /** Inline colour/weight inside a row's body. */
841
- declare function Ink({
842
- tone,
843
- bold,
844
- className,
845
- ...props
846
- }: HTMLAttributes<HTMLSpanElement> & {
847
- tone?: Tone;
848
- bold?: boolean;
849
- }): _$react.JSX.Element;
850
- //#endregion
851
676
  //#region src/components/agent/Transcript.d.ts
852
677
  interface TranscriptProps {
853
678
  state: TranscriptState;
854
- /** Builds the download URL for a delivered file (see FileCard). Typically
855
- * `(path) => client.sessionFileUrl(sessionId, path)`. */
856
679
  fileUrl?: (path: string) => string;
857
- /** Builds the URL for an uploaded attachment. Typically
858
- * `(id) => client.attachmentUrl(sessionId, id)`. Same-origin and
859
- * cookie-authenticated, which is what lets an `<img src>` render one. */
860
680
  attachmentUrl?: (attachmentId: string) => string;
861
- /** Whether this gateway serves `@file` search here — the empty state must not
862
- * advertise an affordance the composer doesn't have. */
863
681
  canBrowseFiles?: boolean;
864
- /** Reads a host file as a data URL, for tool calls whose output is a picture
865
- * on the host (codex's `image_gen`). Omit and those cards name the path. */
866
682
  hostImage?: (path: string) => Promise<string | undefined>;
867
- /**
868
- * How a turn is drawn: `cards` (default, the chat convention) or `terminal`,
869
- * which is not a set of branches in these components but its own renderer.
870
- * See {@link TranscriptVariant}.
871
- */
872
683
  variant?: TranscriptVariant;
873
- /**
874
- * How much air each row gets: `comfortable` (default — a blank line between
875
- * messages, as the Claude Code CLI does) or `compact`. Independent of
876
- * {@link TranscriptVariant}. See {@link TranscriptDensity}.
877
- */
878
684
  density?: TranscriptDensity;
879
- /** Terminal theme only: the character cell, in whole pixels. See
880
- * {@link TerminalSurface}. */
881
685
  fontSize?: number;
882
686
  lineHeight?: number;
883
- /** Terminal theme only: the pointer affordances a real terminal cannot offer.
884
- * `false` for none. See {@link TerminalAffordances}. */
885
687
  affordances?: TerminalAffordances | boolean;
886
- /** Hold the prompt of the turn being read at the top of the scroller. Works
887
- * in both variants: the terminal clips to one line, cards shows a frosted
888
- * bar. The *real* row is pinned, not a copy — see `TranscriptRows`. */
889
688
  stickyPrompt?: boolean;
890
- /**
891
- * Mount the overview scrubber — a 12px rail of marks (your prompts, each
892
- * turn's response and result as one mark, errors, the pending approval, the
893
- * catch-up boundary) over the scroller's right edge. Two rails behind one
894
- * prop: under `terminal` it is the pixel-exact ruler that replaces the
895
- * native scrollbar (positions ride the height calculator; drag scrubs), and
896
- * under `cards` it is the **proportional annotation rail** — positioned by
897
- * `itemIndex / items.length`, because proportional text gives the
898
- * calculator no claim there — where the native scrollbar stays and the rail
899
- * only peeks and jumps. With `affordances={false}` either rail degrades to
900
- * passive paint — no drag, peek or click.
901
- */
902
689
  scrubber?: boolean;
903
- /**
904
- * Bookmarked item indices, painted as full-width marks on the rail. Paint
905
- * only, deliberately: the store — and the affordance that writes it — is
906
- * the client's, the way the unread watermarks are, not the panel's.
907
- */
908
- scrubberMarks?: readonly number[];
909
- /**
910
- * The attach replay is still landing (`useClaudeSession().replaying`): rows
911
- * render, measure and pin exactly as normal but nothing paints, and a loading
912
- * line shows in their place; when it flips false the settled tail appears in
913
- * one frame. Hiding is by *visibility*, never by not mounting — see the
914
- * comment at the render site. Optional: an embedder that never passes it
915
- * gets today's behaviour, and a short or empty session holds for no visible
916
- * time at all (the frame between attach and replay-complete).
917
- */
690
+ bookmarks?: readonly string[];
918
691
  replaying?: boolean;
919
- /**
920
- * Catch-up: `from` is how many items had been seen last time, `since` when
921
- * that was. A recap row is drawn at that boundary and everything above it is
922
- * dimmed. Omit (or pass a boundary at/after the end) and the transcript
923
- * renders exactly as before.
924
- */
925
692
  catchUp?: {
926
693
  from: number;
927
694
  since?: number;
928
695
  };
929
- /**
930
- * Filled with a closure that scrolls the recap row into view — the seam the
931
- * panel's catch-up strip presses. A ref rather than a DOM query because the
932
- * rows are virtualized: when the recap row isn't mounted, only the
933
- * virtualizer knows where it would be. Optional; embedders without a
934
- * catch-up strip never touch it. `null` while no transcript is mounted.
935
- */
936
696
  jumpToRecapRef?: RefObject<(() => void) | null>;
937
- /**
938
- * Filled with a closure that re-pins the transcript to the bottom, so a host
939
- * can resume following after the reader has scrolled away. The panel presses
940
- * it on send: choosing to say something is choosing to watch what happens
941
- * next, and a transcript left parked where you were reading makes a sent
942
- * message look like it did nothing at all.
943
- */
944
697
  repinRef?: RefObject<(() => void) | null>;
945
- /**
946
- * Scroll a tool call into view — bump `nonce` to ask again for the same one.
947
- *
948
- * The seam a *list* needs: sub-agent work is nested inside the `Task` call
949
- * that spawned it, so "open that sub-agent" can only ever mean "take me to its
950
- * row". A `parentToolUseId` works here as well as the Task's own id, since the
951
- * lookup resolves an absorbed child to the row that folded it.
952
- *
953
- * A prop rather than a ref (the shape `jumpToRecapRef` uses) because the asker
954
- * is outside this webview entirely and the request travels as data; a ref
955
- * would need a live closure at the other end of a postMessage bridge.
956
- */
957
698
  reveal?: {
958
699
  toolUseId: string;
959
700
  nonce: number;
960
701
  };
961
- /**
962
- * Render **only** the work one sub-agent did, rather than the conversation —
963
- * the sub-agent takeover's frame.
964
- *
965
- * Membership is `subagentItems` (`terminal/blocks.ts`), which is also the rule
966
- * iOS will mirror: everything the agent produced, and not the spawning `Task`
967
- * call itself, which *is* the frame rather than a row in it.
968
- *
969
- * Features are switched off internally whenever it is set, and the gate lives
970
- * here rather than at the call site on purpose: each is keyed to a
971
- * **full-transcript item index**, so a host that passed a frame and a catch-up
972
- * boundary together would not be making a strange choice, it would be making
973
- * an incoherent one. Those are the catch-up boundary and its recap row, the
974
- * sticky prompt, `reveal`, and the scrubber's **bookmarks** (host indices in
975
- * full-transcript space).
976
- *
977
- * The **scrubber itself stays**, and the distinction is the point: the rail
978
- * derives every one of its inputs from the rows it is given, and inside a
979
- * frame those are the sub-agent's own — so it marks that agent's prompts,
980
- * answers and failures at that agent's offsets. It was originally gated with
981
- * the marks, on the reasonable-looking argument that they are one feature;
982
- * they are two, and a fifty-tool agent run is exactly where a rail earns its
983
- * keep. What stays besides is everything that makes a long stream readable —
984
- * virtualization, the height epoch, the follow spring, the replay hold.
985
- */
986
702
  frame?: {
987
703
  parentToolUseId: string;
988
704
  };
989
- /**
990
- * Raise the takeover from a `Task` row. Absent draws no affordance, which is
991
- * what the plain renderer and the cards variant get: cards folds nothing, so
992
- * it has no task blocks to hang this on, and reaches the takeover from the
993
- * sessions list instead.
994
- */
995
705
  onOpenSubagent?: (toolUseId: string) => void;
996
- /**
997
- * Replaces the default empty state when the transcript has no items. Pass a
998
- * `ReactNode` to show your product's own onboarding instead of WorkerDeck's
999
- * generic "`>_` Tell the agent what to do." placeholder.
1000
- */
1001
706
  emptyState?: ReactNode;
1002
707
  className?: string;
1003
708
  }
@@ -1014,7 +719,7 @@ declare function Transcript({
1014
719
  affordances,
1015
720
  stickyPrompt,
1016
721
  scrubber,
1017
- scrubberMarks,
722
+ bookmarks,
1018
723
  replaying,
1019
724
  catchUp,
1020
725
  jumpToRecapRef,
@@ -1027,40 +732,10 @@ declare function Transcript({
1027
732
  }: TranscriptProps): _$react.JSX.Element;
1028
733
  //#endregion
1029
734
  //#region src/components/terminal/surface.d.ts
1030
- /**
1031
- * The root of the terminal theme: the element that establishes the character
1032
- * cell every row inside it lands on.
1033
- *
1034
- * It exists as a component rather than a class because the cell has to be *set*
1035
- * somewhere — the font, the size and the line height together are what make
1036
- * `1ch` mean one column and `--term-line` mean one row — and because that is the
1037
- * one place a host is allowed to change the metrics. Everything below this
1038
- * element measures itself in those two units and never in pixels.
1039
- *
1040
- * The geometry and the palette live in `styles/terminal.css`; this only names
1041
- * the element and hands down the two numbers.
1042
- */
1043
735
  interface TerminalSurfaceProps extends HTMLAttributes<HTMLDivElement> {
1044
- /**
1045
- * Cell size in **whole pixels**. Fractional values put every other row on a
1046
- * half-pixel: text softens and the diff bands show a seam, which is exactly
1047
- * what a grid renderer must not do. Defaults (13/18) are the CLI's own.
1048
- */
1049
736
  fontSize?: number;
1050
737
  lineHeight?: number;
1051
- /**
1052
- * How far a full-bleed band reaches past the content edge — normally the
1053
- * scroller's own horizontal padding. A band cancels it with matched negative
1054
- * margin and padding, so a diff hunk's wash runs to the viewport edge the way
1055
- * a terminal's line does, instead of stopping at a gutter.
1056
- */
1057
738
  bleed?: string;
1058
- /**
1059
- * The things a real terminal cannot do — the pointer hover fill, the
1060
- * hover-revealed copy actions. `false` turns them all off, an object picks.
1061
- * Default: all on. See {@link TerminalAffordances}; none of them costs layout,
1062
- * so switching them off changes no glyph's position.
1063
- */
1064
739
  affordances?: TerminalAffordances | boolean;
1065
740
  }
1066
741
  declare function TerminalSurface({
@@ -1075,39 +750,14 @@ declare function TerminalSurface({
1075
750
  }: TerminalSurfaceProps): _$react.JSX.Element;
1076
751
  //#endregion
1077
752
  //#region src/components/terminal/TerminalTranscript.d.ts
1078
- /**
1079
- * The transcript, drawn as a terminal.
1080
- *
1081
- * The whole of the layout is here and it is four lines long, which is the point:
1082
- * items become row blocks, a blank line goes between blocks that do not belong
1083
- * together, and the working line is one more row at the end. There is no gap
1084
- * scale, no density knob and no variant branch — a terminal has one line height
1085
- * and one type size, and everything the theme can express is expressed in which
1086
- * rows exist and what marker each carries.
1087
- *
1088
- * Not virtualized yet: the row blocks are the part that has to be right first,
1089
- * and the existing `Transcript` already owns a hard-won virtualizer plus the
1090
- * scroll-regime rules it needs. This renders into that shell when the rows are
1091
- * settled, rather than growing a second copy of that logic.
1092
- */
1093
753
  interface TerminalTranscriptProps {
1094
754
  state: TranscriptState;
1095
- /** Builds the download URL for a delivered file. */
1096
755
  fileUrl?: (path: string) => string;
1097
- /** Cell metrics, in whole pixels. See {@link TerminalSurface}. */
1098
756
  fontSize?: number;
1099
757
  lineHeight?: number;
1100
- /** The pointer affordances a real terminal has no way to offer — hover fill,
1101
- * hover-revealed copy. `false` for none. See {@link TerminalAffordances}. */
1102
758
  affordances?: TerminalAffordances | boolean;
1103
759
  className?: string;
1104
760
  }
1105
- /**
1106
- * One transcript item as terminal rows. Exported because the virtualized shell
1107
- * in `agent/Transcript.tsx` renders rows through it: the theme owns how a row
1108
- * looks, that component owns which rows are mounted, and neither needs a copy
1109
- * of the other.
1110
- */
1111
761
  declare function TerminalItemView({
1112
762
  item,
1113
763
  fileUrl
@@ -1128,15 +778,8 @@ declare function TerminalTranscript({
1128
778
  interface TerminalStatusLineProps {
1129
779
  className?: string;
1130
780
  state: TranscriptState;
1131
- /** Plan windows to read from, when they should not be the session's own — the
1132
- * gateway's per-profile state merged over this transcript's. See
1133
- * {@link StatusBarProps.rateLimits}. Absent = `state.rateLimits`. */
1134
781
  rateLimits?: Record<string, RateLimitInfo>;
1135
- /** How the client is doing at reaching the gateway. Wins the status slot when
1136
- * the socket is down — see above. */
1137
782
  connection?: ConnectionState;
1138
- /** Opens the panel that answers each reading's own question. Omit and the
1139
- * reading is text rather than something to press. */
1140
783
  onOpenStatus?: () => void;
1141
784
  onOpenContext?: () => void;
1142
785
  onOpenUsage?: () => void;
@@ -1152,27 +795,9 @@ declare function TerminalStatusLine({
1152
795
  }: TerminalStatusLineProps): _$react.JSX.Element;
1153
796
  //#endregion
1154
797
  //#region src/components/terminal/PermissionPrompt.d.ts
1155
- /**
1156
- * The approval, as the CLI draws it: a rule, what is being asked and about what,
1157
- * the change itself, a dashed rule, the question, numbered answers, and the keys.
1158
- *
1159
- * Two things it does that the card version does not, both taken from the CLI:
1160
- *
1161
- * - **It shows the change, not the payload.** For a file edit, `old_string` and
1162
- * `new_string` are a diff — so it renders one, rather than the JSON input a
1163
- * reader would have to diff in their head. Without line numbers, necessarily:
1164
- * the edit has not happened and this client has never read the file (see
1165
- * {@link previewPatch}). Everything else falls back to the input.
1166
- * - **The heading is the engine's own sentence.** `displayName` ("Edit file")
1167
- * over `title`, never "wants to use {tool}" composed here — for codex an
1168
- * approval is an *escalation after a sandbox refusal*, and the runner has
1169
- * already written the sentence that says so.
1170
- */
1171
798
  interface TerminalPermissionPromptProps {
1172
799
  request: PermissionRequest;
1173
800
  onApprove: (requestId: string) => void;
1174
- /** `message` is fed back to the agent, which can then try something else;
1175
- * `interrupt` also stops the turn. */
1176
801
  onDeny: (requestId: string, message?: string, interrupt?: boolean) => void;
1177
802
  className?: string;
1178
803
  }
@@ -1185,11 +810,8 @@ declare function TerminalPermissionPrompt({
1185
810
  //#endregion
1186
811
  //#region src/components/terminal/QuestionPrompt.d.ts
1187
812
  interface TerminalQuestionPromptProps {
1188
- /** A pending permission whose toolName is 'AskUserQuestion'. */
1189
813
  request: PermissionRequest;
1190
- /** Allow the tool with `updatedInput` (the original input plus `answers`). */
1191
814
  onAnswer: (requestId: string, updatedInput: Record<string, unknown>) => void;
1192
- /** Deny the tool — the model proceeds without an answer. */
1193
815
  onDismiss: (requestId: string, message?: string) => void;
1194
816
  className?: string;
1195
817
  }
@@ -1201,15 +823,6 @@ declare function TerminalQuestionPrompt({
1201
823
  }: TerminalQuestionPromptProps): _$react.JSX.Element;
1202
824
  //#endregion
1203
825
  //#region src/components/terminal/diff.d.ts
1204
- /**
1205
- * A patch for a change that has **not happened yet** — an approval prompt's
1206
- * `Edit`, where the input names the old and new text but no line numbers exist
1207
- * because the edit has not been applied and this client has never read the file.
1208
- *
1209
- * `newStart: 0` is how it says so, and {@link TerminalDiff} reads that back: a
1210
- * diff whose hunks all start at zero renders without a number column rather than
1211
- * printing a column of zeroes or inventing an offset.
1212
- */
1213
826
  declare function previewPatch(input: unknown): FilePatch | undefined;
1214
827
  declare function TerminalDiff({
1215
828
  patch
@@ -1220,7 +833,6 @@ declare function TerminalDiff({
1220
833
  //#region src/components/terminal/markdown.d.ts
1221
834
  interface TerminalMarkdownProps {
1222
835
  children: string;
1223
- /** Streaming text: tolerate half-written markdown (unclosed fences, half links). */
1224
836
  streaming?: boolean;
1225
837
  className?: string;
1226
838
  }
@@ -1230,20 +842,48 @@ declare const TerminalMarkdown: _$react.MemoExoticComponent<({
1230
842
  className
1231
843
  }: TerminalMarkdownProps) => _$react.JSX.Element>;
1232
844
  //#endregion
845
+ //#region src/components/terminal/row.d.ts
846
+ type Tone = 'fg' | 'bright' | 'dim' | 'faint' | 'mark' | 'blue' | 'green' | 'red' | 'yellow' | 'magenta';
847
+ interface RowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
848
+ glyph?: ReactNode;
849
+ glyphTone?: Tone;
850
+ tone?: Tone;
851
+ bold?: boolean;
852
+ indent?: 0 | 1 | 2 | 3;
853
+ columns?: number;
854
+ children?: ReactNode;
855
+ }
856
+ declare function Row({
857
+ glyph,
858
+ glyphTone,
859
+ tone,
860
+ bold,
861
+ indent,
862
+ columns,
863
+ className,
864
+ children,
865
+ style,
866
+ ...props
867
+ }: RowProps): _$react.JSX.Element;
868
+ declare function Blank(): _$react.JSX.Element;
869
+ declare function Band({
870
+ className,
871
+ ...props
872
+ }: HTMLAttributes<HTMLDivElement>): _$react.JSX.Element;
873
+ declare function Ink({
874
+ tone,
875
+ bold,
876
+ className,
877
+ ...props
878
+ }: HTMLAttributes<HTMLSpanElement> & {
879
+ tone?: Tone;
880
+ bold?: boolean;
881
+ }): _$react.JSX.Element;
882
+ //#endregion
1233
883
  //#region src/components/agent/Conversation.d.ts
1234
884
  interface ConversationProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
1235
885
  children: ReactNode;
1236
886
  }
1237
- /** Scroll container that stays pinned to the bottom while streaming, unless the user
1238
- * scrolls up — plus a floating scroll-to-bottom button.
1239
- *
1240
- * **Nothing here animates its scroll position.** `initial` and `resize` are both
1241
- * `'instant'` and are no longer configurable: the follow spring's job is to
1242
- * *stay* at the bottom, not to travel there, and every travel a reader has ever
1243
- * complained about on this surface was an animation we asked for. The `resize`
1244
- * prop used to exist so a caller could pick, which required the caller to know
1245
- * whether the transcript was streaming or replaying — a latch's worth of
1246
- * machinery to decide something that has one right answer. */
1247
887
  declare function Conversation({
1248
888
  className,
1249
889
  children,
@@ -1266,19 +906,6 @@ declare function ConversationScrollButton({
1266
906
  interface MessageProps extends HTMLAttributes<HTMLDivElement> {
1267
907
  from: 'user' | 'assistant';
1268
908
  }
1269
- /**
1270
- * One chat turn row.
1271
- *
1272
- * `cards`: user messages sit in a bubble, assistant content is flat and
1273
- * full-width. Both are **left-aligned**: the transcript is a log read top to
1274
- * bottom, and an editor-shaped host (a full-width session view beside a sessions
1275
- * rail) has no right edge to anchor to — a bubble drifting right in a 1600px
1276
- * column separates a prompt from the reply it produced. The bubble alone is
1277
- * enough to say who spoke.
1278
- *
1279
- * The terminal theme draws none of this: it is its own renderer
1280
- * (`components/terminal/`) and mounts instead of these rows.
1281
- */
1282
909
  declare function Message({
1283
910
  from,
1284
911
  className,
@@ -1293,12 +920,9 @@ declare function MessageContent({
1293
920
  //#region src/components/agent/Response.d.ts
1294
921
  interface ResponseProps {
1295
922
  children: string;
1296
- /** Streaming text: tolerate incomplete markdown (unclosed fences, half links). */
1297
923
  streaming?: boolean;
1298
924
  className?: string;
1299
925
  }
1300
- /** Markdown renderer for assistant output — streaming-safe via streamdown, code
1301
- * highlighted with shiki (dual theme follows [data-theme] through the dark: variant). */
1302
926
  declare const Response: _$react.MemoExoticComponent<({
1303
927
  children,
1304
928
  streaming,
@@ -1308,13 +932,10 @@ declare const Response: _$react.MemoExoticComponent<({
1308
932
  //#region src/components/agent/Reasoning.d.ts
1309
933
  interface ReasoningProps {
1310
934
  children: string;
1311
- /** Auto-opens while true, auto-closes shortly after it flips false. */
1312
935
  isStreaming?: boolean;
1313
936
  defaultOpen?: boolean;
1314
937
  className?: string;
1315
938
  }
1316
- /** Collapsible extended-thinking block: open while the model is thinking, tucks itself
1317
- * away once the thought is finished (unless the user toggled it manually). */
1318
939
  declare function Reasoning({
1319
940
  children,
1320
941
  isStreaming,
@@ -1324,26 +945,11 @@ declare function Reasoning({
1324
945
  //#endregion
1325
946
  //#region src/components/agent/Loader.d.ts
1326
947
  interface LoaderProps {
1327
- /** Overrides the cycling verb — for a state that has one true name
1328
- * ("Starting session…"). */
1329
948
  label?: string;
1330
- /** When the current run began, for the elapsed clock. Absent = no clock.
1331
- * Unused by the card treatment; kept so the `cards` and `terminal` loaders
1332
- * take the same call site in `Transcript`. */
1333
949
  startedAt?: number;
1334
- /** Context tokens in play. Same story as `startedAt`. */
1335
950
  tokens?: number;
1336
951
  className?: string;
1337
952
  }
1338
- /**
1339
- * "The agent is working and hasn't produced output yet."
1340
- *
1341
- * Three dots pulsing in CSS — the chat convention, for the `cards` variant. The
1342
- * terminal theme has its own working line (`terminal/items.tsx`'s `WorkingRow`,
1343
- * with the mark's pulse in the gutter and the run's readings beside the verb),
1344
- * because there it is a *row of the transcript* rather than a spinner floating
1345
- * over one.
1346
- */
1347
953
  declare function Loader({
1348
954
  label,
1349
955
  className
@@ -1355,13 +961,6 @@ type ToolCallItem = Extract<TranscriptItem, {
1355
961
  }>;
1356
962
  interface ToolCallCardProps {
1357
963
  item: ToolCallItem;
1358
- /**
1359
- * Reads a host file as a data URL, for tools whose output is a picture on the
1360
- * host. Resolves `undefined` when the gateway won't serve that path — a
1361
- * generated image saved outside the allowed roots (codex's default
1362
- * `$CODEX_HOME/generated_images/`) is one, and the card then names the path
1363
- * instead of showing it.
1364
- */
1365
964
  hostImage?: (path: string) => Promise<string | undefined>;
1366
965
  className?: string;
1367
966
  }
@@ -1377,14 +976,9 @@ type FileDeliveredItem = Extract<TranscriptItem, {
1377
976
  }>;
1378
977
  interface FileCardProps {
1379
978
  item: FileDeliveredItem;
1380
- /** Download URL for the delivered path (the server's session file route).
1381
- * Without it the card renders informational only. */
1382
979
  href?: string;
1383
980
  className?: string;
1384
981
  }
1385
- /** A file the agent handed over (`file_delivered`): name, size, download link.
1386
- * The file lives in the session's in-memory VFS — the link works while the
1387
- * session lives. */
1388
982
  declare function FileCard({
1389
983
  item,
1390
984
  href,
@@ -1395,23 +989,9 @@ declare function FileCard({
1395
989
  interface PermissionPromptProps {
1396
990
  request: PermissionRequest;
1397
991
  onApprove: (requestId: string) => void;
1398
- /** `message` is fed back to the agent, which can then try something else;
1399
- * `interrupt` also stops the turn. */
1400
992
  onDeny: (requestId: string, message?: string, interrupt?: boolean) => void;
1401
993
  className?: string;
1402
994
  }
1403
- /**
1404
- * Generic allow/deny prompt for a pending permission request.
1405
- *
1406
- * Three outcomes, not two: denying usually means "not that, try something else",
1407
- * so plain Deny lets the turn continue (with an optional reason the agent reads)
1408
- * while "Deny & stop" also interrupts.
1409
- *
1410
- * The heading is whatever the engine authored — `title`, else `displayName`.
1411
- * Composing "wants to use {tool}" instead would be wrong for codex, where an
1412
- * approval is usually an *escalation after a sandbox refusal* and the runner has
1413
- * already written the sentence that says so.
1414
- */
1415
995
  declare function PermissionPrompt({
1416
996
  request,
1417
997
  onApprove,
@@ -1425,23 +1005,14 @@ type QuestionBehaviorMeta = {
1425
1005
  label: string;
1426
1006
  description: string;
1427
1007
  };
1428
- /** The AskUserQuestion policies surfaced on job/session creation forms. */
1429
1008
  declare const QUESTION_BEHAVIORS: QuestionBehaviorMeta[];
1430
- /** Extract well-formed questions from an AskUserQuestion permission request's input. */
1431
1009
  declare function parseUserQuestions(input: Record<string, unknown>): UserQuestion[];
1432
1010
  interface QuestionPromptProps {
1433
- /** A pending permission whose toolName is 'AskUserQuestion'. */
1434
1011
  request: PermissionRequest;
1435
- /** Allow the tool with `updatedInput` (the original input plus `answers`). */
1436
1012
  onAnswer: (requestId: string, updatedInput: Record<string, unknown>) => void;
1437
- /** Deny the tool — the model proceeds without an answer. */
1438
1013
  onDismiss: (requestId: string, message?: string) => void;
1439
1014
  className?: string;
1440
1015
  }
1441
- /** Interactive form for the AskUserQuestion tool: option buttons per question
1442
- * (multi-select where the question allows it), a free-text "Other" escape hatch,
1443
- * and the focused option's preview. Falls back to nothing renderable → the caller
1444
- * should show a generic PermissionPrompt if `parseUserQuestions` finds no questions. */
1445
1016
  declare function QuestionPrompt({
1446
1017
  request,
1447
1018
  onAnswer,
@@ -1450,107 +1021,44 @@ declare function QuestionPrompt({
1450
1021
  }: QuestionPromptProps): _$react.JSX.Element;
1451
1022
  //#endregion
1452
1023
  //#region src/components/agent/Composer.d.ts
1453
- /** Files matching an `@` query, for the composer's file trigger. Structural so
1454
- * the ui package doesn't have to reach for the protocol's `HostFileMatch`. */
1455
1024
  type ComposerFileMatch = {
1456
1025
  path: string;
1457
1026
  relative: string;
1458
1027
  };
1459
- /** Imperative surface for panels that draft a message the user then finishes —
1460
- * the skills dialog's "Use this skill". Nothing here sends. */
1461
1028
  type ComposerHandle = {
1462
- /** Append plain text at the caret's end and focus, separating it from
1463
- * whatever is already there. */
1464
- insertText: (text: string) => void; /** Put the caret in the field, changing nothing. */
1029
+ insertText: (text: string) => void;
1465
1030
  focus: () => void;
1466
1031
  };
1467
1032
  interface ComposerProps {
1468
- /** `attachmentIds` are the staged uploads, in the order they were picked. */
1469
1033
  onSend: (text: string, attachmentIds: string[]) => void;
1470
1034
  onInterrupt: () => void;
1471
1035
  busy: boolean;
1472
- /** Disable input entirely (session failed/closed). */
1473
1036
  disabled?: boolean;
1474
1037
  placeholder?: string;
1475
- /** Slash commands offered as autocomplete; picked ones render as chips. */
1476
1038
  commands?: SlashCommandInfo[];
1477
- /**
1478
- * Skills offered under a **`$`** popover of their own — codex's sigil, kept
1479
- * separate from `/` because the two behave differently. A skill is a typing
1480
- * aid, not a command: picking one inserts editable text (the skill's own
1481
- * `defaultPrompt` where it has one, else `$name`) and nothing is sent. No
1482
- * engine parses `$skillname` as syntax, which is exactly why these can never
1483
- * resolve to a chip the way `commands` do.
1484
- */
1485
1039
  skills?: SkillInfo[];
1486
- /** Host-file search behind the `@` trigger. Omit to leave `@` inert — a
1487
- * gateway without host files has nothing to complete. */
1488
1040
  onSearchFiles?: (query: string, options: {
1489
1041
  signal: AbortSignal;
1490
1042
  }) => Promise<ComposerFileMatch[]>;
1491
- /** Attachment staging (see `useAttachments`). Omit for a text-only composer. */
1492
1043
  attachments?: UseAttachmentsResult;
1493
- /** Left side of the toolbar row (mode selects, …). */
1494
1044
  toolbar?: ReactNode;
1495
- /**
1496
- * `'stacked'` (default) gives the buttons a row of their own under the field —
1497
- * right where a toolbar belongs. `'inline'` puts the field and the buttons on
1498
- * ONE line, growing from a single row as the message does: for a host whose
1499
- * session controls live in its own chrome (VS Code's status bar), where the
1500
- * empty composer would otherwise spend two rows saying nothing.
1501
- */
1502
1045
  layout?: 'stacked' | 'inline';
1503
- /**
1504
- * Terminal theme only: the cell the composer draws on. Passed straight
1505
- * through to its own {@link TerminalSurface}, and it has to be passed — the
1506
- * composer sits outside the transcript's scroller, so it establishes a second
1507
- * surface, and a surface handed no metrics falls back to the 13/18 default. A
1508
- * host running the transcript at its editor's size and the composer at the
1509
- * default would have the caret land on a different column from the text above
1510
- * it, which is the one thing this theme exists to prevent.
1511
- */
1512
1046
  fontSize?: number;
1513
1047
  lineHeight?: number;
1514
- /** Terminal theme only; see {@link TerminalAffordances}. */
1515
1048
  affordances?: TerminalAffordances | boolean;
1049
+ /**
1050
+ * Where unsent text is remembered between mounts. The composer is remounted on every session switch, so without
1051
+ * this a half-written prompt dies with the switch. Omit to keep the composer stateless across mounts.
1052
+ */
1053
+ draft?: {
1054
+ initialText: string;
1055
+ save: (text: string) => void;
1056
+ clear: () => void;
1057
+ };
1516
1058
  className?: string;
1517
1059
  ref?: Ref<ComposerHandle>;
1518
1060
  }
1519
- /**
1520
- * What a picked skill types into the composer.
1521
- *
1522
- * The engine's own `defaultPrompt` when it declared one — it knows what its
1523
- * skill wants to be asked — and otherwise `$name`, which is codex's native way
1524
- * of referring to a skill in prompt text: its `skill-creator` documents the form
1525
- * (`Use $skill-x at /path/to/skill-x to solve problem y`) and its own bundled
1526
- * prompts are written that way ("Use $pdf to …"). Spelling it the way the engine
1527
- * spells it beats paraphrasing into "Use the X skill to".
1528
- *
1529
- * Either way it ends in a space so the caret lands ready for the rest of the
1530
- * sentence, and either way it is ordinary text: nothing here is submitted, and
1531
- * nothing is parsed back out.
1532
- */
1533
1061
  declare function skillPrompt(skill: SkillInfo): string;
1534
- /**
1535
- * Framed prompt input built on prompt-area's contentEditable.
1536
- *
1537
- * Three completions ride the same field and behave nothing alike. `/` is the
1538
- * CLI's command list and `$` is the engine's skill list — both local, so they
1539
- * filter completely and instantly; `@` is a search against the host filesystem,
1540
- * debounced and abortable so a fast typist makes one request rather than eight.
1541
- *
1542
- * `/` and `$` are separate keys rather than one merged menu, and that mirrors
1543
- * the engines themselves: codex completes skills on `$` and reserves `/` for
1544
- * commands. The behaviours differ too — a command resolves to a **chip**,
1545
- * because the CLI really does parse `/name` out of the message, while a skill
1546
- * resolves to plain editable **text**, because no engine parses `$name` as
1547
- * syntax; it is prose the model reads. Rendering them alike would promise
1548
- * something that does not happen.
1549
- *
1550
- * Files can arrive three ways — the paperclip, a drop, or a paste — because on a
1551
- * desktop all three are things people already do, and the upload starts the
1552
- * moment one lands rather than at send time.
1553
- */
1554
1062
  declare function Composer({
1555
1063
  onSend,
1556
1064
  onInterrupt,
@@ -1566,28 +1074,20 @@ declare function Composer({
1566
1074
  fontSize,
1567
1075
  lineHeight,
1568
1076
  affordances,
1077
+ draft,
1569
1078
  className,
1570
1079
  ref
1571
1080
  }: ComposerProps): _$react.JSX.Element;
1572
1081
  //#endregion
1573
1082
  //#region src/components/agent/ModelSelect.d.ts
1574
1083
  interface ModelSelectProps {
1575
- /** Models the session can switch to (TranscriptState.models). */
1576
1084
  models: ModelOption[];
1577
- /** The session's current model id (TranscriptState.model), possibly decorated
1578
- * (e.g. "claude-fable-5[1m]") — matched leniently against the options.
1579
- * `undefined` selects the list's default row, if it has one. */
1580
1085
  model?: string;
1581
- /** `undefined` = back to the CLI's default model. */
1582
1086
  onModelChange: (model?: string) => void;
1583
- /** 'toolbar' (default) is the composer's compact borderless trigger;
1584
- * 'form' is a standard field-sized Select for create/settings forms. */
1585
1087
  variant?: 'toolbar' | 'form';
1586
1088
  disabled?: boolean;
1587
1089
  className?: string;
1588
1090
  }
1589
- /** Compact model switcher for the composer toolbar; fed by the `capabilities` event.
1590
- * Rows render CLI-style: bold display name with the model's description beneath. */
1591
1091
  declare function ModelSelect({
1592
1092
  models,
1593
1093
  model,
@@ -1600,42 +1100,15 @@ declare function ModelSelect({
1600
1100
  //#region src/components/agent/StatusBar.d.ts
1601
1101
  interface StatusBarProps {
1602
1102
  state: TranscriptState;
1603
- /**
1604
- * Plan windows to draw, when they should not be the session's own. The panel
1605
- * hands over the gateway's per-profile state merged over this transcript's
1606
- * reading (`mergeUsage`): a session's own `rate_limit` readings arrive only at
1607
- * a turn's edges, so one idle since yesterday would otherwise render
1608
- * yesterday's number as current. Absent = `state.rateLimits`, which is what a
1609
- * bar composed by hand outside the panel gets.
1610
- */
1611
1103
  rateLimits?: Record<string, RateLimitInfo>;
1612
- /** @deprecated Pass {@link StatusBarProps.connection}; kept so an embedder
1613
- * still handing over a boolean keeps working. */
1104
+ /** @deprecated Pass {@link StatusBarProps.connection}. */
1614
1105
  connected?: boolean;
1615
- /** How the client is doing at reaching the gateway. A dropped socket wins the
1616
- * status slot: the session status held over a dead socket is a stale reading,
1617
- * and presenting it as a live one is the thing worth avoiding. */
1618
1106
  connection?: ConnectionState;
1619
- /**
1620
- * Where the gauges lead. Each one opens the panel that answers *its* question
1621
- * — the two meters measure different things, so sending both to one "details"
1622
- * list would be a detour every time. Omit a handler and that gauge stays a
1623
- * read-only tooltip.
1624
- */
1625
1107
  onOpenStatus?: () => void;
1626
1108
  onOpenContext?: () => void;
1627
1109
  onOpenUsage?: () => void;
1628
- /**
1629
- * The session's own controls (model, permission mode), for
1630
- * `controlsSurface: 'status'`. They sit at the end of the readings cluster —
1631
- * status, context, usage, then what you can *change* — rather than out by the
1632
- * actions menu, because they belong with the session facts they act on.
1633
- */
1634
1110
  controls?: ReactNode;
1635
- /** Trailing slot — the session-actions menu, at the bar's trailing edge. */
1636
1111
  actions?: ReactNode;
1637
- /** Which edge the bar sits on, so its separating rule goes on the other side.
1638
- * Placement is the panel's decision; this only styles it. */
1639
1112
  placement?: 'top' | 'bottom';
1640
1113
  className?: string;
1641
1114
  }
@@ -1660,13 +1133,6 @@ interface ContextDialogProps {
1660
1133
  onOpenChange: (open: boolean) => void;
1661
1134
  className?: string;
1662
1135
  }
1663
- /**
1664
- * What is in the model's context window right now, category by category.
1665
- *
1666
- * One of the three panels the status bar opens. Context, usage and session info
1667
- * are different questions asked at different moments, so they are different
1668
- * screens rather than one "details" list you scroll past two answers to reach.
1669
- */
1670
1136
  declare function ContextDialog({
1671
1137
  usage,
1672
1138
  open,
@@ -1676,33 +1142,15 @@ declare function ContextDialog({
1676
1142
  //#endregion
1677
1143
  //#region src/components/agent/UsageDialog.d.ts
1678
1144
  interface UsageDialogProps {
1679
- /**
1680
- * Windows in reading order — session, weekly, then per-model weeklies.
1681
- *
1682
- * `updatedAt`/`inferredReset` ride each window because the readings no longer
1683
- * share one clock: the panel merges the gateway's per-profile state over this
1684
- * session's, so a `five_hour` learned from a sibling session two minutes ago
1685
- * can sit beside a `seven_day` this session last heard about yesterday.
1686
- * `inferredReset` marks the ones the *gateway* zeroed because their own reset
1687
- * time passed with nothing newer — a floor, not a report.
1688
- */
1689
1145
  rateLimits: UsageWindowRow[];
1690
- /** claude.ai plan behind the windows ('max', 'pro', …), when there is one. */
1691
1146
  subscriptionType?: string;
1692
1147
  engine: ProfileEngine;
1693
1148
  totalCostUsd: number;
1694
- /** When the *freshest* of the windows was read, for the footer line. Readings
1695
- * arrive one per turn at best (and for an idle session, not at all), so a
1696
- * stale one is normal and worth saying out loud. */
1697
1149
  updatedAt?: number;
1698
1150
  open: boolean;
1699
1151
  onOpenChange: (open: boolean) => void;
1700
1152
  className?: string;
1701
1153
  }
1702
- /**
1703
- * The session's view of the plan: every window as a meter (see
1704
- * {@link UsageMeters}), the plan tier, and what this session itself has cost.
1705
- */
1706
1154
  declare function UsageDialog({
1707
1155
  rateLimits,
1708
1156
  subscriptionType,
@@ -1715,39 +1163,13 @@ declare function UsageDialog({
1715
1163
  }: UsageDialogProps): _$react.JSX.Element;
1716
1164
  //#endregion
1717
1165
  //#region src/components/agent/UsageMeters.d.ts
1718
- /**
1719
- * Ticking clock — the countdowns and the pace markers both move with it, and a
1720
- * minute is the finest resolution either of them prints.
1721
- *
1722
- * `active` is what a dialog passes its `open`: a closed panel's clock is a timer
1723
- * re-rendering something nobody can see.
1724
- */
1725
1166
  declare function useMinuteClock(active?: boolean): number;
1726
- /**
1727
- * The plan's rate-limit windows, spelled out: how much of each is used, how that
1728
- * compares to the pace that would spend the window exactly, and when it resets.
1729
- *
1730
- * The pace marker is the point. A bar alone says "17% used", which is only
1731
- * alarming or reassuring once you know how far into the week you are — so every
1732
- * window draws a tick at the elapsed share of its duration. Left of the tick is
1733
- * under budget, right of it is ahead of it. The duration comes from the window
1734
- * key (5h, 7d) because the engine reports a reset time and a percentage and
1735
- * never a duration; a window whose key doesn't say gets no marker rather than a
1736
- * guessed one.
1737
- *
1738
- * Its own component rather than the Usage dialog's private helper because two
1739
- * surfaces draw these now — the session panel's Usage panel, from the session's
1740
- * readings merged with the gateway's, and the dashboard's profile page, straight
1741
- * off `ProfileInfo.usage` with no session in sight. Same account, same bars.
1742
- */
1743
1167
  declare function UsageMeters({
1744
1168
  windows,
1745
1169
  now,
1746
1170
  className
1747
1171
  }: {
1748
- /** In reading order — protocol's `orderUsageWindows`. */windows: UsageWindowRow[];
1749
- /** A shared clock, when the caller already ticks one. Omitted, this ticks its
1750
- * own for as long as it is mounted. */
1172
+ windows: UsageWindowRow[];
1751
1173
  now?: number;
1752
1174
  className?: string;
1753
1175
  }): _$react.JSX.Element;
@@ -1760,14 +1182,6 @@ interface SessionInfoDialogProps {
1760
1182
  open: boolean;
1761
1183
  onOpenChange: (open: boolean) => void;
1762
1184
  }
1763
- /**
1764
- * What this session *is*: engine, profile, model, mode, where it runs, which
1765
- * credentials it found, and the files it has handed over.
1766
- *
1767
- * The identity half of the session's facts. Context and usage have their own
1768
- * panels — they change every turn and are consulted mid-run, while everything
1769
- * here is fixed at creation and looked up once.
1770
- */
1771
1185
  declare function SessionInfoDialog({
1772
1186
  state,
1773
1187
  client,
@@ -1782,27 +1196,9 @@ interface McpDialogProps {
1782
1196
  sessionId: string | undefined;
1783
1197
  open: boolean;
1784
1198
  onOpenChange: (open: boolean) => void;
1785
- /**
1786
- * Whether this engine can reconnect/enable/disable a server
1787
- * (`EngineCapabilities.mcpServerActions`). False renders the panel read-only:
1788
- * codex reports rich status but exposes no per-server action, and buttons
1789
- * that 501 are worse than buttons that aren't there.
1790
- */
1791
1199
  canManageServers?: boolean;
1792
1200
  className?: string;
1793
1201
  }
1794
- /**
1795
- * The session's MCP servers, at the CLI's own `/mcp` depth: servers → one server
1796
- * → its tools → one tool, with Reconnect / Enable / Disable where they apply.
1797
- *
1798
- * Two things vary by engine rather than being fixed here. **The actions** exist
1799
- * only where the engine has them (`canManageServers`): codex reports rich status
1800
- * but has no per-server reconnect or toggle, so its panel is read-only. And
1801
- * **tool parameters** appear only where the engine reports a schema — codex
1802
- * returns each tool's full JSON Schema, the Agent SDK returns none at all, so
1803
- * the tool view either renders it or says why it can't, rather than leaving a
1804
- * silent gap or claiming the absence is universal.
1805
- */
1806
1202
  declare function McpDialog({
1807
1203
  client,
1808
1204
  sessionId,
@@ -1817,24 +1213,9 @@ interface SkillsDialogProps {
1817
1213
  skills: SkillInfo[] | undefined;
1818
1214
  open: boolean;
1819
1215
  onOpenChange: (open: boolean) => void;
1820
- /** Insert a skill's opening message into the composer, if the host offers
1821
- * that. Omit and the dialog is read-only. */
1822
1216
  onUse?: (skill: SkillInfo) => void;
1823
1217
  className?: string;
1824
1218
  }
1825
- /**
1826
- * What this session's engine can do beyond its own tools: the skills it found,
1827
- * grouped by where they came from, with one drilled-down view each.
1828
- *
1829
- * The framing matters more here than in most panels. A skill is **not** a
1830
- * command — the model decides to use one by reading its description, and there
1831
- * is no wire syntax that invokes it. So this screen is a *discovery* surface,
1832
- * and the one action it offers ("Use this skill") is honest about being a
1833
- * drafting aid: it types a message for the operator to edit and send.
1834
- *
1835
- * Fed from the session's `skills` event rather than a REST route, because that
1836
- * is the channel the engine refreshes on its own when a skill changes on disk.
1837
- */
1838
1219
  declare function SkillsDialog({
1839
1220
  skills,
1840
1221
  open,
@@ -1846,20 +1227,10 @@ declare function SkillsDialog({
1846
1227
  //#region src/components/agent/HostFilesDialog.d.ts
1847
1228
  interface HostFilesDialogProps {
1848
1229
  client: WorkerDeckClient;
1849
- /** The session's working directory — the browser is rooted here. */
1850
1230
  cwd: string | undefined;
1851
1231
  open: boolean;
1852
1232
  onOpenChange: (open: boolean) => void;
1853
1233
  }
1854
- /**
1855
- * Browse the project the session is working in.
1856
- *
1857
- * Deliberately rooted at the session's cwd rather than at the server's
1858
- * `hostFiles.roots`: the roots are the *security* boundary (the server enforces
1859
- * them on every request), but what someone wants while watching an agent is this
1860
- * project's tree. Read-only — writing is a separate server opt-in and not
1861
- * something a session viewer should be doing behind the agent's back.
1862
- */
1863
1234
  declare function HostFilesDialog({
1864
1235
  client,
1865
1236
  cwd,
@@ -1900,28 +1271,6 @@ declare function SessionList({
1900
1271
  }: SessionListProps): _$react.JSX.Element;
1901
1272
  //#endregion
1902
1273
  //#region src/components/agent/SessionStatusIcon.d.ts
1903
- /**
1904
- * State as one glyph — a ringing bell when it wants a human, a spinner while it
1905
- * works, a moon when it is only sleeping. Replaces the text badge: in a sidebar
1906
- * the word costs more room than it earns, and the states that matter are the two
1907
- * you can recognise without reading.
1908
- *
1909
- * **It reads `row.state`, not `info.status`, and that distinction is the whole
1910
- * point of the row model.** `sessionState` already folds in the arm this glyph
1911
- * cannot see for itself: a *background* sub-agent outlives its turn by design,
1912
- * so the turn ends, `status` comes to rest at `idle`, and the agent keeps
1913
- * working. Reading the raw status drew a **moon on a row filed under the
1914
- * "Working" header** — the list contradicting itself on one line, which is
1915
- * exactly what a derived view model exists to prevent. The value was in scope
1916
- * and unread.
1917
- *
1918
- * The terminal statuses still come off `info.status`, because `ended` collapses
1919
- * `failed` and `closed` into one bucket and those are worth telling apart here.
1920
- *
1921
- * It lives in its own file rather than inside the dashboard's browser because
1922
- * the extension's cards draw it too, and a second copy there is how the two
1923
- * lists last disagreed about what a parked session looks like.
1924
- */
1925
1274
  declare function SessionStatusIcon({
1926
1275
  row,
1927
1276
  className
@@ -1931,109 +1280,24 @@ declare function SessionStatusIcon({
1931
1280
  }): _$react.JSX.Element;
1932
1281
  //#endregion
1933
1282
  //#region src/components/agent/SessionBrowser.d.ts
1934
- /**
1935
- * A sessions list with the affordances a list of thirty needs: search, facets,
1936
- * grouping, sorting, unread counts, and one honest line about what is hidden.
1937
- *
1938
- * The *rules* are `@workerdeck/protocol`'s (`filterRows`/`groupRows`/
1939
- * `subsetSummary`), not this component's — the VS Code sidebar renders the same
1940
- * model with workbench chrome, its activity-bar badge counts the same rows this
1941
- * would show, and iOS mirrors them in Swift. What lives here is the styled
1942
- * rendering of that model, so a host that wants the dashboard's look gets it
1943
- * without reimplementing the model behind it.
1944
- *
1945
- * `SessionList` remains beside this for the plain case (a fixed set of rows, no
1946
- * controls); this is what you reach for when the list is the screen.
1947
- */
1948
1283
  interface SessionBrowserProps {
1949
1284
  rows: SessionRow[];
1950
1285
  config: ViewConfig;
1951
1286
  onConfigChange: (config: ViewConfig) => void;
1952
- /** The host's own folders, if it has such a notion. Absent — a dashboard, a
1953
- * phone — makes the scope filter genuinely inert rather than empty. */
1954
1287
  scope?: WorkspaceScope;
1955
1288
  activeId?: string;
1956
- /**
1957
- * Which sub-agent the host currently has open, by tool-use id — the *finer*
1958
- * of the two selections. The card holding it drops to the secondary grey and
1959
- * that step takes the blue; see `SessionItem`. A host with no sub-agent
1960
- * surface leaves it undefined and nothing changes.
1961
- */
1962
1289
  activeSubagentId?: string;
1963
1290
  onSelect?: (row: SessionRow) => void;
1964
1291
  onDelete?: (row: SessionRow) => void;
1965
- /**
1966
- * Rename, from the row's pencil. Empty string restores the derived title. A
1967
- * gateway edit (`PATCH /sessions/:id`), never a local override — every client
1968
- * should see the same name. Omit to make titles read-only.
1969
- *
1970
- * A hover affordance rather than the extension's double-click-the-title,
1971
- * because here a single click on the row navigates: the *first* click of a
1972
- * double-click would have already left the page.
1973
- */
1974
1292
  onRename?: (row: SessionRow, title: string) => void;
1975
- /**
1976
- * Clear the conversation in place, from the row's eraser. Same session, empty
1977
- * context — **not** a delete: the engine keeps the old conversation and it
1978
- * stays resumable, which is why the row's copy never says "deleted".
1979
- *
1980
- * Rendered only where the session's own capability record allows it
1981
- * (`capabilities.clearContext`, absent = false), so a row that cannot be
1982
- * cleared has no eraser rather than one that errors. Omit the prop to have
1983
- * none at all — a host with no way to send a session command has nothing to
1984
- * hang it on (this is a WS command, not a REST route).
1985
- */
1986
1293
  onClearContext?: (row: SessionRow) => void;
1987
- /** Open a session *at* one of its sub-agents, when the host can scroll a
1988
- * transcript to a `Task` row. Absent, the sub-agent list still expands and a
1989
- * step just opens its session — see `SessionRowItemProps`. */
1990
1294
  onSelectSubagent?: (row: SessionRow, toolUseId: string) => void;
1991
- /** Open a session and travel to one of its **tasks** — see
1992
- * `SessionItem.onRevealStep`. A task has no agent behind it, so it is a place
1993
- * to go rather than a thing to open, and framing it as an agent drew an empty
1994
- * view. */
1995
1295
  onRevealStep?: (row: SessionRow, toolUseId: string) => void;
1996
- /** Rendered when nothing at all exists (as opposed to nothing matching). */
1997
1296
  emptyState?: React.ReactNode;
1998
- /**
1999
- * Whether the search + facet bar is shown. Defaults to `true` — a list that
2000
- * *is* the screen shows its controls.
2001
- *
2002
- * A host with somewhere better to put the toggle (a view title bar) passes
2003
- * `false` and owns the boolean itself, the way the VS Code extension does: the
2004
- * key lives where the commands do. Two rules come with it, and they are why
2005
- * this hides only the bar and nothing else — **closing the bar never clears
2006
- * the filters**, and the subset line below it renders either way, so a list
2007
- * filtered by a control you can't currently see still says so.
2008
- */
2009
1297
  showControls?: boolean;
2010
- /**
2011
- * Resolved project-icon bytes by content hash — `useProjectIcons`' output.
2012
- *
2013
- * Passed in rather than fetched here for the reason `ProjectIcon` states: the
2014
- * wire carries an *address*, and who can fetch it differs per client. Absent,
2015
- * or a hash not in it yet, simply draws no picture; the project's name is
2016
- * already there.
2017
- */
2018
1298
  projectIcons?: Record<string, string>;
2019
1299
  className?: string;
2020
1300
  }
2021
- /**
2022
- * How a list row is drawn, in one place, so `SidebarRow` in `web` matches this
2023
- * exactly rather than approximating it — the dashboard's other three sidebars
2024
- * are that component, and a sessions list that hovered differently from the
2025
- * gateways list beside it would read as a different product.
2026
- *
2027
- * Two rules are load-bearing:
2028
- *
2029
- * - **Fill means hover, and only hover.** It stays on the row whether or not
2030
- * the row is selected, because a selected row still has to answer the
2031
- * pointer. Selection gets the gutter instead.
2032
- * - **`ml-0` on the selected row is not cosmetic.** It hands the accent border
2033
- * the 4px the margin was holding, so the text does not shift sideways as a
2034
- * row becomes the selected one. The squared left corners are what let the bar
2035
- * sit flush against the sidebar edge.
2036
- */
2037
1301
  declare function rowShapeClass(active: boolean): string;
2038
1302
  declare function SessionBrowser({
2039
1303
  rows,
@@ -2055,132 +1319,22 @@ declare function SessionBrowser({
2055
1319
  }: SessionBrowserProps): _$react.JSX.Element;
2056
1320
  //#endregion
2057
1321
  //#region src/components/agent/SessionItem.d.ts
2058
- /**
2059
- * One session in a list — the **card**, and the only drawing of it in the
2060
- * product.
2061
- *
2062
- * The dashboard's `SessionBrowser` and the VS Code sidebar both render this;
2063
- * before it existed they rendered two hand-kept copies that agreed on the model
2064
- * and disagreed on every measurement, and the two lists read as two products.
2065
- * iOS mirrors this file's geometry rather than either copy.
2066
- *
2067
- * ## The shape
2068
- *
2069
- * A 4px-padded, 4px-rounded card whose whole surface is the hit target, holding
2070
- * two 20px lines and, when it is open, the work under them.
2071
- *
2072
- * **Line one is state and identity**: the status glyph leads, the title takes
2073
- * the rest, and the line closes with the unread badge and the context ring. The
2074
- * glyph leads because a sessions list is scanned for *state* first — which of
2075
- * these is working, which is waiting on me — and the title is what you read once
2076
- * the glyph has told you which row to read. The two readings that close the line
2077
- * are the two that change while you are looking at them.
2078
- *
2079
- * **Line two is identity and cost**: the engine's mark and its model in the
2080
- * vendor's own colour, then the project, then everything else the host wants
2081
- * said, then the age — a `·`-joined run that ends in the one part of it that
2082
- * keeps moving. The line's right edge belongs to the disclosure (which doubles
2083
- * as the count of the work below, so the card says how much there is without
2084
- * being opened) and to the host's own actions.
2085
- *
2086
- * **The gutter is one 16px cell, shared by both lines.** The two glyphs are
2087
- * different sizes and laying them out as plain flex children starts the two
2088
- * text columns at different x — two pixels, invisible as a measurement and
2089
- * obvious as a misalignment. Centring inside a fixed cell fixes the text edges
2090
- * and the ink centres at once. It is the terminal gutter's argument at card
2091
- * scale.
2092
- *
2093
- * ## Selection
2094
- *
2095
- * **Selection is the card's own fill**, not a gutter bar: the card is an inset
2096
- * shape with air around it, so filling it is unambiguous in a way a fill on a
2097
- * full-bleed row is not, and it leaves the left edge to the state glyph.
2098
- *
2099
- * There are **two selections at two grains**, and the card and its steps split
2100
- * them:
2101
- *
2102
- * | what is on screen | card | the step |
2103
- * | --- | --- | --- |
2104
- * | nothing | transparent, hovers | transparent, hovers |
2105
- * | this session | `--row-selected` (blue) | transparent, hovers |
2106
- * | one of its sub-agents | `--row-selected-weak` (grey) | `--row-selected` (blue) |
2107
- *
2108
- * **The blue always marks the finest thing selected.** Opening a sub-agent
2109
- * selects its session too, so both claims are true at once and the blue can only
2110
- * carry one; it goes to the agent, and the card steps back to grey — present,
2111
- * holding what you are looking at, not itself the thing you are looking at.
2112
- * Reversing that (blue card, blue row inside it) says nothing, which is what a
2113
- * blue-on-blue card looked like.
2114
- *
2115
- * A filled card does **not** also answer hover: the fill is already spent, and a
2116
- * selected row that lightened under the pointer read as a third state nobody
2117
- * could name. Its steps still do, on `--row-active`, which is a tint and so
2118
- * works on all three grounds.
2119
- *
2120
- * A **task** never takes the blue. It is a reference to a place inside a
2121
- * session, so pressing one selects the session and travels to its marker — see
2122
- * `StepRow`.
2123
- */
2124
1322
  interface SessionItemProps {
2125
1323
  row: SessionRow;
2126
- /** This session is the one the host is showing. */
2127
1324
  active?: boolean;
2128
- /**
2129
- * Which sub-agent is open, by `Step.key` — the *finer* of the two selections.
2130
- * When it names one of this card's agents, that step takes the blue and the
2131
- * card drops to the secondary grey. A key belonging to some other card's
2132
- * agent, or to a task, changes nothing here.
2133
- */
2134
1325
  activeStepKey?: string;
2135
- /** Shown when the list is not already grouped by gateway. */
2136
1326
  showGateway?: boolean;
2137
- /**
2138
- * False when the list is already grouped by project — the header above has
2139
- * said the name, so the card must not spend its metadata line repeating it.
2140
- * What takes the slot is the *sub-path inside the project*
2141
- * (`projectSubpath`): `packages/ui`, `packages/server` — the one thing the
2142
- * header cannot say and the only thing that tells two sessions in one repo
2143
- * apart. A session at the project root has nothing to add and the slot
2144
- * disappears entirely. Exactly the rule `showGateway` follows one facet over.
2145
- */
2146
1327
  showProject?: boolean;
2147
- /** Resolved project-icon bytes by content hash. A hash this map has not got
2148
- * yet simply draws no icon. */
2149
1328
  projectIcons?: Record<string, string>;
2150
- /** Uncontrolled by default — pass both to drive expansion from the host. */
2151
1329
  expanded?: boolean;
2152
1330
  onExpandedChange?: (expanded: boolean) => void;
2153
1331
  onSelect?: () => void;
2154
- /** Open the session *at* one of its sub-agents — hand the panel body over to
2155
- * that agent's own work. Only ever called for an **agent** step. Absent is not
2156
- * a missing feature: without it a step just opens the session, which is all a
2157
- * host with no sub-agent surface can offer. */
2158
1332
  onSelectSubagent?: (toolUseId: string) => void;
2159
- /**
2160
- * Open the session and travel to a **task**'s row in the transcript — where
2161
- * the work was started, and where it finished.
2162
- *
2163
- * A separate seam from `onSelectSubagent` because the destinations are
2164
- * different, and conflating them is not a styling detail: a task has no agent
2165
- * behind it, so framing its tool-use id selects **no items at all** and the
2166
- * panel draws an empty agent view. That was the bug. A task is a reference,
2167
- * and the only honest thing to do with a reference is follow it.
2168
- */
2169
1333
  onRevealStep?: (toolUseId: string) => void;
2170
- /** Enables in-place rename. The trigger is the host's — see `renameOn`. */
2171
1334
  onRename?: (title: string) => void;
2172
- /**
2173
- * How a rename starts. `doubleClick` is the editor feel (a rename is a thing
2174
- * you do to the word you are looking at); `external` means the host opens it
2175
- * from its own affordance — a menu entry, a pencil in `actions` — and drives
2176
- * it through `editing`/`onEditingChange`.
2177
- */
2178
1335
  renameOn?: 'doubleClick' | 'external';
2179
1336
  editing?: boolean;
2180
1337
  onEditingChange?: (editing: boolean) => void;
2181
- /** The card's trailing controls, at the end of line two. A single overflow
2182
- * glyph is what the design draws; a host with three always-on actions can put
2183
- * them here instead. */
2184
1338
  actions?: ReactNode;
2185
1339
  className?: string;
2186
1340
  }
@@ -2205,25 +1359,8 @@ declare function SessionItem({
2205
1359
  }: SessionItemProps): _$react.JSX.Element;
2206
1360
  //#endregion
2207
1361
  //#region src/components/agent/EngineIcon.d.ts
2208
- /**
2209
- * Which mark a session wears.
2210
- *
2211
- * The two first-party engines are named directly. A `provider` session is
2212
- * whatever the host wired up, so its *model* is the only thing that says whose
2213
- * it is — sniffed loosely on purpose (`gemini-2.5-pro`, `deepseek-chat`,
2214
- * `kimi-k2`), and falling through to no mark rather than guessing wrong.
2215
- */
2216
1362
  declare function engineMark(engine: string, model?: string): string | undefined;
2217
- /** The colour a session's engine mark wears. Pass it to `EngineIcon`'s
2218
- * `className` rather than to a parent: the svg carries its own `text-fg-3`,
2219
- * and only a class on the element itself is merged over it. */
2220
1363
  declare function vendorMarkClass(engine: string, model?: string): string;
2221
- /** The colour the model *name* wears beside that mark — muted unless the vendor
2222
- * is one whose accent survives at label size. See `VENDOR_TEXT`.
2223
- *
2224
- * The fallback is `text-fg-3` rather than the metadata line's own `text-fg-4`,
2225
- * so an unbranded model still sits one step above the project and gateway
2226
- * beside it — the order the spec lists them in, held without a colour. */
2227
1364
  declare function vendorTextClass(engine: string, model?: string): string;
2228
1365
  declare function EngineIcon({
2229
1366
  engine,
@@ -2236,88 +1373,18 @@ declare function EngineIcon({
2236
1373
  }): _$react.JSX.Element;
2237
1374
  //#endregion
2238
1375
  //#region src/components/agent/SessionSteps.d.ts
2239
- /**
2240
- * The work *under* a session row, and the one row shape every client renders it
2241
- * through.
2242
- *
2243
- * This lived inside the VS Code webview first, which is exactly why the
2244
- * dashboard had none of it. Nothing in here is extension-specific: a session's
2245
- * sub-agents are a protocol fact, and a disclosure over them is a list
2246
- * affordance. It sits in `packages/ui` so the sidebar, the dashboard and (in its
2247
- * own idiom) the phone are annotating rows the same way rather than three ways.
2248
- *
2249
- * Today the only source is `SessionInfo.subagents`. The other — the CLI's own
2250
- * **task checklist**, the to-do list it keeps for the current turn — is what the
2251
- * design was drawn from, and it is not built: nothing on the wire carries it yet
2252
- * (see `_docs/features/sub-agent-handling.md`, second thread, which opens with
2253
- * "check a capture" rather than "design a surface"). When it arrives it is a
2254
- * *source*, not a second row component: checklist when the session has one, its
2255
- * sub-agents otherwise.
2256
- *
2257
- * That is also why `state` has a `pending` arm no sub-agent can produce. A
2258
- * sub-agent record exists only once dispatched, so it is never queued; a to-do
2259
- * is queued for most of its life, and dropping the state would mean widening the
2260
- * union later — the shape is cheaper to state now than to retrofit.
2261
- */
2262
1376
  type Step = {
2263
1377
  key: string;
2264
- label: string; /** What one of these is called, for the disclosure's count. */
1378
+ label: string;
2265
1379
  noun: string;
2266
- /**
2267
- * Both kinds press. The kind decides **where the press goes**, which is the
2268
- * whole of the distinction.
2269
- *
2270
- * An **agent** has an identity and work of its own, so it wears the sub-agent
2271
- * colour and opens that agent's own frame. A **task** is something the model
2272
- * described with no agent behind it (`isAgentRecord`), so there is no frame:
2273
- * framing its id selects no items and draws an empty screen. What it has
2274
- * instead is a *place* — the spawning call's row in the transcript — so it is
2275
- * muted, never selected, and travels there. See `StepRow` for why an inert
2276
- * row was the worse answer.
2277
- *
2278
- * Two values and not a boolean because the checklist source this shape was
2279
- * drawn for (see above) produces the second kind natively — a to-do is a task
2280
- * in exactly this sense, and it will slot in here rather than widening
2281
- * anything.
2282
- */
2283
1380
  kind: 'agent' | 'task';
2284
- state: 'done' | 'running' | 'pending' | 'failed'; /** A trailing reading — a sub-agent's tool count. Absent draws nothing. */
1381
+ state: 'done' | 'running' | 'pending' | 'failed';
2285
1382
  detail?: string;
2286
1383
  title: string;
2287
1384
  onSelect: () => void;
2288
1385
  };
2289
- /**
2290
- * The steps under one session, **agents first**.
2291
- *
2292
- * The two kinds do different things when pressed and are worth different
2293
- * amounts of attention: an agent has work of its own to go and read, a task is a
2294
- * marker in a transcript. Interleaved in dispatch order they read as one
2295
- * undifferentiated list, and the rows you can actually open are scattered
2296
- * through it. Grouped, the openable ones are a block at the top and the markers
2297
- * are a tail you can skip.
2298
- *
2299
- * Stable **within** each group, deliberately: dispatch order is the only order
2300
- * these records have that means anything (it is the order the work was started
2301
- * in), so the sort partitions and never reorders inside a partition.
2302
- *
2303
- * `onSelect` is handed the **kind** as well as the id, because the two kinds go
2304
- * to different places — see `SessionItem`, which is what routes them. Passing
2305
- * only the id is what let a task be opened as if it were an agent, and a framed
2306
- * task id matches no items, so the panel drew an **empty agent view**.
2307
- */
2308
1386
  declare function sessionSteps(info: SessionInfo, onSelect: (toolUseId: string, kind: Step['kind']) => void): Step[];
2309
- /** How many of these are still going — the live half of the disclosure's count. */
2310
1387
  declare function runningSteps(steps: readonly Step[]): number;
2311
- /**
2312
- * The disclosure, which is also the reading: `3 agents` — or `2 of 3 agents`
2313
- * while some have settled, because "how many are still going" is the live
2314
- * question and a bare total answers it wrong the moment one finishes.
2315
- *
2316
- * Sub-agents are an annotation on a working row rather than a state of their own
2317
- * (see `runningSubagents` in protocol's `session-list.ts`), so this never
2318
- * competes with the row's status glyph: that still says what the *session* is
2319
- * doing.
2320
- */
2321
1388
  declare function StepToggle({
2322
1389
  expanded,
2323
1390
  running,
@@ -2331,78 +1398,17 @@ declare function StepToggle({
2331
1398
  noun: string;
2332
1399
  onToggle: () => void;
2333
1400
  }): _$react.JSX.Element;
2334
- /**
2335
- * One step under its session — **pressable, all of them**, and what a press
2336
- * means is what tells the two kinds apart.
2337
- *
2338
- * Pressing an **agent** hands the panel over to that agent's own work
2339
- * (`SessionPanel.openSubagent`): it is not a session and never becomes one, but
2340
- * it has a surface, so it can be the selected thing. Pressing a **task** selects
2341
- * the *session* and travels to that task's marker inside it — a task is a
2342
- * reference to a place in a transcript, not a thing with a screen, so it can be
2343
- * followed but never held.
2344
- *
2345
- * That is a reversal, and a deliberate one. A task used to be inert markup on
2346
- * the argument that "a disabled-looking button still announces itself as one" —
2347
- * correct about the markup, wrong about the premise, because there *was* always
2348
- * somewhere to go and the row simply swallowed the click on its way there. A row
2349
- * that looks like a list item, sits in a list, and does nothing when pressed is
2350
- * the worse lie. So every step answers the pointer and every step answers a
2351
- * press; only what the press does differs.
2352
- *
2353
- * Divided from the card's header by **indentation and its own hit shape**, not
2354
- * by a rule. The rules came first, on the argument that at 11px an indent is not
2355
- * enough to say "list inside a row" — and they were right about the reading and
2356
- * wrong about the cost: a stack of hairlines across every open card turned the
2357
- * list into a ledger, and a rule cannot answer a pointer. A step that lights up
2358
- * under the cursor and fills when it is the one on screen says *list* far more
2359
- * plainly than a line between two of them, and it says it while doing the job
2360
- * the rule could not.
2361
- *
2362
- * **Only an agent can wear the selection**, and `active` is guarded on that here
2363
- * rather than trusted from the caller: a host that hands back a task's key is
2364
- * describing where it navigated, not what it selected, and the row must not
2365
- * paint itself blue for it.
2366
- *
2367
- * The hover is `--row-active` — **alpha, not a flat fill** — because this row
2368
- * has to answer the pointer on three different grounds: a transparent card, a
2369
- * blue one (its session is selected), and a grey one (a sibling agent is). A
2370
- * flat value tuned for any of those is wrong on the other two; a tint darkens or
2371
- * lifts whatever it lands on. It is the one place in the list where the alpha
2372
- * token earns its keep.
2373
- */
2374
1401
  declare function StepRow({
2375
1402
  step,
2376
1403
  active,
2377
1404
  onSelect
2378
1405
  }: {
2379
1406
  step: Step;
2380
- /** The panel is showing this step's own work. Ignored for tasks, which cannot
2381
- * be the selected thing — see above. */
2382
1407
  active?: boolean;
2383
1408
  onSelect: () => void;
2384
1409
  }): _$react.JSX.Element;
2385
1410
  //#endregion
2386
1411
  //#region src/components/agent/SubagentStrip.d.ts
2387
- /**
2388
- * The one line above a sub-agent takeover: who this is, how it is doing, and the
2389
- * way back.
2390
- *
2391
- * **It claims exactly what the `TaskRow` it was opened from claims** — the same
2392
- * `taskBusy` / `taskFailed` / tool count over the same items — and deliberately
2393
- * *not* `SubagentInfo.status`. Protocol documents those two as divergent on
2394
- * purpose (`index.ts:1476-1487`), but that divergence is transcript-versus-*list*
2395
- * and this surface **is** the transcript. The disagreement that must not exist
2396
- * here is between a header and the rows directly beneath it.
2397
- *
2398
- * The rollup is still allowed one job — naming an agent whose `Task` call is not
2399
- * in the transcript — because a label is not content, and `SessionInfo.subagents`
2400
- * keeps only eight settled records (`SUBAGENT_HISTORY`), so it can never be the
2401
- * source of what a frame *shows*.
2402
- *
2403
- * Both variants, because the panel has two and a strip that only existed in one
2404
- * would make the takeover a terminal-theme feature rather than a session feature.
2405
- */
2406
1412
  declare function SubagentStrip({
2407
1413
  task,
2408
1414
  items,
@@ -2412,10 +1418,8 @@ declare function SubagentStrip({
2412
1418
  fontSize,
2413
1419
  lineHeight
2414
1420
  }: {
2415
- /** The spawning call. Absent when the transcript does not have it — the strip
2416
- * still draws, because the way back must exist even when the content cannot. */
2417
- task: ToolCallItem$1 | undefined; /** The frame's items, for the busy reading and the tool count. */
2418
- items: readonly TranscriptItem[]; /** Fallback name when there is no task item. */
1421
+ task: ToolCallItem$1 | undefined;
1422
+ items: readonly TranscriptItem[];
2419
1423
  label: string;
2420
1424
  onBack: () => void;
2421
1425
  terminal: boolean;
@@ -2431,9 +1435,7 @@ declare function ProjectIcon({
2431
1435
  className
2432
1436
  }: {
2433
1437
  icon: ProjectIcon$1 | undefined;
2434
- /** Resolved bytes for the `image` arm — an object URL or a data URL. The
2435
- * caller fetches (see the note above); absent draws nothing. */
2436
- src?: string; /** The project's name, for the alt text. */
1438
+ src?: string;
2437
1439
  name?: string;
2438
1440
  className?: string;
2439
1441
  }): _$react.JSX.Element | null;
@@ -2441,29 +1443,11 @@ declare function ProjectIcon({
2441
1443
  //#region src/components/agent/SessionEmptyState.d.ts
2442
1444
  interface SessionEmptyStateProps {
2443
1445
  cwd?: string;
2444
- /** Whether `/command` completion is live yet — the CLI reports its commands a
2445
- * beat after the session starts, and promising a feature that isn't wired up
2446
- * yet is worse than not mentioning it. */
2447
1446
  hasCommands?: boolean;
2448
- /** Whether the engine has reported skills the `/` popover can offer. Its own
2449
- * flag, not a variant of `hasCommands`: what `/` does differs — a command is
2450
- * submitted, a skill is typed for you to edit — and an engine can have one
2451
- * without the other. */
2452
1447
  hasSkills?: boolean;
2453
- /** Whether this gateway serves `@file` search for the session's directory. */
2454
1448
  canBrowseFiles?: boolean;
2455
1449
  className?: string;
2456
1450
  }
2457
- /**
2458
- * What a session shows before it has said anything: where the agent is sitting,
2459
- * and what the composer accepts beyond prose.
2460
- *
2461
- * Every hint is conditional on the affordance actually existing — an engine
2462
- * without slash commands, or a gateway without host files, is not told about
2463
- * them. Deliberately no project name (the header already carries it) and no
2464
- * brand mark (its geometry is inlined in several places already and they are
2465
- * meant to stay identical).
2466
- */
2467
1451
  declare function SessionEmptyState({
2468
1452
  cwd,
2469
1453
  hasCommands,
@@ -2473,16 +1457,6 @@ declare function SessionEmptyState({
2473
1457
  }: SessionEmptyStateProps): _$react.JSX.Element;
2474
1458
  //#endregion
2475
1459
  //#region src/components/agent/PromptTokenText.d.ts
2476
- /**
2477
- * A sent message, with its `@file` and `/command` tokens styled the way the CLI
2478
- * writes them: monospace and tinted, no background — the bubble already has one,
2479
- * and a second fill inside it reads as a button.
2480
- *
2481
- * Literal text, never markdown: what was typed is what was sent. The one pass
2482
- * over it is this, so a message reads the same after sending as it did in the
2483
- * composer. Two tokens, two meanings — a file is a reference, a command is an
2484
- * action — so they are told apart by hue rather than by shape alone.
2485
- */
2486
1460
  declare function PromptTokenText({
2487
1461
  text,
2488
1462
  className
@@ -2499,23 +1473,6 @@ declare const STATUS_META: Record<SessionStatus, {
2499
1473
  }>;
2500
1474
  //#endregion
2501
1475
  //#region src/components/agent/ContextRing.d.ts
2502
- /**
2503
- * How full a session's context window is, sized for a **list row**.
2504
- *
2505
- * The reading the session screen has always drawn, moved somewhere it answers a
2506
- * question the session screen cannot: *which* of these thirty sessions is
2507
- * bloating. That is also why it is a ring and not a number — across a list, a
2508
- * ring is read at a glance and `71%` has to be read one row at a time.
2509
- *
2510
- * **Absent draws nothing, and absent is not zero.** A promptless session, a
2511
- * parked one from before the field existed, or an engine that reports no window
2512
- * has no reading; an empty ring would claim its context is empty rather than
2513
- * unknown. The title carries the exact numbers for anyone who wants them.
2514
- *
2515
- * Shared rather than spelled per client: the dashboard's row and the VS Code
2516
- * sidebar's card both draw it, and two copies would be two sets of thresholds
2517
- * the day one of them is nudged.
2518
- */
2519
1476
  declare function ContextRing({
2520
1477
  usage,
2521
1478
  size,
@@ -2530,42 +1487,10 @@ declare function ContextRing({
2530
1487
  declare function cn(...inputs: ClassValue[]): string;
2531
1488
  //#endregion
2532
1489
  //#region src/lib/clipboard.d.ts
2533
- /**
2534
- * Copy text to the clipboard, on origins where the modern API does not exist.
2535
- *
2536
- * `navigator.clipboard` is gated on a **secure context**: HTTPS, or localhost.
2537
- * A WorkerDeck dashboard reached the way it is meant to be reached — plain HTTP
2538
- * on a LAN address, from a laptop or a phone — is neither, so `navigator.clipboard`
2539
- * is `undefined` there and touching `.writeText` throws outright. That is the
2540
- * normal deployment, not an edge case, which is why this falls back rather than
2541
- * feature-detecting into a disabled button.
2542
- *
2543
- * The fallback is `document.execCommand('copy')` over an off-screen textarea.
2544
- * It is deprecated and it is also the only thing that works here; every browser
2545
- * still implements it. Returns whether the text actually landed, so a caller can
2546
- * avoid claiming success it did not have.
2547
- */
2548
1490
  declare function copyText(value: string): Promise<boolean>;
2549
1491
  //#endregion
2550
1492
  //#region src/lib/tool-icon.d.ts
2551
- /**
2552
- * An icon per tool, so a transcript can be skimmed by shape rather than read.
2553
- *
2554
- * The same mapping the iOS app makes, in lucide's vocabulary rather than SF
2555
- * Symbols — the two clients should be recognisably showing the same thing. An
2556
- * unknown tool falls back to a wrench, and an MCP tool (`mcp__server__name`) to
2557
- * the puzzle piece the MCP screens use, because "which server is this from" is
2558
- * the useful thing to see at a glance.
2559
- */
2560
1493
  declare function toolIcon(toolName: string): LucideIcon;
2561
- /**
2562
- * Does this tool *change* the workspace?
2563
- *
2564
- * Worth its own colour in a transcript: skimming a run, "what did it edit" is a
2565
- * different question from "what did it look at", and a write is the one you
2566
- * might need to undo. Names from both first-party engines; an MCP tool is
2567
- * unknowable from its name, so it reads as neutral rather than guessed.
2568
- */
2569
1494
  declare function isMutatingTool(toolName: string): boolean;
2570
1495
  //#endregion
2571
1496
  export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, type BadgeProps, Band, Blank, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type ChipSegment, CodeBlock, type CodeBlockProps, Composer, type ComposerFileMatch, type ComposerHandle, type ComposerProps, ContextDialog, type ContextDialogProps, ContextRing, Conversation, ConversationContent, type ConversationProps, ConversationScrollButton, CopyAction, CopyButton, type CopyButtonProps, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, Empty, EmptyKey, EngineIcon, FileCard, type FileCardProps, type FileDeliveredItem, HostFilesDialog, type HostFilesDialogProps, Ink, Input, Loader, McpDialog, type McpDialogProps, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, type MessageProps, ModelSelect, type ModelSelectProps, PERMISSION_MODES, type PermissionModeChoice, type PermissionModeMeta, PermissionModeSelect, type PermissionModeSelectProps, PermissionPrompt, type PermissionPromptProps, ProgressRing, type ProgressRingProps, ProjectIcon, PromptArea, type PromptAreaHandle, type PromptAreaProps, PromptTokenText, QUESTION_BEHAVIORS, type QuestionBehaviorMeta, QuestionPrompt, type QuestionPromptProps, Reasoning, type ReasoningProps, Response, type ResponseProps, Row, type RowProps, STATUS_META, type Segment, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, type SessionBrowserProps, type SessionControls, SessionEmptyState, type SessionEmptyStateProps, SessionInfoDialog, type SessionInfoDialogProps, SessionItem, type SessionItemProps, SessionList, SessionListItem, type SessionListItemProps, type SessionListProps, SessionPanel, type SessionPanelProps, SessionStatusIcon, type SessionSurfacePanel, type SessionVitals, SkillsDialog, type SkillsDialogProps, Spinner, Splitter, type SplitterProps, StatusBar, type StatusBarProps, type Step, StepRow, StepToggle, SubagentStrip, type TerminalAffordances, TerminalDiff, TerminalItemView, TerminalMarkdown, type TerminalMarkdownProps, type TerminalMetrics, TerminalPermissionPrompt, type TerminalPermissionPromptProps, TerminalQuestionPrompt, type TerminalQuestionPromptProps, TerminalStatusLine, type TerminalStatusLineProps, TerminalSurface, type TerminalSurfaceProps, TerminalTranscript, type TerminalTranscriptProps, type TextSegment, Textarea, Tip, Toaster, type Tone, ToolCallCard, type ToolCallCardProps, type ToolCallItem, TooltipContent, TooltipProvider, Transcript, type TranscriptDensity, TranscriptDensityProvider, type TranscriptFont, type TranscriptProps, type TranscriptVariant, TranscriptVariantProvider, type TriggerConfig, type TriggerSuggestion, UsageDialog, type UsageDialogProps, UsageMeters, WithActions, badgeVariants, buttonVariants, cn, commandTrigger, copyText, engineMark, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, previewPatch, rateLimitWindowSeconds, rowShapeClass, runningSteps, segmentsToPlainText, sessionSteps, skillPrompt, toast, toolIcon, toolInputPreview, useAffordances, useMinuteClock, usePromptAreaState, useTranscriptDensity, useTranscriptVariant, vendorMarkClass, vendorTextClass };