@workerdeck/ui 1.2.0 → 1.4.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 (43) hide show
  1. package/README.md +4 -0
  2. package/build/{SessionPanel-yNO60Tzw.d.mts → SessionPanel-BSwUJDwg.d.mts} +3 -8
  3. package/build/{SessionPanel-DVhnUwXw.mjs → SessionPanel-DQp2oStr.mjs} +384 -277
  4. package/build/SessionPanel-DQp2oStr.mjs.map +1 -0
  5. package/build/{format-C4h4jZL_.d.mts → format-TVRJzYUj.d.mts} +1 -9
  6. package/build/format.d.mts +1 -6
  7. package/build/format.mjs +1 -1
  8. package/build/index.d.mts +35 -10
  9. package/build/index.mjs +38 -12
  10. package/build/index.mjs.map +1 -1
  11. package/build/scoped.css +7 -0
  12. package/build/{status-BW2xj79g.mjs → status-C4TAgVSc.mjs} +1 -14
  13. package/build/status-C4TAgVSc.mjs.map +1 -0
  14. package/build/workspace.d.mts +3 -2
  15. package/build/workspace.mjs +4 -3
  16. package/build/workspace.mjs.map +1 -1
  17. package/package.json +4 -4
  18. package/src/components/agent/Composer.tsx +2 -4
  19. package/src/components/agent/ContextDialog.tsx +17 -2
  20. package/src/components/agent/ContextRing.tsx +36 -7
  21. package/src/components/agent/EntryIcon.tsx +2 -4
  22. package/src/components/agent/McpDialog.tsx +2 -0
  23. package/src/components/agent/SessionItem.tsx +1 -1
  24. package/src/components/agent/SessionPanel.tsx +198 -186
  25. package/src/components/agent/SessionWorkspace.tsx +3 -0
  26. package/src/components/agent/StatusBar.tsx +12 -4
  27. package/src/components/agent/ToolCallCard.tsx +6 -1
  28. package/src/components/agent/TranscriptItemView.tsx +1 -6
  29. package/src/components/agent/TranscriptRows.tsx +4 -6
  30. package/src/components/agent/held-sends.tsx +73 -0
  31. package/src/components/agent/tool-titles.tsx +12 -0
  32. package/src/components/agent/use-subagent-frame.ts +8 -10
  33. package/src/components/agent/use-transcript-jumps.ts +7 -9
  34. package/src/components/terminal/TerminalTranscript.tsx +12 -1
  35. package/src/components/terminal/height.ts +0 -2
  36. package/src/components/terminal/items.tsx +5 -7
  37. package/src/index.ts +2 -0
  38. package/src/lib/context-note.ts +24 -0
  39. package/src/lib/css.ts +3 -5
  40. package/src/lib/format.ts +1 -8
  41. package/src/lib/status.ts +3 -5
  42. package/build/SessionPanel-DVhnUwXw.mjs.map +0 -1
  43. package/build/status-BW2xj79g.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { C as toolInputPreview, S as rateLimitWindowSeconds, a as meterTintClass, b as formatTokens, d as COMPACTION_TEXT, f as formatAgoPrecise, g as formatDuration, h as formatCountdown, m as formatCost, p as formatBytes, r as meterColorClass, v as formatRateLimitWindowLong, y as formatRelativeTime } from "./status-BW2xj79g.mjs";
