@workerdeck/ui 0.13.0 → 0.16.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 (69) hide show
  1. package/README.md +72 -0
  2. package/build/{SessionPanel-CZMA44NM.d.mts → SessionPanel-B9CHoq8x.d.mts} +213 -27
  3. package/build/{SessionPanel-CKQa4i0Y.mjs → SessionPanel-DII9MmQ8.mjs} +5192 -2542
  4. package/build/SessionPanel-DII9MmQ8.mjs.map +1 -0
  5. package/build/{format-ljc3lKpA.d.mts → format-DfI_je9S.d.mts} +1 -1
  6. package/build/format.d.mts +39 -4
  7. package/build/format.mjs +2 -118
  8. package/build/index.d.mts +494 -45
  9. package/build/index.mjs +182 -24
  10. package/build/index.mjs.map +1 -1
  11. package/build/status-Ydzi7n6j.mjs +143 -0
  12. package/build/status-Ydzi7n6j.mjs.map +1 -0
  13. package/build/workspace.d.mts +13 -1
  14. package/build/workspace.mjs +111 -5
  15. package/build/workspace.mjs.map +1 -1
  16. package/package.json +14 -7
  17. package/src/components/agent/Composer.tsx +251 -84
  18. package/src/components/agent/Conversation.tsx +12 -12
  19. package/src/components/agent/FileCard.tsx +0 -26
  20. package/src/components/agent/FileTree.tsx +9 -8
  21. package/src/components/agent/Loader.tsx +22 -72
  22. package/src/components/agent/Message.tsx +11 -43
  23. package/src/components/agent/PermissionPrompt.tsx +0 -92
  24. package/src/components/agent/QuestionPrompt.tsx +0 -122
  25. package/src/components/agent/Reasoning.tsx +5 -19
  26. package/src/components/agent/Response.tsx +1 -132
  27. package/src/components/agent/SessionBrowser.tsx +35 -25
  28. package/src/components/agent/SessionPanel.tsx +312 -63
  29. package/src/components/agent/SessionWorkspace.tsx +36 -0
  30. package/src/components/agent/StatusBar.tsx +70 -15
  31. package/src/components/agent/ToolCallCard.tsx +17 -111
  32. package/src/components/agent/Transcript.tsx +710 -203
  33. package/src/components/agent/UsageDialog.tsx +20 -106
  34. package/src/components/agent/UsageMeters.tsx +133 -0
  35. package/src/components/agent/pulse.tsx +3 -2
  36. package/src/components/agent/transcript-rows.ts +82 -0
  37. package/src/components/agent/transcript-variant.tsx +43 -51
  38. package/src/components/agent/use-height-epoch.ts +60 -0
  39. package/src/components/agent/use-path-links.ts +147 -0
  40. package/src/components/agent/use-transcript-jumps.ts +190 -0
  41. package/src/components/prompt-area/cursor-helpers.ts +65 -0
  42. package/src/components/prompt-area/use-prompt-area.ts +16 -10
  43. package/src/components/terminal/PermissionPrompt.tsx +119 -0
  44. package/src/components/terminal/QuestionPrompt.tsx +322 -0
  45. package/src/components/terminal/StatusLine.tsx +159 -0
  46. package/src/components/terminal/TerminalTranscript.tsx +147 -0
  47. package/src/components/terminal/affordances.tsx +118 -0
  48. package/src/components/terminal/diff.tsx +130 -0
  49. package/src/components/terminal/height.ts +727 -0
  50. package/src/components/terminal/items.tsx +449 -0
  51. package/src/components/terminal/markdown.tsx +191 -0
  52. package/src/components/terminal/press.tsx +120 -0
  53. package/src/components/terminal/prompt.tsx +343 -0
  54. package/src/components/terminal/result-preview.ts +72 -0
  55. package/src/components/terminal/row.tsx +132 -0
  56. package/src/components/terminal/scrubber.tsx +663 -0
  57. package/src/components/terminal/surface.tsx +80 -0
  58. package/src/components/terminal/tool-run.ts +91 -0
  59. package/src/components/ui/Badge.tsx +6 -1
  60. package/src/components/ui/Empty.tsx +56 -0
  61. package/src/components/ui/Splitter.tsx +14 -0
  62. package/src/index.ts +36 -0
  63. package/src/lib/status.ts +59 -3
  64. package/src/lib/tool-icon.ts +14 -0
  65. package/src/styles/terminal.css +1011 -0
  66. package/src/styles/theme.css +73 -0
  67. package/build/SessionPanel-CKQa4i0Y.mjs.map +0 -1
  68. package/build/format.mjs.map +0 -1
  69. package/src/components/agent/line-prompt.tsx +0 -249
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 { _ as permissionModeChoices, a as SessionVitals, c as TranscriptVariant, d as useTranscriptVariant, f as PERMISSION_MODES, g as PermissionModeSelectProps, h as PermissionModeSelect, i as SessionSurfacePanel, l as TranscriptVariantProvider, m as PermissionModeMeta, n as SessionPanel, o as TranscriptDensity, p as PermissionModeChoice, r as SessionPanelProps, s as TranscriptDensityProvider, t as SessionControls, u as useTranscriptDensity, v as permissionModeMeta } from "./SessionPanel-CZMA44NM.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-DfI_je9S.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-B9CHoq8x.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";
@@ -15,7 +15,7 @@ import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
15
15
  import * as _$_base_ui_react_tooltip0 from "@base-ui/react/tooltip";
