@workerdeck/ui 0.11.0 → 0.12.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/build/{SessionPanel-CyhygZx_.d.mts → SessionPanel-Dy9lQrOV.d.mts} +44 -2
- package/build/{SessionPanel-_U8tjX29.mjs → SessionPanel-NQ8ksCfj.mjs} +280 -215
- package/build/SessionPanel-NQ8ksCfj.mjs.map +1 -0
- package/build/format.d.mts +65 -1
- package/build/format.mjs +118 -1
- package/build/format.mjs.map +1 -0
- package/build/index.d.mts +67 -7
- package/build/index.mjs +330 -5
- package/build/index.mjs.map +1 -1
- package/build/workspace.d.mts +28 -1
- package/build/workspace.mjs +14 -2
- package/build/workspace.mjs.map +1 -1
- package/package.json +4 -4
- package/src/components/agent/Loader.tsx +8 -46
- package/src/components/agent/SessionBrowser.tsx +428 -0
- package/src/components/agent/SessionPanel.tsx +28 -1
- package/src/components/agent/SessionWorkspace.tsx +35 -0
- package/src/components/agent/ToolCallCard.tsx +11 -2
- package/src/components/agent/Transcript.tsx +26 -8
- package/src/components/agent/pulse.tsx +60 -0
- package/src/components/agent/transcript-variant.tsx +62 -0
- package/src/format.ts +1 -0
- package/src/index.ts +4 -0
- package/src/lib/status.ts +124 -0
- package/build/SessionPanel-_U8tjX29.mjs.map +0 -1
|
@@ -5572,6 +5572,48 @@ function useTranscriptVariant() {
|
|
|
5572
5572
|
function useLines() {
|
|
5573
5573
|
return useTranscriptVariant() === "lines";
|
|
5574
5574
|
}
|
|
5575
|
+
const DensityContext = createContext("comfortable");
|
|
5576
|
+
function TranscriptDensityProvider({ value, children }) {
|
|
5577
|
+
return /* @__PURE__ */ jsx(DensityContext.Provider, {
|
|
5578
|
+
value,
|
|
5579
|
+
children
|
|
5580
|
+
});
|
|
5581
|
+
}
|
|
5582
|
+
function useTranscriptDensity() {
|
|
5583
|
+
return useContext(DensityContext);
|
|
5584
|
+
}
|
|
5585
|
+
/**
|
|
5586
|
+
* The gap between two rows, per variant and density — the whole of the density
|
|
5587
|
+
* feature, since it is the only vertical spacing between rows that exists.
|
|
5588
|
+
*
|
|
5589
|
+
* `className` goes on the **measured** wrapper (see `Transcript`), so the gap is
|
|
5590
|
+
* part of each row's measured height and no pixel constant is load-bearing.
|
|
5591
|
+
* `px` is fed to `estimateSize` alone, where being approximate is the contract:
|
|
5592
|
+
* it sets the scrollbar's length before rows mount and is replaced by a real
|
|
5593
|
+
* measurement the moment one does.
|
|
5594
|
+
*
|
|
5595
|
+
* `lines` + `compact` is the only combination with no gap at all: there the
|
|
5596
|
+
* row's own `py-0.5` is the entire separation, which is what makes it compact.
|
|
5597
|
+
*/
|
|
5598
|
+
const ROW_GAP = {
|
|
5599
|
+
cards: {
|
|
5600
|
+
comfortable: {
|
|
5601
|
+
className: "pt-4",
|
|
5602
|
+
px: 16
|
|
5603
|
+
},
|
|
5604
|
+
compact: {
|
|
5605
|
+
className: "pt-2",
|
|
5606
|
+
px: 8
|
|
5607
|
+
}
|
|
5608
|
+
},
|
|
5609
|
+
lines: {
|
|
5610
|
+
comfortable: {
|
|
5611
|
+
className: "pt-4",
|
|
5612
|
+
px: 16
|
|
5613
|
+
},
|
|
5614
|
+
compact: { px: 0 }
|
|
5615
|
+
}
|
|
5616
|
+
};
|
|
5575
5617
|
/**
|
|
5576
5618
|
* The left gutter of a line item: one glyph, fixed width, so every row's text
|
|
5577
5619
|
* starts on the same column no matter which kind of event it is. Decorative —
|
|
@@ -6818,27 +6860,68 @@ function FileCard({ item, href, className }) {
|
|
|
6818
6860
|
});
|
|
6819
6861
|
}
|
|
6820
6862
|
//#endregion
|
|
6821
|
-
//#region src/components/agent/
|
|
6863
|
+
//#region src/components/agent/pulse.tsx
|
|
6822
6864
|
/**
|
|
6823
|
-
* The
|
|
6865
|
+
* The brand mark's pulse, as characters — the working marker every surface in the
|
|
6866
|
+
* transcript animates.
|
|
6824
6867
|
*
|
|
6825
|
-
*
|
|
6826
|
-
*
|
|
6827
|
-
*
|
|
6828
|
-
*
|
|
6829
|
-
*
|
|
6868
|
+
* These are the mark's own four states (`docs/assets/BRAND.md`, "The loading
|
|
6869
|
+
* state"): a dot, an outline, a semi and a full diamond, built in the SVG from
|
|
6870
|
+
* two shapes rather than four drawings. 150ms each, so one cycle is the 0.6s
|
|
6871
|
+
* clock the marker pulses on in `icon-loading.svg` — the same rhythm, in the
|
|
6872
|
+
* medium a transcript row actually has.
|
|
6873
|
+
*
|
|
6874
|
+
* BRAND.md's caveat applies and is satisfied here: `U+25C6/7/8` are East-Asian
|
|
6875
|
+
* *ambiguous width*, so they can render double-width in a terminal under an
|
|
6876
|
+
* East-Asian locale and shift every line with them. They are safe wherever the
|
|
6877
|
+
* glyph is centred in a fixed-width box, which is what `LineGlyph` is. Anything
|
|
6878
|
+
* writing to a real terminal must use the ASCII set instead.
|
|
6830
6879
|
*/
|
|
6831
|
-
const
|
|
6832
|
-
"
|
|
6833
|
-
"
|
|
6834
|
-
"
|
|
6835
|
-
"
|
|
6836
|
-
"✽",
|
|
6837
|
-
"✻",
|
|
6838
|
-
"✶",
|
|
6839
|
-
"✳"
|
|
6880
|
+
const PULSE_FRAMES = [
|
|
6881
|
+
"⋄",
|
|
6882
|
+
"◇",
|
|
6883
|
+
"◈",
|
|
6884
|
+
"◆"
|
|
6840
6885
|
];
|
|
6841
|
-
|
|
6886
|
+
/**
|
|
6887
|
+
* The resting state. Stopping the animation lands on the complete mark rather
|
|
6888
|
+
* than on a half-drawn frame — the same property that makes the SVG's
|
|
6889
|
+
* `prefers-reduced-motion` free (see BRAND.md: `translateY(0)` *is* the mark).
|
|
6890
|
+
*/
|
|
6891
|
+
const PULSE_REST = PULSE_FRAMES[PULSE_FRAMES.length - 1];
|
|
6892
|
+
/** The OS-level "stop moving things" setting. A spinner is decoration — the word
|
|
6893
|
+
* beside it carries the meaning — so honouring this costs nothing. */
|
|
6894
|
+
function usePrefersReducedMotion() {
|
|
6895
|
+
const [reduced, setReduced] = useState(false);
|
|
6896
|
+
useEffect(() => {
|
|
6897
|
+
const query = window.matchMedia?.("(prefers-reduced-motion: reduce)");
|
|
6898
|
+
if (!query) return;
|
|
6899
|
+
setReduced(query.matches);
|
|
6900
|
+
const onChange = () => setReduced(query.matches);
|
|
6901
|
+
query.addEventListener("change", onChange);
|
|
6902
|
+
return () => query.removeEventListener("change", onChange);
|
|
6903
|
+
}, []);
|
|
6904
|
+
return reduced;
|
|
6905
|
+
}
|
|
6906
|
+
/**
|
|
6907
|
+
* The current pulse frame, ticking while `animated`. Callers mount this only
|
|
6908
|
+
* while something is actually in flight, so nothing here runs on an idle
|
|
6909
|
+
* session; with reduced motion, or when not animating, it holds at rest.
|
|
6910
|
+
*/
|
|
6911
|
+
function usePulse(animated) {
|
|
6912
|
+
const reduced = usePrefersReducedMotion();
|
|
6913
|
+
const running = animated && !reduced;
|
|
6914
|
+
const [frame, setFrame] = useState(0);
|
|
6915
|
+
useEffect(() => {
|
|
6916
|
+
if (!running) return;
|
|
6917
|
+
const timer = setInterval(() => setFrame((f) => f + 1), 150);
|
|
6918
|
+
return () => clearInterval(timer);
|
|
6919
|
+
}, [running]);
|
|
6920
|
+
if (!running) return PULSE_REST;
|
|
6921
|
+
return PULSE_FRAMES[frame % PULSE_FRAMES.length];
|
|
6922
|
+
}
|
|
6923
|
+
//#endregion
|
|
6924
|
+
//#region src/components/agent/Loader.tsx
|
|
6842
6925
|
/**
|
|
6843
6926
|
* What it says it is doing while it hasn't said anything yet. Cycled on a slow
|
|
6844
6927
|
* clock so a long turn doesn't sit under one frozen word — a still label reads
|
|
@@ -6859,42 +6942,17 @@ const VERBS = [
|
|
|
6859
6942
|
"Noodling"
|
|
6860
6943
|
];
|
|
6861
6944
|
const VERB_MS = 4e3;
|
|
6862
|
-
/** Ticks while mounted, at the spinner's rate. Mounted only while a turn is in
|
|
6863
|
-
* flight, so nothing here runs on an idle session. */
|
|
6864
|
-
function useFrames(animated) {
|
|
6865
|
-
const [frame, setFrame] = useState(0);
|
|
6866
|
-
useEffect(() => {
|
|
6867
|
-
if (!animated) return;
|
|
6868
|
-
const timer = setInterval(() => setFrame((f) => f + 1), FRAME_MS);
|
|
6869
|
-
return () => clearInterval(timer);
|
|
6870
|
-
}, [animated]);
|
|
6871
|
-
return frame;
|
|
6872
|
-
}
|
|
6873
|
-
/** The OS-level "stop moving things" setting. A spinner is decoration; the word
|
|
6874
|
-
* beside it carries the meaning, so honouring this costs nothing. */
|
|
6875
|
-
function usePrefersReducedMotion() {
|
|
6876
|
-
const [reduced, setReduced] = useState(false);
|
|
6877
|
-
useEffect(() => {
|
|
6878
|
-
const query = window.matchMedia?.("(prefers-reduced-motion: reduce)");
|
|
6879
|
-
if (!query) return;
|
|
6880
|
-
setReduced(query.matches);
|
|
6881
|
-
const onChange = () => setReduced(query.matches);
|
|
6882
|
-
query.addEventListener("change", onChange);
|
|
6883
|
-
return () => query.removeEventListener("change", onChange);
|
|
6884
|
-
}, []);
|
|
6885
|
-
return reduced;
|
|
6886
|
-
}
|
|
6887
6945
|
/**
|
|
6888
6946
|
* "The agent is working and hasn't produced output yet."
|
|
6889
6947
|
*
|
|
6890
|
-
* `lines`: a terminal working line —
|
|
6891
|
-
* the readings that answer "should I still be
|
|
6892
|
-
* `cards`: the three-dot pulse, unchanged
|
|
6948
|
+
* `lines`: a terminal working line — the mark's own pulse in the gutter (see
|
|
6949
|
+
* `pulse.tsx`), a verb, and the readings that answer "should I still be
|
|
6950
|
+
* waiting?" in one parenthesis. `cards`: the three-dot pulse, unchanged — the
|
|
6951
|
+
* dashboard's loader is not a gutter glyph and has no column to pulse in.
|
|
6893
6952
|
*/
|
|
6894
6953
|
function Loader({ label, startedAt, tokens, className }) {
|
|
6895
6954
|
const lines = useLines();
|
|
6896
|
-
const
|
|
6897
|
-
const frame = useFrames(lines && !reducedMotion);
|
|
6955
|
+
const pulse = usePulse(lines);
|
|
6898
6956
|
if (!lines) return /* @__PURE__ */ jsxs("div", {
|
|
6899
6957
|
"data-slot": "loader",
|
|
6900
6958
|
className: cn("flex items-center gap-2 py-1 text-body-sm text-fg-4", className),
|
|
@@ -6918,7 +6976,7 @@ function Loader({ label, startedAt, tokens, className }) {
|
|
|
6918
6976
|
className: cn("flex items-baseline gap-2", className),
|
|
6919
6977
|
children: [/* @__PURE__ */ jsx(LineGlyph, {
|
|
6920
6978
|
className: "text-accent",
|
|
6921
|
-
children:
|
|
6979
|
+
children: pulse
|
|
6922
6980
|
}), /* @__PURE__ */ jsxs("span", {
|
|
6923
6981
|
className: "min-w-0 flex-1 text-body-sm leading-5 text-fg-3",
|
|
6924
6982
|
children: [
|
|
@@ -7229,6 +7287,7 @@ function ToolCallCard({ item, hostImage, className }) {
|
|
|
7229
7287
|
const status = item.status ?? (item.result === void 0 ? "running" : "settled");
|
|
7230
7288
|
const badge = STATE_BADGE[status];
|
|
7231
7289
|
const isError = status === "failed" || item.result?.isError === true;
|
|
7290
|
+
const pulse = usePulse(lines && badge.busy);
|
|
7232
7291
|
const Icon = toolIcon(item.name);
|
|
7233
7292
|
const resultText = item.result?.text ?? "";
|
|
7234
7293
|
const truncated = !fullResult && resultText.length > RESULT_PREVIEW_CHARS;
|
|
@@ -7284,7 +7343,7 @@ function ToolCallCard({ item, hostImage, className }) {
|
|
|
7284
7343
|
children: [
|
|
7285
7344
|
/* @__PURE__ */ jsx(LineGlyph, {
|
|
7286
7345
|
className: status === "settled" && !isError && isMutatingTool(item.name) ? "text-success" : STATE_GLYPH[status],
|
|
7287
|
-
children: badge.busy ?
|
|
7346
|
+
children: badge.busy ? pulse : "●"
|
|
7288
7347
|
}),
|
|
7289
7348
|
/* @__PURE__ */ jsxs("span", {
|
|
7290
7349
|
className: "min-w-0 flex-1 truncate text-body-sm leading-5 text-fg-3",
|
|
@@ -7304,7 +7363,6 @@ function ToolCallCard({ item, hostImage, className }) {
|
|
|
7304
7363
|
className: "shrink-0 text-label text-fg-4",
|
|
7305
7364
|
children: item.backend
|
|
7306
7365
|
}) : null,
|
|
7307
|
-
badge.busy ? /* @__PURE__ */ jsx(Spinner, { className: "size-3 shrink-0 self-center text-fg-4" }) : null,
|
|
7308
7366
|
status === "deferred" ? /* @__PURE__ */ jsx(Clock, { className: "size-3 shrink-0 self-center text-fg-4" }) : null,
|
|
7309
7367
|
isError && !badge.busy ? /* @__PURE__ */ jsx("span", {
|
|
7310
7368
|
className: "shrink-0 text-label text-danger",
|
|
@@ -7707,7 +7765,7 @@ function nestedClass(item, lines) {
|
|
|
7707
7765
|
* transient UI state (an expanded tool card, an opened reasoning block) resets
|
|
7708
7766
|
* once the row scrolls far enough away to unmount.
|
|
7709
7767
|
*/
|
|
7710
|
-
function TranscriptRows({ rows, boundary, since, lines, fileUrl, attachmentUrl, hostImage, jumpToRecapRef }) {
|
|
7768
|
+
function TranscriptRows({ rows, boundary, since, lines, gap, fileUrl, attachmentUrl, hostImage, jumpToRecapRef }) {
|
|
7711
7769
|
const stick = useStickToBottomContext();
|
|
7712
7770
|
const [scrollElement, setScrollElement] = useState(null);
|
|
7713
7771
|
useEffect(() => {
|
|
@@ -7719,7 +7777,7 @@ function TranscriptRows({ rows, boundary, since, lines, fileUrl, attachmentUrl,
|
|
|
7719
7777
|
if (scrollElement && virtualizer.scrollElement !== scrollElement) virtualizer.scrollOffset = scrollElement.scrollTop;
|
|
7720
7778
|
return scrollElement;
|
|
7721
7779
|
},
|
|
7722
|
-
estimateSize: () => lines ? 32 : 100,
|
|
7780
|
+
estimateSize: () => (lines ? 32 : 100) + gap.px,
|
|
7723
7781
|
overscan: 8,
|
|
7724
7782
|
getItemKey: (index) => rows[index].key,
|
|
7725
7783
|
useFlushSync: true
|
|
@@ -7769,7 +7827,7 @@ function TranscriptRows({ rows, boundary, since, lines, fileUrl, attachmentUrl,
|
|
|
7769
7827
|
return /* @__PURE__ */ jsx("div", {
|
|
7770
7828
|
ref: virtualizer.measureElement,
|
|
7771
7829
|
"data-index": virtualRow.index,
|
|
7772
|
-
className: cn("absolute inset-x-0 top-0",
|
|
7830
|
+
className: cn("absolute inset-x-0 top-0", virtualRow.index > 0 && gap.className),
|
|
7773
7831
|
style: { transform: `translateY(${virtualRow.start}px)` },
|
|
7774
7832
|
children: "item" in row ? /* @__PURE__ */ jsx("div", {
|
|
7775
7833
|
className: cn(lines && "-mx-1 rounded-sm px-1 py-0.5 transition-colors hover:bg-surface-hover", boundary !== void 0 && row.index < boundary && "opacity-45", nestedClass(row.item, lines)),
|
|
@@ -7787,8 +7845,9 @@ function TranscriptRows({ rows, boundary, since, lines, fileUrl, attachmentUrl,
|
|
|
7787
7845
|
})
|
|
7788
7846
|
});
|
|
7789
7847
|
}
|
|
7790
|
-
function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage, variant = "cards", catchUp, jumpToRecapRef, className }) {
|
|
7848
|
+
function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage, variant = "cards", density = "comfortable", catchUp, jumpToRecapRef, className }) {
|
|
7791
7849
|
const lines = variant === "lines";
|
|
7850
|
+
const gap = ROW_GAP[variant][density];
|
|
7792
7851
|
const runStartedAt = useRunStart(state.status);
|
|
7793
7852
|
const following = useSettled(state.items.length, state.status);
|
|
7794
7853
|
const boundary = catchUp && catchUp.from > 0 && catchUp.from < state.items.length ? catchUp.from : void 0;
|
|
@@ -7829,6 +7888,7 @@ function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage,
|
|
|
7829
7888
|
boundary,
|
|
7830
7889
|
since: catchUp?.since,
|
|
7831
7890
|
lines,
|
|
7891
|
+
gap,
|
|
7832
7892
|
fileUrl,
|
|
7833
7893
|
attachmentUrl,
|
|
7834
7894
|
hostImage,
|
|
@@ -7992,7 +8052,7 @@ const INTERACTIVE = [
|
|
|
7992
8052
|
* the engine name — an absent capability hides the control instead of offering
|
|
7993
8053
|
* one that can only fail.
|
|
7994
8054
|
*/
|
|
7995
|
-
function SessionPanel({ client, sessionId, header, panelSurface = "internal", statusSurface = "internal", onOpenPanel, onVitals, transcriptVariant = "cards", controlsSurface = "internal", onControls, focusComposerOnClick = false, unseen, className }) {
|
|
8055
|
+
function SessionPanel({ client, sessionId, header, panelSurface = "internal", statusSurface = "internal", onOpenPanel, onVitals, transcriptVariant = "cards", transcriptDensity = "comfortable", controlsSurface = "internal", onControls, focusComposerOnClick = false, unseen, className }) {
|
|
7996
8056
|
const external = panelSurface === "external";
|
|
7997
8057
|
const statusExternal = statusSurface === "external";
|
|
7998
8058
|
const controlsExternal = controlsSurface === "external";
|
|
@@ -8068,7 +8128,8 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
8068
8128
|
const controls = useRef({
|
|
8069
8129
|
setModel: (model) => setters.current.setModel(model),
|
|
8070
8130
|
setPermissionMode: (mode) => setters.current.setPermissionMode(mode),
|
|
8071
|
-
interrupt: () => setters.current.interrupt()
|
|
8131
|
+
interrupt: () => setters.current.interrupt(),
|
|
8132
|
+
focusComposer: () => composerRef.current?.focus()
|
|
8072
8133
|
});
|
|
8073
8134
|
useEffect(() => {
|
|
8074
8135
|
const handler = onControlsRef.current;
|
|
@@ -8151,168 +8212,172 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
8151
8212
|
};
|
|
8152
8213
|
return /* @__PURE__ */ jsx(TranscriptVariantProvider, {
|
|
8153
8214
|
value: transcriptVariant,
|
|
8154
|
-
children: /* @__PURE__ */
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
protocolMismatch,
|
|
8173
|
-
", this build renders v",
|
|
8174
|
-
PROTOCOL_VERSION,
|
|
8175
|
-
". Some events may not render."
|
|
8176
|
-
]
|
|
8177
|
-
}) : null,
|
|
8178
|
-
protocolError ? /* @__PURE__ */ jsx(Notice, {
|
|
8179
|
-
level: "error",
|
|
8180
|
-
onDismiss: () => setProtocolError(void 0),
|
|
8181
|
-
children: protocolError
|
|
8182
|
-
}) : null,
|
|
8183
|
-
/* @__PURE__ */ jsx(Transcript, {
|
|
8184
|
-
state,
|
|
8185
|
-
fileUrl: sessionId ? (path) => client.sessionFileUrl(sessionId, path) : void 0,
|
|
8186
|
-
attachmentUrl: sessionId ? (id) => client.attachmentUrl(sessionId, id) : void 0,
|
|
8187
|
-
canBrowseFiles: hostFiles.available,
|
|
8188
|
-
hostImage,
|
|
8189
|
-
variant: transcriptVariant,
|
|
8190
|
-
catchUp: catchUp && newCount > 0 ? {
|
|
8191
|
-
from: catchUp.itemCount,
|
|
8192
|
-
since: catchUp.since
|
|
8193
|
-
} : void 0,
|
|
8194
|
-
jumpToRecapRef: jumpToRecap
|
|
8195
|
-
}),
|
|
8196
|
-
catchUp && newCount > 0 ? /* @__PURE__ */ jsx("div", {
|
|
8197
|
-
className: "px-3 pb-1",
|
|
8198
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
8199
|
-
"data-slot": "catch-up",
|
|
8200
|
-
className: "mx-auto flex w-full max-w-[var(--wd-content-max-w,48rem)] items-center gap-2 text-label text-fg-3",
|
|
8215
|
+
children: /* @__PURE__ */ jsx(TranscriptDensityProvider, {
|
|
8216
|
+
value: transcriptDensity,
|
|
8217
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
8218
|
+
"data-slot": "session-panel",
|
|
8219
|
+
onClick: handleClick,
|
|
8220
|
+
className: cn("flex h-full min-h-0 flex-col overflow-hidden bg-bg", className),
|
|
8221
|
+
children: [
|
|
8222
|
+
headerTakesActions ? header({ actions: menu }) : header,
|
|
8223
|
+
statusExternal ? null : /* @__PURE__ */ jsx(StatusBar, {
|
|
8224
|
+
state,
|
|
8225
|
+
connection,
|
|
8226
|
+
onOpenStatus: external && !onOpenPanel ? void 0 : () => openPanel("info"),
|
|
8227
|
+
onOpenContext: external && !onOpenPanel ? void 0 : () => openPanel("context"),
|
|
8228
|
+
onOpenUsage: external && !onOpenPanel ? void 0 : () => openPanel("usage"),
|
|
8229
|
+
actions: headerTakesActions ? void 0 : menu
|
|
8230
|
+
}),
|
|
8231
|
+
protocolMismatch !== void 0 ? /* @__PURE__ */ jsxs(Notice, {
|
|
8232
|
+
level: "warning",
|
|
8201
8233
|
children: [
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
/* @__PURE__ */ jsxs("span", {
|
|
8208
|
-
className: "min-w-0 flex-1 truncate",
|
|
8209
|
-
children: [
|
|
8210
|
-
newCount,
|
|
8211
|
-
" new ",
|
|
8212
|
-
newCount === 1 ? "row" : "rows",
|
|
8213
|
-
catchUp.since !== void 0 ? ` since you were last here` : ""
|
|
8214
|
-
]
|
|
8215
|
-
}),
|
|
8216
|
-
/* @__PURE__ */ jsx("button", {
|
|
8217
|
-
type: "button",
|
|
8218
|
-
onClick: () => jumpToRecap.current?.(),
|
|
8219
|
-
className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
|
|
8220
|
-
children: "jump"
|
|
8221
|
-
}),
|
|
8222
|
-
/* @__PURE__ */ jsx("button", {
|
|
8223
|
-
type: "button",
|
|
8224
|
-
onClick: () => setCaughtUp(true),
|
|
8225
|
-
className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
|
|
8226
|
-
children: "dismiss"
|
|
8227
|
-
})
|
|
8234
|
+
"Server speaks protocol v",
|
|
8235
|
+
protocolMismatch,
|
|
8236
|
+
", this build renders v",
|
|
8237
|
+
PROTOCOL_VERSION,
|
|
8238
|
+
". Some events may not render."
|
|
8228
8239
|
]
|
|
8229
|
-
})
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
request,
|
|
8237
|
-
onAnswer: approve,
|
|
8238
|
-
onDismiss: (id) => deny(id, "Question dismissed by user")
|
|
8239
|
-
}, request.id) : /* @__PURE__ */ jsx(PermissionPrompt, {
|
|
8240
|
-
request,
|
|
8241
|
-
onApprove: approve,
|
|
8242
|
-
onDeny: deny
|
|
8243
|
-
}, request.id))
|
|
8244
|
-
})
|
|
8245
|
-
}) : null,
|
|
8246
|
-
/* @__PURE__ */ jsx(Composer, {
|
|
8247
|
-
ref: composerRef,
|
|
8248
|
-
onSend: handleSend,
|
|
8249
|
-
onInterrupt: interrupt,
|
|
8250
|
-
busy,
|
|
8251
|
-
disabled: ended || !sessionId,
|
|
8252
|
-
commands: capabilities.slashCommands ? commands : void 0,
|
|
8253
|
-
skills: capabilities.skillsList ? state.skills : void 0,
|
|
8254
|
-
attachments,
|
|
8255
|
-
onSearchFiles: hostFiles.available ? (query, options) => hostFiles.search(query, {
|
|
8256
|
-
...options,
|
|
8257
|
-
limit: 8
|
|
8258
|
-
}) : void 0,
|
|
8259
|
-
layout: controlsExternal ? "inline" : "stacked",
|
|
8260
|
-
toolbar: controlsExternal ? void 0 : /* @__PURE__ */ jsxs(Fragment$1, { children: [models.length ? /* @__PURE__ */ jsx(ModelSelect, {
|
|
8261
|
-
models,
|
|
8262
|
-
model: effectiveModel,
|
|
8263
|
-
onModelChange: setModel,
|
|
8264
|
-
disabled: ended
|
|
8265
|
-
}) : null, state.permissionMode ? /* @__PURE__ */ jsx(PermissionModeSelect, {
|
|
8266
|
-
mode: state.permissionMode,
|
|
8267
|
-
onModeChange: setPermissionMode,
|
|
8268
|
-
modes: capabilities.permissionModes,
|
|
8269
|
-
canBypass: state.session?.canBypassPermissions,
|
|
8270
|
-
disabled: ended
|
|
8271
|
-
}) : null] })
|
|
8272
|
-
}),
|
|
8273
|
-
!external ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8274
|
-
/* @__PURE__ */ jsx(SessionInfoDialog, {
|
|
8240
|
+
}) : null,
|
|
8241
|
+
protocolError ? /* @__PURE__ */ jsx(Notice, {
|
|
8242
|
+
level: "error",
|
|
8243
|
+
onDismiss: () => setProtocolError(void 0),
|
|
8244
|
+
children: protocolError
|
|
8245
|
+
}) : null,
|
|
8246
|
+
/* @__PURE__ */ jsx(Transcript, {
|
|
8275
8247
|
state,
|
|
8276
|
-
client,
|
|
8277
|
-
sessionId,
|
|
8278
|
-
|
|
8279
|
-
|
|
8248
|
+
fileUrl: sessionId ? (path) => client.sessionFileUrl(sessionId, path) : void 0,
|
|
8249
|
+
attachmentUrl: sessionId ? (id) => client.attachmentUrl(sessionId, id) : void 0,
|
|
8250
|
+
canBrowseFiles: hostFiles.available,
|
|
8251
|
+
hostImage,
|
|
8252
|
+
variant: transcriptVariant,
|
|
8253
|
+
density: transcriptDensity,
|
|
8254
|
+
catchUp: catchUp && newCount > 0 ? {
|
|
8255
|
+
from: catchUp.itemCount,
|
|
8256
|
+
since: catchUp.since
|
|
8257
|
+
} : void 0,
|
|
8258
|
+
jumpToRecapRef: jumpToRecap
|
|
8280
8259
|
}),
|
|
8281
|
-
/* @__PURE__ */ jsx(
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8260
|
+
catchUp && newCount > 0 ? /* @__PURE__ */ jsx("div", {
|
|
8261
|
+
className: "px-3 pb-1",
|
|
8262
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
8263
|
+
"data-slot": "catch-up",
|
|
8264
|
+
className: "mx-auto flex w-full max-w-[var(--wd-content-max-w,48rem)] items-center gap-2 text-label text-fg-3",
|
|
8265
|
+
children: [
|
|
8266
|
+
/* @__PURE__ */ jsx("span", {
|
|
8267
|
+
"aria-hidden": true,
|
|
8268
|
+
className: "select-none text-accent",
|
|
8269
|
+
children: "※"
|
|
8270
|
+
}),
|
|
8271
|
+
/* @__PURE__ */ jsxs("span", {
|
|
8272
|
+
className: "min-w-0 flex-1 truncate",
|
|
8273
|
+
children: [
|
|
8274
|
+
newCount,
|
|
8275
|
+
" new ",
|
|
8276
|
+
newCount === 1 ? "row" : "rows",
|
|
8277
|
+
catchUp.since !== void 0 ? ` since you were last here` : ""
|
|
8278
|
+
]
|
|
8279
|
+
}),
|
|
8280
|
+
/* @__PURE__ */ jsx("button", {
|
|
8281
|
+
type: "button",
|
|
8282
|
+
onClick: () => jumpToRecap.current?.(),
|
|
8283
|
+
className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
|
|
8284
|
+
children: "jump"
|
|
8285
|
+
}),
|
|
8286
|
+
/* @__PURE__ */ jsx("button", {
|
|
8287
|
+
type: "button",
|
|
8288
|
+
onClick: () => setCaughtUp(true),
|
|
8289
|
+
className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
|
|
8290
|
+
children: "dismiss"
|
|
8291
|
+
})
|
|
8292
|
+
]
|
|
8293
|
+
})
|
|
8294
|
+
}) : null,
|
|
8295
|
+
capabilities.interactiveApprovals && state.pendingApprovals.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
8296
|
+
className: "px-3 pb-2",
|
|
8297
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
8298
|
+
className: "mx-auto flex w-full max-w-[var(--wd-content-max-w,48rem)] flex-col gap-2",
|
|
8299
|
+
children: state.pendingApprovals.map((request) => request.toolName === "AskUserQuestion" && parseUserQuestions(request.input).length > 0 ? /* @__PURE__ */ jsx(QuestionPrompt, {
|
|
8300
|
+
request,
|
|
8301
|
+
onAnswer: approve,
|
|
8302
|
+
onDismiss: (id) => deny(id, "Question dismissed by user")
|
|
8303
|
+
}, request.id) : /* @__PURE__ */ jsx(PermissionPrompt, {
|
|
8304
|
+
request,
|
|
8305
|
+
onApprove: approve,
|
|
8306
|
+
onDeny: deny
|
|
8307
|
+
}, request.id))
|
|
8308
|
+
})
|
|
8309
|
+
}) : null,
|
|
8310
|
+
/* @__PURE__ */ jsx(Composer, {
|
|
8311
|
+
ref: composerRef,
|
|
8312
|
+
onSend: handleSend,
|
|
8313
|
+
onInterrupt: interrupt,
|
|
8314
|
+
busy,
|
|
8315
|
+
disabled: ended || !sessionId,
|
|
8316
|
+
commands: capabilities.slashCommands ? commands : void 0,
|
|
8317
|
+
skills: capabilities.skillsList ? state.skills : void 0,
|
|
8318
|
+
attachments,
|
|
8319
|
+
onSearchFiles: hostFiles.available ? (query, options) => hostFiles.search(query, {
|
|
8320
|
+
...options,
|
|
8321
|
+
limit: 8
|
|
8322
|
+
}) : void 0,
|
|
8323
|
+
layout: controlsExternal ? "inline" : "stacked",
|
|
8324
|
+
toolbar: controlsExternal ? void 0 : /* @__PURE__ */ jsxs(Fragment$1, { children: [models.length ? /* @__PURE__ */ jsx(ModelSelect, {
|
|
8325
|
+
models,
|
|
8326
|
+
model: effectiveModel,
|
|
8327
|
+
onModelChange: setModel,
|
|
8328
|
+
disabled: ended
|
|
8329
|
+
}) : null, state.permissionMode ? /* @__PURE__ */ jsx(PermissionModeSelect, {
|
|
8330
|
+
mode: state.permissionMode,
|
|
8331
|
+
onModeChange: setPermissionMode,
|
|
8332
|
+
modes: capabilities.permissionModes,
|
|
8333
|
+
canBypass: state.session?.canBypassPermissions,
|
|
8334
|
+
disabled: ended
|
|
8335
|
+
}) : null] })
|
|
8307
8336
|
}),
|
|
8308
|
-
/* @__PURE__ */
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8337
|
+
!external ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8338
|
+
/* @__PURE__ */ jsx(SessionInfoDialog, {
|
|
8339
|
+
state,
|
|
8340
|
+
client,
|
|
8341
|
+
sessionId,
|
|
8342
|
+
open: panel === "info",
|
|
8343
|
+
onOpenChange: (next) => setPanel(next ? "info" : void 0)
|
|
8344
|
+
}),
|
|
8345
|
+
/* @__PURE__ */ jsx(ContextDialog, {
|
|
8346
|
+
usage: state.contextUsage,
|
|
8347
|
+
open: panel === "context",
|
|
8348
|
+
onOpenChange: (next) => setPanel(next ? "context" : void 0)
|
|
8349
|
+
}),
|
|
8350
|
+
/* @__PURE__ */ jsx(UsageDialog, {
|
|
8351
|
+
rateLimits: windows,
|
|
8352
|
+
subscriptionType: state.subscriptionType,
|
|
8353
|
+
engine: state.engine ?? "claude",
|
|
8354
|
+
totalCostUsd: state.totalCostUsd,
|
|
8355
|
+
updatedAt: state.rateLimitsUpdatedAt,
|
|
8356
|
+
open: panel === "usage",
|
|
8357
|
+
onOpenChange: (next) => setPanel(next ? "usage" : void 0)
|
|
8358
|
+
}),
|
|
8359
|
+
/* @__PURE__ */ jsx(McpDialog, {
|
|
8360
|
+
client,
|
|
8361
|
+
sessionId,
|
|
8362
|
+
canManageServers: capabilities.mcpServerActions,
|
|
8363
|
+
open: panel === "mcp",
|
|
8364
|
+
onOpenChange: (next) => setPanel(next ? "mcp" : void 0)
|
|
8365
|
+
}),
|
|
8366
|
+
/* @__PURE__ */ jsx(SkillsDialog, {
|
|
8367
|
+
skills: state.skills,
|
|
8368
|
+
open: panel === "skills",
|
|
8369
|
+
onOpenChange: (next) => setPanel(next ? "skills" : void 0),
|
|
8370
|
+
onUse: (skill) => composerRef.current?.insertText(skillPrompt(skill))
|
|
8371
|
+
}),
|
|
8372
|
+
/* @__PURE__ */ jsx(HostFilesDialog, {
|
|
8373
|
+
client,
|
|
8374
|
+
cwd: state.cwd,
|
|
8375
|
+
open: panel === "files",
|
|
8376
|
+
onOpenChange: (next) => setPanel(next ? "files" : void 0)
|
|
8377
|
+
})
|
|
8378
|
+
] }) : null
|
|
8379
|
+
]
|
|
8380
|
+
})
|
|
8316
8381
|
})
|
|
8317
8382
|
});
|
|
8318
8383
|
}
|
|
@@ -8404,6 +8469,6 @@ function Notice({ level, onDismiss, children }) {
|
|
|
8404
8469
|
});
|
|
8405
8470
|
}
|
|
8406
8471
|
//#endregion
|
|
8407
|
-
export {
|
|
8472
|
+
export { Tip as $, PermissionModeSelect as A, commandTrigger as B, TranscriptDensityProvider as C, Button as Ct, isMutatingTool as D, useTranscriptVariant as E, McpDialog as F, plainTextToSegments as G, mentionTrigger as H, HostFilesDialog as I, Splitter as J, segmentsToPlainText as K, ContextDialog as L, permissionModeMeta as M, ModelSelect as N, toolIcon as O, SkillsDialog as P, copyText as Q, Composer as R, Response as S, badgeVariants as St, useTranscriptDensity as T, cn as Tt, usePromptAreaState as U, hashtagTrigger as V, PromptArea as W, Spinner as X, CodeBlock as Y, CopyButton as Z, SessionInfoDialog as _, SelectItemText as _t, SessionEmptyState as a, DialogContent as at, parseUserQuestions as b, Input as bt, Message as c, DialogTrigger as ct, FileCard as d, MenuItem as dt, TooltipContent as et, Conversation as f, MenuSeparator as ft, STATUS_META as g, SelectItem as gt, StatusBar as h, SelectContent as ht, ToolCallCard as i, DialogClose as it, permissionModeChoices as j, PERMISSION_MODES as k, MessageContent as l, Menu$1 as lt, ConversationScrollButton as m, Select$1 as mt, UsageDialog as n, Dialog$1 as nt, Reasoning as o, DialogHeader as ot, ConversationContent as p, MenuTrigger as pt, ProgressRing as q, Transcript as r, DialogBody as rt, PromptTokenText as s, DialogRow as st, SessionPanel as t, TooltipProvider as tt, Loader as u, MenuContent as ut, QUESTION_BEHAVIORS as v, SelectTrigger as vt, TranscriptVariantProvider as w, buttonVariants as wt, PermissionPrompt as x, Badge as xt, QuestionPrompt as y, SelectValue as yt, skillPrompt as z };
|
|
8408
8473
|
|
|
8409
|
-
//# sourceMappingURL=SessionPanel-
|
|
8474
|
+
//# sourceMappingURL=SessionPanel-NQ8ksCfj.mjs.map
|