1
+ import { C as toolInputPreview, S as rateLimitWindowSeconds, a as meterTintClass, b as formatTokens, d as COMPACTION_TEXT, f as formatAgoPrecise, g as formatDuration, h as formatCountdown, m as formatCost, p as formatBytes, r as meterColorClass, v as formatRateLimitWindowLong, y as formatRelativeTime } from "./status-C4TAgVSc.mjs";
2
2
  import { Fragment, createContext, forwardRef, memo, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { clsx } from "clsx";
@@ -9,7 +9,7 @@ import { ArrowDown, ArrowDownCircle, ArrowLeft, ArrowUp, AtSign, Brain, ChartPie
9
9
  import { Menu } from "@base-ui/react/menu";
10
10
  import { Dialog } from "@base-ui/react/dialog";
11
11
  import { Tooltip } from "@base-ui/react/tooltip";
12
- import { PROTOCOL_VERSION, mergeUsage, orderUsageWindows, subagentLabel, usageInfos } from "@workerdeck/protocol";
12
+ import { PROTOCOL_VERSION, mergeUsage, orderUsageWindows, subagentLabel, toolTitle, usageInfos } from "@workerdeck/protocol";
13
13
  import { recapLine, scanPromptTokens, summarizeSince, useAttachments, useClaudeSession, useDraft, useHostFileSearch, useProfileUsage, useToolCallHost } from "@workerdeck/react";
14
14
  import { Streamdown } from "streamdown";
15
15
  import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
@@ -4974,6 +4974,18 @@ function useToolResultFetcher() {
4974
4974
  return useContext(FetchContext);
4975
4975
  }
4976
4976
  //#endregion
4977
+ //#region src/components/agent/tool-titles.tsx
4978
+ const TitlesContext = createContext(void 0);
4979
+ function ToolTitleProvider({ value, children }) {
4980
+ return /* @__PURE__ */ jsx(TitlesContext.Provider, {
4981
+ value,
4982
+ children
4983
+ });
4984
+ }
4985
+ function useToolTitle(name) {
4986
+ return toolTitle(name, useContext(TitlesContext));
4987
+ }
4988
+ //#endregion
4977
4989
  //#region src/components/agent/tool-result-image.tsx
4978
4990
  const noop = async () => void 0;
4979
4991
  const ImageContext = createContext(noop);
@@ -5270,6 +5282,7 @@ function ToolRow({ item }) {
5270
5282
  const command = item.input?.command;
5271
5283
  const copyable = typeof command === "string" ? command : text;
5272
5284
  const todos = todoPreview(item.name, item.input);
5285
+ const title = useToolTitle(item.name);
5273
5286
  return /* @__PURE__ */ jsx("div", {
5274
5287
  ref: reveal,
5275
5288
  className: open ? "term-open" : void 0,
@@ -5286,11 +5299,12 @@ function ToolRow({ item }) {
5286
5299
  glyph: busy ? pulse : "●",
5287
5300
  glyphTone: tone,
5288
5301
  tone: "fg",
5302
+ title: title ? item.name : void 0,
5289
5303
  children: [
5290
5304
  /* @__PURE__ */ jsx(Ink, {
5291
5305
  bold: true,
5292
5306
  tone: "bright",
5293
- children: item.name
5307
+ children: title ?? item.name
5294
5308
  }),
5295
5309
  /* @__PURE__ */ jsxs(Ink, {
5296
5310
  tone: "dim",
@@ -5300,6 +5314,10 @@ function ToolRow({ item }) {
5300
5314
  ")"
5301
5315
  ]
5302
5316
  }),
5317
+ title && open ? /* @__PURE__ */ jsxs(Ink, {
5318
+ tone: "faint",
5319
+ children: [" · ", item.name]
5320
+ }) : null,
5303
5321
  item.backend && item.backend !== "server" ? /* @__PURE__ */ jsxs(Ink, {
5304
5322
  tone: "faint",
5305
5323
  children: [" · ", item.backend]
@@ -5441,11 +5459,6 @@ function TurnResultRow$1({ item }) {
5441
5459
  children: message
5442
5460
  }, index))] });
5443
5461
  }
5444
- /**
5445
- * One row, deliberately. A rule with a centred label reads better and costs the height book a
5446
- * second measurement for a row that carries no content — and the point here is only that the
5447
- * boundary is *visible*, so the ring dropping 90% → 15% stops reading as a bug.
5448
- */
5449
5462
  function CompactionRow$1() {
5450
5463
  return /* @__PURE__ */ jsx(Row, {
5451
5464
  glyph: "≡",
@@ -5946,17 +5959,24 @@ function extensionOf(name) {
5946
5959
  }
5947
5960
  //#endregion
5948
5961
  //#region src/lib/css.ts
5949
- /**
5950
- * Pass a colour through only if this engine can actually parse it. Category colours arrive
5951
- * from the CLI as untrusted strings, and an unparseable one must fall back to the token
5952
- * colour rather than reaching the DOM.
5953
- */
5954
5962
  function cssColor(color) {
5955
5963
  return typeof CSS !== "undefined" && CSS.supports("color", color) ? color : void 0;
5956
5964
  }
5957
5965
  //#endregion
5966
+ //#region src/lib/context-note.ts
5967
+ const CODEX_CONTEXT_NOTE = {
5968
+ summary: "Codex budgets 272K input by default and reports 95% of it, so a 1M-class model reads ~258k. That is codex’s price tier, not the model’s ceiling — and it is the number auto-compaction fires on, so the meter is honest.",
5969
+ hint: "Raising it is yours to set: model_context_window in ~/.codex/config.toml — and watch for auto-compaction failing afterwards.",
5970
+ detail: ["To raise it, set model_context_window in ~/.codex/config.toml, up to 872000 (reported as 828400). Codex clamps to its own max_context_window, itself below OpenAI’s stated 922,000 max input.", "Above 272K input, a request bills at 2x input / 1.5x output for the whole request. WorkerDeck never writes this setting — it is a cost decision on your account."],
5971
+ caveat: "Raise it and watch for auto-compaction failing: openai/codex #16068 reports it stops firing after the first overflow. Unverified here on 0.149.0."
5972
+ };
5973
+ function contextNote(engine) {
5974
+ return (engine ?? "claude") === "codex" ? CODEX_CONTEXT_NOTE : void 0;
5975
+ }
5976
+ //#endregion
5958
5977
  //#region src/components/agent/ContextDialog.tsx
5959
- function ContextDialog({ usage, open, onOpenChange, className }) {
5978
+ function ContextDialog({ usage, engine, open, onOpenChange, className }) {
5979
+ const note = contextNote(engine);
5960
5980
  return /* @__PURE__ */ jsx(Dialog$1, {
5961
5981
  open,
5962
5982
  onOpenChange,
@@ -5965,7 +5985,7 @@ function ContextDialog({ usage, open, onOpenChange, className }) {
5965
5985
  children: [/* @__PURE__ */ jsx(DialogHeader, {
5966
5986
  title: "Context",
5967
5987
  description: usage?.model
5968
- }), /* @__PURE__ */ jsx(DialogBody, { children: !usage ? /* @__PURE__ */ jsx("p", {
5988
+ }), /* @__PURE__ */ jsxs(DialogBody, { children: [!usage ? /* @__PURE__ */ jsx("p", {
5969
5989
  className: "py-6 text-center text-body-sm text-fg-4",
5970
5990
  children: "No reading yet — the context window is measured after a turn completes."
5971
5991
  }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
@@ -6031,16 +6051,32 @@ function ContextDialog({ usage, open, onOpenChange, className }) {
6031
6051
  })
6032
6052
  })]
6033
6053
  }) : null
6034
- ] }) })]
6054
+ ] }), note ? /* @__PURE__ */ jsxs("div", {
6055
+ className: "mt-5 border-t border-border pt-4",
6056
+ children: [
6057
+ /* @__PURE__ */ jsx("h3", {
6058
+ className: "text-label font-medium text-fg-3",
6059
+ children: "Why this window is 272K"
6060
+ }),
6061
+ /* @__PURE__ */ jsx("p", {
6062
+ className: "mt-2 text-body-sm text-fg-2",
6063
+ children: note.summary
6064
+ }),
6065
+ note.detail.map((line) => /* @__PURE__ */ jsx("p", {
6066
+ className: "mt-2 text-body-sm text-fg-3",
6067
+ children: line
6068
+ }, line)),
6069
+ /* @__PURE__ */ jsx("p", {
6070
+ className: "mt-2 text-body-sm text-warning",
6071
+ children: note.caveat
6072
+ })
6073
+ ]
6074
+ }) : null] })]
6035
6075
  })
6036
6076
  });
6037
6077
  }
6038
6078
  //#endregion
6039
6079
  //#region src/components/agent/EntryIcon.tsx
6040
- /**
6041
- * The icon for one host directory entry. A symlink is drawn as a link and never silently
6042
- * resolved — the caller decides what a symlink means, the tree only says it is one.
6043
- */
6044
6080
  function EntryIcon({ type }) {
6045
6081
  if (type === "dir") return /* @__PURE__ */ jsx(Folder, { className: "size-3.5 shrink-0 text-accent" });
6046
6082
  if (type === "symlink") return /* @__PURE__ */ jsx(Link2, { className: "size-3.5 shrink-0 text-fg-4" });
@@ -6402,10 +6438,17 @@ function ServerView({ server, busy, canManage, onAct, onSelectTool }) {
6402
6438
  type: "button",
6403
6439
  onClick: () => onSelectTool(t.name),
6404
6440
  className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-surface-hover",
6405
- children: [/* @__PURE__ */ jsx("span", {
6406
- className: "min-w-0 flex-1 truncate font-mono text-label text-fg-1",
6407
- children: t.name
6408
- }), /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0 text-fg-4" })]
6441
+ children: [
6442
+ /* @__PURE__ */ jsx("span", {
6443
+ className: "min-w-0 flex-1 truncate font-mono text-label text-fg-1",
6444
+ children: t.name
6445
+ }),
6446
+ t.title ? /* @__PURE__ */ jsx("span", {
6447
+ className: "min-w-0 shrink truncate text-label text-fg-4",
6448
+ children: t.title
6449
+ }) : null,
6450
+ /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0 text-fg-4" })
6451
+ ]
6409
6452
  }) }, t.name))
6410
6453
  })] })
6411
6454
  ]
