@workerdeck/ui 0.7.0 → 0.11.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 (61) hide show
  1. package/README.md +81 -3
  2. package/build/SessionPanel-CyhygZx_.d.mts +277 -0
  3. package/build/SessionPanel-_U8tjX29.mjs +8409 -0
  4. package/build/SessionPanel-_U8tjX29.mjs.map +1 -0
  5. package/build/format-DqR56Y8l.mjs +162 -0
  6. package/build/format-DqR56Y8l.mjs.map +1 -0
  7. package/build/format-ljc3lKpA.d.mts +59 -0
  8. package/build/format.d.mts +2 -0
  9. package/build/format.mjs +2 -0
  10. package/build/index.d.mts +615 -87
  11. package/build/index.mjs +6 -5081
  12. package/build/index.mjs.map +1 -1
  13. package/build/workspace.d.mts +199 -0
  14. package/build/workspace.mjs +849 -0
  15. package/build/workspace.mjs.map +1 -0
  16. package/package.json +22 -4
  17. package/src/components/agent/CodeEditor.tsx +300 -0
  18. package/src/components/agent/Composer.tsx +522 -87
  19. package/src/components/agent/ContextDialog.tsx +99 -0
  20. package/src/components/agent/Conversation.tsx +11 -3
  21. package/src/components/agent/EditorTabs.tsx +165 -0
  22. package/src/components/agent/FileCard.tsx +26 -0
  23. package/src/components/agent/FileTree.tsx +287 -0
  24. package/src/components/agent/FileViewer.tsx +148 -0
  25. package/src/components/agent/HostFilesDialog.tsx +218 -0
  26. package/src/components/agent/Loader.tsx +120 -14
  27. package/src/components/agent/McpDialog.tsx +363 -0
  28. package/src/components/agent/Message.tsx +51 -17
  29. package/src/components/agent/ModelSelect.tsx +34 -6
  30. package/src/components/agent/PermissionModeSelect.tsx +133 -22
  31. package/src/components/agent/PermissionPrompt.tsx +164 -6
  32. package/src/components/agent/PromptTokenText.tsx +39 -0
  33. package/src/components/agent/QuestionPrompt.tsx +122 -0
  34. package/src/components/agent/Reasoning.tsx +20 -5
  35. package/src/components/agent/Response.tsx +128 -0
  36. package/src/components/agent/SessionEmptyState.tsx +65 -0
  37. package/src/components/agent/SessionInfoDialog.tsx +163 -0
  38. package/src/components/agent/SessionPanel.tsx +756 -90
  39. package/src/components/agent/SessionWorkspace.tsx +282 -0
  40. package/src/components/agent/SkillsDialog.tsx +195 -0
  41. package/src/components/agent/StatusBar.tsx +85 -18
  42. package/src/components/agent/ToolCallCard.tsx +243 -30
  43. package/src/components/agent/Transcript.tsx +540 -27
  44. package/src/components/agent/UsageDialog.tsx +168 -0
  45. package/src/components/agent/line-prompt.tsx +249 -0
  46. package/src/components/agent/transcript-variant.tsx +61 -0
  47. package/src/components/prompt-area/prompt-area-engine.ts +53 -0
  48. package/src/components/prompt-area/types.ts +15 -0
  49. package/src/components/prompt-area/use-prompt-area.ts +20 -0
  50. package/src/components/ui/CodeBlock.tsx +40 -2
  51. package/src/components/ui/CopyButton.tsx +28 -3
  52. package/src/components/ui/Dialog.tsx +92 -0
  53. package/src/components/ui/Menu.tsx +55 -0
  54. package/src/components/ui/Splitter.tsx +133 -0
  55. package/src/components/ui/Tooltip.tsx +22 -5
  56. package/src/format.ts +10 -0
  57. package/src/index.ts +63 -2
  58. package/src/lib/clipboard.ts +56 -0
  59. package/src/lib/format.ts +114 -0
  60. package/src/lib/tool-icon.ts +96 -0
  61. package/src/workspace.ts +28 -0
package/build/index.d.mts CHANGED
@@ -1,16 +1,22 @@
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 { a as SessionVitals, c as useTranscriptVariant, d as PermissionModeMeta, f as PermissionModeSelect, h as permissionModeMeta, i as SessionSurfacePanel, l as PERMISSION_MODES, m as permissionModeChoices, n as SessionPanel, o as TranscriptVariant, p as PermissionModeSelectProps, r as SessionPanelProps, s as TranscriptVariantProvider, t as SessionControls, u as PermissionModeChoice } from "./SessionPanel-CyhygZx_.mjs";
1
3
  import * as _$react from "react";
2
- import { ButtonHTMLAttributes, FunctionComponent, HTMLAttributes, InputHTMLAttributes, ReactNode, TextareaHTMLAttributes } from "react";
4
+ import { ButtonHTMLAttributes, FunctionComponent, HTMLAttributes, InputHTMLAttributes, ReactElement, ReactNode, Ref, RefObject, TextareaHTMLAttributes } from "react";
3
5
  import { VariantProps } from "class-variance-authority";
4
6
  import { ClassValue } from "clsx";
5
7
  import * as _$_base_ui_react_select0 from "@base-ui/react/select";
6
8
  import { Select as Select$1 } from "@base-ui/react/select";
9
+ import { LucideIcon } from "lucide-react";
7
10
  import * as _$_base_ui_react_alert_dialog0 from "@base-ui/react/alert-dialog";
8
11
  import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
12
+ import { Menu as Menu$1 } from "@base-ui/react/menu";
13
+ import * as _$_base_ui_react_dialog0 from "@base-ui/react/dialog";
14
+ import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
9
15
  import * as _$_base_ui_react_tooltip0 from "@base-ui/react/tooltip";
10
16
  import { Tooltip } from "@base-ui/react/tooltip";
11
17
  import { toast } from "sonner";
