@workerdeck/ui 0.7.0 → 0.10.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.
- package/README.md +44 -3
- package/build/index.d.mts +767 -21
- package/build/index.mjs +3268 -348
- package/build/index.mjs.map +1 -1
- package/package.json +5 -4
- package/src/components/agent/CodeEditor.tsx +300 -0
- package/src/components/agent/Composer.tsx +379 -56
- package/src/components/agent/ContextDialog.tsx +99 -0
- package/src/components/agent/EditorTabs.tsx +165 -0
- package/src/components/agent/FileTree.tsx +287 -0
- package/src/components/agent/FileViewer.tsx +148 -0
- package/src/components/agent/HostFilesDialog.tsx +218 -0
- package/src/components/agent/McpDialog.tsx +363 -0
- package/src/components/agent/ModelSelect.tsx +34 -6
- package/src/components/agent/PermissionModeSelect.tsx +99 -22
- package/src/components/agent/PermissionPrompt.tsx +72 -6
- package/src/components/agent/PromptTokenText.tsx +39 -0
- package/src/components/agent/SessionEmptyState.tsx +65 -0
- package/src/components/agent/SessionInfoDialog.tsx +163 -0
- package/src/components/agent/SessionPanel.tsx +380 -40
- package/src/components/agent/SessionWorkspace.tsx +282 -0
- package/src/components/agent/SkillsDialog.tsx +195 -0
- package/src/components/agent/StatusBar.tsx +85 -18
- package/src/components/agent/ToolCallCard.tsx +80 -4
- package/src/components/agent/Transcript.tsx +109 -12
- package/src/components/agent/UsageDialog.tsx +168 -0
- package/src/components/prompt-area/prompt-area-engine.ts +53 -0
- package/src/components/prompt-area/types.ts +15 -0
- package/src/components/prompt-area/use-prompt-area.ts +20 -0
- package/src/components/ui/CopyButton.tsx +8 -1
- package/src/components/ui/Dialog.tsx +92 -0
- package/src/components/ui/Menu.tsx +55 -0
- package/src/components/ui/Splitter.tsx +133 -0
- package/src/components/ui/Tooltip.tsx +22 -5
- package/src/index.ts +53 -1
- package/src/lib/clipboard.ts +56 -0
- package/src/lib/format.ts +48 -0
- package/src/lib/tool-icon.ts +74 -0
package/build/index.d.mts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import * as _$react from "react";
|
|
2
|
-
import { ButtonHTMLAttributes, FunctionComponent, HTMLAttributes, InputHTMLAttributes, ReactNode, TextareaHTMLAttributes } from "react";
|
|
2
|
+
import { ButtonHTMLAttributes, CSSProperties, FunctionComponent, HTMLAttributes, InputHTMLAttributes, ReactElement, ReactNode, Ref, TextareaHTMLAttributes } from "react";
|
|
3
3
|
import { VariantProps } from "class-variance-authority";
|
|
4
4
|
import { ClassValue } from "clsx";
|
|
5
5
|
import * as _$_base_ui_react_select0 from "@base-ui/react/select";
|
|
6
6
|
import { Select as Select$1 } from "@base-ui/react/select";
|
|
7
|
+
import { LucideIcon } from "lucide-react";
|
|
7
8
|
import * as _$_base_ui_react_alert_dialog0 from "@base-ui/react/alert-dialog";
|
|
8
9
|
import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
|
|
10
|
+
import { Menu as Menu$1 } from "@base-ui/react/menu";
|
|
11
|
+
import * as _$_base_ui_react_dialog0 from "@base-ui/react/dialog";
|
|
12
|
+
import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
|
|
9
13
|
import * as _$_base_ui_react_tooltip0 from "@base-ui/react/tooltip";
|
|
10
14
|
import { Tooltip } from "@base-ui/react/tooltip";
|
|
11
15
|
import { toast } from "sonner";
|
|
12
|
-
import { ModelOption, PermissionMode, PermissionRequest, QuestionBehavior, SessionInfo, SessionStatus, SlashCommandInfo, UserQuestion } from "@workerdeck/protocol";
|
|
13
|
-
import { TranscriptItem, TranscriptState } from "@workerdeck/react";
|
|
16
|
+
import { ContextUsage, ModelOption, PermissionMode, PermissionRequest, ProfileEngine, QuestionBehavior, RateLimitInfo, SessionInfo, SessionStatus, SkillInfo, SlashCommandInfo, UserQuestion } from "@workerdeck/protocol";
|
|
17
|
+
import { ConnectionState, OpenFile, TranscriptItem, TranscriptState, UseAttachmentsResult, UseHostFileSearchResult, UseHostFileTreeResult } from "@workerdeck/react";
|
|
14
18
|
import * as _$class_variance_authority_types0 from "class-variance-authority/types";
|
|
15
19
|
import { WorkerDeckClient } from "@workerdeck/client";
|
|
16
20
|
|
|
@@ -80,16 +84,65 @@ declare const AlertDialogContent: FunctionComponent<AlertDialog$1.Popup.Props>;
|
|
|
80
84
|
declare const AlertDialogTitle: FunctionComponent<AlertDialog$1.Title.Props>;
|
|
81
85
|
declare const AlertDialogDescription: FunctionComponent<AlertDialog$1.Description.Props>;
|
|
82
86
|
//#endregion
|
|
87
|
+
//#region src/components/ui/Menu.d.ts
|
|
88
|
+
declare const Menu: <Payload>(props: Menu$1.Root.Props<Payload>) => _$react.JSX.Element;
|
|
89
|
+
declare const MenuTrigger: Menu$1.Trigger;
|
|
90
|
+
declare const MenuContent: FunctionComponent<Menu$1.Popup.Props & Pick<Menu$1.Positioner.Props, 'align' | 'side' | 'sideOffset'>>;
|
|
91
|
+
declare const MenuItem: FunctionComponent<Menu$1.Item.Props & {
|
|
92
|
+
destructive?: boolean;
|
|
93
|
+
}>;
|
|
94
|
+
declare const MenuSeparator: FunctionComponent<Menu$1.Separator.Props>;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/components/ui/Dialog.d.ts
|
|
97
|
+
declare const Dialog: typeof Dialog$1.Root;
|
|
98
|
+
declare const DialogTrigger: Dialog$1.Trigger;
|
|
99
|
+
declare const DialogClose: _$react.ForwardRefExoticComponent<Omit<_$_base_ui_react_dialog0.DialogCloseProps, "ref"> & _$react.RefAttributes<HTMLButtonElement>>;
|
|
100
|
+
/**
|
|
101
|
+
* A dismissible panel, sized for reading rather than confirming — the web
|
|
102
|
+
* counterpart of the iOS app's detail sheets (context, usage, session info, MCP).
|
|
103
|
+
*
|
|
104
|
+
* Taller than {@link AlertDialogContent} and scrollable inside, because these
|
|
105
|
+
* carry lists whose length is the engine's business, not the layout's.
|
|
106
|
+
*/
|
|
107
|
+
declare const DialogContent: FunctionComponent<Dialog$1.Popup.Props & {
|
|
108
|
+
size?: 'sm' | 'md' | 'lg';
|
|
109
|
+
}>;
|
|
110
|
+
/** Title row with the close button, pinned above the scrolling body. */
|
|
111
|
+
declare const DialogHeader: FunctionComponent<{
|
|
112
|
+
title: string;
|
|
113
|
+
description?: string; /** Rendered between the title and the close button. */
|
|
114
|
+
actions?: React.ReactNode;
|
|
115
|
+
}>;
|
|
116
|
+
/** The scrolling region under the header. */
|
|
117
|
+
declare const DialogBody: FunctionComponent<React.HTMLAttributes<HTMLDivElement>>;
|
|
118
|
+
/** A label/value row — the shape every one of these panels is mostly made of. */
|
|
119
|
+
declare const DialogRow: FunctionComponent<{
|
|
120
|
+
label: string;
|
|
121
|
+
children: React.ReactNode;
|
|
122
|
+
mono?: boolean;
|
|
123
|
+
}>;
|
|
124
|
+
//#endregion
|
|
83
125
|
//#region src/components/ui/Tooltip.d.ts
|
|
84
126
|
declare const TooltipProvider: _$react.FC<_$_base_ui_react_tooltip0.TooltipProviderProps>;
|
|
85
127
|
declare const TooltipContent: FunctionComponent<Tooltip.Popup.Props & Pick<Tooltip.Positioner.Props, 'side' | 'sideOffset'>>;
|
|
86
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* Convenience wrapper: `<Tip content="..."><Button/></Tip>`.
|
|
130
|
+
*
|
|
131
|
+
* Pass `render` when the trigger must *be* an element you already have — a tab, a
|
|
132
|
+
* row — rather than something wrapped in a span. The default span is fine beside
|
|
133
|
+
* a button but would break any layout that styles its own children (a flex tab
|
|
134
|
+
* strip gets an extra box between the container and its items).
|
|
135
|
+
*/
|
|
87
136
|
declare function Tip({
|
|
88
137
|
content,
|
|
138
|
+
render,
|
|
139
|
+
side,
|
|
89
140
|
children
|
|
90
141
|
}: {
|
|
91
142
|
content: ReactNode;
|
|
92
|
-
|
|
143
|
+
render?: ReactElement;
|
|
144
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
145
|
+
children?: ReactNode;
|
|
93
146
|
}): _$react.JSX.Element;
|
|
94
147
|
//#endregion
|
|
95
148
|
//#region src/components/ui/Sonner.d.ts
|
|
@@ -132,6 +185,57 @@ declare function CodeBlock({
|
|
|
132
185
|
className
|
|
133
186
|
}: CodeBlockProps): _$react.JSX.Element;
|
|
134
187
|
//#endregion
|
|
188
|
+
//#region src/components/ui/Splitter.d.ts
|
|
189
|
+
interface SplitterProps {
|
|
190
|
+
/**
|
|
191
|
+
* ARIA's sense of the word: a `vertical` splitter is a vertical bar between
|
|
192
|
+
* two side-by-side panes, and it resizes a **width**. A `horizontal` one sits
|
|
193
|
+
* between stacked panes and resizes a **height**.
|
|
194
|
+
*/
|
|
195
|
+
orientation: 'vertical' | 'horizontal';
|
|
196
|
+
/** Current size of the pane this splitter controls, in pixels. */
|
|
197
|
+
value: number;
|
|
198
|
+
onValueChange: (value: number) => void;
|
|
199
|
+
min: number;
|
|
200
|
+
max: number;
|
|
201
|
+
/** Keyboard step. */
|
|
202
|
+
step?: number;
|
|
203
|
+
/** Set when dragging the splitter *away* from the origin should shrink the
|
|
204
|
+
* controlled pane — i.e. the pane is on the right or the bottom. */
|
|
205
|
+
inverted?: boolean;
|
|
206
|
+
/** Required: "Resize" alone does not say which of two splitters this is. */
|
|
207
|
+
'aria-label': string;
|
|
208
|
+
className?: string;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* A draggable pane divider.
|
|
212
|
+
*
|
|
213
|
+
* Hand-rolled rather than depended on: `@base-ui/react` ships no splitter, the
|
|
214
|
+
* behaviour is a hundred lines of pointer events, and this repo's instinct at
|
|
215
|
+
* this layer is to own it (the composer is vendored for the same reason).
|
|
216
|
+
*
|
|
217
|
+
* Pointer capture is what makes it survive a fast drag — without it the pointer
|
|
218
|
+
* leaves the 5px bar within a frame and the moves go to whatever is underneath,
|
|
219
|
+
* which for this layout is an iframe-free but still selection-happy code pane.
|
|
220
|
+
* The drag origin is captured on pointerdown and every move is measured against
|
|
221
|
+
* it, so the pane cannot drift relative to the cursor over a long drag the way
|
|
222
|
+
* per-move deltas do once clamping is involved.
|
|
223
|
+
*
|
|
224
|
+
* Keyboard-operable and announced as a separator, because a pane you can only
|
|
225
|
+
* size by dragging is a pane some people cannot size.
|
|
226
|
+
*/
|
|
227
|
+
declare function Splitter({
|
|
228
|
+
orientation,
|
|
229
|
+
value,
|
|
230
|
+
onValueChange,
|
|
231
|
+
min,
|
|
232
|
+
max,
|
|
233
|
+
step,
|
|
234
|
+
inverted,
|
|
235
|
+
'aria-label': label,
|
|
236
|
+
className
|
|
237
|
+
}: SplitterProps): _$react.JSX.Element;
|
|
238
|
+
//#endregion
|
|
135
239
|
//#region src/components/ui/ProgressRing.d.ts
|
|
136
240
|
interface ProgressRingProps {
|
|
137
241
|
/** Filled share, 0–100 (clamped). */
|
|
@@ -235,6 +339,21 @@ type TriggerConfig = {
|
|
|
235
339
|
* Return the display text for the chip, or void to use `suggestion.label`.
|
|
236
340
|
*/
|
|
237
341
|
onSelect?: (suggestion: TriggerSuggestion) => string | void;
|
|
342
|
+
/**
|
|
343
|
+
* For 'dropdown' mode: opt a suggestion out of becoming a chip.
|
|
344
|
+
*
|
|
345
|
+
* Return a string and the trigger's range is replaced with that **plain,
|
|
346
|
+
* editable text** — the trigger character included — with the caret left at
|
|
347
|
+
* its end. Return undefined and the suggestion resolves to a chip as usual,
|
|
348
|
+
* so one dropdown can mix both kinds.
|
|
349
|
+
*
|
|
350
|
+
* For suggestions that are a typing aid rather than a token: something the
|
|
351
|
+
* user is meant to finish and edit, where a chip would falsely promise the
|
|
352
|
+
* host parses it back out. Takes precedence over `onSelect`, which is not
|
|
353
|
+
* called for a text-resolved suggestion (there is no chip to label), and
|
|
354
|
+
* `onChipAdd` does not fire either.
|
|
355
|
+
*/
|
|
356
|
+
insertAsText?: (suggestion: TriggerSuggestion) => string | undefined;
|
|
238
357
|
/**
|
|
239
358
|
* For 'callback' and 'launch' modes: called when the trigger is activated.
|
|
240
359
|
* Receives the full input text and cursor position. For 'launch' it fires on
|
|
@@ -581,14 +700,33 @@ declare function getChipsByTrigger(segments: Segment[], trigger: string): ChipSe
|
|
|
581
700
|
interface SessionPanelProps {
|
|
582
701
|
client: WorkerDeckClient;
|
|
583
702
|
sessionId: string | undefined;
|
|
584
|
-
/**
|
|
585
|
-
|
|
703
|
+
/**
|
|
704
|
+
* Optional slot rendered at the top, above the status bar.
|
|
705
|
+
*
|
|
706
|
+
* Pass a **function** to take the session-actions (`⋯`) menu into your own
|
|
707
|
+
* chrome: it is called with the menu element, and wherever you put it is
|
|
708
|
+
* where it lives — the status bar then renders without it, so it never
|
|
709
|
+
* appears twice. Pass a plain node (or nothing) and the menu stays in the
|
|
710
|
+
* status bar's trailing slot.
|
|
711
|
+
*
|
|
712
|
+
* The seam exists because the menu can only be *built* here — it needs the
|
|
713
|
+
* capability record, the host-file verdict and the panel's own dialog state —
|
|
714
|
+
* but an embedder with a real header usually wants it up there with the rest
|
|
715
|
+
* of the session's controls, not stranded on the status line.
|
|
716
|
+
*/
|
|
717
|
+
header?: ReactNode | ((slots: {
|
|
718
|
+
actions: ReactNode;
|
|
719
|
+
}) => ReactNode);
|
|
586
720
|
className?: string;
|
|
587
721
|
}
|
|
588
722
|
/**
|
|
589
723
|
* The all-in-one embeddable session surface: status bar, streaming transcript,
|
|
590
724
|
* permission prompts, composer. Attaches via useClaudeSession; remount (key) to switch
|
|
591
725
|
* sessions.
|
|
726
|
+
*
|
|
727
|
+
* Every affordance is gated on the session's **capability record** rather than on
|
|
728
|
+
* the engine name — an absent capability hides the control instead of offering
|
|
729
|
+
* one that can only fail.
|
|
592
730
|
*/
|
|
593
731
|
declare function SessionPanel({
|
|
594
732
|
client,
|
|
@@ -597,17 +735,221 @@ declare function SessionPanel({
|
|
|
597
735
|
className
|
|
598
736
|
}: SessionPanelProps): _$react.JSX.Element;
|
|
599
737
|
//#endregion
|
|
738
|
+
//#region src/components/agent/SessionWorkspace.d.ts
|
|
739
|
+
interface SessionWorkspaceProps {
|
|
740
|
+
client: WorkerDeckClient;
|
|
741
|
+
sessionId: string | undefined;
|
|
742
|
+
/** Passed straight through to {@link SessionPanel} — including the render-prop
|
|
743
|
+
* form that claims the session-actions menu. */
|
|
744
|
+
header?: SessionPanelProps['header'];
|
|
745
|
+
/** Rail width in pixels on first render. */
|
|
746
|
+
defaultRailWidth?: number;
|
|
747
|
+
/** Start with the file rail collapsed even on a wide viewport. */
|
|
748
|
+
defaultRailCollapsed?: boolean;
|
|
749
|
+
className?: string;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* A VS Code-shaped workspace around a live session: file tree on the left, open
|
|
753
|
+
* files above, the agent below.
|
|
754
|
+
*
|
|
755
|
+
* **Strictly additive.** {@link SessionPanel} is untouched and still the whole
|
|
756
|
+
* session surface on its own — an embedder picks one or the other, and one that
|
|
757
|
+
* has its own file tree keeps using the panel.
|
|
758
|
+
*
|
|
759
|
+
* Two things here are load-bearing and easy to break:
|
|
760
|
+
*
|
|
761
|
+
* 1. **The editor region is absent from the layout when nothing is open**, not
|
|
762
|
+
* collapsed to zero height. A zero-height pane leaves a draggable splitter and
|
|
763
|
+
* parks the composer at an odd offset; absence is what makes the agent's
|
|
764
|
+
* "claims the full column" state actually look like the panel alone.
|
|
765
|
+
* 2. **`SessionPanel` keeps its position in the tree across that transition.** It
|
|
766
|
+
* holds the WebSocket attach and the entire transcript, so moving it between
|
|
767
|
+
* parents — or wrapping it conditionally — would remount it and drop the
|
|
768
|
+
* session's rendered history on the floor the first time someone opens a file.
|
|
769
|
+
* The conditional children before it are `? :` expressions that leave a null in
|
|
770
|
+
* their slot, which is exactly what keeps its index stable.
|
|
771
|
+
*/
|
|
772
|
+
declare function SessionWorkspace({
|
|
773
|
+
client,
|
|
774
|
+
sessionId,
|
|
775
|
+
header,
|
|
776
|
+
defaultRailWidth,
|
|
777
|
+
defaultRailCollapsed,
|
|
778
|
+
className
|
|
779
|
+
}: SessionWorkspaceProps): _$react.JSX.Element;
|
|
780
|
+
//#endregion
|
|
781
|
+
//#region src/components/agent/FileTree.d.ts
|
|
782
|
+
interface FileTreeProps {
|
|
783
|
+
/** Tree state from `useHostFileTree` — this component holds none of its own. */
|
|
784
|
+
tree: UseHostFileTreeResult;
|
|
785
|
+
/** Optional search from `useHostFileSearch`; omit and the box is not offered. */
|
|
786
|
+
search?: UseHostFileSearchResult;
|
|
787
|
+
/** Path of the focused file, highlighted in the tree. */
|
|
788
|
+
activePath?: string;
|
|
789
|
+
onOpenFile: (path: string) => void;
|
|
790
|
+
/** Offered as a button in the header when given. */
|
|
791
|
+
onCollapse?: () => void;
|
|
792
|
+
style?: CSSProperties;
|
|
793
|
+
className?: string;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* The workspace's left rail: an expandable tree of the session's project,
|
|
797
|
+
* with a search box over the same fuzzy route `@file` completion uses.
|
|
798
|
+
*
|
|
799
|
+
* Presentational by construction — every piece of state it renders comes from
|
|
800
|
+
* the hooks in `@workerdeck/react`, and the only thing it owns is the search
|
|
801
|
+
* query, which is the text in its own input.
|
|
802
|
+
*
|
|
803
|
+
* Searching replaces the tree with matches rather than filtering it: the route
|
|
804
|
+
* answers with paths from all over the project, and threading those back into
|
|
805
|
+
* tree positions would mean expanding a dozen directories to show six results.
|
|
806
|
+
*/
|
|
807
|
+
declare function FileTree({
|
|
808
|
+
tree,
|
|
809
|
+
search,
|
|
810
|
+
activePath,
|
|
811
|
+
onOpenFile,
|
|
812
|
+
onCollapse,
|
|
813
|
+
style,
|
|
814
|
+
className
|
|
815
|
+
}: FileTreeProps): _$react.JSX.Element;
|
|
816
|
+
//#endregion
|
|
817
|
+
//#region src/components/agent/EditorTabs.d.ts
|
|
818
|
+
interface EditorTabsProps {
|
|
819
|
+
files: OpenFile[];
|
|
820
|
+
activePath?: string;
|
|
821
|
+
onActivate: (path: string) => void;
|
|
822
|
+
onClose: (path: string) => void;
|
|
823
|
+
className?: string;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* The open-file tab strip.
|
|
827
|
+
*
|
|
828
|
+
* Hand-rolled rather than built on `@base-ui/react`'s `Tabs`: a VS Code tab
|
|
829
|
+
* carries a close button, and a `<button>` inside a `<button>` is invalid HTML —
|
|
830
|
+
* getting the primitive to render something else costs more than the roving
|
|
831
|
+
* tabindex it would have provided. So that part is here, explicitly, along with
|
|
832
|
+
* the two affordances that actually make a tab strip feel right: middle-click to
|
|
833
|
+
* close, and the active tab scrolling itself into view.
|
|
834
|
+
*
|
|
835
|
+
* Deliberately state-free. Which files are open, which is focused and what
|
|
836
|
+
* closing does are all decided by `useOpenFiles`.
|
|
837
|
+
*/
|
|
838
|
+
declare function EditorTabs({
|
|
839
|
+
files,
|
|
840
|
+
activePath,
|
|
841
|
+
onActivate,
|
|
842
|
+
onClose,
|
|
843
|
+
className
|
|
844
|
+
}: EditorTabsProps): _$react.JSX.Element;
|
|
845
|
+
//#endregion
|
|
846
|
+
//#region src/components/agent/FileViewer.d.ts
|
|
847
|
+
interface FileViewerProps {
|
|
848
|
+
file: OpenFile | undefined;
|
|
849
|
+
/** From `/fs/roots`. False renders the editor read-only rather than letting
|
|
850
|
+
* someone type into a file this gateway will refuse to write. */
|
|
851
|
+
canWrite?: boolean;
|
|
852
|
+
onChange?: (path: string, content: string) => void;
|
|
853
|
+
onSave?: (path: string) => void;
|
|
854
|
+
/** Discard this tab's edits — local only, no re-read. */
|
|
855
|
+
onRevert?: (path: string) => void;
|
|
856
|
+
/** Take the version on disk, discarding this tab's edits. */
|
|
857
|
+
onReload?: (path: string) => void;
|
|
858
|
+
/** Take this tab's version, over whatever is on disk now. */
|
|
859
|
+
onOverwrite?: (path: string) => void;
|
|
860
|
+
onDismissConflict?: (path: string) => void;
|
|
861
|
+
className?: string;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* The focused file: Monaco, plus the states a file can be in that are not
|
|
865
|
+
* "here is some text".
|
|
866
|
+
*
|
|
867
|
+
* No path row — the tab's tooltip carries the path and the size, and a line of
|
|
868
|
+
* monospace above every file is chrome that never earns its height.
|
|
869
|
+
*/
|
|
870
|
+
declare function FileViewer({
|
|
871
|
+
file,
|
|
872
|
+
canWrite,
|
|
873
|
+
onChange,
|
|
874
|
+
onSave,
|
|
875
|
+
onRevert,
|
|
876
|
+
onReload,
|
|
877
|
+
onOverwrite,
|
|
878
|
+
onDismissConflict,
|
|
879
|
+
className
|
|
880
|
+
}: FileViewerProps): _$react.JSX.Element | null;
|
|
881
|
+
//#endregion
|
|
882
|
+
//#region src/components/agent/CodeEditor.d.ts
|
|
883
|
+
interface CodeEditorProps {
|
|
884
|
+
/** Absolute path — decides the language and identifies the model. */
|
|
885
|
+
path: string;
|
|
886
|
+
/** Text to show. Applied to the model when it differs from what is on screen,
|
|
887
|
+
* so an external reload lands without fighting the user's cursor. */
|
|
888
|
+
value: string;
|
|
889
|
+
onChange?: (value: string) => void;
|
|
890
|
+
/** Ctrl/Cmd+S. Wired inside Monaco because the editor swallows keydown. */
|
|
891
|
+
onSave?: () => void;
|
|
892
|
+
readOnly?: boolean;
|
|
893
|
+
className?: string;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Monaco — VS Code's own editor — behind a small React surface.
|
|
897
|
+
*
|
|
898
|
+
* Two deliberate choices, both about `@workerdeck/ui` being a **published
|
|
899
|
+
* library** rather than an app:
|
|
900
|
+
*
|
|
901
|
+
* 1. **Loaded on demand.** The `import()` is inside an effect, so Monaco is a
|
|
902
|
+
* separate chunk that arrives when someone first opens a file. A dashboard
|
|
903
|
+
* that never opens one never pays for it, and Monaco's ~90 language grammars
|
|
904
|
+
* are themselves lazy (each `registerLanguage` carries an `import()` loader),
|
|
905
|
+
* so opening a `.ts` file fetches the TypeScript grammar and nothing else.
|
|
906
|
+
* 2. **No `MonacoEnvironment` is configured here, and none is needed.** Workers
|
|
907
|
+
* in a library become every embedder's bootstrapping problem, and
|
|
908
|
+
* `packages/web` ships prebuilt static files at a domain root, which is
|
|
909
|
+
* exactly where hardcoded worker URLs break. The editor is configured so it
|
|
910
|
+
* never asks for one: `wordBasedSuggestions` and `quickSuggestions` off,
|
|
911
|
+
* no diff editor. A host that wants the worker-backed language services
|
|
912
|
+
* (TypeScript IntelliSense, JSON schema validation) sets `MonacoEnvironment`
|
|
913
|
+
* itself before the first file is opened — Monaco is a singleton and nothing
|
|
914
|
+
* here fights that.
|
|
915
|
+
*
|
|
916
|
+
* One model per path, kept across tab switches, so undo history and view state
|
|
917
|
+
* survive clicking away and back — which is most of what makes tabs feel like
|
|
918
|
+
* tabs rather than like re-opening a file.
|
|
919
|
+
*/
|
|
920
|
+
declare function CodeEditor({
|
|
921
|
+
path,
|
|
922
|
+
value,
|
|
923
|
+
onChange,
|
|
924
|
+
onSave,
|
|
925
|
+
readOnly,
|
|
926
|
+
className
|
|
927
|
+
}: CodeEditorProps): _$react.JSX.Element;
|
|
928
|
+
//#endregion
|
|
600
929
|
//#region src/components/agent/Transcript.d.ts
|
|
601
930
|
interface TranscriptProps {
|
|
602
931
|
state: TranscriptState;
|
|
603
932
|
/** Builds the download URL for a delivered file (see FileCard). Typically
|
|
604
933
|
* `(path) => client.sessionFileUrl(sessionId, path)`. */
|
|
605
934
|
fileUrl?: (path: string) => string;
|
|
935
|
+
/** Builds the URL for an uploaded attachment. Typically
|
|
936
|
+
* `(id) => client.attachmentUrl(sessionId, id)`. Same-origin and
|
|
937
|
+
* cookie-authenticated, which is what lets an `<img src>` render one. */
|
|
938
|
+
attachmentUrl?: (attachmentId: string) => string;
|
|
939
|
+
/** Whether this gateway serves `@file` search here — the empty state must not
|
|
940
|
+
* advertise an affordance the composer doesn't have. */
|
|
941
|
+
canBrowseFiles?: boolean;
|
|
942
|
+
/** Reads a host file as a data URL, for tool calls whose output is a picture
|
|
943
|
+
* on the host (codex's `image_gen`). Omit and those cards name the path. */
|
|
944
|
+
hostImage?: (path: string) => Promise<string | undefined>;
|
|
606
945
|
className?: string;
|
|
607
946
|
}
|
|
608
947
|
declare function Transcript({
|
|
609
948
|
state,
|
|
610
949
|
fileUrl,
|
|
950
|
+
attachmentUrl,
|
|
951
|
+
canBrowseFiles,
|
|
952
|
+
hostImage,
|
|
611
953
|
className
|
|
612
954
|
}: TranscriptProps): _$react.JSX.Element;
|
|
613
955
|
//#endregion
|
|
@@ -699,10 +1041,19 @@ type ToolCallItem = Extract<TranscriptItem, {
|
|
|
699
1041
|
}>;
|
|
700
1042
|
interface ToolCallCardProps {
|
|
701
1043
|
item: ToolCallItem;
|
|
1044
|
+
/**
|
|
1045
|
+
* Reads a host file as a data URL, for tools whose output is a picture on the
|
|
1046
|
+
* host. Resolves `undefined` when the gateway won't serve that path — a
|
|
1047
|
+
* generated image saved outside the allowed roots (codex's default
|
|
1048
|
+
* `$CODEX_HOME/generated_images/`) is one, and the card then names the path
|
|
1049
|
+
* instead of showing it.
|
|
1050
|
+
*/
|
|
1051
|
+
hostImage?: (path: string) => Promise<string | undefined>;
|
|
702
1052
|
className?: string;
|
|
703
1053
|
}
|
|
704
1054
|
declare function ToolCallCard({
|
|
705
1055
|
item,
|
|
1056
|
+
hostImage,
|
|
706
1057
|
className
|
|
707
1058
|
}: ToolCallCardProps): _$react.JSX.Element;
|
|
708
1059
|
//#endregion
|
|
@@ -730,9 +1081,23 @@ declare function FileCard({
|
|
|
730
1081
|
interface PermissionPromptProps {
|
|
731
1082
|
request: PermissionRequest;
|
|
732
1083
|
onApprove: (requestId: string) => void;
|
|
733
|
-
|
|
1084
|
+
/** `message` is fed back to the agent, which can then try something else;
|
|
1085
|
+
* `interrupt` also stops the turn. */
|
|
1086
|
+
onDeny: (requestId: string, message?: string, interrupt?: boolean) => void;
|
|
734
1087
|
className?: string;
|
|
735
1088
|
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Generic allow/deny prompt for a pending permission request.
|
|
1091
|
+
*
|
|
1092
|
+
* Three outcomes, not two: denying usually means "not that, try something else",
|
|
1093
|
+
* so plain Deny lets the turn continue (with an optional reason the agent reads)
|
|
1094
|
+
* while "Deny & stop" also interrupts.
|
|
1095
|
+
*
|
|
1096
|
+
* The heading is whatever the engine authored — `title`, else `displayName`.
|
|
1097
|
+
* Composing "wants to use {tool}" instead would be wrong for codex, where an
|
|
1098
|
+
* approval is usually an *escalation after a sandbox refusal* and the runner has
|
|
1099
|
+
* already written the sentence that says so.
|
|
1100
|
+
*/
|
|
736
1101
|
declare function PermissionPrompt({
|
|
737
1102
|
request,
|
|
738
1103
|
onApprove,
|
|
@@ -771,8 +1136,22 @@ declare function QuestionPrompt({
|
|
|
771
1136
|
}: QuestionPromptProps): _$react.JSX.Element;
|
|
772
1137
|
//#endregion
|
|
773
1138
|
//#region src/components/agent/Composer.d.ts
|
|
1139
|
+
/** Files matching an `@` query, for the composer's file trigger. Structural so
|
|
1140
|
+
* the ui package doesn't have to reach for the protocol's `HostFileMatch`. */
|
|
1141
|
+
type ComposerFileMatch = {
|
|
1142
|
+
path: string;
|
|
1143
|
+
relative: string;
|
|
1144
|
+
};
|
|
1145
|
+
/** Imperative surface for panels that draft a message the user then finishes —
|
|
1146
|
+
* the skills dialog's "Use this skill". Nothing here sends. */
|
|
1147
|
+
type ComposerHandle = {
|
|
1148
|
+
/** Append plain text at the caret's end and focus, separating it from
|
|
1149
|
+
* whatever is already there. */
|
|
1150
|
+
insertText: (text: string) => void;
|
|
1151
|
+
};
|
|
774
1152
|
interface ComposerProps {
|
|
775
|
-
|
|
1153
|
+
/** `attachmentIds` are the staged uploads, in the order they were picked. */
|
|
1154
|
+
onSend: (text: string, attachmentIds: string[]) => void;
|
|
776
1155
|
onInterrupt: () => void;
|
|
777
1156
|
busy: boolean;
|
|
778
1157
|
/** Disable input entirely (session failed/closed). */
|
|
@@ -780,14 +1159,62 @@ interface ComposerProps {
|
|
|
780
1159
|
placeholder?: string;
|
|
781
1160
|
/** Slash commands offered as autocomplete; picked ones render as chips. */
|
|
782
1161
|
commands?: SlashCommandInfo[];
|
|
783
|
-
/**
|
|
1162
|
+
/**
|
|
1163
|
+
* Skills offered under a **`$`** popover of their own — codex's sigil, kept
|
|
1164
|
+
* separate from `/` because the two behave differently. A skill is a typing
|
|
1165
|
+
* aid, not a command: picking one inserts editable text (the skill's own
|
|
1166
|
+
* `defaultPrompt` where it has one, else `$name`) and nothing is sent. No
|
|
1167
|
+
* engine parses `$skillname` as syntax, which is exactly why these can never
|
|
1168
|
+
* resolve to a chip the way `commands` do.
|
|
1169
|
+
*/
|
|
1170
|
+
skills?: SkillInfo[];
|
|
1171
|
+
/** Host-file search behind the `@` trigger. Omit to leave `@` inert — a
|
|
1172
|
+
* gateway without host files has nothing to complete. */
|
|
1173
|
+
onSearchFiles?: (query: string, options: {
|
|
1174
|
+
signal: AbortSignal;
|
|
1175
|
+
}) => Promise<ComposerFileMatch[]>;
|
|
1176
|
+
/** Attachment staging (see `useAttachments`). Omit for a text-only composer. */
|
|
1177
|
+
attachments?: UseAttachmentsResult;
|
|
1178
|
+
/** Left side of the toolbar row (mode selects, …). */
|
|
784
1179
|
toolbar?: ReactNode;
|
|
785
1180
|
className?: string;
|
|
1181
|
+
ref?: Ref<ComposerHandle>;
|
|
786
1182
|
}
|
|
787
|
-
/**
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
*
|
|
1183
|
+
/**
|
|
1184
|
+
* What a picked skill types into the composer.
|
|
1185
|
+
*
|
|
1186
|
+
* The engine's own `defaultPrompt` when it declared one — it knows what its
|
|
1187
|
+
* skill wants to be asked — and otherwise `$name`, which is codex's native way
|
|
1188
|
+
* of referring to a skill in prompt text: its `skill-creator` documents the form
|
|
1189
|
+
* (`Use $skill-x at /path/to/skill-x to solve problem y`) and its own bundled
|
|
1190
|
+
* prompts are written that way ("Use $pdf to …"). Spelling it the way the engine
|
|
1191
|
+
* spells it beats paraphrasing into "Use the X skill to".
|
|
1192
|
+
*
|
|
1193
|
+
* Either way it ends in a space so the caret lands ready for the rest of the
|
|
1194
|
+
* sentence, and either way it is ordinary text: nothing here is submitted, and
|
|
1195
|
+
* nothing is parsed back out.
|
|
1196
|
+
*/
|
|
1197
|
+
declare function skillPrompt(skill: SkillInfo): string;
|
|
1198
|
+
/**
|
|
1199
|
+
* Framed prompt input built on prompt-area's contentEditable.
|
|
1200
|
+
*
|
|
1201
|
+
* Three completions ride the same field and behave nothing alike. `/` is the
|
|
1202
|
+
* CLI's command list and `$` is the engine's skill list — both local, so they
|
|
1203
|
+
* filter completely and instantly; `@` is a search against the host filesystem,
|
|
1204
|
+
* debounced and abortable so a fast typist makes one request rather than eight.
|
|
1205
|
+
*
|
|
1206
|
+
* `/` and `$` are separate keys rather than one merged menu, and that mirrors
|
|
1207
|
+
* the engines themselves: codex completes skills on `$` and reserves `/` for
|
|
1208
|
+
* commands. The behaviours differ too — a command resolves to a **chip**,
|
|
1209
|
+
* because the CLI really does parse `/name` out of the message, while a skill
|
|
1210
|
+
* resolves to plain editable **text**, because no engine parses `$name` as
|
|
1211
|
+
* syntax; it is prose the model reads. Rendering them alike would promise
|
|
1212
|
+
* something that does not happen.
|
|
1213
|
+
*
|
|
1214
|
+
* Files can arrive three ways — the paperclip, a drop, or a paste — because on a
|
|
1215
|
+
* desktop all three are things people already do, and the upload starts the
|
|
1216
|
+
* moment one lands rather than at send time.
|
|
1217
|
+
*/
|
|
791
1218
|
declare function Composer({
|
|
792
1219
|
onSend,
|
|
793
1220
|
onInterrupt,
|
|
@@ -795,8 +1222,12 @@ declare function Composer({
|
|
|
795
1222
|
disabled,
|
|
796
1223
|
placeholder,
|
|
797
1224
|
commands,
|
|
1225
|
+
skills,
|
|
1226
|
+
onSearchFiles,
|
|
1227
|
+
attachments,
|
|
798
1228
|
toolbar,
|
|
799
|
-
className
|
|
1229
|
+
className,
|
|
1230
|
+
ref
|
|
800
1231
|
}: ComposerProps): _$react.JSX.Element;
|
|
801
1232
|
//#endregion
|
|
802
1233
|
//#region src/components/agent/ModelSelect.d.ts
|
|
@@ -828,21 +1259,43 @@ declare function ModelSelect({
|
|
|
828
1259
|
//#endregion
|
|
829
1260
|
//#region src/components/agent/PermissionModeSelect.d.ts
|
|
830
1261
|
type PermissionModeMeta = {
|
|
831
|
-
value: PermissionMode;
|
|
1262
|
+
value: PermissionMode; /** The name Claude Code itself uses. */
|
|
832
1263
|
label: string;
|
|
1264
|
+
/** The chip form, for bars where the label shares a line with three other
|
|
1265
|
+
* things and "Bypass permissions" would eat half of it. */
|
|
1266
|
+
shortLabel: string; /** What the mode actually does — the CLI's own one-liners. */
|
|
833
1267
|
description: string;
|
|
1268
|
+
icon: LucideIcon;
|
|
834
1269
|
dangerous?: boolean;
|
|
835
1270
|
};
|
|
836
|
-
/**
|
|
1271
|
+
/**
|
|
1272
|
+
* The modes surfaced across UI surfaces (session creation, in-session switcher),
|
|
1273
|
+
* ordered by how much of the approval gate they give away.
|
|
1274
|
+
*
|
|
1275
|
+
* Notably `default` is **"Manual"**: the wire value is `default`, but calling it
|
|
1276
|
+
* that in the UI conflates a real mode (ask me every time) with "whatever the
|
|
1277
|
+
* server picked", which is the one confusion a mode chip exists to avoid. The
|
|
1278
|
+
* naming, the icons and the summaries are shared with the iOS app on purpose —
|
|
1279
|
+
* the two surfaces should read as the same list.
|
|
1280
|
+
*/
|
|
837
1281
|
declare const PERMISSION_MODES: PermissionModeMeta[];
|
|
1282
|
+
declare const permissionModeMeta: (mode: PermissionMode) => PermissionModeMeta | undefined;
|
|
838
1283
|
interface PermissionModeSelectProps {
|
|
839
1284
|
/** The session's current mode (TranscriptState.permissionMode). */
|
|
840
1285
|
mode?: PermissionMode;
|
|
841
1286
|
onModeChange: (mode: PermissionMode) => void;
|
|
842
1287
|
/** Restrict what is offered — most of {@link PERMISSION_MODES} is Claude Code
|
|
843
|
-
* vocabulary the
|
|
844
|
-
* pass
|
|
1288
|
+
* vocabulary the other engines have no meaning for. Defaults to all of them;
|
|
1289
|
+
* pass the session's `capabilities.permissionModes`. */
|
|
845
1290
|
modes?: readonly PermissionMode[];
|
|
1291
|
+
/**
|
|
1292
|
+
* Whether this session may be switched into `bypassPermissions` at all. The
|
|
1293
|
+
* CLI refuses unless the process was spawned for it, so a session that didn't
|
|
1294
|
+
* ask up front can never gain it. The row is shown disabled rather than hidden
|
|
1295
|
+
* — "you can't have this here" is a more useful answer than a row that
|
|
1296
|
+
* silently isn't there. `undefined` (an older server) offers it.
|
|
1297
|
+
*/
|
|
1298
|
+
canBypass?: boolean;
|
|
846
1299
|
/** 'toolbar' (default) is the composer's compact borderless trigger;
|
|
847
1300
|
* 'form' is a standard field-sized Select for create/settings forms. */
|
|
848
1301
|
variant?: 'toolbar' | 'form';
|
|
@@ -854,6 +1307,7 @@ declare function PermissionModeSelect({
|
|
|
854
1307
|
mode,
|
|
855
1308
|
onModeChange,
|
|
856
1309
|
modes,
|
|
1310
|
+
canBypass,
|
|
857
1311
|
variant,
|
|
858
1312
|
disabled,
|
|
859
1313
|
className
|
|
@@ -862,15 +1316,205 @@ declare function PermissionModeSelect({
|
|
|
862
1316
|
//#region src/components/agent/StatusBar.d.ts
|
|
863
1317
|
interface StatusBarProps {
|
|
864
1318
|
state: TranscriptState;
|
|
865
|
-
|
|
1319
|
+
/** @deprecated Pass {@link StatusBarProps.connection}; kept so an embedder
|
|
1320
|
+
* still handing over a boolean keeps working. */
|
|
1321
|
+
connected?: boolean;
|
|
1322
|
+
/** How the client is doing at reaching the gateway. A dropped socket wins the
|
|
1323
|
+
* status slot: the session status held over a dead socket is a stale reading,
|
|
1324
|
+
* and presenting it as a live one is the thing worth avoiding. */
|
|
1325
|
+
connection?: ConnectionState;
|
|
1326
|
+
/**
|
|
1327
|
+
* Where the gauges lead. Each one opens the panel that answers *its* question
|
|
1328
|
+
* — the two meters measure different things, so sending both to one "details"
|
|
1329
|
+
* list would be a detour every time. Omit a handler and that gauge stays a
|
|
1330
|
+
* read-only tooltip.
|
|
1331
|
+
*/
|
|
1332
|
+
onOpenStatus?: () => void;
|
|
1333
|
+
onOpenContext?: () => void;
|
|
1334
|
+
onOpenUsage?: () => void;
|
|
1335
|
+
/** Trailing slot — the session-actions menu, in the panel's top-right. */
|
|
1336
|
+
actions?: ReactNode;
|
|
866
1337
|
className?: string;
|
|
867
1338
|
}
|
|
868
1339
|
declare function StatusBar({
|
|
869
1340
|
state,
|
|
870
1341
|
connected,
|
|
1342
|
+
connection,
|
|
1343
|
+
onOpenStatus,
|
|
1344
|
+
onOpenContext,
|
|
1345
|
+
onOpenUsage,
|
|
1346
|
+
actions,
|
|
871
1347
|
className
|
|
872
1348
|
}: StatusBarProps): _$react.JSX.Element;
|
|
873
1349
|
//#endregion
|
|
1350
|
+
//#region src/components/agent/ContextDialog.d.ts
|
|
1351
|
+
interface ContextDialogProps {
|
|
1352
|
+
usage?: ContextUsage;
|
|
1353
|
+
open: boolean;
|
|
1354
|
+
onOpenChange: (open: boolean) => void;
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* What is in the model's context window right now, category by category.
|
|
1358
|
+
*
|
|
1359
|
+
* One of the three panels the status bar opens. Context, usage and session info
|
|
1360
|
+
* are different questions asked at different moments, so they are different
|
|
1361
|
+
* screens rather than one "details" list you scroll past two answers to reach.
|
|
1362
|
+
*/
|
|
1363
|
+
declare function ContextDialog({
|
|
1364
|
+
usage,
|
|
1365
|
+
open,
|
|
1366
|
+
onOpenChange
|
|
1367
|
+
}: ContextDialogProps): _$react.JSX.Element;
|
|
1368
|
+
//#endregion
|
|
1369
|
+
//#region src/components/agent/UsageDialog.d.ts
|
|
1370
|
+
interface UsageDialogProps {
|
|
1371
|
+
/** Windows in reading order — session, weekly, then per-model weeklies. */
|
|
1372
|
+
rateLimits: Array<{
|
|
1373
|
+
key: string;
|
|
1374
|
+
info: RateLimitInfo;
|
|
1375
|
+
}>;
|
|
1376
|
+
/** claude.ai plan behind the windows ('max', 'pro', …), when there is one. */
|
|
1377
|
+
subscriptionType?: string;
|
|
1378
|
+
engine: ProfileEngine;
|
|
1379
|
+
totalCostUsd: number;
|
|
1380
|
+
/** Local receipt time of the last window update. `rate_limit` events are one
|
|
1381
|
+
* per turn at best, so a stale reading is normal and worth saying out loud. */
|
|
1382
|
+
updatedAt?: number;
|
|
1383
|
+
open: boolean;
|
|
1384
|
+
onOpenChange: (open: boolean) => void;
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* The plan's rate-limit windows, spelled out: how much of each is used, how that
|
|
1388
|
+
* compares to the pace that would spend the window exactly, and when it resets.
|
|
1389
|
+
*
|
|
1390
|
+
* The pace marker is the point. A bar alone says "17% used", which is only
|
|
1391
|
+
* alarming or reassuring once you know how far into the week you are — so every
|
|
1392
|
+
* window draws a tick at the elapsed share of its duration. Left of the tick is
|
|
1393
|
+
* under budget, right of it is ahead of it. The duration comes from the window
|
|
1394
|
+
* key (5h, 7d) because the CLI reports a reset time and a percentage and never a
|
|
1395
|
+
* duration; a window whose key doesn't say gets no marker rather than a guessed one.
|
|
1396
|
+
*/
|
|
1397
|
+
declare function UsageDialog({
|
|
1398
|
+
rateLimits,
|
|
1399
|
+
subscriptionType,
|
|
1400
|
+
engine,
|
|
1401
|
+
totalCostUsd,
|
|
1402
|
+
updatedAt,
|
|
1403
|
+
open,
|
|
1404
|
+
onOpenChange
|
|
1405
|
+
}: UsageDialogProps): _$react.JSX.Element;
|
|
1406
|
+
//#endregion
|
|
1407
|
+
//#region src/components/agent/SessionInfoDialog.d.ts
|
|
1408
|
+
interface SessionInfoDialogProps {
|
|
1409
|
+
state: TranscriptState;
|
|
1410
|
+
client: WorkerDeckClient;
|
|
1411
|
+
sessionId: string | undefined;
|
|
1412
|
+
open: boolean;
|
|
1413
|
+
onOpenChange: (open: boolean) => void;
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* What this session *is*: engine, profile, model, mode, where it runs, which
|
|
1417
|
+
* credentials it found, and the files it has handed over.
|
|
1418
|
+
*
|
|
1419
|
+
* The identity half of the session's facts. Context and usage have their own
|
|
1420
|
+
* panels — they change every turn and are consulted mid-run, while everything
|
|
1421
|
+
* here is fixed at creation and looked up once.
|
|
1422
|
+
*/
|
|
1423
|
+
declare function SessionInfoDialog({
|
|
1424
|
+
state,
|
|
1425
|
+
client,
|
|
1426
|
+
sessionId,
|
|
1427
|
+
open,
|
|
1428
|
+
onOpenChange
|
|
1429
|
+
}: SessionInfoDialogProps): _$react.JSX.Element;
|
|
1430
|
+
//#endregion
|
|
1431
|
+
//#region src/components/agent/McpDialog.d.ts
|
|
1432
|
+
interface McpDialogProps {
|
|
1433
|
+
client: WorkerDeckClient;
|
|
1434
|
+
sessionId: string | undefined;
|
|
1435
|
+
open: boolean;
|
|
1436
|
+
onOpenChange: (open: boolean) => void;
|
|
1437
|
+
/**
|
|
1438
|
+
* Whether this engine can reconnect/enable/disable a server
|
|
1439
|
+
* (`EngineCapabilities.mcpServerActions`). False renders the panel read-only:
|
|
1440
|
+
* codex reports rich status but exposes no per-server action, and buttons
|
|
1441
|
+
* that 501 are worse than buttons that aren't there.
|
|
1442
|
+
*/
|
|
1443
|
+
canManageServers?: boolean;
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* The session's MCP servers, at the CLI's own `/mcp` depth: servers → one server
|
|
1447
|
+
* → its tools → one tool, with Reconnect / Enable / Disable where they apply.
|
|
1448
|
+
*
|
|
1449
|
+
* Two things vary by engine rather than being fixed here. **The actions** exist
|
|
1450
|
+
* only where the engine has them (`canManageServers`): codex reports rich status
|
|
1451
|
+
* but has no per-server reconnect or toggle, so its panel is read-only. And
|
|
1452
|
+
* **tool parameters** appear only where the engine reports a schema — codex
|
|
1453
|
+
* returns each tool's full JSON Schema, the Agent SDK returns none at all, so
|
|
1454
|
+
* the tool view either renders it or says why it can't, rather than leaving a
|
|
1455
|
+
* silent gap or claiming the absence is universal.
|
|
1456
|
+
*/
|
|
1457
|
+
declare function McpDialog({
|
|
1458
|
+
client,
|
|
1459
|
+
sessionId,
|
|
1460
|
+
open,
|
|
1461
|
+
onOpenChange,
|
|
1462
|
+
canManageServers
|
|
1463
|
+
}: McpDialogProps): _$react.JSX.Element;
|
|
1464
|
+
//#endregion
|
|
1465
|
+
//#region src/components/agent/SkillsDialog.d.ts
|
|
1466
|
+
interface SkillsDialogProps {
|
|
1467
|
+
skills: SkillInfo[] | undefined;
|
|
1468
|
+
open: boolean;
|
|
1469
|
+
onOpenChange: (open: boolean) => void;
|
|
1470
|
+
/** Insert a skill's opening message into the composer, if the host offers
|
|
1471
|
+
* that. Omit and the dialog is read-only. */
|
|
1472
|
+
onUse?: (skill: SkillInfo) => void;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* What this session's engine can do beyond its own tools: the skills it found,
|
|
1476
|
+
* grouped by where they came from, with one drilled-down view each.
|
|
1477
|
+
*
|
|
1478
|
+
* The framing matters more here than in most panels. A skill is **not** a
|
|
1479
|
+
* command — the model decides to use one by reading its description, and there
|
|
1480
|
+
* is no wire syntax that invokes it. So this screen is a *discovery* surface,
|
|
1481
|
+
* and the one action it offers ("Use this skill") is honest about being a
|
|
1482
|
+
* drafting aid: it types a message for the operator to edit and send.
|
|
1483
|
+
*
|
|
1484
|
+
* Fed from the session's `skills` event rather than a REST route, because that
|
|
1485
|
+
* is the channel the engine refreshes on its own when a skill changes on disk.
|
|
1486
|
+
*/
|
|
1487
|
+
declare function SkillsDialog({
|
|
1488
|
+
skills,
|
|
1489
|
+
open,
|
|
1490
|
+
onOpenChange,
|
|
1491
|
+
onUse
|
|
1492
|
+
}: SkillsDialogProps): _$react.JSX.Element;
|
|
1493
|
+
//#endregion
|
|
1494
|
+
//#region src/components/agent/HostFilesDialog.d.ts
|
|
1495
|
+
interface HostFilesDialogProps {
|
|
1496
|
+
client: WorkerDeckClient;
|
|
1497
|
+
/** The session's working directory — the browser is rooted here. */
|
|
1498
|
+
cwd: string | undefined;
|
|
1499
|
+
open: boolean;
|
|
1500
|
+
onOpenChange: (open: boolean) => void;
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Browse the project the session is working in.
|
|
1504
|
+
*
|
|
1505
|
+
* Deliberately rooted at the session's cwd rather than at the server's
|
|
1506
|
+
* `hostFiles.roots`: the roots are the *security* boundary (the server enforces
|
|
1507
|
+
* them on every request), but what someone wants while watching an agent is this
|
|
1508
|
+
* project's tree. Read-only — writing is a separate server opt-in and not
|
|
1509
|
+
* something a session viewer should be doing behind the agent's back.
|
|
1510
|
+
*/
|
|
1511
|
+
declare function HostFilesDialog({
|
|
1512
|
+
client,
|
|
1513
|
+
cwd,
|
|
1514
|
+
open,
|
|
1515
|
+
onOpenChange
|
|
1516
|
+
}: HostFilesDialogProps): _$react.JSX.Element;
|
|
1517
|
+
//#endregion
|
|
874
1518
|
//#region src/components/agent/SessionList.d.ts
|
|
875
1519
|
interface SessionListItemProps {
|
|
876
1520
|
session: SessionInfo;
|
|
@@ -901,6 +1545,59 @@ declare function SessionList({
|
|
|
901
1545
|
className
|
|
902
1546
|
}: SessionListProps): _$react.JSX.Element;
|
|
903
1547
|
//#endregion
|
|
1548
|
+
//#region src/components/agent/SessionEmptyState.d.ts
|
|
1549
|
+
interface SessionEmptyStateProps {
|
|
1550
|
+
cwd?: string;
|
|
1551
|
+
/** Whether `/command` completion is live yet — the CLI reports its commands a
|
|
1552
|
+
* beat after the session starts, and promising a feature that isn't wired up
|
|
1553
|
+
* yet is worse than not mentioning it. */
|
|
1554
|
+
hasCommands?: boolean;
|
|
1555
|
+
/** Whether the engine has reported skills the `/` popover can offer. Its own
|
|
1556
|
+
* flag, not a variant of `hasCommands`: what `/` does differs — a command is
|
|
1557
|
+
* submitted, a skill is typed for you to edit — and an engine can have one
|
|
1558
|
+
* without the other. */
|
|
1559
|
+
hasSkills?: boolean;
|
|
1560
|
+
/** Whether this gateway serves `@file` search for the session's directory. */
|
|
1561
|
+
canBrowseFiles?: boolean;
|
|
1562
|
+
className?: string;
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* What a session shows before it has said anything: where the agent is sitting,
|
|
1566
|
+
* and what the composer accepts beyond prose.
|
|
1567
|
+
*
|
|
1568
|
+
* Every hint is conditional on the affordance actually existing — an engine
|
|
1569
|
+
* without slash commands, or a gateway without host files, is not told about
|
|
1570
|
+
* them. Deliberately no project name (the header already carries it) and no
|
|
1571
|
+
* brand mark (its geometry is inlined in several places already and they are
|
|
1572
|
+
* meant to stay identical).
|
|
1573
|
+
*/
|
|
1574
|
+
declare function SessionEmptyState({
|
|
1575
|
+
cwd,
|
|
1576
|
+
hasCommands,
|
|
1577
|
+
hasSkills,
|
|
1578
|
+
canBrowseFiles,
|
|
1579
|
+
className
|
|
1580
|
+
}: SessionEmptyStateProps): _$react.JSX.Element;
|
|
1581
|
+
//#endregion
|
|
1582
|
+
//#region src/components/agent/PromptTokenText.d.ts
|
|
1583
|
+
/**
|
|
1584
|
+
* A sent message, with its `@file` and `/command` tokens styled the way the CLI
|
|
1585
|
+
* writes them: monospace and tinted, no background — the bubble already has one,
|
|
1586
|
+
* and a second fill inside it reads as a button.
|
|
1587
|
+
*
|
|
1588
|
+
* Literal text, never markdown: what was typed is what was sent. The one pass
|
|
1589
|
+
* over it is this, so a message reads the same after sending as it did in the
|
|
1590
|
+
* composer. Two tokens, two meanings — a file is a reference, a command is an
|
|
1591
|
+
* action — so they are told apart by hue rather than by shape alone.
|
|
1592
|
+
*/
|
|
1593
|
+
declare function PromptTokenText({
|
|
1594
|
+
text,
|
|
1595
|
+
className
|
|
1596
|
+
}: {
|
|
1597
|
+
text: string;
|
|
1598
|
+
className?: string;
|
|
1599
|
+
}): _$react.JSX.Element;
|
|
1600
|
+
//#endregion
|
|
904
1601
|
//#region src/components/agent/status.d.ts
|
|
905
1602
|
declare const STATUS_META: Record<SessionStatus, {
|
|
906
1603
|
label: string;
|
|
@@ -911,6 +1608,36 @@ declare const STATUS_META: Record<SessionStatus, {
|
|
|
911
1608
|
//#region src/lib/utils.d.ts
|
|
912
1609
|
declare function cn(...inputs: ClassValue[]): string;
|
|
913
1610
|
//#endregion
|
|
1611
|
+
//#region src/lib/clipboard.d.ts
|
|
1612
|
+
/**
|
|
1613
|
+
* Copy text to the clipboard, on origins where the modern API does not exist.
|
|
1614
|
+
*
|
|
1615
|
+
* `navigator.clipboard` is gated on a **secure context**: HTTPS, or localhost.
|
|
1616
|
+
* A WorkerDeck dashboard reached the way it is meant to be reached — plain HTTP
|
|
1617
|
+
* on a LAN address, from a laptop or a phone — is neither, so `navigator.clipboard`
|
|
1618
|
+
* is `undefined` there and touching `.writeText` throws outright. That is the
|
|
1619
|
+
* normal deployment, not an edge case, which is why this falls back rather than
|
|
1620
|
+
* feature-detecting into a disabled button.
|
|
1621
|
+
*
|
|
1622
|
+
* The fallback is `document.execCommand('copy')` over an off-screen textarea.
|
|
1623
|
+
* It is deprecated and it is also the only thing that works here; every browser
|
|
1624
|
+
* still implements it. Returns whether the text actually landed, so a caller can
|
|
1625
|
+
* avoid claiming success it did not have.
|
|
1626
|
+
*/
|
|
1627
|
+
declare function copyText(value: string): Promise<boolean>;
|
|
1628
|
+
//#endregion
|
|
1629
|
+
//#region src/lib/tool-icon.d.ts
|
|
1630
|
+
/**
|
|
1631
|
+
* An icon per tool, so a transcript can be skimmed by shape rather than read.
|
|
1632
|
+
*
|
|
1633
|
+
* The same mapping the iOS app makes, in lucide's vocabulary rather than SF
|
|
1634
|
+
* Symbols — the two clients should be recognisably showing the same thing. An
|
|
1635
|
+
* unknown tool falls back to a wrench, and an MCP tool (`mcp__server__name`) to
|
|
1636
|
+
* the puzzle piece the MCP screens use, because "which server is this from" is
|
|
1637
|
+
* the useful thing to see at a glance.
|
|
1638
|
+
*/
|
|
1639
|
+
declare function toolIcon(toolName: string): LucideIcon;
|
|
1640
|
+
//#endregion
|
|
914
1641
|
//#region src/lib/format.d.ts
|
|
915
1642
|
declare function formatCost(usd: number | undefined): string;
|
|
916
1643
|
declare function formatDuration(ms: number): string;
|
|
@@ -920,8 +1647,27 @@ declare function formatBytes(bytes: number): string;
|
|
|
920
1647
|
/** Countdown to an epoch-ms deadline: "2h 18m", "12m", "<1m"; "now" once passed. */
|
|
921
1648
|
declare function formatCountdown(untilEpochMs: number, now?: number): string;
|
|
922
1649
|
declare function formatRelativeTime(epochMs: number | undefined, now?: number): string;
|
|
1650
|
+
/**
|
|
1651
|
+
* Human label for a rate-limit window key, compact: 'five_hour' → "5h",
|
|
1652
|
+
* 'seven_day_opus' → "7d opus". The per-model suffix is an open set — the CLI
|
|
1653
|
+
* adds buckets as plans gain them — so it is rewritten rather than enumerated.
|
|
1654
|
+
*/
|
|
1655
|
+
declare function formatRateLimitWindow(key: string): string;
|
|
1656
|
+
/** The same key spelled out, where there is room: 'five_hour' → "5-hour
|
|
1657
|
+
* session", 'seven_day_fable' → "Weekly · Fable". */
|
|
1658
|
+
declare function formatRateLimitWindowLong(key: string): string;
|
|
1659
|
+
/**
|
|
1660
|
+
* How long a rate-limit window is, in seconds — the denominator behind the pace
|
|
1661
|
+
* marker. Derived from the key rather than reported: the CLI sends a reset time
|
|
1662
|
+
* and a percentage, never a duration. `undefined` for a window whose key doesn't
|
|
1663
|
+
* say, and the marker is then simply not drawn rather than guessed.
|
|
1664
|
+
*/
|
|
1665
|
+
declare function rateLimitWindowSeconds(key: string): number | undefined;
|
|
1666
|
+
/** "8 secs ago" / "3 mins ago" — a freshness line finer-grained than
|
|
1667
|
+
* {@link formatRelativeTime}, because a poll that just landed should say so. */
|
|
1668
|
+
declare function formatAgoPrecise(epochMs: number, now?: number): string;
|
|
923
1669
|
/** Compact one-line preview of a tool input for card headers. */
|
|
924
1670
|
declare function toolInputPreview(input: unknown, max?: number): string;
|
|
925
1671
|
//#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 };
|
|
1672
|
+
export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type ChipSegment, CodeBlock, type CodeBlockProps, CodeEditor, type CodeEditorProps, 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, EditorTabs, type EditorTabsProps, FileCard, type FileCardProps, type FileDeliveredItem, FileTree, type FileTreeProps, FileViewer, type FileViewerProps, HostFilesDialog, type HostFilesDialogProps, Input, Loader, McpDialog, type McpDialogProps, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, 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, PromptTokenText, QUESTION_BEHAVIORS, type QuestionBehaviorMeta, QuestionPrompt, type QuestionPromptProps, Reasoning, type ReasoningProps, Response, type ResponseProps, STATUS_META, type Segment, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionEmptyState, type SessionEmptyStateProps, SessionInfoDialog, type SessionInfoDialogProps, SessionList, SessionListItem, type SessionListItemProps, type SessionListProps, SessionPanel, type SessionPanelProps, SessionWorkspace, type SessionWorkspaceProps, 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 TriggerConfig, type TriggerSuggestion, UsageDialog, type UsageDialogProps, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, getChipsByTrigger, hashtagTrigger, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState };
|
|
927
1673
|
//# sourceMappingURL=index.d.mts.map
|