@@ -6416,6 +6459,10 @@ function ToolView({ tool }) {
6416
6459
  return /* @__PURE__ */ jsxs("div", {
6417
6460
  className: "flex flex-col gap-3",
6418
6461
  children: [
6462
+ tool.title ? /* @__PURE__ */ jsx("p", {
6463
+ className: "text-body-sm font-medium text-fg-1",
6464
+ children: tool.title
6465
+ }) : null,
6419
6466
  tool.description ? /* @__PURE__ */ jsx("p", {
6420
6467
  className: "text-body-sm whitespace-pre-wrap text-fg-2",
6421
6468
  children: tool.description
@@ -7048,14 +7095,6 @@ function blockNeedsBlank(previous, next) {
7048
7095
  }
7049
7096
  //#endregion
7050
7097
  //#region src/components/agent/use-subagent-frame.ts
7051
- /**
7052
- * The sub-agent frame machine: which agent frame is on screen, how it is entered (a host
7053
- * `openSubagent` request or a Task row in the transcript), how it is left (Escape, the strip's
7054
- * Back, or the host withdrawing), and what the transcript reveals on the way out. The frame
7055
- * round-trips through the host's URL — the anti-loop rules live in GOTCHAS ("The sub-agent
7056
- * frame round-trips through the URL"); here they mean: entry keys on the nonce alone, and the
7057
- * report is deduped through a ref, so an echo of our own report is inert on arrival.
7058
- */
7059
7098
  function useSubagentFrame(options) {
7060
7099
  const { sessionId, items, session, reveal, openSubagent, onSubagentChange } = options;
7061
7100
  const [subagentId, setSubagentId] = useState(void 0);
@@ -7960,40 +7999,48 @@ function useNow(intervalMs = 3e4) {
7960
7999
  }, [intervalMs]);
7961
8000
  return now;
7962
8001
  }
7963
- function ContextMeter({ usage }) {
8002
+ function ContextMeter({ usage, engine }) {
8003
+ const note = contextNote(engine);
7964
8004
  return /* @__PURE__ */ jsx(Tip, {
7965
8005
  content: /* @__PURE__ */ jsxs("div", {
7966
- className: "flex min-w-44 flex-col gap-1 py-0.5",
7967
- children: [usage.categories.map((c) => /* @__PURE__ */ jsxs("div", {
7968
- className: "flex items-center gap-2",
7969
- children: [
7970
- /* @__PURE__ */ jsx("span", {
7971
- className: "size-2 shrink-0 rounded-full bg-fg-4",
7972
- style: cssColor(c.color) ? { backgroundColor: c.color } : void 0
7973
- }),
7974
- /* @__PURE__ */ jsx("span", {
7975
- className: "flex-1",
7976
- children: c.name
7977
- }),
7978
- /* @__PURE__ */ jsx("span", {
7979
- className: "font-mono text-fg-3",
7980
- children: formatTokens(c.tokens)
7981
- })
7982
- ]
7983
- }, c.name)), /* @__PURE__ */ jsxs("div", {
7984
- className: "mt-0.5 flex items-center justify-between gap-2 border-t border-border pt-1",
7985
- children: [/* @__PURE__ */ jsx("span", { children: "Total" }), /* @__PURE__ */ jsxs("span", {
7986
- className: "font-mono text-fg-3",
8006
+ className: "flex max-w-64 min-w-44 flex-col gap-1 py-0.5",
8007
+ children: [
8008
+ usage.categories.map((c) => /* @__PURE__ */ jsxs("div", {
8009
+ className: "flex items-center gap-2",
7987
8010
  children: [
7988
- formatTokens(usage.totalTokens),
7989
- " / ",
7990
- formatTokens(usage.maxTokens),
7991
- " (",
7992
- usage.percentage.toFixed(0),
7993
- "%)"
8011
+ /* @__PURE__ */ jsx("span", {
8012
+ className: "size-2 shrink-0 rounded-full bg-fg-4",
8013
+ style: cssColor(c.color) ? { backgroundColor: c.color } : void 0
8014
+ }),
8015
+ /* @__PURE__ */ jsx("span", {
8016
+ className: "flex-1",
8017
+ children: c.name
8018
+ }),
8019
+ /* @__PURE__ */ jsx("span", {
8020
+ className: "font-mono text-fg-3",
8021
+ children: formatTokens(c.tokens)
8022
+ })
7994
8023
  ]
7995
- })]
7996
- })]
8024
+ }, c.name)),
8025
+ /* @__PURE__ */ jsxs("div", {
8026
+ className: "mt-0.5 flex items-center justify-between gap-2 border-t border-border pt-1",
8027
+ children: [/* @__PURE__ */ jsx("span", { children: "Total" }), /* @__PURE__ */ jsxs("span", {
8028
+ className: "font-mono text-fg-3",
8029
+ children: [
8030
+ formatTokens(usage.totalTokens),
8031
+ " / ",
8032
+ formatTokens(usage.maxTokens),
8033
+ " (",
8034
+ usage.percentage.toFixed(0),
8035
+ "%)"
8036
+ ]
8037
+ })]
8038
+ }),
8039
+ note ? /* @__PURE__ */ jsxs("div", {
8040
+ className: "mt-0.5 flex flex-col gap-1 border-t border-border pt-1 text-fg-3",
8041
+ children: [/* @__PURE__ */ jsx("span", { children: note.summary }), /* @__PURE__ */ jsx("span", { children: note.hint })]
8042
+ }) : null
8043
+ ]
7997
8044
  }),
7998
8045
  children: /* @__PURE__ */ jsxs("span", {
7999
8046
  className: cn("inline-flex cursor-default items-center gap-1 font-mono text-label", meterColorClass(usage.percentage)),
@@ -8089,7 +8136,10 @@ function StatusBar({ state, rateLimits, connected, connection, onOpenStatus, onO
8089
8136
  state.capabilities.contextUsage && state.contextUsage ? /* @__PURE__ */ jsx(Slot, {
8090
8137
  onClick: onOpenContext,
8091
8138
  hint: "Context breakdown",
8092
- children: /* @__PURE__ */ jsx(ContextMeter, { usage: state.contextUsage })
8139
+ children: /* @__PURE__ */ jsx(ContextMeter, {
8140
+ usage: state.contextUsage,
8141
+ engine: state.engine
8142
+ })
8093
8143
  }) : null,
8094
8144
  session || weekly ? /* @__PURE__ */ jsx(Slot, {
8095
8145
  onClick: onOpenUsage,
@@ -9641,14 +9691,6 @@ function useHeightEpoch(options) {
9641
9691
  //#region src/components/agent/use-transcript-jumps.ts
9642
9692
  const AIM_PASSES = 4;
9643
9693
  const AIM_SETTLE_MS = 50;
9644
- /**
9645
- * The send re-pin: a held, escape-proof pin, not one `scrollToBottom('instant')` — a trackpad's
9646
- * trailing momentum tick reads as escape intent and aborts the one-shot before its first frame
9647
- * (GOTCHAS "The send re-pin is a held pin"). Every line is load-bearing: clear the stale escape
9648
- * flag, hold through the momentum tail, seed the `ignoreEscapes` record the library only
9649
- * installs one rAF too late, and press the first scroll synchronously. Deliberate detach
9650
- * (`stopScroll`, drag-selection) still wins immediately.
9651
- */
9652
9694
  function repinToBottom(stick) {
9653
9695
  const { state } = stick;
9654
9696
  state.escapedFromLock = false;
@@ -10059,6 +10101,7 @@ function ToolCallCard({ item, hostImage, className }) {
10059
10101
  const badge = STATE_BADGE[status];
10060
10102
  const isError = status === "failed" || item.result?.isError === true;
10061
10103
  const Icon = toolIcon(item.name);
10104
+ const title = useToolTitle(item.name);
10062
10105
  const resultText = item.result?.text ?? "";
10063
10106
  const clipped = !fullResult && resultText.length > RESULT_PREVIEW_CHARS;
10064
10107
  const shownResult = clipped ? resultText.slice(0, RESULT_PREVIEW_CHARS) : resultText;
@@ -10067,6 +10110,10 @@ function ToolCallCard({ item, hostImage, className }) {
10067
10110
  const details = open ? /* @__PURE__ */ jsxs("div", {
10068
10111
  className: "flex flex-col gap-2 border-t border-border p-2.5",
10069
10112
  children: [
10113
+ title ? /* @__PURE__ */ jsx("p", {
10114
+ className: "font-mono text-label text-fg-4",
10115
+ children: item.name
10116
+ }) : null,
10070
10117
  /* @__PURE__ */ jsx(PlainPayload, {
10071
10118
  code: JSON.stringify(item.input, null, 2),
10072
10119
  language: "json",
@@ -10128,8 +10175,9 @@ function ToolCallCard({ item, hostImage, className }) {
10128
10175
  children: [
10129
10176
  /* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0 text-fg-3" }),
10130
10177
  /* @__PURE__ */ jsx("span", {
10131
- className: "shrink-0 font-mono text-body-sm font-medium text-fg-1",
10132
- children: item.name
10178
+ className: cn("shrink-0 text-body-sm font-medium text-fg-1", title === void 0 && "font-mono"),
10179
+ title: item.name,
10180
+ children: title ?? item.name
10133
10181
  }),
10134
10182
  item.backend && item.backend !== "server" ? /* @__PURE__ */ jsx(Badge, {
10135
10183
  variant: "neutral",
@@ -10244,7 +10292,6 @@ function NoticeRow({ item }) {
10244
10292
  children: item.text
10245
10293
  });
10246
10294
  }
10247
- /** The item-view switch: one transcript item, drawn for the active variant. */
10248
10295
  function TranscriptItemView({ item, fileUrl, attachmentUrl, hostImage, terminal }) {
10249
10296
  if (terminal) return /* @__PURE__ */ jsx(TerminalItemView, {
10250
10297
  item,
@@ -10283,11 +10330,6 @@ function TranscriptItemView({ item, fileUrl, attachmentUrl, hostImage, terminal
10283
10330
  default: return null;
10284
10331
  }
10285
10332
  }
10286
- /**
10287
- * The cards spelling of a compaction boundary — a rule with the label through it, the same shape
10288
- * `RecapRow` uses below, because both are boundaries rather than messages. The terminal spelling is
10289
- * `terminal/items.tsx`'s `CompactionRow`, one grid row, and the two share `COMPACTION_TEXT`.
10290
- */
10291
10333
  function CompactionRow() {
10292
10334
  return /* @__PURE__ */ jsxs("div", {
10293
10335
  "data-slot": "compaction",
@@ -10411,12 +10453,6 @@ function StickyPromptLane({ top, height, gapClass, gapPx, terminal, scrollRoot,
10411
10453
  ]
10412
10454
  });
10413
10455
  }
10414
- /**
10415
- * The virtualized row lane and its scroll-ownership regime. Two things want to write
10416
- * `scrollTop` — the follow spring and the virtualizer's size-change corrections — and they are
10417
- * split by regime here: pinned, corrections are suppressed outright; escaped, the virtualizer
10418
- * corrects so the scrollback holds still (GOTCHAS "The transcript is virtualized").
10419
- */
10420
10456
  function TranscriptRows({ rows, boundary, since, terminal, replaying, stickyPrompt, frameParentId, onOpenSubagent, gap, fontSize, lineHeight, items, pendingApprovals, scrubber, bookmarks, affordances, fileUrl, attachmentUrl, hostImage, jumpToRecapRef, repinRef, reveal }) {
10421
10457
  const stick = useStickToBottomContext();
10422
10458
  const [scrollElement, setScrollElement] = useState(null);
@@ -10787,6 +10823,65 @@ function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage,
10787
10823
  });
10788
10824
  }
10789
10825
  //#endregion
10826
+ //#region src/components/agent/held-sends.tsx
10827
+ function useHeldSends(options) {
10828
+ const [held, setHeld] = useState([]);
10829
+ const queue = useRef([]);
10830
+ const sendRef = useRef(options.send);
10831
+ sendRef.current = options.send;
10832
+ const flush = useCallback(() => {
10833
+ const queued = queue.current;
10834
+ if (queued.length === 0) return;
10835
+ queue.current = [];
10836
+ setHeld([]);
10837
+ for (const item of queued) sendRef.current(item.text, item.attachmentIds);
10838
+ }, []);
10839
+ useEffect(() => {
10840
+ if (!options.busy) flush();
10841
+ }, [options.busy, flush]);
10842
+ return {
10843
+ held,
10844
+ submit: useCallback((text, attachmentIds) => {
10845
+ if (!options.hold || !options.busy) {
10846
+ sendRef.current(text, attachmentIds);
10847
+ return;
10848
+ }
10849
+ queue.current = [...queue.current, {
10850
+ text,
10851
+ attachmentIds
10852
+ }];
10853
+ setHeld(queue.current);
10854
+ }, [options.hold, options.busy]),
10855
+ flush
10856
+ };
10857
+ }
10858
+ function HeldSendsBar({ held, onSendNow }) {
10859
+ if (held.length === 0) return null;
10860
+ return /* @__PURE__ */ jsx("div", {
10861
+ className: "px-3 pt-2",
10862
+ children: /* @__PURE__ */ jsxs("div", {
10863
+ className: "mx-auto flex w-full max-w-[var(--wd-transcript-max-width)] items-center gap-2 rounded-md border border-border bg-surface px-3 py-1.5 text-label text-fg-3",
10864
+ children: [
10865
+ /* @__PURE__ */ jsx(Clock, { className: "size-3.5 shrink-0" }),
10866
+ /* @__PURE__ */ jsxs("span", {
10867
+ className: "min-w-0 flex-1 truncate",
10868
+ children: [
10869
+ held.length === 1 ? "1 message" : `${held.length} messages`,
10870
+ " waiting for this turn to end — ",
10871
+ held[held.length - 1].text
10872
+ ]
10873
+ }),
10874
+ /* @__PURE__ */ jsx("button", {
10875
+ type: "button",
10876
+ onClick: onSendNow,
10877
+ className: "shrink-0 underline-offset-2 hover:underline",
10878
+ children: "Send now"
10879
+ })
10880
+ ]
10881
+ })
10882
+ });
10883
+ }
10884
+ //#endregion
10790
10885
  //#region src/components/agent/UsageMeters.tsx
10791
10886
  function useMinuteClock(active = true) {
10792
10887
  const [now, setNow] = useState(() => Date.now());
@@ -10938,7 +11033,7 @@ const INTERACTIVE = [
10938
11033
  "[role=\"radio\"]",
10939
11034
  "[role=\"tab\"]"
10940
11035
  ].join(",");
10941
- function SessionPanel({ client, sessionId, header, panelSurface = "internal", statusSurface = "internal", statusPlacement = "top", onOpenPanel, onVitals, transcriptVariant = "cards", transcriptDensity = "comfortable", transcriptFont = "sans", affordances, terminalMetrics, scrubber = false, bookmarks, onToggleBookmark, reveal, openSubagent, onSubagentChange, stickyPrompt = false, controlsSurface = "internal", onControls, focusComposerOnClick = false, unseen, readOnly = false, toolHost, clientTools, cacheTranscript, emptyState, onLinkClick, fontSize, className }) {
11036
+ function SessionPanel({ client, sessionId, header, panelSurface = "internal", statusSurface = "internal", statusPlacement = "top", onOpenPanel, onVitals, transcriptVariant = "cards", transcriptDensity = "comfortable", transcriptFont = "sans", midTurnSend = "fold", affordances, terminalMetrics, scrubber = false, bookmarks, onToggleBookmark, reveal, openSubagent, onSubagentChange, stickyPrompt = false, controlsSurface = "internal", onControls, focusComposerOnClick = false, unseen, readOnly = false, toolHost, clientTools, cacheTranscript, emptyState, onLinkClick, fontSize, className }) {
10942
11037
  const effectiveTermFontSize = terminalMetrics?.fontSize ?? fontSize;
10943
11038
  const effectiveTermLineHeight = terminalMetrics?.lineHeight ?? (fontSize !== void 0 ? Math.round(fontSize * (18 / 13)) : void 0);
10944
11039
  const external = panelSurface === "external";
@@ -11096,6 +11191,11 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
11096
11191
  argumentHint: "<model>"
11097
11192
  }, ...state.commands];
11098
11193
  }, [state.commands]);
11194
+ const heldSends = useHeldSends({
11195
+ hold: midTurnSend === "hold",
11196
+ busy: busy && !ended,
11197
+ send
11198
+ });
11099
11199
  const handleSend = (text, attachmentIds) => {
11100
11200
  if (attachmentIds.length === 0) {
11101
11201
  const modelCommand = /^\/model\s+(\S+)$/.exec(text);
@@ -11110,7 +11210,7 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
11110
11210
  }
11111
11211
  setCaughtUp(true);
11112
11212
  repinTranscript.current?.();
11113
- send(text, attachmentIds);
11213
+ heldSends.submit(text, attachmentIds);
11114
11214
  };
11115
11215
  const actionsMenu = /* @__PURE__ */ jsxs(Menu$1, { children: [/* @__PURE__ */ jsx(MenuTrigger, { render: /* @__PURE__ */ jsx(Button, {
11116
11216
  variant: "ghost",
@@ -11200,199 +11300,206 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
11200
11300
  value: transcriptDensity,
11201
11301
  children: /* @__PURE__ */ jsx(ToolResultFetchProvider, {
11202
11302
  value: loadFullResult,
11203
- children: /* @__PURE__ */ jsx(ToolResultImageProvider, {
11204
- value: resultImages,
11205
- children: /* @__PURE__ */ jsxs("div", {
11206
- ref: panelRef,
11207
- "data-slot": "session-panel",
11208
- "data-agent-font": transcriptFont,
11209
- onClick: handleClick,
11210
- className: cn("flex h-full min-h-0 flex-col overflow-hidden bg-bg", className),
11211
- style: fontSize !== void 0 ? { "--wd-font-size": `${Math.round(fontSize)}px` } : void 0,
11212
- children: [
11213
- headerTakesActions ? header({ actions: menu }) : header,
11214
- statusPlacement === "top" ? statusBar : null,
11215
- protocolMismatch !== void 0 ? /* @__PURE__ */ jsxs(Notice, {
11216
- level: "warning",
11217
- children: [
11218
- "Server speaks protocol v",
11219
- protocolMismatch,
11220
- ", this build renders v",
11221
- PROTOCOL_VERSION,
11222
- ". Some events may not render."
11223
- ]
11224
- }) : null,
11225
- protocolError ? /* @__PURE__ */ jsx(Notice, {
11226
- level: "error",
11227
- onDismiss: () => setProtocolError(void 0),
11228
- children: protocolError
11229
- }) : null,
11230
- subagentId !== void 0 ? /* @__PURE__ */ jsx(SubagentStrip, {
11231
- task: subagentTask,
11232
- items: subagentFrameItems,
11233
- label: subagentFallbackLabel,
11234
- onBack: leaveSubagent,
11235
- terminal,
11236
- fontSize: effectiveTermFontSize,
11237
- lineHeight: effectiveTermLineHeight
11238
- }) : null,
11239
- /* @__PURE__ */ jsx(BookmarkProvider, {
11240
- value: bookmarkHandle,
11241
- children: /* @__PURE__ */ jsx(Transcript, {
11242
- state,
11243
- fileUrl: sessionId ? (path) => client.sessionFileUrl(sessionId, path) : void 0,
11244
- attachmentUrl: sessionId ? (id) => client.attachmentUrl(sessionId, id) : void 0,
11245
- canBrowseFiles: hostFiles.available,
11246
- hostImage,
11247
- variant: transcriptVariant,
11248
- density: transcriptDensity,
11249
- fontSize: effectiveTermFontSize,
11250
- lineHeight: effectiveTermLineHeight,
11251
- affordances,
11252
- stickyPrompt,
11253
- scrubber,
11254
- bookmarks,
11255
- replaying,
11256
- catchUp: catchUp && newCount > 0 ? {
11257
- from: catchUp.itemCount,
11258
- since: catchUp.since
11259
- } : void 0,
11260
- reveal: returnReveal ?? reveal,
11261
- frame: subagentId === void 0 ? void 0 : { parentToolUseId: subagentId },
11262
- onOpenSubagent: enterSubagent,
11263
- emptyState,
11264
- jumpToRecapRef: jumpToRecap,
11265
- repinRef: repinTranscript
11266
- }, subagentId ?? "session")
11267
- }),
11268
- catchUp && newCount > 0 && !replaying && subagentId === void 0 ? /* @__PURE__ */ jsx("div", {
11269
- className: "px-3 pb-1",
11270
- children: /* @__PURE__ */ jsxs("div", {
11271
- "data-slot": "catch-up",
11272
- className: "mx-auto flex w-full max-w-[var(--wd-transcript-max-width)] items-center gap-2 text-label text-fg-3",
11303
+ children: /* @__PURE__ */ jsx(ToolTitleProvider, {
11304
+ value: state.toolTitles,
11305
+ children: /* @__PURE__ */ jsx(ToolResultImageProvider, {
11306
+ value: resultImages,
11307
+ children: /* @__PURE__ */ jsxs("div", {
11308
+ ref: panelRef,
11309
+ "data-slot": "session-panel",
11310
+ "data-agent-font": transcriptFont,
11311
+ onClick: handleClick,
11312
+ className: cn("flex h-full min-h-0 flex-col overflow-hidden bg-bg", className),
11313
+ style: fontSize !== void 0 ? { "--wd-font-size": `${Math.round(fontSize)}px` } : void 0,
11314
+ children: [
11315
+ headerTakesActions ? header({ actions: menu }) : header,
11316
+ statusPlacement === "top" ? statusBar : null,
11317
+ protocolMismatch !== void 0 ? /* @__PURE__ */ jsxs(Notice, {
11318
+ level: "warning",
11273
11319
  children: [
11274
- /* @__PURE__ */ jsx("span", {
11275
- "aria-hidden": true,
11276
- className: cn("select-none", terminal ? "text-fg-3" : "text-accent"),
11277
- children: "※"
11278
- }),
11279
- /* @__PURE__ */ jsxs("span", {
11280
- className: "min-w-0 flex-1 truncate",
11281
- children: [
11282
- newCount,
11283
- " new ",
11284
- newCount === 1 ? "row" : "rows",
11285
- catchUp.since !== void 0 ? ` since you were last here` : ""
11286
- ]
11287
- }),
11288
- /* @__PURE__ */ jsx("button", {
11289
- type: "button",
11290
- onClick: () => jumpToRecap.current?.(),
11291
- className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
11292
- children: "jump"
11293
- }),
11294
- /* @__PURE__ */ jsx("button", {
11295
- type: "button",
11296
- onClick: () => setCaughtUp(true),
11297
- className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
11298
- children: "dismiss"
11299
- })
11320
+ "Server speaks protocol v",
11321
+ protocolMismatch,
11322
+ ", this build renders v",
11323
+ PROTOCOL_VERSION,
11324
+ ". Some events may not render."
11300
11325
  ]
11301
- })
11302
- }) : null,
11303
- !readOnly && capabilities.interactiveApprovals && state.pendingApprovals.length > 0 ? /* @__PURE__ */ jsx("div", {
11304
- className: cn(terminal ? "pb-2" : "px-3 pb-2"),
11305
- children: /* @__PURE__ */ jsx(PromptSurface, {
11326
+ }) : null,
11327
+ protocolError ? /* @__PURE__ */ jsx(Notice, {
11328
+ level: "error",
11329
+ onDismiss: () => setProtocolError(void 0),
11330
+ children: protocolError
11331
+ }) : null,
11332
+ subagentId !== void 0 ? /* @__PURE__ */ jsx(SubagentStrip, {
11333
+ task: subagentTask,
11334
+ items: subagentFrameItems,
11335
+ label: subagentFallbackLabel,
11336
+ onBack: leaveSubagent,
11306
11337
  terminal,
11307
- metrics: {
11338
+ fontSize: effectiveTermFontSize,
11339
+ lineHeight: effectiveTermLineHeight
11340
+ }) : null,
11341
+ /* @__PURE__ */ jsx(BookmarkProvider, {
11342
+ value: bookmarkHandle,
11343
+ children: /* @__PURE__ */ jsx(Transcript, {
11344
+ state,
11345
+ fileUrl: sessionId ? (path) => client.sessionFileUrl(sessionId, path) : void 0,
11346
+ attachmentUrl: sessionId ? (id) => client.attachmentUrl(sessionId, id) : void 0,
11347
+ canBrowseFiles: hostFiles.available,
11348
+ hostImage,
11349
+ variant: transcriptVariant,
11350
+ density: transcriptDensity,
11308
11351
  fontSize: effectiveTermFontSize,
11309
- lineHeight: effectiveTermLineHeight
11310
- },
11311
- affordances,
11312
- children: state.pendingApprovals.map((request) => {
11313
- const isQuestion = request.toolName === "AskUserQuestion" && parseUserQuestions(request.input).length > 0;
11314
- if (terminal) return isQuestion ? /* @__PURE__ */ jsx(TerminalQuestionPrompt, {
11315
- request,
11316
- onAnswer: approve,
11317
- onDismiss: (id) => deny(id, "Question dismissed by user")
11318
- }, request.id) : /* @__PURE__ */ jsx(TerminalPermissionPrompt, {
11319
- request,
11320
- onApprove: approve,
11321
- onDeny: deny
11322
- }, request.id);
11323
- return isQuestion ? /* @__PURE__ */ jsx(QuestionPrompt, {
11324
- request,
11325
- onAnswer: approve,
11326
- onDismiss: (id) => deny(id, "Question dismissed by user")
11327
- }, request.id) : /* @__PURE__ */ jsx(PermissionPrompt, {
11328
- request,
11329
- onApprove: approve,
11330
- onDeny: deny
11331
- }, request.id);
11332
- })
11333
- })
11334
- }) : null,
11335
- readOnly || subagentId !== void 0 ? null : /* @__PURE__ */ jsx(Composer, {
11336
- ref: composerRef,
11337
- onSend: handleSend,
11338
- onInterrupt: interrupt,
11339
- busy,
11340
- disabled: ended || !sessionId,
11341
- commands: capabilities.slashCommands ? commands : void 0,
11342
- skills: capabilities.skillsList ? state.skills : void 0,
11343
- attachments,
11344
- draft,
11345
- onSearchFiles: hostFiles.available ? searchComposerFiles : void 0,
11346
- layout: controlsExternal ? "inline" : "stacked",
11347
- toolbar: controlsExternal ? void 0 : sessionControls,
11348
- fontSize: effectiveTermFontSize,
11349
- lineHeight: effectiveTermLineHeight,
11350
- affordances
11351
- }),
11352
- statusPlacement === "bottom" ? statusBar : null,
11353
- !external ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
11354
- /* @__PURE__ */ jsx(SessionInfoDialog, {
11355
- state,
11356
- client,
11357
- sessionId,
11358
- open: panel === "info",
11359
- onOpenChange: (next) => setPanel(next ? "info" : void 0)
11352
+ lineHeight: effectiveTermLineHeight,
11353
+ affordances,
11354
+ stickyPrompt,
11355
+ scrubber,
11356
+ bookmarks,
11357
+ replaying,
11358
+ catchUp: catchUp && newCount > 0 ? {
11359
+ from: catchUp.itemCount,
11360
+ since: catchUp.since
11361
+ } : void 0,
11362
+ reveal: returnReveal ?? reveal,
11363
+ frame: subagentId === void 0 ? void 0 : { parentToolUseId: subagentId },
11364
+ onOpenSubagent: enterSubagent,
11365
+ emptyState,
11366
+ jumpToRecapRef: jumpToRecap,
11367
+ repinRef: repinTranscript
11368
+ }, subagentId ?? "session")
11360
11369
  }),
11361
- /* @__PURE__ */ jsx(ContextDialog, {
11362
- usage: state.contextUsage,
11363
- open: panel === "context",
11364
- onOpenChange: (next) => setPanel(next ? "context" : void 0)
11365
- }),
11366
- /* @__PURE__ */ jsx(UsageDialog, {
11367
- rateLimits: windows,
11368
- subscriptionType: state.subscriptionType,
11369
- engine: state.engine ?? "claude",
11370
- totalCostUsd: state.totalCostUsd,
11371
- updatedAt: usageUpdatedAt,
11372
- open: panel === "usage",
11373
- onOpenChange: (next) => setPanel(next ? "usage" : void 0)
11374
- }),
11375
- /* @__PURE__ */ jsx(McpDialog, {
11376
- client,
11377
- sessionId,
11378
- canManageServers: capabilities.mcpServerActions,
11379
- open: panel === "mcp",
11380
- onOpenChange: (next) => setPanel(next ? "mcp" : void 0)
11381
- }),
11382
- /* @__PURE__ */ jsx(SkillsDialog, {
11383
- skills: state.skills,
11384
- open: panel === "skills",
11385
- onOpenChange: (next) => setPanel(next ? "skills" : void 0),
11386
- onUse: (skill) => composerRef.current?.insertText(skillPrompt(skill))
11387
- }),
11388
- /* @__PURE__ */ jsx(HostFilesDialog, {
11389
- client,
11390
- cwd: state.cwd,
11391
- open: panel === "files",
11392
- onOpenChange: (next) => setPanel(next ? "files" : void 0)
11393
- })
11394
- ] }) : null
11395
- ]
11370
+ catchUp && newCount > 0 && !replaying && subagentId === void 0 ? /* @__PURE__ */ jsx("div", {
11371
+ className: "px-3 pb-1",
11372
+ children: /* @__PURE__ */ jsxs("div", {
11373
+ "data-slot": "catch-up",
11374
+ className: "mx-auto flex w-full max-w-[var(--wd-transcript-max-width)] items-center gap-2 text-label text-fg-3",
11375
+ children: [
11376
+ /* @__PURE__ */ jsx("span", {
11377
+ "aria-hidden": true,
11378
+ className: cn("select-none", terminal ? "text-fg-3" : "text-accent"),
11379
+ children: "※"
11380
+ }),
11381
+ /* @__PURE__ */ jsxs("span", {
11382
+ className: "min-w-0 flex-1 truncate",
11383
+ children: [
11384
+ newCount,
11385
+ " new ",
11386
+ newCount === 1 ? "row" : "rows",
11387
+ catchUp.since !== void 0 ? ` since you were last here` : ""
11388
+ ]
11389
+ }),
11390
+ /* @__PURE__ */ jsx("button", {
11391
+ type: "button",
11392
+ onClick: () => jumpToRecap.current?.(),
11393
+ className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
11394
+ children: "jump"
11395
+ }),
11396
+ /* @__PURE__ */ jsx("button", {
11397
+ type: "button",
11398
+ onClick: () => setCaughtUp(true),
11399
+ className: "shrink-0 underline-offset-2 hover:text-fg-1 hover:underline",
11400
+ children: "dismiss"
11401
+ })
11402
+ ]
11403
+ })
11404
+ }) : null,
11405
+ !readOnly && capabilities.interactiveApprovals && state.pendingApprovals.length > 0 ? /* @__PURE__ */ jsx("div", {
11406
+ className: cn(terminal ? "pb-2" : "px-3 pb-2"),
11407
+ children: /* @__PURE__ */ jsx(PromptSurface, {
11408
+ terminal,
11409
+ metrics: {
11410
+ fontSize: effectiveTermFontSize,
11411
+ lineHeight: effectiveTermLineHeight
11412
+ },
11413
+ affordances,
11414
+ children: state.pendingApprovals.map((request) => {
11415
+ const isQuestion = request.toolName === "AskUserQuestion" && parseUserQuestions(request.input).length > 0;
11416
+ if (terminal) return isQuestion ? /* @__PURE__ */ jsx(TerminalQuestionPrompt, {
11417
+ request,
11418
+ onAnswer: approve,
11419
+ onDismiss: (id) => deny(id, "Question dismissed by user")
11420
+ }, request.id) : /* @__PURE__ */ jsx(TerminalPermissionPrompt, {
11421
+ request,
11422
+ onApprove: approve,
11423
+ onDeny: deny
11424
+ }, request.id);
11425
+ return isQuestion ? /* @__PURE__ */ jsx(QuestionPrompt, {
11426
+ request,
11427
+ onAnswer: approve,
11428
+ onDismiss: (id) => deny(id, "Question dismissed by user")
11429
+ }, request.id) : /* @__PURE__ */ jsx(PermissionPrompt, {
11430
+ request,
11431
+ onApprove: approve,
11432
+ onDeny: deny
11433
+ }, request.id);
11434
+ })
11435
+ })
11436
+ }) : null,
11437
+ readOnly || subagentId !== void 0 ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(HeldSendsBar, {
11438
+ held: heldSends.held,
11439
+ onSendNow: heldSends.flush
11440
+ }), /* @__PURE__ */ jsx(Composer, {
11441
+ ref: composerRef,
11442
+ onSend: handleSend,
11443
+ onInterrupt: interrupt,
11444
+ busy,
11445
+ disabled: ended || !sessionId,
11446
+ commands: capabilities.slashCommands ? commands : void 0,
11447
+ skills: capabilities.skillsList ? state.skills : void 0,
11448
+ attachments,
11449
+ draft,
11450
+ onSearchFiles: hostFiles.available ? searchComposerFiles : void 0,
11451
+ layout: controlsExternal ? "inline" : "stacked",
11452
+ toolbar: controlsExternal ? void 0 : sessionControls,
11453
+ fontSize: effectiveTermFontSize,
11454
+ lineHeight: effectiveTermLineHeight,
11455
+ affordances
11456
+ })] }),
11457
+ statusPlacement === "bottom" ? statusBar : null,
11458
+ !external ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
11459
+ /* @__PURE__ */ jsx(SessionInfoDialog, {
11460
+ state,
11461
+ client,
11462
+ sessionId,
11463
+ open: panel === "info",
11464
+ onOpenChange: (next) => setPanel(next ? "info" : void 0)
11465
+ }),
11466
+ /* @__PURE__ */ jsx(ContextDialog, {
11467
+ usage: state.contextUsage,
11468
+ engine: state.engine ?? "claude",
11469
+ open: panel === "context",
11470
+ onOpenChange: (next) => setPanel(next ? "context" : void 0)
11471
+ }),
11472
+ /* @__PURE__ */ jsx(UsageDialog, {
11473
+ rateLimits: windows,
11474
+ subscriptionType: state.subscriptionType,
11475
+ engine: state.engine ?? "claude",
11476
+ totalCostUsd: state.totalCostUsd,
11477
+ updatedAt: usageUpdatedAt,
11478
+ open: panel === "usage",
11479
+ onOpenChange: (next) => setPanel(next ? "usage" : void 0)
11480
+ }),
11481
+ /* @__PURE__ */ jsx(McpDialog, {
11482
+ client,
11483
+ sessionId,
11484
+ canManageServers: capabilities.mcpServerActions,
11485
+ open: panel === "mcp",
11486
+ onOpenChange: (next) => setPanel(next ? "mcp" : void 0)
11487
+ }),
11488
+ /* @__PURE__ */ jsx(SkillsDialog, {
11489
+ skills: state.skills,
11490
+ open: panel === "skills",
11491
+ onOpenChange: (next) => setPanel(next ? "skills" : void 0),
11492
+ onUse: (skill) => composerRef.current?.insertText(skillPrompt(skill))
11493
+ }),
11494
+ /* @__PURE__ */ jsx(HostFilesDialog, {
11495
+ client,
11496
+ cwd: state.cwd,
11497
+ open: panel === "files",
11498
+ onOpenChange: (next) => setPanel(next ? "files" : void 0)
11499
+ })
11500
+ ] }) : null
11501
+ ]
11502
+ })
11396
11503
  })
11397
11504
  })
11398
11505
  })
@@ -11461,6 +11568,6 @@ function Notice({ level, onDismiss, children }) {
11461
11568
  });
11462
11569
  }
11463
11570
  //#endregion
11464
- export { isMutatingTool as $, PERMISSION_MODES as A, MenuItem as At, Composer as B, Input as Bt, TerminalPermissionPrompt as C, DialogClose as Ct, SubagentStrip as D, DialogTrigger as Dt, parseUserQuestions as E, DialogRow as Et, SkillsDialog as F, SelectItem as Ft, previewPatch as G, cn as Gt, TerminalSurface as H, badgeVariants as Ht, McpDialog as I, SelectItemText as It, Ink as J, Band as K, HostFilesDialog as L, SelectTrigger as Lt, permissionModeChoices as M, MenuTrigger as Mt, permissionModeMeta as N, Select$1 as Nt, PermissionPrompt as O, Menu$1 as Ot, ModelSelect as P, SelectContent as Pt, useAffordances as Q, EntryIcon as R, SelectValue as Rt, TerminalQuestionPrompt as S, DialogBody as St, QuestionPrompt as T, DialogHeader as Tt, TerminalMarkdown as U, Button as Ut, skillPrompt as V, Badge as Vt, TerminalDiff as W, buttonVariants as Wt, CopyAction as X, Row as Y, WithActions as Z, ConversationContent as _, copyText as _t, Transcript as a, commandTrigger as at, STATUS_META as b, TooltipProvider as bt, PromptTokenText as c, usePromptAreaState as ct, FileCard as d, segmentsToPlainText as dt, toolIcon as et, TerminalItemView as f, ProgressRing as ft, Conversation as g, CopyButton as gt, Loader as h, Spinner as ht, useMinuteClock as i, useTranscriptVariant as it, PermissionModeSelect as j, MenuSeparator as jt, Response as k, MenuContent as kt, Message as l, PromptArea as lt, SessionEmptyState as m, CodeBlock as mt, UsageDialog as n, TranscriptVariantProvider as nt, ToolCallCard as o, hashtagTrigger as ot, TerminalTranscript as p, Splitter as pt, Blank as q, UsageMeters as r, useTranscriptDensity as rt, Reasoning as s, mentionTrigger as st, SessionPanel as t, TranscriptDensityProvider as tt, MessageContent as u, plainTextToSegments as ut, ConversationScrollButton as v, Tip as vt, QUESTION_BEHAVIORS as w, DialogContent as wt, SessionInfoDialog as x, Dialog$1 as xt, StatusBar as y, TooltipContent as yt, ContextDialog as z, PortalScope as zt };
11571
+ export { Ink as $, PermissionPrompt as A, DialogHeader as At, EntryIcon as B, SelectItem as Bt, SessionInfoDialog as C, Tip as Ct, QuestionPrompt as D, DialogBody as Dt, QUESTION_BEHAVIORS as E, Dialog$1 as Et, permissionModeMeta as F, MenuItem as Ft, TerminalSurface as G, Input as Gt, contextNote as H, SelectTrigger as Ht, ModelSelect as I, MenuSeparator as It, TerminalMarkdown as J, Button as Jt, ToolTitleProvider as K, Badge as Kt, SkillsDialog as L, MenuTrigger as Lt, PERMISSION_MODES as M, DialogTrigger as Mt, PermissionModeSelect as N, Menu$1 as Nt, parseUserQuestions as O, DialogClose as Ot, permissionModeChoices as P, MenuContent as Pt, Blank as Q, McpDialog as R, Select$1 as Rt, STATUS_META as S, copyText as St, TerminalPermissionPrompt as T, TooltipProvider as Tt, Composer as U, SelectValue as Ut, ContextDialog as V, SelectItemText as Vt, skillPrompt as W, PortalScope as Wt, previewPatch as X, cn as Xt, TerminalDiff as Y, buttonVariants as Yt, Band as Z, Loader as _, ProgressRing as _t, HeldSendsBar as a, toolIcon as at, ConversationScrollButton as b, Spinner as bt, ToolCallCard as c, useTranscriptDensity as ct, Message as d, hashtagTrigger as dt, Row as et, MessageContent as f, mentionTrigger as ft, SessionEmptyState as g, segmentsToPlainText as gt, TerminalTranscript as h, plainTextToSegments as ht, useMinuteClock as i, isMutatingTool as it, Response as j, DialogRow as jt, SubagentStrip as k, DialogContent as kt, Reasoning as l, useTranscriptVariant as lt, TerminalItemView as m, PromptArea as mt, UsageDialog as n, WithActions as nt, useHeldSends as o, TranscriptDensityProvider as ot, FileCard as p, usePromptAreaState as pt, useToolTitle as q, badgeVariants as qt, UsageMeters as r, useAffordances as rt, Transcript as s, TranscriptVariantProvider as st, SessionPanel as t, CopyAction as tt, PromptTokenText as u, commandTrigger as ut, Conversation as v, Splitter as vt, TerminalQuestionPrompt as w, TooltipContent as wt, StatusBar as x, CopyButton as xt, ConversationContent as y, CodeBlock as yt, HostFilesDialog as z, SelectContent as zt };
11465
11572
 
11466
- //# sourceMappingURL=SessionPanel-DVhnUwXw.mjs.map
11573
+ //# sourceMappingURL=SessionPanel-DQp2oStr.mjs.map