12
- import { ModelOption, PermissionMode, PermissionRequest, QuestionBehavior, SessionInfo, SessionStatus, SlashCommandInfo, UserQuestion } from "@workerdeck/protocol";
13
- import { TranscriptItem, TranscriptState } from "@workerdeck/react";
18
+ import { ContextUsage, ModelOption, PermissionRequest, ProfileEngine, QuestionBehavior, RateLimitInfo, SessionInfo, SessionStatus, SkillInfo, SlashCommandInfo, UserQuestion } from "@workerdeck/protocol";
19
+ import { ConnectionState, TranscriptItem, TranscriptState, UseAttachmentsResult } from "@workerdeck/react";
14
20
  import * as _$class_variance_authority_types0 from "class-variance-authority/types";
15
21
  import { WorkerDeckClient } from "@workerdeck/client";
16
22
 
@@ -80,16 +86,65 @@ declare const AlertDialogContent: FunctionComponent<AlertDialog$1.Popup.Props>;
80
86
  declare const AlertDialogTitle: FunctionComponent<AlertDialog$1.Title.Props>;
81
87
  declare const AlertDialogDescription: FunctionComponent<AlertDialog$1.Description.Props>;
82
88
  //#endregion
89
+ //#region src/components/ui/Menu.d.ts
90
+ declare const Menu: <Payload>(props: Menu$1.Root.Props<Payload>) => _$react.JSX.Element;
91
+ declare const MenuTrigger: Menu$1.Trigger;
92
+ declare const MenuContent: FunctionComponent<Menu$1.Popup.Props & Pick<Menu$1.Positioner.Props, 'align' | 'side' | 'sideOffset'>>;
93
+ declare const MenuItem: FunctionComponent<Menu$1.Item.Props & {
94
+ destructive?: boolean;
95
+ }>;
96
+ declare const MenuSeparator: FunctionComponent<Menu$1.Separator.Props>;
97
+ //#endregion
98
+ //#region src/components/ui/Dialog.d.ts
99
+ declare const Dialog: typeof Dialog$1.Root;
100
+ declare const DialogTrigger: Dialog$1.Trigger;
101
+ 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
+ declare const DialogContent: FunctionComponent<Dialog$1.Popup.Props & {
110
+ size?: 'sm' | 'md' | 'lg';
111
+ }>;
112
+ /** Title row with the close button, pinned above the scrolling body. */
113
+ declare const DialogHeader: FunctionComponent<{
114
+ title: string;
115
+ description?: string; /** Rendered between the title and the close button. */
116
+ actions?: React.ReactNode;
117
+ }>;
118
+ /** The scrolling region under the header. */
119
+ declare const DialogBody: FunctionComponent<React.HTMLAttributes<HTMLDivElement>>;
120
+ /** A label/value row — the shape every one of these panels is mostly made of. */
121
+ declare const DialogRow: FunctionComponent<{
122
+ label: string;
123
+ children: React.ReactNode;
124
+ mono?: boolean;
125
+ }>;
126
+ //#endregion
83
127
  //#region src/components/ui/Tooltip.d.ts
84
128
  declare const TooltipProvider: _$react.FC<_$_base_ui_react_tooltip0.TooltipProviderProps>;
85
129
  declare const TooltipContent: FunctionComponent<Tooltip.Popup.Props & Pick<Tooltip.Positioner.Props, 'side' | 'sideOffset'>>;
86
- /** Convenience wrapper: <Tip content="..."><Button/></Tip> */
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
+ */
87
138
  declare function Tip({
88
139
  content,
140
+ render,
141
+ side,
89
142
  children
90
143
  }: {
91
144
  content: ReactNode;
92
- children: ReactNode;
145
+ render?: ReactElement;
146
+ side?: 'top' | 'right' | 'bottom' | 'left';
147
+ children?: ReactNode;
93
148
  }): _$react.JSX.Element;
94
149
  //#endregion
95
150
  //#region src/components/ui/Sonner.d.ts
@@ -99,9 +154,13 @@ declare function Toaster(): _$react.JSX.Element;
99
154
  //#region src/components/ui/CopyButton.d.ts
100
155
  interface CopyButtonProps extends Omit<ButtonProps, 'onClick' | 'children'> {
101
156
  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
+ glyph?: boolean;
102
160
  }