16
16
  import { Tooltip } from "@base-ui/react/tooltip";
17
17
  import { toast } from "sonner";
18
- import { ContextUsage, ModelOption, PermissionRequest, ProfileEngine, QuestionBehavior, RateLimitInfo, SessionInfo, SessionRow, SessionStatus, SkillInfo, SlashCommandInfo, UserQuestion, ViewConfig, WorkspaceScope } from "@workerdeck/protocol";
18
+ import { ContextUsage, FilePatch, ModelOption, PermissionRequest, ProfileEngine, QuestionBehavior, RateLimitInfo, SessionInfo, SessionRow, SessionStatus, SkillInfo, SlashCommandInfo, UsageWindowRow, UserQuestion, ViewConfig, WorkspaceScope } from "@workerdeck/protocol";
19
19
  import { ConnectionState, TranscriptItem, TranscriptState, UseAttachmentsResult } from "@workerdeck/react";
20
20
  import * as _$class_variance_authority_types0 from "class-variance-authority/types";
21
21
  import { WorkerDeckClient } from "@workerdeck/client";
@@ -218,6 +218,12 @@ interface SplitterProps {
218
218
  max: number;
219
219
  /** Keyboard step. */
220
220
  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
+ defaultValue?: number;
221
227
  /** Set when dragging the splitter *away* from the origin should shrink the
222
228
  * controlled pane — i.e. the pane is on the right or the bottom. */
223
229
  inverted?: boolean;
@@ -249,11 +255,49 @@ declare function Splitter({
249
255
  min,
250
256
  max,
251
257
  step,
258
+ defaultValue,
252
259
  inverted,
253
260
  'aria-label': label,
254
261
  className
255
262
  }: SplitterProps): _$react.JSX.Element;
256
263
  //#endregion
264
+ //#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
+ declare function Empty({
282
+ icon,
283
+ title,
284
+ description,
285
+ action,
286
+ onAction
287
+ }: {
288
+ icon: ReactNode;
289
+ title: string;
290
+ description?: ReactNode;
291
+ action?: string;
292
+ onAction?: () => void;
293
+ }): _$react.JSX.Element;
294
+ /** A key or icon named inline in an empty state's description — "use the + above". */
295
+ declare function EmptyKey({
296
+ children
297
+ }: {
298
+ children: ReactNode;
299
+ }): _$react.JSX.Element;
300
+ //#endregion
257
301
  //#region src/components/ui/ProgressRing.d.ts
258
302
  interface ProgressRingProps {
259
303
  /** Filled share, 0–100 (clamped). */
@@ -714,6 +758,91 @@ declare function isSegmentsEmpty(segments: Segment[]): boolean;
714
758
  /** Extracts chips matching a specific trigger character. */
715
759
  declare function getChipsByTrigger(segments: Segment[], trigger: string): ChipSegment[];
716
760
  //#endregion
761
+ //#region src/components/terminal/row.d.ts
762
+ /**
763
+ * The primitives every terminal row is built from.
764
+ *
765
+ * There are three, and that is the whole vocabulary: a {@link Row} (a gutter
766
+ * cell and a body cell), a {@link Blank} (one empty line), and a {@link Band} (a
767
+ * run of rows carrying a full-bleed background). Anything the theme draws — a
768
+ * message, a tool call, a diff hunk, an approval prompt — is some arrangement of
769
+ * those, which is what keeps the grid a property of the renderer rather than a
770
+ * thing each component re-derives.
771
+ *
772
+ * Geometry is in `styles/terminal.css`. These components choose a class, a
773
+ * marker and a tone; they never carry a measurement.
774
+ */
775
+ /** The palette, as a name. See the `[data-tone]` rules in `terminal.css`. */
776
+ type Tone = 'fg' | 'bright' | 'dim' | 'faint' | 'mark' | 'blue' | 'green' | 'red' | 'yellow' | 'magenta';
777
+ interface RowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
778
+ /**
779
+ * What sits in the gutter — `●`, `⎿`, `>`, a list bullet, or nothing. Kept to
780
+ * the width of the gutter (`--term-cell`, two columns by default): a wider
781
+ * marker would push its own body off the column every other row starts on.
782
+ * Omitted, the gutter is still drawn as empty space, so an unmarked row's
783
+ * text lines up with a marked one's.
784
+ */
785
+ glyph?: ReactNode;
786
+ /** The marker's colour. Defaults to dim — the marker is structure, not content. */
787
+ glyphTone?: Tone;
788
+ /** The body's colour. */
789
+ tone?: Tone;
790
+ bold?: boolean;
791
+ /** Indent levels, one character cell each. A child row's marker then sits
792
+ * exactly under its parent row's first letter. */
793
+ indent?: 0 | 1 | 2 | 3;
794
+ /**
795
+ * Gutter width in columns, when the marker needs other than two — an ordered
796
+ * list's `10.` is four, a prompt's `❯ 1.` is five, and a framed payload wants
797
+ * `0`. Changes only this row's split, so the body still starts on a whole
798
+ * column.
799
+ */
800
+ columns?: number;
801
+ children?: ReactNode;
802
+ }
803
+ declare function Row({
804
+ glyph,
805
+ glyphTone,
806
+ tone,
807
+ bold,
808
+ indent,
809
+ columns,
810
+ className,
811
+ children,
812
+ style,
813
+ ...props
814
+ }: RowProps): _$react.JSX.Element;
815
+ /**
816
+ * One empty line — the theme's only vertical spacing.
817
+ *
818
+ * A terminal separates blocks with a blank line, not with padding, and saying it
819
+ * that way has a practical payoff: spacing is part of the row list, so it can be
820
+ * decided by whoever knows whether two blocks belong together (a tool call and
821
+ * its output do not get one; two assistant turns do), instead of by a margin
822
+ * rule that cannot tell them apart.
823
+ */
824
+ declare function Blank(): _$react.JSX.Element;
825
+ /**
826
+ * A run of rows under a background: a code block, a command's output, a diff
827
+ * hunk. Full-bleed — the wash reaches the scroller's edges, because in a
828
+ * terminal the line is the full width of the screen. See `--term-bleed` on
829
+ * {@link TerminalSurface}.
830
+ */
831
+ declare function Band({
832
+ className,
833
+ ...props
834
+ }: HTMLAttributes<HTMLDivElement>): _$react.JSX.Element;
835
+ /** Inline colour/weight inside a row's body. */
836
+ declare function Ink({
837
+ tone,
838
+ bold,
839
+ className,
840
+ ...props
841
+ }: HTMLAttributes<HTMLSpanElement> & {
842
+ tone?: Tone;
843
+ bold?: boolean;
844
+ }): _$react.JSX.Element;
845
+ //#endregion
717
846
  //#region src/components/agent/Transcript.d.ts
718
847
  interface TranscriptProps {
719
848
  state: TranscriptState;
@@ -731,9 +860,9 @@ interface TranscriptProps {
731
860
  * on the host (codex's `image_gen`). Omit and those cards name the path. */
732
861
  hostImage?: (path: string) => Promise<string | undefined>;
733
862
  /**
734
- * How a turn is drawn: `cards` (default, the chat convention) or `lines` —
735
- * full-width transparent line items with a gutter glyph, for hosts where
736
- * vertical space is scarce. See {@link TranscriptVariant}.
863
+ * How a turn is drawn: `cards` (default, the chat convention) or `terminal`,
864
+ * which is not a set of branches in these components but its own renderer.
865
+ * See {@link TranscriptVariant}.
737
866
  */
738
867
  variant?: TranscriptVariant;
739
868
  /**
@@ -742,6 +871,42 @@ interface TranscriptProps {
742
871
  * {@link TranscriptVariant}. See {@link TranscriptDensity}.
743
872
  */
744
873
  density?: TranscriptDensity;
874
+ /** Terminal theme only: the character cell, in whole pixels. See
875
+ * {@link TerminalSurface}. */
876
+ fontSize?: number;
877
+ lineHeight?: number;
878
+ /** Terminal theme only: the pointer affordances a real terminal cannot offer.
879
+ * `false` for none. See {@link TerminalAffordances}. */
880
+ affordances?: TerminalAffordances | boolean;
881
+ /** Terminal theme only: hold the prompt of the turn being read at the top of
882
+ * the scroller. The *real* row is pinned, not a copy — see `TranscriptRows`. */
883
+ stickyPrompt?: boolean;
884
+ /**
885
+ * Terminal theme only: mount the overview-ruler scrubber — a 2ch rail of
886
+ * marks (your prompts, each turn's response and result as one mark, errors,
887
+ * the pending approval, the catch-up boundary) that replaces the native
888
+ * scrollbar. Ignored under `cards`: the rail's positions ride the height
889
+ * calculator, which has no claim there. With `affordances={false}` the rail
890
+ * degrades to passive paint — no drag, peek or click — and the native
891
+ * scrollbar stays. See {@link TerminalScrubber}.
892
+ */
893
+ scrubber?: boolean;
894
+ /**
895
+ * Bookmarked item indices, painted as full-width marks on the rail. Paint
896
+ * only, deliberately: the store — and the affordance that writes it — is
897
+ * the client's, the way the unread watermarks are, not the panel's.
898
+ */
899
+ scrubberMarks?: readonly number[];
900
+ /**
901
+ * The attach replay is still landing (`useClaudeSession().replaying`): rows
902
+ * render, measure and pin exactly as normal but nothing paints, and a loading
903
+ * line shows in their place; when it flips false the settled tail appears in
904
+ * one frame. Hiding is by *visibility*, never by not mounting — see the
905
+ * comment at the render site. Optional: an embedder that never passes it
906
+ * gets today's behaviour, and a short or empty session holds for no visible
907
+ * time at all (the frame between attach and replay-complete).
908
+ */
909
+ replaying?: boolean;
745
910
  /**
746
911
  * Catch-up: `from` is how many items had been seen last time, `since` when
747
912
  * that was. A recap row is drawn at that boundary and everything above it is
@@ -760,6 +925,14 @@ interface TranscriptProps {
760
925
  * catch-up strip never touch it. `null` while no transcript is mounted.
761
926
  */
762
927
  jumpToRecapRef?: RefObject<(() => void) | null>;
928
+ /**
929
+ * Filled with a closure that re-pins the transcript to the bottom, so a host
930
+ * can resume following after the reader has scrolled away. The panel presses
931
+ * it on send: choosing to say something is choosing to watch what happens
932
+ * next, and a transcript left parked where you were reading makes a sent
933
+ * message look like it did nothing at all.
934
+ */
935
+ repinRef?: RefObject<(() => void) | null>;
763
936
  className?: string;
764
937
  }
765
938
  declare function Transcript({
@@ -770,29 +943,234 @@ declare function Transcript({
770
943
  hostImage,
771
944
  variant,
772
945
  density,
946
+ fontSize,
947
+ lineHeight,
948
+ affordances,
949
+ stickyPrompt,
950
+ scrubber,
951
+ scrubberMarks,
952
+ replaying,
773
953
  catchUp,
774
954
  jumpToRecapRef,
955
+ repinRef,
775
956
  className
776
957
  }: TranscriptProps): _$react.JSX.Element;
777
958
  //#endregion
959
+ //#region src/components/terminal/surface.d.ts
960
+ /**
961
+ * The root of the terminal theme: the element that establishes the character
962
+ * cell every row inside it lands on.
963
+ *
964
+ * It exists as a component rather than a class because the cell has to be *set*
965
+ * somewhere — the font, the size and the line height together are what make
966
+ * `1ch` mean one column and `--term-line` mean one row — and because that is the
967
+ * one place a host is allowed to change the metrics. Everything below this
968
+ * element measures itself in those two units and never in pixels.
969
+ *
970
+ * The geometry and the palette live in `styles/terminal.css`; this only names
971
+ * the element and hands down the two numbers.
972
+ */
973
+ interface TerminalSurfaceProps extends HTMLAttributes<HTMLDivElement> {
974
+ /**
975
+ * Cell size in **whole pixels**. Fractional values put every other row on a
976
+ * half-pixel: text softens and the diff bands show a seam, which is exactly
977
+ * what a grid renderer must not do. Defaults (13/18) are the CLI's own.
978
+ */
979
+ fontSize?: number;
980
+ lineHeight?: number;
981
+ /**
982
+ * How far a full-bleed band reaches past the content edge — normally the
983
+ * scroller's own horizontal padding. A band cancels it with matched negative
984
+ * margin and padding, so a diff hunk's wash runs to the viewport edge the way
985
+ * a terminal's line does, instead of stopping at a gutter.
986
+ */
987
+ bleed?: string;
988
+ /**
989
+ * The things a real terminal cannot do — the pointer hover fill, the
990
+ * hover-revealed copy actions. `false` turns them all off, an object picks.
991
+ * Default: all on. See {@link TerminalAffordances}; none of them costs layout,
992
+ * so switching them off changes no glyph's position.
993
+ */
994
+ affordances?: TerminalAffordances | boolean;
995
+ }
996
+ declare function TerminalSurface({
997
+ fontSize,
998
+ lineHeight,
999
+ bleed,
1000
+ affordances,
1001
+ className,
1002
+ style,
1003
+ children,
1004
+ ...props
1005
+ }: TerminalSurfaceProps): _$react.JSX.Element;
1006
+ //#endregion
1007
+ //#region src/components/terminal/TerminalTranscript.d.ts
1008
+ /**
1009
+ * The transcript, drawn as a terminal.
1010
+ *
1011
+ * The whole of the layout is here and it is four lines long, which is the point:
1012
+ * items become row blocks, a blank line goes between blocks that do not belong
1013
+ * together, and the working line is one more row at the end. There is no gap
1014
+ * scale, no density knob and no variant branch — a terminal has one line height
1015
+ * and one type size, and everything the theme can express is expressed in which
1016
+ * rows exist and what marker each carries.
1017
+ *
1018
+ * Not virtualized yet: the row blocks are the part that has to be right first,
1019
+ * and the existing `Transcript` already owns a hard-won virtualizer plus the
1020
+ * scroll-regime rules it needs. This renders into that shell when the rows are
1021
+ * settled, rather than growing a second copy of that logic.
1022
+ */
1023
+ interface TerminalTranscriptProps {
1024
+ state: TranscriptState;
1025
+ /** Builds the download URL for a delivered file. */
1026
+ fileUrl?: (path: string) => string;
1027
+ /** Cell metrics, in whole pixels. See {@link TerminalSurface}. */
1028
+ fontSize?: number;
1029
+ lineHeight?: number;
1030
+ /** The pointer affordances a real terminal has no way to offer — hover fill,
1031
+ * hover-revealed copy. `false` for none. See {@link TerminalAffordances}. */
1032
+ affordances?: TerminalAffordances | boolean;
1033
+ className?: string;
1034
+ }
1035
+ /**
1036
+ * One transcript item as terminal rows. Exported because the virtualized shell
1037
+ * in `agent/Transcript.tsx` renders rows through it: the theme owns how a row
1038
+ * looks, that component owns which rows are mounted, and neither needs a copy
1039
+ * of the other.
1040
+ */
1041
+ declare function TerminalItemView({
1042
+ item,
1043
+ fileUrl
1044
+ }: {
1045
+ item: TranscriptItem;
1046
+ fileUrl?: (path: string) => string;
1047
+ }): _$react.JSX.Element | null;
1048
+ declare function TerminalTranscript({
1049
+ state,
1050
+ fileUrl,
1051
+ fontSize,
1052
+ lineHeight,
1053
+ affordances,
1054
+ className
1055
+ }: TerminalTranscriptProps): _$react.JSX.Element;
1056
+ //#endregion
1057
+ //#region src/components/terminal/StatusLine.d.ts
1058
+ interface TerminalStatusLineProps {
1059
+ state: TranscriptState;
1060
+ /** Plan windows to read from, when they should not be the session's own — the
1061
+ * gateway's per-profile state merged over this transcript's. See
1062
+ * {@link StatusBarProps.rateLimits}. Absent = `state.rateLimits`. */
1063
+ rateLimits?: Record<string, RateLimitInfo>;
1064
+ /** How the client is doing at reaching the gateway. Wins the status slot when
1065
+ * the socket is down — see above. */
1066
+ connection?: ConnectionState;
1067
+ /** Opens the panel that answers each reading's own question. Omit and the
1068
+ * reading is text rather than something to press. */
1069
+ onOpenStatus?: () => void;
1070
+ onOpenContext?: () => void;
1071
+ onOpenUsage?: () => void;
1072
+ }
1073
+ declare function TerminalStatusLine({
1074
+ state,
1075
+ rateLimits,
1076
+ connection,
1077
+ onOpenStatus,
1078
+ onOpenContext,
1079
+ onOpenUsage
1080
+ }: TerminalStatusLineProps): _$react.JSX.Element;
1081
+ //#endregion
1082
+ //#region src/components/terminal/PermissionPrompt.d.ts
1083
+ /**
1084
+ * The approval, as the CLI draws it: a rule, what is being asked and about what,
1085
+ * the change itself, a dashed rule, the question, numbered answers, and the keys.
1086
+ *
1087
+ * Two things it does that the card version does not, both taken from the CLI:
1088
+ *
1089
+ * - **It shows the change, not the payload.** For a file edit, `old_string` and
1090
+ * `new_string` are a diff — so it renders one, rather than the JSON input a
1091
+ * reader would have to diff in their head. Without line numbers, necessarily:
1092
+ * the edit has not happened and this client has never read the file (see
1093
+ * {@link previewPatch}). Everything else falls back to the input.
1094
+ * - **The heading is the engine's own sentence.** `displayName` ("Edit file")
1095
+ * over `title`, never "wants to use {tool}" composed here — for codex an
1096
+ * approval is an *escalation after a sandbox refusal*, and the runner has
1097
+ * already written the sentence that says so.
1098
+ */
1099
+ interface TerminalPermissionPromptProps {
1100
+ request: PermissionRequest;
1101
+ onApprove: (requestId: string) => void;
1102
+ /** `message` is fed back to the agent, which can then try something else;
1103
+ * `interrupt` also stops the turn. */
1104
+ onDeny: (requestId: string, message?: string, interrupt?: boolean) => void;
1105
+ }
1106
+ declare function TerminalPermissionPrompt({
1107
+ request,
1108
+ onApprove,
1109
+ onDeny
1110
+ }: TerminalPermissionPromptProps): _$react.JSX.Element;
1111
+ //#endregion
1112
+ //#region src/components/terminal/QuestionPrompt.d.ts
1113
+ interface TerminalQuestionPromptProps {
1114
+ /** A pending permission whose toolName is 'AskUserQuestion'. */
1115
+ request: PermissionRequest;
1116
+ /** Allow the tool with `updatedInput` (the original input plus `answers`). */
1117
+ onAnswer: (requestId: string, updatedInput: Record<string, unknown>) => void;
1118
+ /** Deny the tool — the model proceeds without an answer. */
1119
+ onDismiss: (requestId: string, message?: string) => void;
1120
+ }
1121
+ declare function TerminalQuestionPrompt({
1122
+ request,
1123
+ onAnswer,
1124
+ onDismiss
1125
+ }: TerminalQuestionPromptProps): _$react.JSX.Element;
1126
+ //#endregion
1127
+ //#region src/components/terminal/diff.d.ts
1128
+ /**
1129
+ * A patch for a change that has **not happened yet** — an approval prompt's
1130
+ * `Edit`, where the input names the old and new text but no line numbers exist
1131
+ * because the edit has not been applied and this client has never read the file.
1132
+ *
1133
+ * `newStart: 0` is how it says so, and {@link TerminalDiff} reads that back: a
1134
+ * diff whose hunks all start at zero renders without a number column rather than
1135
+ * printing a column of zeroes or inventing an offset.
1136
+ */
1137
+ declare function previewPatch(input: unknown): FilePatch | undefined;
1138
+ declare function TerminalDiff({
1139
+ patch
1140
+ }: {
1141
+ patch: FilePatch;
1142
+ }): _$react.JSX.Element;
1143
+ //#endregion
1144
+ //#region src/components/terminal/markdown.d.ts
1145
+ interface TerminalMarkdownProps {
1146
+ children: string;
1147
+ /** Streaming text: tolerate half-written markdown (unclosed fences, half links). */
1148
+ streaming?: boolean;
1149
+ className?: string;
1150
+ }
1151
+ declare const TerminalMarkdown: _$react.MemoExoticComponent<({
1152
+ children,
1153
+ streaming,
1154
+ className
1155
+ }: TerminalMarkdownProps) => _$react.JSX.Element>;
1156
+ //#endregion
778
1157
  //#region src/components/agent/Conversation.d.ts
779
1158
  interface ConversationProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
780
1159
  children: ReactNode;
781
- /**
782
- * How the view follows content that grows. `'smooth'` is right for a live
783
- * turn — the text scrolls as it is written. `'instant'` is right while a
784
- * transcript is *filling* (an attach replaying a whole session), where
785
- * animating each arrival makes opening a session a several-second journey
786
- * from its first row to its last.
787
- */
788
- resize?: 'smooth' | 'instant';
789
1160
  }
790
1161
  /** Scroll container that stays pinned to the bottom while streaming, unless the user
791
- * scrolls up — plus a floating scroll-to-bottom button. */
1162
+ * scrolls up — plus a floating scroll-to-bottom button.
1163
+ *
1164
+ * **Nothing here animates its scroll position.** `initial` and `resize` are both
1165
+ * `'instant'` and are no longer configurable: the follow spring's job is to
1166
+ * *stay* at the bottom, not to travel there, and every travel a reader has ever
1167
+ * complained about on this surface was an animation we asked for. The `resize`
1168
+ * prop used to exist so a caller could pick, which required the caller to know
1169
+ * whether the transcript was streaming or replaying — a latch's worth of
1170
+ * machinery to decide something that has one right answer. */
792
1171
  declare function Conversation({
793
1172
  className,
794
1173
  children,
795
- resize,
796
1174
  ...props
797
1175
  }: ConversationProps): _$react.JSX.Element;
798
1176
  declare function ConversationContent({
@@ -822,10 +1200,8 @@ interface MessageProps extends HTMLAttributes<HTMLDivElement> {
822
1200
  * column separates a prompt from the reply it produced. The bubble alone is
823
1201
  * enough to say who spoke.
824
1202
  *
825
- * `lines`: both are left-aligned full-width line items behind a gutter glyph
826
- * `❯` for what was typed, `●` for what the model said. No bubble: a prompt is
827
- * already distinguishable by its marker, and the bubble's padding is vertical
828
- * space the terminal treatment refuses to spend.
1203
+ * The terminal theme draws none of this: it is its own renderer
1204
+ * (`components/terminal/`) and mounts instead of these rows.
829
1205
  */
830
1206
  declare function Message({
831
1207
  from,
@@ -875,24 +1251,25 @@ interface LoaderProps {
875
1251
  /** Overrides the cycling verb — for a state that has one true name
876
1252
  * ("Starting session…"). */
877
1253
  label?: string;
878
- /** When the current run began, for the elapsed clock. Absent = no clock. */
1254
+ /** When the current run began, for the elapsed clock. Absent = no clock.
1255
+ * Unused by the card treatment; kept so the `cards` and `terminal` loaders
1256
+ * take the same call site in `Transcript`. */
879
1257
  startedAt?: number;
880
- /** Context tokens in play, shown beside the clock. */
1258
+ /** Context tokens in play. Same story as `startedAt`. */
881
1259
  tokens?: number;
882
1260
  className?: string;
883
1261
  }
884
1262
  /**
885
1263
  * "The agent is working and hasn't produced output yet."
886
1264
  *
887
- * `lines`: a terminal working line — the mark's own pulse in the gutter (see
888
- * `pulse.tsx`), a verb, and the readings that answer "should I still be
889
- * waiting?" in one parenthesis. `cards`: the three-dot pulse, unchanged the
890
- * dashboard's loader is not a gutter glyph and has no column to pulse in.
1265
+ * Three dots pulsing in CSS — the chat convention, for the `cards` variant. The
1266
+ * terminal theme has its own working line (`terminal/items.tsx`'s `WorkingRow`,
1267
+ * with the mark's pulse in the gutter and the run's readings beside the verb),
1268
+ * because there it is a *row of the transcript* rather than a spinner floating
1269
+ * over one.
891
1270
  */
892
1271
  declare function Loader({
893
1272
  label,
894
- startedAt,
895
- tokens,
896
1273
  className
897
1274
  }: LoaderProps): _$react.JSX.Element;
898
1275
  //#endregion
@@ -1047,6 +1424,19 @@ interface ComposerProps {
1047
1424
  * empty composer would otherwise spend two rows saying nothing.
1048
1425
  */
1049
1426
  layout?: 'stacked' | 'inline';
1427
+ /**
1428
+ * Terminal theme only: the cell the composer draws on. Passed straight
1429
+ * through to its own {@link TerminalSurface}, and it has to be passed — the
1430
+ * composer sits outside the transcript's scroller, so it establishes a second
1431
+ * surface, and a surface handed no metrics falls back to the 13/18 default. A
1432
+ * host running the transcript at its editor's size and the composer at the
1433
+ * default would have the caret land on a different column from the text above
1434
+ * it, which is the one thing this theme exists to prevent.
1435
+ */
1436
+ fontSize?: number;
1437
+ lineHeight?: number;
1438
+ /** Terminal theme only; see {@link TerminalAffordances}. */
1439
+ affordances?: TerminalAffordances | boolean;
1050
1440
  className?: string;
1051
1441
  ref?: Ref<ComposerHandle>;
1052
1442
  }
@@ -1097,6 +1487,9 @@ declare function Composer({
1097
1487
  attachments,
1098
1488
  toolbar,
1099
1489
  layout,
1490
+ fontSize,
1491
+ lineHeight,
1492
+ affordances,
1100
1493
  className,
1101
1494
  ref
1102
1495
  }: ComposerProps): _$react.JSX.Element;
@@ -1131,6 +1524,15 @@ declare function ModelSelect({
1131
1524
  //#region src/components/agent/StatusBar.d.ts
1132
1525
  interface StatusBarProps {
1133
1526
  state: TranscriptState;
1527
+ /**
1528
+ * Plan windows to draw, when they should not be the session's own. The panel
1529
+ * hands over the gateway's per-profile state merged over this transcript's
1530
+ * reading (`mergeUsage`): a session's own `rate_limit` readings arrive only at
1531
+ * a turn's edges, so one idle since yesterday would otherwise render
1532
+ * yesterday's number as current. Absent = `state.rateLimits`, which is what a
1533
+ * bar composed by hand outside the panel gets.
1534
+ */
1535
+ rateLimits?: Record<string, RateLimitInfo>;
1134
1536
  /** @deprecated Pass {@link StatusBarProps.connection}; kept so an embedder
1135
1537
  * still handing over a boolean keeps working. */
1136
1538
  connected?: boolean;
@@ -1147,6 +1549,13 @@ interface StatusBarProps {
1147
1549
  onOpenStatus?: () => void;
1148
1550
  onOpenContext?: () => void;
1149
1551
  onOpenUsage?: () => void;
1552
+ /**
1553
+ * The session's own controls (model, permission mode), for
1554
+ * `controlsSurface: 'status'`. They sit at the end of the readings cluster —
1555
+ * status, context, usage, then what you can *change* — rather than out by the
1556
+ * actions menu, because they belong with the session facts they act on.
1557
+ */
1558
+ controls?: ReactNode;
1150
1559
  /** Trailing slot — the session-actions menu, at the bar's trailing edge. */
1151
1560
  actions?: ReactNode;
1152
1561
  /** Which edge the bar sits on, so its separating rule goes on the other side.
@@ -1156,11 +1565,13 @@ interface StatusBarProps {
1156
1565
  }
1157
1566
  declare function StatusBar({
1158
1567
  state,
1568
+ rateLimits,
1159
1569
  connected,
1160
1570
  connection,
1161
1571
  onOpenStatus,
1162
1572
  onOpenContext,
1163
1573
  onOpenUsage,
1574
+ controls,
1164
1575
  actions,
1165
1576
  placement,
1166
1577
  className
@@ -1187,31 +1598,31 @@ declare function ContextDialog({
1187
1598
  //#endregion
1188
1599
  //#region src/components/agent/UsageDialog.d.ts
1189
1600
  interface UsageDialogProps {
1190
- /** Windows in reading order — session, weekly, then per-model weeklies. */
1191
- rateLimits: Array<{
1192
- key: string;
1193
- info: RateLimitInfo;
1194
- }>;
1601
+ /**
1602
+ * Windows in reading order — session, weekly, then per-model weeklies.
1603
+ *
1604
+ * `updatedAt`/`inferredReset` ride each window because the readings no longer
1605
+ * share one clock: the panel merges the gateway's per-profile state over this
1606
+ * session's, so a `five_hour` learned from a sibling session two minutes ago
1607
+ * can sit beside a `seven_day` this session last heard about yesterday.
1608
+ * `inferredReset` marks the ones the *gateway* zeroed because their own reset
1609
+ * time passed with nothing newer — a floor, not a report.
1610
+ */
1611
+ rateLimits: UsageWindowRow[];
1195
1612
  /** claude.ai plan behind the windows ('max', 'pro', …), when there is one. */
1196
1613
  subscriptionType?: string;
1197
1614
  engine: ProfileEngine;
1198
1615
  totalCostUsd: number;
1199
- /** Local receipt time of the last window update. `rate_limit` events are one
1200
- * per turn at best, so a stale reading is normal and worth saying out loud. */
1616
+ /** When the *freshest* of the windows was read, for the footer line. Readings
1617
+ * arrive one per turn at best (and for an idle session, not at all), so a
1618
+ * stale one is normal and worth saying out loud. */
1201
1619
  updatedAt?: number;
1202
1620
  open: boolean;
1203
1621
  onOpenChange: (open: boolean) => void;
1204
1622
  }
1205
1623
  /**
1206
- * The plan's rate-limit windows, spelled out: how much of each is used, how that
1207
- * compares to the pace that would spend the window exactly, and when it resets.
1208
- *
1209
- * The pace marker is the point. A bar alone says "17% used", which is only
1210
- * alarming or reassuring once you know how far into the week you are — so every
1211
- * window draws a tick at the elapsed share of its duration. Left of the tick is
1212
- * under budget, right of it is ahead of it. The duration comes from the window
1213
- * key (5h, 7d) because the CLI reports a reset time and a percentage and never a
1214
- * duration; a window whose key doesn't say gets no marker rather than a guessed one.
1624
+ * The session's view of the plan: every window as a meter (see
1625
+ * {@link UsageMeters}), the plan tier, and what this session itself has cost.
1215
1626
  */
1216
1627
  declare function UsageDialog({
1217
1628
  rateLimits,
@@ -1223,6 +1634,44 @@ declare function UsageDialog({
1223
1634
  onOpenChange
1224
1635
  }: UsageDialogProps): _$react.JSX.Element;
1225
1636
  //#endregion
1637
+ //#region src/components/agent/UsageMeters.d.ts
1638
+ /**
1639
+ * Ticking clock — the countdowns and the pace markers both move with it, and a
1640
+ * minute is the finest resolution either of them prints.
1641
+ *
1642
+ * `active` is what a dialog passes its `open`: a closed panel's clock is a timer
1643
+ * re-rendering something nobody can see.
1644
+ */
1645
+ declare function useMinuteClock(active?: boolean): number;
1646
+ /**
1647
+ * The plan's rate-limit windows, spelled out: how much of each is used, how that
1648
+ * compares to the pace that would spend the window exactly, and when it resets.
1649
+ *
1650
+ * The pace marker is the point. A bar alone says "17% used", which is only
1651
+ * alarming or reassuring once you know how far into the week you are — so every
1652
+ * window draws a tick at the elapsed share of its duration. Left of the tick is
1653
+ * under budget, right of it is ahead of it. The duration comes from the window
1654
+ * key (5h, 7d) because the engine reports a reset time and a percentage and
1655
+ * never a duration; a window whose key doesn't say gets no marker rather than a
1656
+ * guessed one.
1657
+ *
1658
+ * Its own component rather than the Usage dialog's private helper because two
1659
+ * surfaces draw these now — the session panel's Usage panel, from the session's
1660
+ * readings merged with the gateway's, and the dashboard's profile page, straight
1661
+ * off `ProfileInfo.usage` with no session in sight. Same account, same bars.
1662
+ */
1663
+ declare function UsageMeters({
1664
+ windows,
1665
+ now,
1666
+ className
1667
+ }: {
1668
+ /** In reading order — protocol's `orderUsageWindows`. */windows: UsageWindowRow[];
1669
+ /** A shared clock, when the caller already ticks one. Omitted, this ticks its
1670
+ * own for as long as it is mounted. */
1671
+ now?: number;
1672
+ className?: string;
1673
+ }): _$react.JSX.Element;
1674
+ //#endregion
1226
1675
  //#region src/components/agent/SessionInfoDialog.d.ts
1227
1676
  interface SessionInfoDialogProps {
1228
1677
  state: TranscriptState;
@@ -1570,5 +2019,5 @@ declare function toolIcon(toolName: string): LucideIcon;
1570
2019
  */
1571
2020
  declare function isMutatingTool(toolName: string): boolean;
1572
2021
  //#endregion
1573
- export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type ChipSegment, CodeBlock, type CodeBlockProps, Composer, type ComposerFileMatch, type ComposerHandle, type ComposerProps, ContextDialog, type ContextDialogProps, Conversation, ConversationContent, type ConversationProps, ConversationScrollButton, CopyButton, type CopyButtonProps, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, EngineIcon, FileCard, type FileCardProps, type FileDeliveredItem, HostFilesDialog, type HostFilesDialogProps, 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, PromptArea, type PromptAreaHandle, type PromptAreaProps, PromptTokenText, QUESTION_BEHAVIORS, type QuestionBehaviorMeta, QuestionPrompt, type QuestionPromptProps, Reasoning, type ReasoningProps, Response, type ResponseProps, STATUS_META, type Segment, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, type SessionBrowserProps, type SessionControls, SessionEmptyState, type SessionEmptyStateProps, SessionInfoDialog, type SessionInfoDialogProps, 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 TextSegment, Textarea, Tip, Toaster, ToolCallCard, type ToolCallCardProps, type ToolCallItem, TooltipContent, TooltipProvider, Transcript, type TranscriptDensity, TranscriptDensityProvider, type TranscriptProps, type TranscriptVariant, TranscriptVariantProvider, type TriggerConfig, type TriggerSuggestion, UsageDialog, type UsageDialogProps, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
2022
+ 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, 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, 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, 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 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, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, previewPatch, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, useAffordances, useMinuteClock, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
1574
2023
  //# sourceMappingURL=index.d.mts.map