103
161
  declare function CopyButton({
104
162
  value,
163
+ glyph,
105
164
  className,
106
165
  variant,
107
166
  size,
@@ -121,6 +180,17 @@ interface CodeBlockProps {
121
180
  /** Header label, e.g. a language or "Parameters". */
122
181
  label?: ReactNode;
123
182
  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
+ variant?: 'panel' | 'plain';
124
194
  className?: string;
125
195
  }
126
196
  /** Plain (unhighlighted) code panel for structured data like tool inputs. Markdown code
@@ -129,9 +199,61 @@ declare function CodeBlock({
129
199
  code,
130
200
  label,
131
201
  copyable,
202
+ variant,
132
203
  className
133
204
  }: CodeBlockProps): _$react.JSX.Element;
134
205
  //#endregion
206
+ //#region src/components/ui/Splitter.d.ts
207
+ 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
+ orientation: 'vertical' | 'horizontal';
214
+ /** Current size of the pane this splitter controls, in pixels. */
215
+ value: number;
216
+ onValueChange: (value: number) => void;
217
+ min: number;
218
+ max: number;
219
+ /** Keyboard step. */
220
+ step?: number;
221
+ /** Set when dragging the splitter *away* from the origin should shrink the
222
+ * controlled pane — i.e. the pane is on the right or the bottom. */
223
+ inverted?: boolean;
224
+ /** Required: "Resize" alone does not say which of two splitters this is. */
225
+ 'aria-label': string;
226
+ className?: string;
227
+ }
228
+ /**
229
+ * A draggable pane divider.
230
+ *
231
+ * Hand-rolled rather than depended on: `@base-ui/react` ships no splitter, the
232
+ * behaviour is a hundred lines of pointer events, and this repo's instinct at
233
+ * this layer is to own it (the composer is vendored for the same reason).
234
+ *
235
+ * Pointer capture is what makes it survive a fast drag — without it the pointer
236
+ * leaves the 5px bar within a frame and the moves go to whatever is underneath,
237
+ * which for this layout is an iframe-free but still selection-happy code pane.
238
+ * The drag origin is captured on pointerdown and every move is measured against
239
+ * it, so the pane cannot drift relative to the cursor over a long drag the way
240
+ * per-move deltas do once clamping is involved.
241
+ *
242
+ * Keyboard-operable and announced as a separator, because a pane you can only
243
+ * size by dragging is a pane some people cannot size.
244
+ */
245
+ declare function Splitter({
246
+ orientation,
247
+ value,
248
+ onValueChange,
249
+ min,
250
+ max,
251
+ step,
252
+ inverted,
253
+ 'aria-label': label,
254
+ className
255
+ }: SplitterProps): _$react.JSX.Element;
256
+ //#endregion
135
257
  //#region src/components/ui/ProgressRing.d.ts
136
258
  interface ProgressRingProps {
137
259
  /** Filled share, 0–100 (clamped). */
@@ -235,6 +357,21 @@ type TriggerConfig = {
235
357
  * Return the display text for the chip, or void to use `suggestion.label`.
236
358
  */
237
359
  onSelect?: (suggestion: TriggerSuggestion) => string | void;
360
+ /**
361
+ * For 'dropdown' mode: opt a suggestion out of becoming a chip.
362
+ *
363
+ * Return a string and the trigger's range is replaced with that **plain,
364
+ * editable text** — the trigger character included — with the caret left at
365
+ * its end. Return undefined and the suggestion resolves to a chip as usual,
366
+ * so one dropdown can mix both kinds.
367
+ *
368
+ * For suggestions that are a typing aid rather than a token: something the
369
+ * user is meant to finish and edit, where a chip would falsely promise the
370
+ * host parses it back out. Takes precedence over `onSelect`, which is not
371
+ * called for a text-resolved suggestion (there is no chip to label), and
372
+ * `onChipAdd` does not fire either.
373
+ */
374
+ insertAsText?: (suggestion: TriggerSuggestion) => string | undefined;
238
375
  /**
239
376
  * For 'callback' and 'launch' modes: called when the trigger is activated.
240
377
  * Receives the full input text and cursor position. For 'launch' it fires on
@@ -577,49 +714,78 @@ declare function isSegmentsEmpty(segments: Segment[]): boolean;
577
714
  /** Extracts chips matching a specific trigger character. */
578
715
  declare function getChipsByTrigger(segments: Segment[], trigger: string): ChipSegment[];
579
716
  //#endregion
580
- //#region src/components/agent/SessionPanel.d.ts
581
- interface SessionPanelProps {
582
- client: WorkerDeckClient;
583
- sessionId: string | undefined;
584
- /** Optional slot rendered at the top, above the status bar. */
585
- header?: ReactNode;
586
- className?: string;
587
- }
588
- /**
589
- * The all-in-one embeddable session surface: status bar, streaming transcript,
590
- * permission prompts, composer. Attaches via useClaudeSession; remount (key) to switch
591
- * sessions.
592
- */
593
- declare function SessionPanel({
594
- client,
595
- sessionId,
596
- header,
597
- className
598
- }: SessionPanelProps): _$react.JSX.Element;
599
- //#endregion
600
717
  //#region src/components/agent/Transcript.d.ts
601
718
  interface TranscriptProps {
602
719
  state: TranscriptState;
603
720
  /** Builds the download URL for a delivered file (see FileCard). Typically
604
721
  * `(path) => client.sessionFileUrl(sessionId, path)`. */
605
722
  fileUrl?: (path: string) => string;
723
+ /** Builds the URL for an uploaded attachment. Typically
724
+ * `(id) => client.attachmentUrl(sessionId, id)`. Same-origin and
725
+ * cookie-authenticated, which is what lets an `<img src>` render one. */
726
+ attachmentUrl?: (attachmentId: string) => string;
727
+ /** Whether this gateway serves `@file` search here — the empty state must not
728
+ * advertise an affordance the composer doesn't have. */
729
+ canBrowseFiles?: boolean;
730
+ /** Reads a host file as a data URL, for tool calls whose output is a picture
731
+ * on the host (codex's `image_gen`). Omit and those cards name the path. */
732
+ hostImage?: (path: string) => Promise<string | undefined>;
733
+ /**
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}.
737
+ */
738
+ variant?: TranscriptVariant;
739
+ /**
740
+ * Catch-up: `from` is how many items had been seen last time, `since` when
741
+ * that was. A recap row is drawn at that boundary and everything above it is
742
+ * dimmed. Omit (or pass a boundary at/after the end) and the transcript
743
+ * renders exactly as before.
744
+ */
745
+ catchUp?: {
746
+ from: number;
747
+ since?: number;
748
+ };
749
+ /**
750
+ * Filled with a closure that scrolls the recap row into view — the seam the
751
+ * panel's catch-up strip presses. A ref rather than a DOM query because the
752
+ * rows are virtualized: when the recap row isn't mounted, only the
753
+ * virtualizer knows where it would be. Optional; embedders without a
754
+ * catch-up strip never touch it. `null` while no transcript is mounted.
755
+ */
756
+ jumpToRecapRef?: RefObject<(() => void) | null>;
606
757
  className?: string;
607
758
  }
608
759
  declare function Transcript({
609
760
  state,
610
761
  fileUrl,
762
+ attachmentUrl,
763
+ canBrowseFiles,
764
+ hostImage,
765
+ variant,
766
+ catchUp,
767
+ jumpToRecapRef,
611
768
  className
612
769
  }: TranscriptProps): _$react.JSX.Element;
613
770
  //#endregion
614
771
  //#region src/components/agent/Conversation.d.ts
615
772
  interface ConversationProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
616
773
  children: ReactNode;
774
+ /**
775
+ * How the view follows content that grows. `'smooth'` is right for a live
776
+ * turn — the text scrolls as it is written. `'instant'` is right while a
777
+ * transcript is *filling* (an attach replaying a whole session), where
778
+ * animating each arrival makes opening a session a several-second journey
779
+ * from its first row to its last.
780
+ */
781
+ resize?: 'smooth' | 'instant';
617
782
  }
618
783
  /** Scroll container that stays pinned to the bottom while streaming, unless the user
619
784
  * scrolls up — plus a floating scroll-to-bottom button. */
620
785
  declare function Conversation({
621
786
  className,
622
787
  children,
788
+ resize,
623
789
  ...props
624
790
  }: ConversationProps): _$react.JSX.Element;
625
791
  declare function ConversationContent({
@@ -639,11 +805,22 @@ declare function ConversationScrollButton({
639
805
  interface MessageProps extends HTMLAttributes<HTMLDivElement> {
640
806
  from: 'user' | 'assistant';
641
807
  }
642
- /** One chat turn row. User messages sit right in a bubble; assistant content is flat,
643
- * full-width (the AI-chat convention — assistant output is the page, user input is quoted). */
808
+ /**
809
+ * One chat turn row.
810
+ *
811
+ * `cards`: user messages sit right in a bubble; assistant content is flat,
812
+ * full-width (the AI-chat convention — assistant output is the page, user input
813
+ * is quoted).
814
+ *
815
+ * `lines`: both are left-aligned full-width line items behind a gutter glyph —
816
+ * `❯` for what was typed, `●` for what the model said. No bubble: a prompt is
817
+ * already distinguishable by its marker, and the bubble's padding is vertical
818
+ * space the terminal treatment refuses to spend.
819
+ */
644
820
  declare function Message({
645
821
  from,
646
822
  className,
823
+ children,
647
824
  ...props
648
825
  }: MessageProps): _$react.JSX.Element;
649
826
  declare function MessageContent({
@@ -684,14 +861,29 @@ declare function Reasoning({
684
861
  }: ReasoningProps): _$react.JSX.Element | null;
685
862
  //#endregion
686
863
  //#region src/components/agent/Loader.d.ts
687
- /** Three-dot pulse shown while the assistant hasn't produced output yet. */
864
+ interface LoaderProps {
865
+ /** Overrides the cycling verb — for a state that has one true name
866
+ * ("Starting session…"). */
867
+ label?: string;
868
+ /** When the current run began, for the elapsed clock. Absent = no clock. */
869
+ startedAt?: number;
870
+ /** Context tokens in play, shown beside the clock. */
871
+ tokens?: number;
872
+ className?: string;
873
+ }
874
+ /**
875
+ * "The agent is working and hasn't produced output yet."
876
+ *
877
+ * `lines`: a terminal working line — animated glyph in the gutter, a verb, and
878
+ * the readings that answer "should I still be waiting?" in one parenthesis.
879
+ * `cards`: the three-dot pulse, unchanged.
880
+ */
688
881
  declare function Loader({
689
882
  label,
883
+ startedAt,
884
+ tokens,
690
885
  className
691
- }: {
692
- label?: string;
693
- className?: string;
694
- }): _$react.JSX.Element;
886
+ }: LoaderProps): _$react.JSX.Element;
695
887
  //#endregion
696
888
  //#region src/components/agent/ToolCallCard.d.ts
697
889
  type ToolCallItem = Extract<TranscriptItem, {
@@ -699,10 +891,19 @@ type ToolCallItem = Extract<TranscriptItem, {
699
891
  }>;
700
892
  interface ToolCallCardProps {
701
893
  item: ToolCallItem;
894
+ /**
895
+ * Reads a host file as a data URL, for tools whose output is a picture on the
896
+ * host. Resolves `undefined` when the gateway won't serve that path — a
897
+ * generated image saved outside the allowed roots (codex's default
898
+ * `$CODEX_HOME/generated_images/`) is one, and the card then names the path
899
+ * instead of showing it.
900
+ */
901
+ hostImage?: (path: string) => Promise<string | undefined>;
702
902
  className?: string;
703
903
  }
704
904
  declare function ToolCallCard({
705
905
  item,
906
+ hostImage,
706
907
  className
707
908
  }: ToolCallCardProps): _$react.JSX.Element;
708
909
  //#endregion
@@ -730,9 +931,23 @@ declare function FileCard({
730
931
  interface PermissionPromptProps {
731
932
  request: PermissionRequest;
732
933
  onApprove: (requestId: string) => void;
733
- onDeny: (requestId: string, message?: string) => void;
934
+ /** `message` is fed back to the agent, which can then try something else;
935
+ * `interrupt` also stops the turn. */
936
+ onDeny: (requestId: string, message?: string, interrupt?: boolean) => void;
734
937
  className?: string;
735
938
  }
939
+ /**
940
+ * Generic allow/deny prompt for a pending permission request.
941
+ *
942
+ * Three outcomes, not two: denying usually means "not that, try something else",
943
+ * so plain Deny lets the turn continue (with an optional reason the agent reads)
944
+ * while "Deny & stop" also interrupts.
945
+ *
946
+ * The heading is whatever the engine authored — `title`, else `displayName`.
947
+ * Composing "wants to use {tool}" instead would be wrong for codex, where an
948
+ * approval is usually an *escalation after a sandbox refusal* and the runner has
949
+ * already written the sentence that says so.
950
+ */
736
951
  declare function PermissionPrompt({
737
952
  request,
738
953
  onApprove,
@@ -771,8 +986,23 @@ declare function QuestionPrompt({
771
986
  }: QuestionPromptProps): _$react.JSX.Element;
772
987
  //#endregion
773
988
  //#region src/components/agent/Composer.d.ts
989
+ /** Files matching an `@` query, for the composer's file trigger. Structural so
990
+ * the ui package doesn't have to reach for the protocol's `HostFileMatch`. */
991
+ type ComposerFileMatch = {
992
+ path: string;
993
+ relative: string;
994
+ };
995
+ /** Imperative surface for panels that draft a message the user then finishes —
996
+ * the skills dialog's "Use this skill". Nothing here sends. */
997
+ type ComposerHandle = {
998
+ /** Append plain text at the caret's end and focus, separating it from
999
+ * whatever is already there. */
1000
+ insertText: (text: string) => void; /** Put the caret in the field, changing nothing. */
1001
+ focus: () => void;
1002
+ };
774
1003
  interface ComposerProps {
775
- onSend: (text: string) => void;
1004
+ /** `attachmentIds` are the staged uploads, in the order they were picked. */
1005
+ onSend: (text: string, attachmentIds: string[]) => void;
776
1006
  onInterrupt: () => void;
777
1007
  busy: boolean;
778
1008
  /** Disable input entirely (session failed/closed). */
@@ -780,14 +1010,70 @@ interface ComposerProps {
780
1010
  placeholder?: string;
781
1011
  /** Slash commands offered as autocomplete; picked ones render as chips. */
782
1012
  commands?: SlashCommandInfo[];
783
- /** Left side of the toolbar row (mode selects, attachments, …). */
1013
+ /**
1014
+ * Skills offered under a **`$`** popover of their own — codex's sigil, kept
1015
+ * separate from `/` because the two behave differently. A skill is a typing
1016
+ * aid, not a command: picking one inserts editable text (the skill's own
1017
+ * `defaultPrompt` where it has one, else `$name`) and nothing is sent. No
1018
+ * engine parses `$skillname` as syntax, which is exactly why these can never
1019
+ * resolve to a chip the way `commands` do.
1020
+ */
1021
+ skills?: SkillInfo[];
1022
+ /** Host-file search behind the `@` trigger. Omit to leave `@` inert — a
1023
+ * gateway without host files has nothing to complete. */
1024
+ onSearchFiles?: (query: string, options: {
1025
+ signal: AbortSignal;
1026
+ }) => Promise<ComposerFileMatch[]>;
1027
+ /** Attachment staging (see `useAttachments`). Omit for a text-only composer. */
1028
+ attachments?: UseAttachmentsResult;
1029
+ /** Left side of the toolbar row (mode selects, …). */
784
1030
  toolbar?: ReactNode;
1031
+ /**
1032
+ * `'stacked'` (default) gives the buttons a row of their own under the field —
1033
+ * right where a toolbar belongs. `'inline'` puts the field and the buttons on
1034
+ * ONE line, growing from a single row as the message does: for a host whose
1035
+ * session controls live in its own chrome (VS Code's status bar), where the
1036
+ * empty composer would otherwise spend two rows saying nothing.
1037
+ */
1038
+ layout?: 'stacked' | 'inline';
785
1039
  className?: string;
1040
+ ref?: Ref<ComposerHandle>;
786
1041
  }
787
- /** Framed prompt input built on prompt-area's contentEditable: typing "/" — at the
788
- * start or after whitespace — opens a suggestion dropdown fed by `commands`, and a
789
- * picked command becomes an inline chip. Submit button flips to stop while a turn
790
- * is running (messages still queue while busy). */
1042
+ /**
1043
+ * What a picked skill types into the composer.
1044
+ *
1045
+ * The engine's own `defaultPrompt` when it declared one — it knows what its
1046
+ * skill wants to be asked — and otherwise `$name`, which is codex's native way
1047
+ * of referring to a skill in prompt text: its `skill-creator` documents the form
1048
+ * (`Use $skill-x at /path/to/skill-x to solve problem y`) and its own bundled
1049
+ * prompts are written that way ("Use $pdf to …"). Spelling it the way the engine
1050
+ * spells it beats paraphrasing into "Use the X skill to".
1051
+ *
1052
+ * Either way it ends in a space so the caret lands ready for the rest of the
1053
+ * sentence, and either way it is ordinary text: nothing here is submitted, and
1054
+ * nothing is parsed back out.
1055
+ */
1056
+ declare function skillPrompt(skill: SkillInfo): string;
1057
+ /**
1058
+ * Framed prompt input built on prompt-area's contentEditable.
1059
+ *
1060
+ * Three completions ride the same field and behave nothing alike. `/` is the
1061
+ * CLI's command list and `$` is the engine's skill list — both local, so they
1062
+ * filter completely and instantly; `@` is a search against the host filesystem,
1063
+ * debounced and abortable so a fast typist makes one request rather than eight.
1064
+ *
1065
+ * `/` and `$` are separate keys rather than one merged menu, and that mirrors
1066
+ * the engines themselves: codex completes skills on `$` and reserves `/` for
1067
+ * commands. The behaviours differ too — a command resolves to a **chip**,
1068
+ * because the CLI really does parse `/name` out of the message, while a skill
1069
+ * resolves to plain editable **text**, because no engine parses `$name` as
1070
+ * syntax; it is prose the model reads. Rendering them alike would promise
1071
+ * something that does not happen.
1072
+ *
1073
+ * Files can arrive three ways — the paperclip, a drop, or a paste — because on a
1074
+ * desktop all three are things people already do, and the upload starts the
1075
+ * moment one lands rather than at send time.
1076
+ */
791
1077
  declare function Composer({
792
1078
  onSend,
793
1079
  onInterrupt,
@@ -795,8 +1081,13 @@ declare function Composer({
795
1081
  disabled,
796
1082
  placeholder,
797
1083
  commands,
1084
+ skills,
1085
+ onSearchFiles,
1086
+ attachments,
798
1087
  toolbar,
799
- className
1088
+ layout,
1089
+ className,
1090
+ ref
800
1091
  }: ComposerProps): _$react.JSX.Element;
801
1092
  //#endregion
802
1093
  //#region src/components/agent/ModelSelect.d.ts
@@ -826,51 +1117,208 @@ declare function ModelSelect({
826
1117
  className
827
1118
  }: ModelSelectProps): _$react.JSX.Element;
828
1119
  //#endregion
829
- //#region src/components/agent/PermissionModeSelect.d.ts
830
- type PermissionModeMeta = {
831
- value: PermissionMode;
832
- label: string;
833
- description: string;
834
- dangerous?: boolean;
835
- };
836
- /** The modes surfaced across UI surfaces (session creation, in-session switcher). */
837
- declare const PERMISSION_MODES: PermissionModeMeta[];
838
- interface PermissionModeSelectProps {
839
- /** The session's current mode (TranscriptState.permissionMode). */
840
- mode?: PermissionMode;
841
- onModeChange: (mode: PermissionMode) => void;
842
- /** Restrict what is offered — most of {@link PERMISSION_MODES} is Claude Code
843
- * vocabulary the provider engine has no meaning for. Defaults to all of them;
844
- * pass `PROVIDER_PERMISSION_MODES` for a provider session. */
845
- modes?: readonly PermissionMode[];
846
- /** 'toolbar' (default) is the composer's compact borderless trigger;
847
- * 'form' is a standard field-sized Select for create/settings forms. */
848
- variant?: 'toolbar' | 'form';
849
- disabled?: boolean;
850
- className?: string;
851
- }
852
- /** Permission-mode switcher: compact in the composer toolbar, field-sized in forms. */
853
- declare function PermissionModeSelect({
854
- mode,
855
- onModeChange,
856
- modes,
857
- variant,
858
- disabled,
859
- className
860
- }: PermissionModeSelectProps): _$react.JSX.Element;
861
- //#endregion
862
1120
  //#region src/components/agent/StatusBar.d.ts
863
1121
  interface StatusBarProps {
864
1122
  state: TranscriptState;
865
- connected: boolean;
1123
+ /** @deprecated Pass {@link StatusBarProps.connection}; kept so an embedder
1124
+ * still handing over a boolean keeps working. */
1125
+ connected?: boolean;
1126
+ /** How the client is doing at reaching the gateway. A dropped socket wins the
1127
+ * status slot: the session status held over a dead socket is a stale reading,
1128
+ * and presenting it as a live one is the thing worth avoiding. */
1129
+ connection?: ConnectionState;
1130
+ /**
1131
+ * Where the gauges lead. Each one opens the panel that answers *its* question
1132
+ * — the two meters measure different things, so sending both to one "details"
1133
+ * list would be a detour every time. Omit a handler and that gauge stays a
1134
+ * read-only tooltip.
1135
+ */
1136
+ onOpenStatus?: () => void;
1137
+ onOpenContext?: () => void;
1138
+ onOpenUsage?: () => void;
1139
+ /** Trailing slot — the session-actions menu, in the panel's top-right. */
1140
+ actions?: ReactNode;
866
1141
  className?: string;
867
1142
  }
868
1143
  declare function StatusBar({
869
1144
  state,
870
1145
  connected,
1146
+ connection,
1147
+ onOpenStatus,
1148
+ onOpenContext,
1149
+ onOpenUsage,
1150
+ actions,
871
1151
  className
872
1152
  }: StatusBarProps): _$react.JSX.Element;
873
1153
  //#endregion
1154
+ //#region src/components/agent/ContextDialog.d.ts
1155
+ interface ContextDialogProps {
1156
+ usage?: ContextUsage;
1157
+ open: boolean;
1158
+ onOpenChange: (open: boolean) => void;
1159
+ }
1160
+ /**
1161
+ * What is in the model's context window right now, category by category.
1162
+ *
1163
+ * One of the three panels the status bar opens. Context, usage and session info
1164
+ * are different questions asked at different moments, so they are different
1165
+ * screens rather than one "details" list you scroll past two answers to reach.
1166
+ */
1167
+ declare function ContextDialog({
1168
+ usage,
1169
+ open,
1170
+ onOpenChange
1171
+ }: ContextDialogProps): _$react.JSX.Element;
1172
+ //#endregion
1173
+ //#region src/components/agent/UsageDialog.d.ts
1174
+ interface UsageDialogProps {
1175
+ /** Windows in reading order — session, weekly, then per-model weeklies. */
1176
+ rateLimits: Array<{
1177
+ key: string;
1178
+ info: RateLimitInfo;
1179
+ }>;
1180
+ /** claude.ai plan behind the windows ('max', 'pro', …), when there is one. */
1181
+ subscriptionType?: string;
1182
+ engine: ProfileEngine;
1183
+ totalCostUsd: number;
1184
+ /** Local receipt time of the last window update. `rate_limit` events are one
1185
+ * per turn at best, so a stale reading is normal and worth saying out loud. */
1186
+ updatedAt?: number;
1187
+ open: boolean;
1188
+ onOpenChange: (open: boolean) => void;
1189
+ }
1190
+ /**
1191
+ * The plan's rate-limit windows, spelled out: how much of each is used, how that
1192
+ * compares to the pace that would spend the window exactly, and when it resets.
1193
+ *
1194
+ * The pace marker is the point. A bar alone says "17% used", which is only
1195
+ * alarming or reassuring once you know how far into the week you are — so every
1196
+ * window draws a tick at the elapsed share of its duration. Left of the tick is
1197
+ * under budget, right of it is ahead of it. The duration comes from the window
1198
+ * key (5h, 7d) because the CLI reports a reset time and a percentage and never a
1199
+ * duration; a window whose key doesn't say gets no marker rather than a guessed one.
1200
+ */
1201
+ declare function UsageDialog({
1202
+ rateLimits,
1203
+ subscriptionType,
1204
+ engine,
1205
+ totalCostUsd,
1206
+ updatedAt,
1207
+ open,
1208
+ onOpenChange
1209
+ }: UsageDialogProps): _$react.JSX.Element;
1210
+ //#endregion
1211
+ //#region src/components/agent/SessionInfoDialog.d.ts
1212
+ interface SessionInfoDialogProps {
1213
+ state: TranscriptState;
1214
+ client: WorkerDeckClient;
1215
+ sessionId: string | undefined;
1216
+ open: boolean;
1217
+ onOpenChange: (open: boolean) => void;
1218
+ }
1219
+ /**
1220
+ * What this session *is*: engine, profile, model, mode, where it runs, which
1221
+ * credentials it found, and the files it has handed over.
1222
+ *
1223
+ * The identity half of the session's facts. Context and usage have their own
1224
+ * panels — they change every turn and are consulted mid-run, while everything
1225
+ * here is fixed at creation and looked up once.
1226
+ */
1227
+ declare function SessionInfoDialog({
1228
+ state,
1229
+ client,
1230
+ sessionId,
1231
+ open,
1232
+ onOpenChange
1233
+ }: SessionInfoDialogProps): _$react.JSX.Element;
1234
+ //#endregion
1235
+ //#region src/components/agent/McpDialog.d.ts
1236
+ interface McpDialogProps {
1237
+ client: WorkerDeckClient;
1238
+ sessionId: string | undefined;
1239
+ open: boolean;
1240
+ onOpenChange: (open: boolean) => void;
1241
+ /**
1242
+ * Whether this engine can reconnect/enable/disable a server
1243
+ * (`EngineCapabilities.mcpServerActions`). False renders the panel read-only:
1244
+ * codex reports rich status but exposes no per-server action, and buttons
1245
+ * that 501 are worse than buttons that aren't there.
1246
+ */
1247
+ canManageServers?: boolean;
1248
+ }
1249
+ /**
1250
+ * The session's MCP servers, at the CLI's own `/mcp` depth: servers → one server
1251
+ * → its tools → one tool, with Reconnect / Enable / Disable where they apply.
1252
+ *
1253
+ * Two things vary by engine rather than being fixed here. **The actions** exist
1254
+ * only where the engine has them (`canManageServers`): codex reports rich status
1255
+ * but has no per-server reconnect or toggle, so its panel is read-only. And
1256
+ * **tool parameters** appear only where the engine reports a schema — codex
1257
+ * returns each tool's full JSON Schema, the Agent SDK returns none at all, so
1258
+ * the tool view either renders it or says why it can't, rather than leaving a
1259
+ * silent gap or claiming the absence is universal.
1260
+ */
1261
+ declare function McpDialog({
1262
+ client,
1263
+ sessionId,
1264
+ open,
1265
+ onOpenChange,
1266
+ canManageServers
1267
+ }: McpDialogProps): _$react.JSX.Element;
1268
+ //#endregion
1269
+ //#region src/components/agent/SkillsDialog.d.ts
1270
+ interface SkillsDialogProps {
1271
+ skills: SkillInfo[] | undefined;
1272
+ open: boolean;
1273
+ onOpenChange: (open: boolean) => void;
1274
+ /** Insert a skill's opening message into the composer, if the host offers
1275
+ * that. Omit and the dialog is read-only. */
1276
+ onUse?: (skill: SkillInfo) => void;
1277
+ }
1278
+ /**
1279
+ * What this session's engine can do beyond its own tools: the skills it found,
1280
+ * grouped by where they came from, with one drilled-down view each.
1281
+ *
1282
+ * The framing matters more here than in most panels. A skill is **not** a
1283
+ * command — the model decides to use one by reading its description, and there
1284
+ * is no wire syntax that invokes it. So this screen is a *discovery* surface,
1285
+ * and the one action it offers ("Use this skill") is honest about being a
1286
+ * drafting aid: it types a message for the operator to edit and send.
1287
+ *
1288
+ * Fed from the session's `skills` event rather than a REST route, because that
1289
+ * is the channel the engine refreshes on its own when a skill changes on disk.
1290
+ */
1291
+ declare function SkillsDialog({
1292
+ skills,
1293
+ open,
1294
+ onOpenChange,
1295
+ onUse
1296
+ }: SkillsDialogProps): _$react.JSX.Element;
1297
+ //#endregion
1298
+ //#region src/components/agent/HostFilesDialog.d.ts
1299
+ interface HostFilesDialogProps {
1300
+ client: WorkerDeckClient;
1301
+ /** The session's working directory — the browser is rooted here. */
1302
+ cwd: string | undefined;
1303
+ open: boolean;
1304
+ onOpenChange: (open: boolean) => void;
1305
+ }
1306
+ /**
1307
+ * Browse the project the session is working in.
1308
+ *
1309
+ * Deliberately rooted at the session's cwd rather than at the server's
1310
+ * `hostFiles.roots`: the roots are the *security* boundary (the server enforces
1311
+ * them on every request), but what someone wants while watching an agent is this
1312
+ * project's tree. Read-only — writing is a separate server opt-in and not
1313
+ * something a session viewer should be doing behind the agent's back.
1314
+ */
1315
+ declare function HostFilesDialog({
1316
+ client,
1317
+ cwd,
1318
+ open,
1319
+ onOpenChange
1320
+ }: HostFilesDialogProps): _$react.JSX.Element;
1321
+ //#endregion
874
1322
  //#region src/components/agent/SessionList.d.ts
875
1323
  interface SessionListItemProps {
876
1324
  session: SessionInfo;
@@ -901,6 +1349,59 @@ declare function SessionList({
901
1349
  className
902
1350
  }: SessionListProps): _$react.JSX.Element;
903
1351
  //#endregion
1352
+ //#region src/components/agent/SessionEmptyState.d.ts
1353
+ interface SessionEmptyStateProps {
1354
+ cwd?: string;
1355
+ /** Whether `/command` completion is live yet — the CLI reports its commands a
1356
+ * beat after the session starts, and promising a feature that isn't wired up
1357
+ * yet is worse than not mentioning it. */
1358
+ hasCommands?: boolean;
1359
+ /** Whether the engine has reported skills the `/` popover can offer. Its own
1360
+ * flag, not a variant of `hasCommands`: what `/` does differs — a command is
1361
+ * submitted, a skill is typed for you to edit — and an engine can have one
1362
+ * without the other. */
1363
+ hasSkills?: boolean;
1364
+ /** Whether this gateway serves `@file` search for the session's directory. */
1365
+ canBrowseFiles?: boolean;
1366
+ className?: string;
1367
+ }
1368
+ /**
1369
+ * What a session shows before it has said anything: where the agent is sitting,
1370
+ * and what the composer accepts beyond prose.
1371
+ *
1372
+ * Every hint is conditional on the affordance actually existing — an engine
1373
+ * without slash commands, or a gateway without host files, is not told about
1374
+ * them. Deliberately no project name (the header already carries it) and no
1375
+ * brand mark (its geometry is inlined in several places already and they are
1376
+ * meant to stay identical).
1377
+ */
1378
+ declare function SessionEmptyState({
1379
+ cwd,
1380
+ hasCommands,
1381
+ hasSkills,
1382
+ canBrowseFiles,
1383
+ className
1384
+ }: SessionEmptyStateProps): _$react.JSX.Element;
1385
+ //#endregion
1386
+ //#region src/components/agent/PromptTokenText.d.ts
1387
+ /**
1388
+ * A sent message, with its `@file` and `/command` tokens styled the way the CLI
1389
+ * writes them: monospace and tinted, no background — the bubble already has one,
1390
+ * and a second fill inside it reads as a button.
1391
+ *
1392
+ * Literal text, never markdown: what was typed is what was sent. The one pass
1393
+ * over it is this, so a message reads the same after sending as it did in the
1394
+ * composer. Two tokens, two meanings — a file is a reference, a command is an
1395
+ * action — so they are told apart by hue rather than by shape alone.
1396
+ */
1397
+ declare function PromptTokenText({
1398
+ text,
1399
+ className
1400
+ }: {
1401
+ text: string;
1402
+ className?: string;
1403
+ }): _$react.JSX.Element;
1404
+ //#endregion
904
1405
  //#region src/components/agent/status.d.ts
905
1406
  declare const STATUS_META: Record<SessionStatus, {
906
1407
  label: string;
@@ -911,17 +1412,44 @@ declare const STATUS_META: Record<SessionStatus, {
911
1412
  //#region src/lib/utils.d.ts
912
1413
  declare function cn(...inputs: ClassValue[]): string;
913
1414
  //#endregion
914
- //#region src/lib/format.d.ts
915
- declare function formatCost(usd: number | undefined): string;
916
- declare function formatDuration(ms: number): string;
917
- /** Compact token count, Claude Code-style: 850 → "850", 359_000 → "359.0k", 1_200_000 → "1.2M". */
918
- declare function formatTokens(tokens: number): string;
919
- declare function formatBytes(bytes: number): string;
920
- /** Countdown to an epoch-ms deadline: "2h 18m", "12m", "<1m"; "now" once passed. */
921
- declare function formatCountdown(untilEpochMs: number, now?: number): string;
922
- declare function formatRelativeTime(epochMs: number | undefined, now?: number): string;
923
- /** Compact one-line preview of a tool input for card headers. */
924
- declare function toolInputPreview(input: unknown, max?: number): string;
925
- //#endregion
926
- export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type ChipSegment, CodeBlock, type CodeBlockProps, Composer, type ComposerProps, Conversation, ConversationContent, type ConversationProps, ConversationScrollButton, CopyButton, type CopyButtonProps, FileCard, type FileCardProps, type FileDeliveredItem, Input, Loader, Message, MessageContent, type MessageProps, ModelSelect, type ModelSelectProps, PERMISSION_MODES, type PermissionModeMeta, PermissionModeSelect, type PermissionModeSelectProps, PermissionPrompt, type PermissionPromptProps, ProgressRing, type ProgressRingProps, PromptArea, type PromptAreaHandle, type PromptAreaProps, QUESTION_BEHAVIORS, type QuestionBehaviorMeta, QuestionPrompt, type QuestionPromptProps, Reasoning, type ReasoningProps, Response, type ResponseProps, STATUS_META, type Segment, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionList, SessionListItem, type SessionListItemProps, type SessionListProps, SessionPanel, type SessionPanelProps, Spinner, StatusBar, type StatusBarProps, type TextSegment, Textarea, Tip, Toaster, ToolCallCard, type ToolCallCardProps, type ToolCallItem, TooltipContent, TooltipProvider, Transcript, type TranscriptProps, type TriggerConfig, type TriggerSuggestion, badgeVariants, buttonVariants, cn, commandTrigger, formatBytes, formatCost, formatCountdown, formatDuration, formatRelativeTime, formatTokens, getChipsByTrigger, hashtagTrigger, isSegmentsEmpty, mentionTrigger, parseUserQuestions, plainTextToSegments, segmentsToPlainText, toast, toolInputPreview, usePromptAreaState };
1415
+ //#region src/lib/clipboard.d.ts
1416
+ /**
1417
+ * Copy text to the clipboard, on origins where the modern API does not exist.
1418
+ *
1419
+ * `navigator.clipboard` is gated on a **secure context**: HTTPS, or localhost.
1420
+ * A WorkerDeck dashboard reached the way it is meant to be reached — plain HTTP
1421
+ * on a LAN address, from a laptop or a phone — is neither, so `navigator.clipboard`
1422
+ * is `undefined` there and touching `.writeText` throws outright. That is the
1423
+ * normal deployment, not an edge case, which is why this falls back rather than
1424
+ * feature-detecting into a disabled button.
1425
+ *
1426
+ * The fallback is `document.execCommand('copy')` over an off-screen textarea.
1427
+ * It is deprecated and it is also the only thing that works here; every browser
1428
+ * still implements it. Returns whether the text actually landed, so a caller can
1429
+ * avoid claiming success it did not have.
1430
+ */
1431
+ declare function copyText(value: string): Promise<boolean>;
1432
+ //#endregion
1433
+ //#region src/lib/tool-icon.d.ts
1434
+ /**
1435
+ * An icon per tool, so a transcript can be skimmed by shape rather than read.
1436
+ *
1437
+ * The same mapping the iOS app makes, in lucide's vocabulary rather than SF
1438
+ * Symbols — the two clients should be recognisably showing the same thing. An
1439
+ * unknown tool falls back to a wrench, and an MCP tool (`mcp__server__name`) to
1440
+ * the puzzle piece the MCP screens use, because "which server is this from" is
1441
+ * the useful thing to see at a glance.
1442
+ */
1443
+ declare function toolIcon(toolName: string): LucideIcon;
1444
+ /**
1445
+ * Does this tool *change* the workspace?
1446
+ *
1447
+ * Worth its own colour in a transcript: skimming a run, "what did it edit" is a
1448
+ * different question from "what did it look at", and a write is the one you
1449
+ * might need to undo. Names from both first-party engines; an MCP tool is
1450
+ * unknowable from its name, so it reads as neutral rather than guessed.
1451
+ */
1452
+ declare function isMutatingTool(toolName: string): boolean;
1453
+ //#endregion
1454
+ 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, 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, type SessionControls, SessionEmptyState, type SessionEmptyStateProps, SessionInfoDialog, type SessionInfoDialogProps, SessionList, SessionListItem, type SessionListItemProps, type SessionListProps, SessionPanel, type SessionPanelProps, 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 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, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptVariant };
927
1455
  //# sourceMappingURL=index.d.mts.map