flavor-code 1.4.1 → 1.4.3-beta.2

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 (76) hide show
  1. package/README.md +32 -2
  2. package/README.zh-CN.md +32 -2
  3. package/dist/{app-4YRKE7VI.js → app-G35YBHPR.js} +873 -641
  4. package/dist/apply-WOW3QU5I.js +51 -0
  5. package/dist/broker-cli-X5H46FZV.js +15 -0
  6. package/dist/check-CSKTV4O2.js +16 -0
  7. package/dist/chunk-3563SW4X.js +10513 -0
  8. package/dist/chunk-3UX2CGDW.js +1955 -0
  9. package/dist/chunk-4TMLXZVZ.js +75 -0
  10. package/dist/chunk-6F66UXBI.js +48 -0
  11. package/dist/{chunk-FAORPP4F.js → chunk-6URQ7FIF.js} +24 -88
  12. package/dist/chunk-6X62CGMA.js +193 -0
  13. package/dist/chunk-7Y64WNBB.js +8930 -0
  14. package/dist/chunk-AA4QNKTF.js +501 -0
  15. package/dist/chunk-BDX777JR.js +11 -0
  16. package/dist/chunk-CVP5OUHD.js +103 -0
  17. package/dist/chunk-EWD7FWTH.js +14547 -0
  18. package/dist/chunk-FAJ6YDZK.js +630 -0
  19. package/dist/{chunk-N5MXHJKD.js → chunk-GTFP2R5I.js} +1 -1
  20. package/dist/{chunk-7YFHRORG.js → chunk-HGTCIHWA.js} +383 -172
  21. package/dist/chunk-IDJAHEG6.js +43501 -0
  22. package/dist/chunk-IQEEFDEE.js +389 -0
  23. package/dist/chunk-IU3UBETC.js +30 -0
  24. package/dist/chunk-K7UGGWJV.js +1003 -0
  25. package/dist/chunk-KRWWCVXA.js +74 -0
  26. package/dist/chunk-OKHV7CTB.js +482 -0
  27. package/dist/chunk-PULWAH6E.js +474 -0
  28. package/dist/chunk-PZ5NKRVA.js +85 -0
  29. package/dist/chunk-RBAZLFKB.js +1022 -0
  30. package/dist/chunk-RV3EXUXM.js +30 -0
  31. package/dist/chunk-SJUIIHIA.js +2130 -0
  32. package/dist/{chunk-VMQWXQEC.js → chunk-T6RE76D2.js} +2003 -493
  33. package/dist/chunk-TIEOVQW6.js +61 -0
  34. package/dist/chunk-WLZUAVVU.js +15 -0
  35. package/dist/chunk-X442CJJH.js +114 -0
  36. package/dist/{chunk-RAYH6K2H.js → chunk-Y7EH4NVO.js} +1 -1
  37. package/dist/{chunk-S32JRDZK.js → chunk-ZKKVSR37.js} +6 -1
  38. package/dist/{claude-ink-JZXNSAQS.js → claude-ink-BE56DB6N.js} +9 -4
  39. package/dist/cli-3MF6EL2H.js +163 -0
  40. package/dist/cli-main.js +3805 -473
  41. package/dist/cli.js +50 -4
  42. package/dist/config/load.d.ts +8 -0
  43. package/dist/config/schema.d.ts +11 -0
  44. package/dist/context/manager.d.ts +2 -0
  45. package/dist/desktop/main.js +4303 -1171
  46. package/dist/desktop/preload.cjs +30 -0
  47. package/dist/desktop-renderer/assets/index-BWklSoOO.css +1 -0
  48. package/dist/desktop-renderer/assets/index-DCqIrF1S.js +153 -0
  49. package/dist/desktop-renderer/assets/{interactive-terminal-1agnYY5L.js → interactive-terminal-B6GbpzIn.js} +1 -1
  50. package/dist/desktop-renderer/index.html +2 -2
  51. package/dist/doctor-OHCGK52S.js +20 -0
  52. package/dist/load-QK6CMLDF.js +25 -0
  53. package/dist/log-ATFIPRNU.js +19 -0
  54. package/dist/manager-5SI4MPES.js +191 -0
  55. package/dist/models/anthropic.d.ts +3 -0
  56. package/dist/node-LOIXT44J.js +879 -0
  57. package/dist/plugin-worker-entry.js +1 -1
  58. package/dist/production-6DIZ6YLQ.js +46 -0
  59. package/dist/production.d.ts +28 -1
  60. package/dist/project-3QXE22TG.js +11 -0
  61. package/dist/react-M6JGXSJZ.js +7 -0
  62. package/dist/recorder-FAGJJH3N.js +11 -0
  63. package/dist/sdk/index.js +30 -8
  64. package/dist/server-2KLKPHPL.js +11 -0
  65. package/dist/session/store.d.ts +1 -0
  66. package/dist/store-ZIHN6363.js +18 -0
  67. package/dist/ui/commands.d.ts +1 -5
  68. package/dist/usage-summary-G5FBOJLK.js +13 -0
  69. package/dist/utils/execFileNoThrow.d.ts +1 -0
  70. package/dist/write-stream-CGD57URC.js +77 -0
  71. package/package.json +1 -1
  72. package/dist/chunk-O2PC44GY.js +0 -26120
  73. package/dist/chunk-ZJCAQXA7.js +0 -169
  74. package/dist/desktop-renderer/assets/index-BM9ugkh9.js +0 -154
  75. package/dist/desktop-renderer/assets/index-Bk6FYhyh.css +0 -1
  76. package/dist/load-UPOG3XQR.js +0 -19
@@ -1,27 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module"; const require = createRequire(import.meta.url);
3
- import {
4
- statusPresentation
5
- } from "./chunk-RAYH6K2H.js";
6
- import {
7
- COMMAND_DESCRIPTIONS,
8
- MVP_COMMANDS,
9
- charWidth,
10
- checkForUpdate,
11
- createGlobTool,
12
- createProductionRuntime,
13
- createTranscriptState,
14
- isDestructiveTool,
15
- message,
16
- modelContentTranscriptText,
17
- packageVersion,
18
- redactErrorText,
19
- thinkingWindow,
20
- transcriptReducer,
21
- withTimeout
22
- } from "./chunk-O2PC44GY.js";
23
- import "./chunk-N5MXHJKD.js";
24
- import "./chunk-7YFHRORG.js";
2
+ import { createRequire as createFlavorRequire } from "node:module"; const require = createFlavorRequire(import.meta.url);
25
3
  import {
26
4
  Box_default,
27
5
  ClockContext,
@@ -33,37 +11,96 @@ import {
33
11
  Text,
34
12
  instances_default,
35
13
  osc,
14
+ require_jsx_runtime,
36
15
  shiftAnchor,
37
16
  stringWidth,
38
17
  stripAnsi,
39
18
  useStdout,
40
19
  use_app_default,
41
20
  use_input_default
42
- } from "./chunk-VMQWXQEC.js";
21
+ } from "./chunk-T6RE76D2.js";
22
+ import {
23
+ require_react
24
+ } from "./chunk-PULWAH6E.js";
25
+ import {
26
+ statusPresentation
27
+ } from "./chunk-Y7EH4NVO.js";
28
+ import {
29
+ source_default
30
+ } from "./chunk-AA4QNKTF.js";
31
+ import {
32
+ COMMAND_DESCRIPTIONS,
33
+ MVP_COMMANDS,
34
+ createGlobTool,
35
+ createProductionRuntime,
36
+ isDestructiveTool
37
+ } from "./chunk-IDJAHEG6.js";
43
38
  import {
44
- execFileNoThrow,
45
39
  getGraphemeSegmenter
46
- } from "./chunk-ZJCAQXA7.js";
47
- import "./chunk-S32JRDZK.js";
40
+ } from "./chunk-TIEOVQW6.js";
41
+ import "./chunk-OKHV7CTB.js";
42
+ import "./chunk-K7UGGWJV.js";
43
+ import {
44
+ execFileNoThrow
45
+ } from "./chunk-IU3UBETC.js";
46
+ import "./chunk-PZ5NKRVA.js";
47
+ import {
48
+ checkForUpdate
49
+ } from "./chunk-6F66UXBI.js";
50
+ import "./chunk-3UX2CGDW.js";
51
+ import {
52
+ k
53
+ } from "./chunk-7Y64WNBB.js";
54
+ import "./chunk-CVP5OUHD.js";
55
+ import "./chunk-3563SW4X.js";
56
+ import "./chunk-RBAZLFKB.js";
57
+ import "./chunk-FAJ6YDZK.js";
58
+ import {
59
+ redactErrorText
60
+ } from "./chunk-WLZUAVVU.js";
61
+ import {
62
+ packageVersion
63
+ } from "./chunk-RV3EXUXM.js";
64
+ import "./chunk-IQEEFDEE.js";
65
+ import "./chunk-GTFP2R5I.js";
66
+ import "./chunk-HGTCIHWA.js";
67
+ import {
68
+ charWidth,
69
+ createTranscriptState,
70
+ modelContentTranscriptText,
71
+ thinkingWindow,
72
+ transcriptReducer,
73
+ withTimeout
74
+ } from "./chunk-SJUIIHIA.js";
75
+ import {
76
+ message
77
+ } from "./chunk-BDX777JR.js";
78
+ import "./chunk-6X62CGMA.js";
79
+ import "./chunk-EWD7FWTH.js";
80
+ import "./chunk-KRWWCVXA.js";
81
+ import "./chunk-X442CJJH.js";
82
+ import {
83
+ __toESM
84
+ } from "./chunk-ZKKVSR37.js";
48
85
 
49
86
  // src/ui/app.tsx
87
+ var import_react8 = __toESM(require_react(), 1);
50
88
  import { basename as basename3 } from "path";
51
89
  import { homedir } from "os";
52
- import { useEffect as useEffect3, useReducer, useRef as useRef4, useState as useState2 } from "react";
53
90
 
54
91
  // src/claude-ink/hooks/use-animation-frame.ts
55
- import { useContext as useContext2, useEffect, useState } from "react";
92
+ var import_react2 = __toESM(require_react(), 1);
56
93
 
57
94
  // src/claude-ink/hooks/use-terminal-viewport.ts
58
- import { useCallback, useContext, useLayoutEffect, useRef } from "react";
95
+ var import_react = __toESM(require_react(), 1);
59
96
  function useTerminalViewport() {
60
- const terminalSize = useContext(TerminalSizeContext);
61
- const elementRef = useRef(null);
62
- const entryRef = useRef({ isVisible: true });
63
- const setElement = useCallback((el) => {
97
+ const terminalSize = (0, import_react.useContext)(TerminalSizeContext);
98
+ const elementRef = (0, import_react.useRef)(null);
99
+ const entryRef = (0, import_react.useRef)({ isVisible: true });
100
+ const setElement = (0, import_react.useCallback)((el) => {
64
101
  elementRef.current = el;
65
102
  }, []);
66
- useLayoutEffect(() => {
103
+ (0, import_react.useLayoutEffect)(() => {
67
104
  const element = elementRef.current;
68
105
  if (!element?.yogaNode || !terminalSize) {
69
106
  return;
@@ -96,11 +133,11 @@ function useTerminalViewport() {
96
133
 
97
134
  // src/claude-ink/hooks/use-animation-frame.ts
98
135
  function useAnimationFrame(intervalMs = 16) {
99
- const clock = useContext2(ClockContext);
136
+ const clock = (0, import_react2.useContext)(ClockContext);
100
137
  const [viewportRef, { isVisible }] = useTerminalViewport();
101
- const [time, setTime] = useState(() => clock?.now() ?? 0);
138
+ const [time, setTime] = (0, import_react2.useState)(() => clock?.now() ?? 0);
102
139
  const active = isVisible && intervalMs !== null;
103
- useEffect(() => {
140
+ (0, import_react2.useEffect)(() => {
104
141
  if (!clock || !active) return;
105
142
  let lastUpdate = clock.now();
106
143
  const onChange = () => {
@@ -116,11 +153,11 @@ function useAnimationFrame(intervalMs = 16) {
116
153
  }
117
154
 
118
155
  // src/claude-ink/hooks/use-selection.ts
119
- import { useContext as useContext3, useMemo, useSyncExternalStore } from "react";
156
+ var import_react3 = __toESM(require_react(), 1);
120
157
  function useSelection() {
121
- useContext3(StdinContext_default);
158
+ (0, import_react3.useContext)(StdinContext_default);
122
159
  const ink = instances_default.get(process.stdout);
123
- return useMemo(() => {
160
+ return (0, import_react3.useMemo)(() => {
124
161
  if (!ink) {
125
162
  return {
126
163
  copySelection: () => "",
@@ -160,10 +197,10 @@ function useSelection() {
160
197
  }
161
198
 
162
199
  // src/claude-ink/hooks/use-terminal-title.ts
163
- import { useContext as useContext4, useEffect as useEffect2 } from "react";
200
+ var import_react4 = __toESM(require_react(), 1);
164
201
  function useTerminalTitle(title) {
165
- const writeRaw = useContext4(TerminalWriteContext);
166
- useEffect2(() => {
202
+ const writeRaw = (0, import_react4.useContext)(TerminalWriteContext);
203
+ (0, import_react4.useEffect)(() => {
167
204
  if (title === null || !writeRaw) return;
168
205
  const clean = stripAnsi(title);
169
206
  writeRaw(osc(OSC.SET_TITLE_AND_ICON, clean));
@@ -171,22 +208,19 @@ function useTerminalTitle(title) {
171
208
  }
172
209
 
173
210
  // src/ui/assistant-text.tsx
174
- import React2 from "react";
211
+ var import_react6 = __toESM(require_react(), 1);
175
212
 
176
213
  // src/ui/markdown.tsx
177
- import React, { useMemo as useMemo2, useRef as useRef2 } from "react";
178
- import chalk2 from "chalk";
179
- import { marked } from "marked";
214
+ var import_react5 = __toESM(require_react(), 1);
180
215
 
181
216
  // src/ui/highlight.ts
182
- import chalk from "chalk";
183
- chalk.level = Math.max(chalk.level, 3);
184
- var KEYWORD = chalk.hex("#c586c0");
185
- var STRING = chalk.hex("#ce9178");
186
- var COMMENT = chalk.gray.italic;
187
- var NUMBER = chalk.hex("#b5cea8");
188
- var FUNCTION = chalk.hex("#dcdcaa");
189
- var ATTRIBUTE = chalk.hex("#d7ba7d");
217
+ source_default.level = Math.max(source_default.level, 3);
218
+ var KEYWORD = source_default.hex("#c586c0");
219
+ var STRING = source_default.hex("#ce9178");
220
+ var COMMENT = source_default.gray.italic;
221
+ var NUMBER = source_default.hex("#b5cea8");
222
+ var FUNCTION = source_default.hex("#dcdcaa");
223
+ var ATTRIBUTE = source_default.hex("#d7ba7d");
190
224
  var KEYWORDS = {
191
225
  javascript: /* @__PURE__ */ new Set([
192
226
  "await",
@@ -613,7 +647,7 @@ function highlightCode(source, language = void 0) {
613
647
  }
614
648
 
615
649
  // src/ui/markdown.tsx
616
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
650
+ var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
617
651
  var CODE_BLOCK_BORDER = {
618
652
  top: "\u2500",
619
653
  bottom: "\u2500",
@@ -625,12 +659,12 @@ var CODE_BLOCK_BORDER = {
625
659
  bottomRight: "\u256F"
626
660
  };
627
661
  function MarkdownViewInner({ text }) {
628
- const stablePrefixRef = useRef2("");
662
+ const stablePrefixRef = (0, import_react5.useRef)("");
629
663
  if (!text.startsWith(stablePrefixRef.current)) stablePrefixRef.current = "";
630
664
  const boundary = stablePrefixRef.current.length;
631
- const suffixTokens = useMemo2(() => {
665
+ const suffixTokens = (0, import_react5.useMemo)(() => {
632
666
  try {
633
- return marked.lexer(text.substring(boundary), { gfm: true, async: false });
667
+ return k.lexer(text.substring(boundary), { gfm: true, async: false });
634
668
  } catch {
635
669
  return [];
636
670
  }
@@ -642,68 +676,68 @@ function MarkdownViewInner({ text }) {
642
676
  if (advance > 0) stablePrefixRef.current = text.substring(0, boundary + advance);
643
677
  const stablePrefix = stablePrefixRef.current;
644
678
  const unstableSuffix = text.substring(stablePrefix.length);
645
- return /* @__PURE__ */ jsxs(Box_default, { flexDirection: "column", width: "100%", children: [
646
- stablePrefix.length > 0 ? /* @__PURE__ */ jsx(MarkdownSegment, { text: stablePrefix }) : null,
647
- unstableSuffix.length > 0 ? /* @__PURE__ */ jsx(MarkdownSegment, { text: unstableSuffix }) : null
679
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", width: "100%", children: [
680
+ stablePrefix.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownSegment, { text: stablePrefix }) : null,
681
+ unstableSuffix.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownSegment, { text: unstableSuffix }) : null
648
682
  ] });
649
683
  }
650
- var MarkdownSegment = React.memo(function MarkdownSegment2({ text }) {
651
- const tokens = useMemo2(() => {
684
+ var MarkdownSegment = import_react5.default.memo(function MarkdownSegment2({ text }) {
685
+ const tokens = (0, import_react5.useMemo)(() => {
652
686
  try {
653
- return marked.lexer(text, { gfm: true, async: false });
687
+ return k.lexer(text, { gfm: true, async: false });
654
688
  } catch {
655
689
  return [];
656
690
  }
657
691
  }, [text]);
658
- return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((token, index) => /* @__PURE__ */ jsx(BlockToken, { token }, index)) });
692
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: tokens.map((token, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockToken, { token }, index)) });
659
693
  });
660
- var MarkdownView = React.memo(MarkdownViewInner);
661
- var BlockToken = React.memo(function BlockToken2({ token }) {
694
+ var MarkdownView = import_react5.default.memo(MarkdownViewInner);
695
+ var BlockToken = import_react5.default.memo(function BlockToken2({ token }) {
662
696
  switch (token.type) {
663
697
  case "space":
664
- return /* @__PURE__ */ jsx(Box_default, { height: 1 });
698
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { height: 1 });
665
699
  case "heading":
666
- return /* @__PURE__ */ jsx(HeadingView, { token });
700
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeadingView, { token });
667
701
  case "paragraph":
668
- return /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsx(InlineTokens, { tokens: token.tokens ?? [] }) });
702
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InlineTokens, { tokens: token.tokens ?? [] }) });
669
703
  case "code":
670
- return /* @__PURE__ */ jsx(CodeBlock, { token });
704
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CodeBlock, { token });
671
705
  case "blockquote":
672
- return /* @__PURE__ */ jsx(BlockquoteView, { token });
706
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockquoteView, { token });
673
707
  case "list":
674
- return /* @__PURE__ */ jsx(ListView, { token });
708
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListView, { token });
675
709
  case "hr":
676
- return /* @__PURE__ */ jsx(HrView, {});
710
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HrView, {});
677
711
  case "table":
678
- return /* @__PURE__ */ jsx(TableView, { token });
712
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableView, { token });
679
713
  case "html":
680
- return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[html]" });
714
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "[html]" });
681
715
  default:
682
716
  if ("text" in token && typeof token.text === "string") {
683
- return /* @__PURE__ */ jsx(Text, { children: token.text });
717
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: token.text });
684
718
  }
685
719
  return null;
686
720
  }
687
721
  });
688
722
  function HeadingView({ token }) {
689
- const styled = useMemo2(() => {
723
+ const styled = (0, import_react5.useMemo)(() => {
690
724
  const inner = renderInlineText(token.tokens);
691
725
  switch (token.depth) {
692
726
  case 1:
693
- return chalk2.bold.hex("#7dd3fc")(inner);
727
+ return source_default.bold.hex("#7dd3fc")(inner);
694
728
  case 2:
695
- return chalk2.bold.hex("#67e8f9")(inner);
729
+ return source_default.bold.hex("#67e8f9")(inner);
696
730
  case 3:
697
- return chalk2.bold.hex("#93c5fd")(inner);
731
+ return source_default.bold.hex("#93c5fd")(inner);
698
732
  default:
699
- return chalk2.italic.hex("#93c5fd")(inner);
733
+ return source_default.italic.hex("#93c5fd")(inner);
700
734
  }
701
735
  }, [token.depth, token.tokens]);
702
- return /* @__PURE__ */ jsx(Text, { children: styled });
736
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: styled });
703
737
  }
704
738
  function CodeBlock({ token }) {
705
- const styledSource = useMemo2(() => highlightCode(token.text, token.lang), [token.text, token.lang]);
706
- const lines = useMemo2(() => styledSource.split("\n"), [styledSource]);
739
+ const styledSource = (0, import_react5.useMemo)(() => highlightCode(token.text, token.lang), [token.text, token.lang]);
740
+ const lines = (0, import_react5.useMemo)(() => styledSource.split("\n"), [styledSource]);
707
741
  const langLabel = token.lang?.trim();
708
742
  const label = langLabel && langLabel.length > 0 ? langLabel : "code";
709
743
  return (
@@ -712,7 +746,7 @@ function CodeBlock({ token }) {
712
746
  // resizes can change that width without changing this memoized token.
713
747
  // Building a line from process.stdout.columns overflows those narrower
714
748
  // parents and desynchronizes the terminal's physical auto-wrap cursor.
715
- /* @__PURE__ */ jsx(
749
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
716
750
  Box_default,
717
751
  {
718
752
  flexDirection: "column",
@@ -722,28 +756,28 @@ function CodeBlock({ token }) {
722
756
  borderColor: "gray",
723
757
  borderText: { content: ` ${label} `, position: "top", align: "start", offset: 1 },
724
758
  opaque: true,
725
- children: /* @__PURE__ */ jsx(Box_default, { flexDirection: "column", paddingX: 1, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text, { color: "gray", wrap: "truncate-end", children: line.length > 0 ? line : " " }, i)) })
759
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", paddingX: 1, children: lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "gray", wrap: "truncate-end", children: line.length > 0 ? line : " " }, i)) })
726
760
  }
727
761
  )
728
762
  );
729
763
  }
730
764
  function BlockquoteView({ token }) {
731
- return /* @__PURE__ */ jsx(Box_default, { flexDirection: "column", children: token.tokens.map((child, i) => {
765
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", children: token.tokens.map((child, i) => {
732
766
  const inline = "tokens" in child ? child.tokens ?? [] : [];
733
- return /* @__PURE__ */ jsxs(Text, { children: [
734
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2502 " }),
735
- /* @__PURE__ */ jsx(InlineTokens, { tokens: inline })
767
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
768
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "gray", children: "\u2502 " }),
769
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InlineTokens, { tokens: inline })
736
770
  ] }, i);
737
771
  }) });
738
772
  }
739
773
  function HrView() {
740
774
  const { stdout } = useStdout();
741
775
  const width = Math.max(8, (stdout?.columns ?? 80) - 4);
742
- return /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2500".repeat(width) });
776
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "gray", children: "\u2500".repeat(width) });
743
777
  }
744
778
  function ListView({ token }) {
745
779
  const start = typeof token.start === "number" ? token.start : 1;
746
- return /* @__PURE__ */ jsx(Box_default, { flexDirection: "column", children: token.items.map((item, i) => /* @__PURE__ */ jsx(ListItemView, { item, index: start + i, ordered: token.ordered }, i)) });
780
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexDirection: "column", children: token.items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListItemView, { item, index: start + i, ordered: token.ordered }, i)) });
747
781
  }
748
782
  function ListItemView({
749
783
  item,
@@ -769,28 +803,28 @@ function ListItemView({
769
803
  blockTokens.push(child);
770
804
  }
771
805
  }
772
- return /* @__PURE__ */ jsxs(Box_default, { flexDirection: "column", children: [
773
- /* @__PURE__ */ jsxs(Text, { children: [
774
- /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
806
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
807
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
808
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: "cyan", children: [
775
809
  bullet,
776
810
  " "
777
811
  ] }),
778
812
  inlineTokens.map((child, i) => {
779
813
  if (child.type === "paragraph") {
780
- return /* @__PURE__ */ jsx(InlineTokens, { tokens: child.tokens ?? [] }, i);
814
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InlineTokens, { tokens: child.tokens ?? [] }, i);
781
815
  }
782
816
  const tokens = child.tokens ?? [];
783
- return tokens.length > 0 ? /* @__PURE__ */ jsx(InlineTokens, { tokens }, i) : /* @__PURE__ */ jsx(Text, { children: child.text }, i);
817
+ return tokens.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InlineTokens, { tokens }, i) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: child.text }, i);
784
818
  })
785
819
  ] }),
786
- blockTokens.map((child, i) => /* @__PURE__ */ jsx(Box_default, { marginLeft: 2, children: /* @__PURE__ */ jsx(BlockToken, { token: child }) }, i))
820
+ blockTokens.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockToken, { token: child }) }, i))
787
821
  ] });
788
822
  }
789
823
  function TableView({ token }) {
790
824
  const { stdout } = useStdout();
791
825
  const maxWidth = stdout?.columns ?? 80;
792
826
  const colCount = token.header.length;
793
- if (colCount === 0) return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[empty table]" });
827
+ if (colCount === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "[empty table]" });
794
828
  const colWidth = Math.max(8, Math.floor((maxWidth - colCount * 3) / colCount));
795
829
  const pad = (value, w, align) => {
796
830
  const stripped = stripAnsi2(value);
@@ -812,33 +846,33 @@ function TableView({ token }) {
812
846
  if (align === "center") return ":" + "\u2500".repeat(colWidth - 2) + ":";
813
847
  return "\u2500".repeat(colWidth);
814
848
  });
815
- return /* @__PURE__ */ jsxs(Box_default, { flexDirection: "column", children: [
816
- /* @__PURE__ */ jsx(Text, { children: token.header.map((cell, i) => pad(cell.text, colWidth, cell.align ?? "left")).join(" \u2502 ") }),
817
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: separator.join(" \u2502 ") }),
818
- token.rows.map((row, ri) => /* @__PURE__ */ jsx(Text, { children: row.map((cell, i) => pad(cell.text, colWidth, token.header[i]?.align ?? "left")).join(" \u2502 ") }, ri))
849
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", children: [
850
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: token.header.map((cell, i) => pad(cell.text, colWidth, cell.align ?? "left")).join(" \u2502 ") }),
851
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: separator.join(" \u2502 ") }),
852
+ token.rows.map((row, ri) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: row.map((cell, i) => pad(cell.text, colWidth, token.header[i]?.align ?? "left")).join(" \u2502 ") }, ri))
819
853
  ] });
820
854
  }
821
855
  function InlineTokens({ tokens }) {
822
- return /* @__PURE__ */ jsx(Text, { children: tokens.map((token, i) => /* @__PURE__ */ jsx(InlineToken, { token }, i)) });
856
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: tokens.map((token, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InlineToken, { token }, i)) });
823
857
  }
824
858
  function InlineToken({ token }) {
825
859
  switch (token.type) {
826
860
  case "text":
827
- return /* @__PURE__ */ jsx(Text, { children: token.raw ?? token.text });
861
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: token.raw ?? token.text });
828
862
  case "strong":
829
- return /* @__PURE__ */ jsx(Text, { bold: true, children: renderInlineText(token.tokens) });
863
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, children: renderInlineText(token.tokens) });
830
864
  case "em":
831
- return /* @__PURE__ */ jsx(Text, { italic: true, children: renderInlineText(token.tokens) });
865
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { italic: true, children: renderInlineText(token.tokens) });
832
866
  case "del":
833
- return /* @__PURE__ */ jsx(Text, { strikethrough: true, children: renderInlineText(token.tokens) });
867
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { strikethrough: true, children: renderInlineText(token.tokens) });
834
868
  case "codespan":
835
- return /* @__PURE__ */ jsx(Text, { color: "black", backgroundColor: "gray", children: token.text });
869
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "black", backgroundColor: "gray", children: token.text });
836
870
  case "link": {
837
871
  const link = token;
838
872
  const inner = renderInlineText(link.tokens);
839
- return /* @__PURE__ */ jsxs(Text, { children: [
873
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
840
874
  inner,
841
- /* @__PURE__ */ jsxs(Text, { dimColor: true, color: "blue", children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, color: "blue", children: [
842
876
  " (",
843
877
  link.href,
844
878
  ")"
@@ -847,21 +881,21 @@ function InlineToken({ token }) {
847
881
  }
848
882
  case "image": {
849
883
  const img = token;
850
- return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
884
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
851
885
  "[image: ",
852
886
  img.text,
853
887
  "]"
854
888
  ] });
855
889
  }
856
890
  case "br":
857
- return /* @__PURE__ */ jsx(Text, { children: "\n" });
891
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: "\n" });
858
892
  case "escape":
859
- return /* @__PURE__ */ jsx(Text, { children: token.text });
893
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: token.text });
860
894
  case "html":
861
895
  return null;
862
896
  default:
863
897
  if ("text" in token && typeof token.text === "string") {
864
- return /* @__PURE__ */ jsx(Text, { children: token.text });
898
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: token.text });
865
899
  }
866
900
  return null;
867
901
  }
@@ -882,13 +916,13 @@ function inlineTokenToString(token) {
882
916
  case "text":
883
917
  return token.raw ?? token.text;
884
918
  case "strong":
885
- return chalk2.bold(renderInlineText(token.tokens));
919
+ return source_default.bold(renderInlineText(token.tokens));
886
920
  case "em":
887
- return chalk2.italic(renderInlineText(token.tokens));
921
+ return source_default.italic(renderInlineText(token.tokens));
888
922
  case "del":
889
- return chalk2.strikethrough(renderInlineText(token.tokens));
923
+ return source_default.strikethrough(renderInlineText(token.tokens));
890
924
  case "codespan":
891
- return chalk2.bgGray.black(` ${token.text} `);
925
+ return source_default.bgGray.black(` ${token.text} `);
892
926
  case "escape":
893
927
  return token.text;
894
928
  case "br":
@@ -896,7 +930,7 @@ function inlineTokenToString(token) {
896
930
  case "link": {
897
931
  const link = token;
898
932
  const inner = renderInlineText(link.tokens);
899
- return `${inner} ${chalk2.blue.underline.dim(`(${link.href})`)}`;
933
+ return `${inner} ${source_default.blue.underline.dim(`(${link.href})`)}`;
900
934
  }
901
935
  default:
902
936
  if ("text" in token && typeof token.text === "string") return token.text;
@@ -905,11 +939,11 @@ function inlineTokenToString(token) {
905
939
  }
906
940
 
907
941
  // src/ui/assistant-text.tsx
908
- import { jsx as jsx2 } from "react/jsx-runtime";
942
+ var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
909
943
  function AssistantTextInner({ text }) {
910
- return /* @__PURE__ */ jsx2(MarkdownView, { text });
944
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MarkdownView, { text });
911
945
  }
912
- var AssistantText = React2.memo(AssistantTextInner);
946
+ var AssistantText = import_react6.default.memo(AssistantTextInner);
913
947
 
914
948
  // src/ui/signals.ts
915
949
  function createSessionInterruptHandler(getSession, shutdown, options) {
@@ -970,8 +1004,8 @@ function wrapPromptInput(input, codePointCursor, options) {
970
1004
  }
971
1005
 
972
1006
  // src/ui/task-progress.tsx
973
- import { useRef as useRef3 } from "react";
974
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1007
+ var import_react7 = __toESM(require_react(), 1);
1008
+ var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
975
1009
  function TaskStatusLine({
976
1010
  block,
977
1011
  interactive,
@@ -983,8 +1017,8 @@ function TaskStatusLine({
983
1017
  const { stdout } = useStdout();
984
1018
  const foreground = interactive && (block.activity === "model" || block.task?.role === "main");
985
1019
  const [ref, time] = useAnimationFrame(running && foreground ? 120 : null);
986
- const startedAt = useRef3(void 0);
987
- const previousState = useRef3(block.state);
1020
+ const startedAt = (0, import_react7.useRef)(void 0);
1021
+ const previousState = (0, import_react7.useRef)(block.state);
988
1022
  if (running && (startedAt.current === void 0 || previousState.current !== "running")) startedAt.current = time;
989
1023
  if (!running) startedAt.current = void 0;
990
1024
  previousState.current = block.state;
@@ -1005,7 +1039,7 @@ function TaskStatusLine({
1005
1039
  }
1006
1040
  const thinking = block.thinkingText;
1007
1041
  const thinkingVisible = running && block.activity === "model" && thinking !== void 0 && thinking.length > 0;
1008
- const thinkingScroll = useRef3({ start: 0, lastTime: time });
1042
+ const thinkingScroll = (0, import_react7.useRef)({ start: 0, lastTime: time });
1009
1043
  if (!thinkingVisible) {
1010
1044
  thinkingScroll.current = { start: 0, lastTime: time };
1011
1045
  }
@@ -1030,28 +1064,28 @@ function TaskStatusLine({
1030
1064
  ...metaLabel === void 0 ? [] : [{ text: ` ${metaLabel}`, color: metaColor ?? "ansi:blackBright" }]
1031
1065
  ];
1032
1066
  const boundedText = textWidth === void 0 || maxTextLines === void 0 ? void 0 : limitTaskTextSegments(textSegments, textWidth, maxTextLines).segments;
1033
- return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "column", width: "100%", children: [
1034
- /* @__PURE__ */ jsx3(Box_default, { ref, flexDirection: "row", width: "100%", children: boundedText === void 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
1035
- /* @__PURE__ */ jsxs2(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: [
1067
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", width: "100%", children: [
1068
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { ref, flexDirection: "row", width: "100%", children: boundedText === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1069
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: [
1036
1070
  presentation.glyph,
1037
1071
  " "
1038
1072
  ] }),
1039
- badge ? /* @__PURE__ */ jsxs2(Text, { color: badgeColor, children: [
1073
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: badgeColor, children: [
1040
1074
  badge,
1041
1075
  " "
1042
1076
  ] }) : null,
1043
- /* @__PURE__ */ jsx3(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: before }),
1044
- statusLabel !== void 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
1045
- /* @__PURE__ */ jsx3(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: " \xB7 " }),
1046
- /* @__PURE__ */ jsx3(Text, { color: statusColor ?? presentation.color, children: statusLabel })
1077
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: before }),
1078
+ statusLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1079
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: " \xB7 " }),
1080
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: statusColor ?? presentation.color, children: statusLabel })
1047
1081
  ] }) : null,
1048
- after ? /* @__PURE__ */ jsx3(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: after }) : null,
1049
- metaLabel === void 0 ? null : /* @__PURE__ */ jsxs2(Text, { color: metaColor ?? "ansi:blackBright", children: [
1082
+ after ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { ...presentation.color === void 0 ? {} : { color: presentation.color }, children: after }) : null,
1083
+ metaLabel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: metaColor ?? "ansi:blackBright", children: [
1050
1084
  " ",
1051
1085
  metaLabel
1052
1086
  ] })
1053
- ] }) : /* @__PURE__ */ jsx3(Text, { children: boundedText.map((segment, index) => /* @__PURE__ */ jsx3(Text, { ...segment.color === void 0 ? {} : { color: segment.color }, children: segment.text }, index)) }) }),
1054
- thinkingLine === void 0 ? null : /* @__PURE__ */ jsx3(ThinkingLineView, { text: thinkingLine })
1087
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: boundedText.map((segment, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { ...segment.color === void 0 ? {} : { color: segment.color }, children: segment.text }, index)) }) }),
1088
+ thinkingLine === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ThinkingLineView, { text: thinkingLine })
1055
1089
  ] });
1056
1090
  }
1057
1091
  function limitTaskTextSegments(segments, width, maxLines = 3) {
@@ -1116,9 +1150,9 @@ function limitTaskTextSegments(segments, width, maxLines = 3) {
1116
1150
  var THINKING_RAIL = "#416f84";
1117
1151
  var THINKING_TEXT = "#91a0a8";
1118
1152
  function ThinkingLineView({ text }) {
1119
- return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", children: [
1120
- /* @__PURE__ */ jsx3(Text, { color: THINKING_RAIL, children: "\u2502 " }),
1121
- /* @__PURE__ */ jsx3(Text, { color: THINKING_TEXT, wrap: "truncate-end", children: text })
1153
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "row", children: [
1154
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: THINKING_RAIL, children: "\u2502 " }),
1155
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: THINKING_TEXT, wrap: "truncate-end", children: text })
1122
1156
  ] });
1123
1157
  }
1124
1158
  var SPLIT_TRACK_MIN_COLUMNS = 96;
@@ -1142,7 +1176,7 @@ function TaskProgressPanel({
1142
1176
  const hoverProps = (track) => ({
1143
1177
  onMouseEnter: () => onHoverChange?.(track)
1144
1178
  });
1145
- return /* @__PURE__ */ jsx3(
1179
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1146
1180
  Box_default,
1147
1181
  {
1148
1182
  flexDirection: "column",
@@ -1150,7 +1184,7 @@ function TaskProgressPanel({
1150
1184
  width: "100%",
1151
1185
  maxHeight,
1152
1186
  onMouseLeave: () => onHoverChange?.(null),
1153
- children: split ? /* @__PURE__ */ jsx3(
1187
+ children: split ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1154
1188
  SplitTracks,
1155
1189
  {
1156
1190
  taskBlocks,
@@ -1162,7 +1196,7 @@ function TaskProgressPanel({
1162
1196
  subagentScrollRef,
1163
1197
  hoverProps
1164
1198
  }
1165
- ) : hasTasks && hasSubagents ? /* @__PURE__ */ jsx3(
1199
+ ) : hasTasks && hasSubagents ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1166
1200
  StackedTracks,
1167
1201
  {
1168
1202
  taskBlocks,
@@ -1174,7 +1208,7 @@ function TaskProgressPanel({
1174
1208
  subagentScrollRef,
1175
1209
  hoverProps
1176
1210
  }
1177
- ) : /* @__PURE__ */ jsx3(
1211
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1178
1212
  SingleTrack,
1179
1213
  {
1180
1214
  role: hasTasks ? "main" : "subagent",
@@ -1203,14 +1237,14 @@ function SplitTracks({
1203
1237
  const availableWidth = columns - SPLIT_TRACK_GUTTER_COLUMNS;
1204
1238
  const leftWidth = Math.max(1, Math.floor(availableWidth * SPLIT_TRACK_MAIN_RATIO));
1205
1239
  const rightWidth = Math.max(1, availableWidth - leftWidth);
1206
- return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1207
- /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", width: "100%", children: [
1208
- /* @__PURE__ */ jsx3(Box_default, { width: leftWidth, ...hoverProps("main"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "main", count: taskBlocks.length, width: leftWidth }) }),
1209
- /* @__PURE__ */ jsx3(Text, { color: "ansi:white", children: "\u2500\u252C\u2500" }),
1210
- /* @__PURE__ */ jsx3(Box_default, { width: rightWidth, ...hoverProps("subagent"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "subagent", count: subagentBlocks.length, width: rightWidth }) })
1240
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "row", width: "100%", children: [
1242
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: leftWidth, ...hoverProps("main"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrackHeader, { role: "main", count: taskBlocks.length, width: leftWidth }) }),
1243
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "ansi:white", children: "\u2500\u252C\u2500" }),
1244
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: rightWidth, ...hoverProps("subagent"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrackHeader, { role: "subagent", count: subagentBlocks.length, width: rightWidth }) })
1211
1245
  ] }),
1212
- contentHeight <= 0 ? null : /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "row", width: "100%", height: contentHeight, children: [
1213
- /* @__PURE__ */ jsx3(Box_default, { width: leftWidth, minWidth: 0, flexDirection: "column", ...hoverProps("main"), children: /* @__PURE__ */ jsx3(
1246
+ contentHeight <= 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "row", width: "100%", height: contentHeight, children: [
1247
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: leftWidth, minWidth: 0, flexDirection: "column", ...hoverProps("main"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1214
1248
  TrackScrollBox,
1215
1249
  {
1216
1250
  ref: mainScrollRef,
@@ -1221,8 +1255,8 @@ function SplitTracks({
1221
1255
  maxTextLines: 2
1222
1256
  }
1223
1257
  ) }),
1224
- /* @__PURE__ */ jsx3(TrackDivider, { height: contentHeight }),
1225
- /* @__PURE__ */ jsx3(Box_default, { width: rightWidth, minWidth: 0, flexDirection: "column", ...hoverProps("subagent"), children: /* @__PURE__ */ jsx3(
1258
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrackDivider, { height: contentHeight }),
1259
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: rightWidth, minWidth: 0, flexDirection: "column", ...hoverProps("subagent"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1226
1260
  TrackScrollBox,
1227
1261
  {
1228
1262
  ref: subagentScrollRef,
@@ -1247,12 +1281,12 @@ function StackedTracks({
1247
1281
  hoverProps
1248
1282
  }) {
1249
1283
  if (height <= 1) {
1250
- return /* @__PURE__ */ jsx3(Box_default, { ...hoverProps("main"), children: /* @__PURE__ */ jsx3(TrackHeader, { role: "main", count: taskBlocks.length, width: columns }) });
1284
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { ...hoverProps("main"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrackHeader, { role: "main", count: taskBlocks.length, width: columns }) });
1251
1285
  }
1252
1286
  const mainHeight = Math.ceil(height / 2);
1253
1287
  const subagentHeight = Math.floor(height / 2);
1254
- return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1255
- /* @__PURE__ */ jsx3(
1288
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1289
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1256
1290
  SingleTrack,
1257
1291
  {
1258
1292
  role: "main",
@@ -1264,7 +1298,7 @@ function StackedTracks({
1264
1298
  hoverProps
1265
1299
  }
1266
1300
  ),
1267
- /* @__PURE__ */ jsx3(
1301
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1268
1302
  SingleTrack,
1269
1303
  {
1270
1304
  role: "subagent",
@@ -1288,9 +1322,9 @@ function SingleTrack({
1288
1322
  hoverProps
1289
1323
  }) {
1290
1324
  const contentHeight = Math.max(0, height - 1);
1291
- return /* @__PURE__ */ jsxs2(Box_default, { flexDirection: "column", width: "100%", height, ...hoverProps(role), children: [
1292
- /* @__PURE__ */ jsx3(TrackHeader, { role, count: blocks.length, width }),
1293
- contentHeight <= 0 ? null : /* @__PURE__ */ jsx3(
1325
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", width: "100%", height, ...hoverProps(role), children: [
1326
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrackHeader, { role, count: blocks.length, width }),
1327
+ contentHeight <= 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1294
1328
  TrackScrollBox,
1295
1329
  {
1296
1330
  ref: scrollRef,
@@ -1311,7 +1345,7 @@ function TrackScrollBox({
1311
1345
  width,
1312
1346
  maxTextLines
1313
1347
  }) {
1314
- return /* @__PURE__ */ jsx3(
1348
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1315
1349
  ScrollBox_default,
1316
1350
  {
1317
1351
  ...ref === void 0 ? {} : { ref },
@@ -1321,7 +1355,7 @@ function TrackScrollBox({
1321
1355
  height,
1322
1356
  maxHeight: height,
1323
1357
  paddingX: 1,
1324
- children: blocks.map((block) => /* @__PURE__ */ jsx3(
1358
+ children: blocks.map((block) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1325
1359
  TaskStatusLine,
1326
1360
  {
1327
1361
  block,
@@ -1339,10 +1373,10 @@ function TrackHeader({ role, count, width }) {
1339
1373
  const label = role === "main" ? `task plan (${count})` : `subagents (${count})`;
1340
1374
  const prefix = `\u2500\u2500 ${label} `;
1341
1375
  const line = prefix.length >= width ? prefix.slice(0, Math.max(0, width)) : `${prefix}${"\u2500".repeat(width - prefix.length)}`;
1342
- return /* @__PURE__ */ jsx3(Text, { color: "ansi:white", wrap: "truncate-end", children: line });
1376
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "ansi:white", wrap: "truncate-end", children: line });
1343
1377
  }
1344
1378
  function TrackDivider({ height }) {
1345
- return /* @__PURE__ */ jsx3(Box_default, { flexDirection: "column", width: SPLIT_TRACK_GUTTER_COLUMNS, flexShrink: 0, children: Array.from({ length: height }, (_, index) => /* @__PURE__ */ jsx3(Text, { color: "ansi:white", children: " \u2502 " }, index)) });
1379
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { flexDirection: "column", width: SPLIT_TRACK_GUTTER_COLUMNS, flexShrink: 0, children: Array.from({ length: height }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "ansi:white", children: " \u2502 " }, index)) });
1346
1380
  }
1347
1381
 
1348
1382
  // src/ui/file-diff-style.ts
@@ -1364,6 +1398,18 @@ var CANDIDATE_KIND_PRIORITY = {
1364
1398
  command: 1,
1365
1399
  tool: 2
1366
1400
  };
1401
+ var SLASH_DESCRIPTION_CHAR_LIMIT = 240;
1402
+ function normalizeSlashDescription(description) {
1403
+ const singleLine = description.replace(/\s+/gu, " ").trim();
1404
+ const points = [...singleLine];
1405
+ if (points.length <= SLASH_DESCRIPTION_CHAR_LIMIT) return singleLine;
1406
+ return `${points.slice(0, SLASH_DESCRIPTION_CHAR_LIMIT - 1).join("")}\u2026`;
1407
+ }
1408
+ function optionalDescription(description) {
1409
+ if (description === void 0) return void 0;
1410
+ const normalized = normalizeSlashDescription(description);
1411
+ return normalized.length === 0 ? void 0 : normalized;
1412
+ }
1367
1413
  function slashCandidatePresentation(selected) {
1368
1414
  return {
1369
1415
  marker: selected ? "\u203A " : " ",
@@ -1374,16 +1420,22 @@ function slashCandidatePresentation(selected) {
1374
1420
  function buildSlashCandidates(commands, plugins, skills, tools = []) {
1375
1421
  const candidates = /* @__PURE__ */ new Map();
1376
1422
  for (const command of commands) {
1377
- candidates.set(command.name, { name: command.name, kind: "command", description: command.description });
1423
+ candidates.set(command.name, {
1424
+ name: command.name,
1425
+ kind: "command",
1426
+ description: normalizeSlashDescription(command.description)
1427
+ });
1378
1428
  }
1379
1429
  for (const plugin of plugins) {
1380
1430
  if (!candidates.has(plugin.name)) {
1381
- candidates.set(plugin.name, plugin.description === void 0 ? { name: plugin.name, kind: "plugin" } : { name: plugin.name, kind: "plugin", description: plugin.description });
1431
+ const description = optionalDescription(plugin.description);
1432
+ candidates.set(plugin.name, description === void 0 ? { name: plugin.name, kind: "plugin" } : { name: plugin.name, kind: "plugin", description });
1382
1433
  }
1383
1434
  }
1384
1435
  for (const tool of tools) {
1385
1436
  if (!candidates.has(tool.name)) {
1386
- candidates.set(tool.name, tool.description === void 0 ? { name: tool.name, kind: "tool" } : { name: tool.name, kind: "tool", description: tool.description });
1437
+ const description = optionalDescription(tool.description);
1438
+ candidates.set(tool.name, description === void 0 ? { name: tool.name, kind: "tool" } : { name: tool.name, kind: "tool", description });
1387
1439
  }
1388
1440
  }
1389
1441
  for (const skill of skills) {
@@ -1391,7 +1443,7 @@ function buildSlashCandidates(commands, plugins, skills, tools = []) {
1391
1443
  candidates.set(skill.name, {
1392
1444
  name: skill.name,
1393
1445
  kind: "skill",
1394
- description: skill.description,
1446
+ description: normalizeSlashDescription(skill.description),
1395
1447
  source: skill.source
1396
1448
  });
1397
1449
  }
@@ -1572,7 +1624,7 @@ function comparePaths(left, right) {
1572
1624
  }
1573
1625
 
1574
1626
  // src/ui/welcome.tsx
1575
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1627
+ var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
1576
1628
  var WIDE_WELCOME_COLUMNS = 72;
1577
1629
  var FLAVOR_ACCENT = "#67D4FF";
1578
1630
  var FLAVOR_WORDMARK = [
@@ -1588,7 +1640,7 @@ function WelcomeCard({
1588
1640
  columns
1589
1641
  }) {
1590
1642
  const wide = Math.max(1, Math.floor(columns)) >= WIDE_WELCOME_COLUMNS;
1591
- const updateHint = updateTo === void 0 ? null : /* @__PURE__ */ jsxs3(Text, { color: "yellowBright", wrap: "wrap", children: [
1643
+ const updateHint = updateTo === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "yellowBright", wrap: "wrap", children: [
1592
1644
  "\u25B2 ",
1593
1645
  "Update available: v",
1594
1646
  packageVersion(),
@@ -1598,8 +1650,8 @@ function WelcomeCard({
1598
1650
  updateTo,
1599
1651
  "\nRun: flavor update"
1600
1652
  ] });
1601
- return /* @__PURE__ */ jsx4(Box_default, { width: "100%", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: wide ? /* @__PURE__ */ jsxs3(Box_default, { width: "100%", flexDirection: "row", children: [
1602
- /* @__PURE__ */ jsxs3(
1653
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: "100%", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: wide ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { width: "100%", flexDirection: "row", children: [
1654
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1603
1655
  Box_default,
1604
1656
  {
1605
1657
  width: "36%",
@@ -1612,55 +1664,55 @@ function WelcomeCard({
1612
1664
  borderColor: "yellow",
1613
1665
  paddingRight: 1,
1614
1666
  children: [
1615
- /* @__PURE__ */ jsx4(Text, { bold: true, color: "yellowBright", children: "Welcome back!" }),
1616
- /* @__PURE__ */ jsx4(Text, { color: FLAVOR_ACCENT, children: FLAVOR_WORDMARK }),
1617
- serviceName === void 0 ? null : /* @__PURE__ */ jsx4(Text, { color: "cyan", wrap: "truncate-end", children: serviceName }),
1618
- /* @__PURE__ */ jsx4(Text, { dimColor: true, wrap: "truncate-end", children: model }),
1619
- /* @__PURE__ */ jsx4(Text, { dimColor: true, wrap: "truncate-end", children: workspaceName }),
1620
- /* @__PURE__ */ jsxs3(Text, { dimColor: true, wrap: "truncate-end", children: [
1667
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { bold: true, color: "yellowBright", children: "Welcome back!" }),
1668
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: FLAVOR_ACCENT, children: FLAVOR_WORDMARK }),
1669
+ serviceName === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", wrap: "truncate-end", children: serviceName }),
1670
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, wrap: "truncate-end", children: model }),
1671
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, wrap: "truncate-end", children: workspaceName }),
1672
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { dimColor: true, wrap: "truncate-end", children: [
1621
1673
  "v",
1622
1674
  packageVersion()
1623
1675
  ] })
1624
1676
  ]
1625
1677
  }
1626
1678
  ),
1627
- /* @__PURE__ */ jsxs3(Box_default, { flexGrow: 1, flexDirection: "column", paddingLeft: 1, children: [
1628
- /* @__PURE__ */ jsx4(Text, { bold: true, color: "yellowBright", children: "Tips for getting started" }),
1629
- /* @__PURE__ */ jsxs3(Text, { children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexGrow: 1, flexDirection: "column", paddingLeft: 1, children: [
1680
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { bold: true, color: "yellowBright", children: "Tips for getting started" }),
1681
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { children: [
1630
1682
  "Run ",
1631
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/init" }),
1683
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "/init" }),
1632
1684
  " to create or refresh FLAVOR.md"
1633
1685
  ] }),
1634
- /* @__PURE__ */ jsxs3(Text, { children: [
1686
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { children: [
1635
1687
  "Type ",
1636
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "@" }),
1688
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "@" }),
1637
1689
  " to attach a project file"
1638
1690
  ] }),
1639
- /* @__PURE__ */ jsx4(Box_default, { height: 1 }),
1640
- /* @__PURE__ */ jsx4(Text, { bold: true, color: "yellowBright", children: "Quick commands" }),
1641
- /* @__PURE__ */ jsxs3(Text, { children: [
1642
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/help" }),
1691
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { height: 1 }),
1692
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { bold: true, color: "yellowBright", children: "Quick commands" }),
1693
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { children: [
1694
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "/help" }),
1643
1695
  " \xB7 ",
1644
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/config" }),
1696
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "/config" }),
1645
1697
  " \xB7 ",
1646
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/tasks" })
1698
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "/tasks" })
1647
1699
  ] }),
1648
1700
  updateHint
1649
1701
  ] })
1650
- ] }) : /* @__PURE__ */ jsxs3(Box_default, { width: "100%", flexDirection: "column", children: [
1651
- /* @__PURE__ */ jsx4(Text, { bold: true, color: FLAVOR_ACCENT, children: "\u25C6 Flavor Code" }),
1652
- /* @__PURE__ */ jsx4(Text, { children: "Welcome back!" }),
1653
- /* @__PURE__ */ jsxs3(Text, { dimColor: true, wrap: "truncate-end", children: [
1702
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { width: "100%", flexDirection: "column", children: [
1703
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { bold: true, color: FLAVOR_ACCENT, children: "\u25C6 Flavor Code" }),
1704
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { children: "Welcome back!" }),
1705
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { dimColor: true, wrap: "truncate-end", children: [
1654
1706
  model,
1655
1707
  " \xB7 ",
1656
1708
  workspaceName,
1657
1709
  " \xB7 v",
1658
1710
  packageVersion()
1659
1711
  ] }),
1660
- /* @__PURE__ */ jsxs3(Text, { children: [
1661
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/init" }),
1712
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { children: [
1713
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "/init" }),
1662
1714
  " setup \xB7 ",
1663
- /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/help" }),
1715
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "/help" }),
1664
1716
  " commands"
1665
1717
  ] }),
1666
1718
  updateHint
@@ -1779,6 +1831,16 @@ function isCode(error, code) {
1779
1831
  // src/ui/clipboard-image.ts
1780
1832
  var CLIPBOARD_TIMEOUT_MS = 1e4;
1781
1833
  var NO_IMAGE_EXIT_CODE = 3;
1834
+ var NO_TEXT_EXIT_CODE = 3;
1835
+ var CLIPBOARD_IMAGE_MAX_BUFFER = Math.ceil(DEFAULT_MAX_IMAGE_BYTES / 3) * 4 + 64 * 1024;
1836
+ var READ_WINDOWS_CLIPBOARD_TEXT = String.raw`
1837
+ Add-Type -AssemblyName System.Windows.Forms
1838
+ if (-not [Windows.Forms.Clipboard]::ContainsText()) { exit 3 }
1839
+ $text = [Windows.Forms.Clipboard]::GetText()
1840
+ if ([string]::IsNullOrEmpty($text)) { exit 3 }
1841
+ $bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
1842
+ [Console]::Out.Write([Convert]::ToBase64String($bytes))
1843
+ `.trim();
1782
1844
  var READ_WINDOWS_CLIPBOARD_IMAGE = String.raw`
1783
1845
  Add-Type -AssemblyName System.Windows.Forms
1784
1846
  Add-Type -AssemblyName System.Drawing
@@ -1843,8 +1905,47 @@ try {
1843
1905
  $.exit(3);
1844
1906
  }
1845
1907
  `.trim();
1846
- function shouldReadClipboardImage(input, key, isPasted) {
1847
- return (key.ctrl || key.meta === true) && input.toLowerCase() === "v" || isPasted && input.length === 0;
1908
+ function clipboardPasteIntent(input, key, isPasted, platform = process.platform) {
1909
+ if (isPasted) return input.length === 0 ? "immediate" : void 0;
1910
+ const pasteModifier = platform === "darwin" ? key.super === true : key.ctrl;
1911
+ return pasteModifier && input.toLowerCase() === "v" ? "deferred" : void 0;
1912
+ }
1913
+ async function readClipboardContent(options = {}) {
1914
+ const text = await readClipboardText(options);
1915
+ if (text !== void 0) return { kind: "text", text };
1916
+ const attachment = await readClipboardImage(options);
1917
+ return attachment === void 0 ? void 0 : { kind: "image", attachment };
1918
+ }
1919
+ async function readClipboardText(options = {}) {
1920
+ const platform = options.platform ?? process.platform;
1921
+ if (platform === "win32") return readWindowsClipboardText({ ...options, platform });
1922
+ if (platform === "darwin") return readMacClipboardText({ ...options, platform });
1923
+ throw new Error("Pasting native clipboard content is currently supported on Windows and macOS only");
1924
+ }
1925
+ async function readWindowsClipboardText(options = {}) {
1926
+ const platform = options.platform ?? process.platform;
1927
+ if (platform !== "win32") throw new Error("Reading clipboard text this way is supported on Windows only");
1928
+ const result = await (options.run ?? execFileNoThrow)(
1929
+ "powershell.exe",
1930
+ ["-NoProfile", "-NonInteractive", "-STA", "-Command", READ_WINDOWS_CLIPBOARD_TEXT],
1931
+ { timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
1932
+ );
1933
+ if (result.code === NO_TEXT_EXIT_CODE) return void 0;
1934
+ if (result.code !== 0) throw clipboardReadError("text", result);
1935
+ const encoded = result.stdout.trim();
1936
+ if (encoded.length === 0) return void 0;
1937
+ return Buffer.from(encoded, "base64").toString("utf8") || void 0;
1938
+ }
1939
+ async function readMacClipboardText(options = {}) {
1940
+ const platform = options.platform ?? process.platform;
1941
+ if (platform !== "darwin") throw new Error("Reading clipboard text this way is supported on macOS only");
1942
+ const result = await (options.run ?? execFileNoThrow)(
1943
+ "pbpaste",
1944
+ ["-Prefer", "txt"],
1945
+ { timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
1946
+ );
1947
+ if (result.code !== 0 || result.stdout.length === 0) return void 0;
1948
+ return result.stdout;
1848
1949
  }
1849
1950
  async function readClipboardImage(options = {}) {
1850
1951
  const platform = options.platform ?? process.platform;
@@ -1860,7 +1961,7 @@ async function readWindowsClipboardImage(options = {}) {
1860
1961
  const result = await (options.run ?? execFileNoThrow)(
1861
1962
  "powershell.exe",
1862
1963
  ["-NoProfile", "-NonInteractive", "-STA", "-Command", READ_WINDOWS_CLIPBOARD_IMAGE],
1863
- { timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
1964
+ { timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false, maxBuffer: CLIPBOARD_IMAGE_MAX_BUFFER }
1864
1965
  );
1865
1966
  return attachmentFromResult(result, options.now?.() ?? /* @__PURE__ */ new Date());
1866
1967
  }
@@ -1872,15 +1973,14 @@ async function readMacClipboardImage(options = {}) {
1872
1973
  const result = await (options.run ?? execFileNoThrow)(
1873
1974
  "osascript",
1874
1975
  ["-l", "JavaScript", "-e", READ_MAC_CLIPBOARD_IMAGE],
1875
- { timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
1976
+ { timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false, maxBuffer: CLIPBOARD_IMAGE_MAX_BUFFER }
1876
1977
  );
1877
1978
  return attachmentFromResult(result, options.now?.() ?? /* @__PURE__ */ new Date());
1878
1979
  }
1879
1980
  function attachmentFromResult(result, now) {
1880
1981
  if (result.code === NO_IMAGE_EXIT_CODE) return void 0;
1881
1982
  if (result.code !== 0) {
1882
- const detail = result.stderr.trim() || result.error?.trim();
1883
- throw new Error(detail ? `Could not read the clipboard image: ${detail}` : "Could not read the clipboard image");
1983
+ throw clipboardReadError("image", result);
1884
1984
  }
1885
1985
  const dataBase64 = result.stdout.trim();
1886
1986
  if (dataBase64.length === 0) return void 0;
@@ -1890,6 +1990,10 @@ function attachmentFromResult(result, now) {
1890
1990
  dataBase64
1891
1991
  };
1892
1992
  }
1993
+ function clipboardReadError(kind, result) {
1994
+ const detail = result.stderr.trim() || result.error?.trim();
1995
+ return new Error(detail ? `Could not read the clipboard ${kind}: ${detail}` : `Could not read the clipboard ${kind}`);
1996
+ }
1893
1997
  function timestamp(value) {
1894
1998
  const year = value.getUTCFullYear();
1895
1999
  const month = String(value.getUTCMonth() + 1).padStart(2, "0");
@@ -1944,8 +2048,9 @@ var PromptHistoryStore = class {
1944
2048
  };
1945
2049
 
1946
2050
  // src/ui/app.tsx
1947
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2051
+ var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
1948
2052
  var HISTORY_CAP = 200;
2053
+ var CLIPBOARD_SHORTCUT_FALLBACK_MS = 300;
1949
2054
  var BUILTIN_SLASH_CANDIDATES = MVP_COMMANDS.map((name) => ({ name, description: COMMAND_DESCRIPTIONS[name] }));
1950
2055
  var PROMPT_HORIZONTAL_PADDING = 1;
1951
2056
  function clonePromptDraft(state) {
@@ -1997,16 +2102,24 @@ function isPlatformShortcut(character, key, letter, platform = process.platform)
1997
2102
  if (character.toLowerCase() !== letter.toLowerCase()) return false;
1998
2103
  return platform === "darwin" ? key.super || key.ctrl : key.ctrl;
1999
2104
  }
2105
+ function isOutputToggleShortcut(character, key) {
2106
+ return key.ctrl && character.toLowerCase() === "o";
2107
+ }
2108
+ function outputToggleShortcut(_platform = process.platform) {
2109
+ return "Ctrl+O";
2110
+ }
2000
2111
  function removeLastCliImageOnBackspace(input, cursor, images) {
2001
2112
  if (input.length === 0 && cursor === 0 && images.length > 0) {
2002
2113
  return { handled: true, images: images.slice(0, -1) };
2003
2114
  }
2004
2115
  return { handled: false, images: [...images] };
2005
2116
  }
2006
- function prepareCliSubmission(input, images) {
2117
+ function prepareCliSubmission(input, images, slashCommands = MVP_COMMANDS) {
2007
2118
  const entered = input.trim();
2008
2119
  if (entered.length === 0 && images.length === 0) return { kind: "empty" };
2009
- if (images.length > 0 && entered.startsWith("/")) {
2120
+ const slashName = /^\/(\S+)/u.exec(entered)?.[1]?.toLowerCase();
2121
+ const isSlashCommand = slashName !== void 0 && slashCommands.some((command) => command.toLowerCase() === slashName);
2122
+ if (images.length > 0 && isSlashCommand) {
2010
2123
  return { kind: "error", message: "Image attachments cannot be used with slash commands." };
2011
2124
  }
2012
2125
  const text = entered || "Analyze the attached image(s).";
@@ -2123,11 +2236,13 @@ async function runTerminalSubmissionChain(options) {
2123
2236
  if (prompt !== void 0) options.onPendingConsumed(options.pending.values);
2124
2237
  }
2125
2238
  }
2126
- function classifyTerminalInput(key) {
2239
+ function classifyTerminalInput(key, activeSession = false) {
2127
2240
  if (key.wheelUp) return { type: "scroll", rows: -3 };
2128
2241
  if (key.wheelDown) return { type: "scroll", rows: 3 };
2129
2242
  if (key.pageUp) return { type: "page", fraction: -0.5 };
2130
2243
  if (key.pageDown) return { type: "page", fraction: 0.5 };
2244
+ if (activeSession && key.upArrow) return { type: "scroll", rows: -3 };
2245
+ if (activeSession && key.downArrow) return { type: "scroll", rows: 3 };
2131
2246
  if (key.upArrow) return { type: "history", direction: "up" };
2132
2247
  if (key.downArrow) return { type: "history", direction: "down" };
2133
2248
  return null;
@@ -2160,62 +2275,67 @@ function appRuntimeOptions(props, output, onApprovalChange) {
2160
2275
  onToolsChange: onApprovalChange
2161
2276
  };
2162
2277
  }
2163
- function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2278
+ function App({ workspace, home, resumeSession, instanceId, palAlias, onSessionEnd }) {
2164
2279
  const { exit } = use_app_default();
2165
2280
  const { stdout } = useStdout();
2166
- const [runtime, setRuntime] = useState2();
2167
- const [input, setInput] = useState2("");
2168
- const [pastedBlocks, setPastedBlocks] = useState2([]);
2169
- const [imageAttachments, setImageAttachments] = useState2([]);
2170
- const [clipboardNotice, setClipboardNotice] = useState2();
2171
- const [history, setHistory] = useState2([]);
2172
- const [historyCursor, setHistoryCursor] = useState2(0);
2173
- const [approvalExpanded, setApprovalExpanded] = useState2(false);
2174
- const [expandedOutput, setExpandedOutput] = useState2(false);
2175
- const [promptCursor, setPromptCursor] = useState2(0);
2176
- const [slashCandidates, setSlashCandidates] = useState2(
2281
+ const [runtime, setRuntime] = (0, import_react8.useState)();
2282
+ const [input, setInput] = (0, import_react8.useState)("");
2283
+ const [pastedBlocks, setPastedBlocks] = (0, import_react8.useState)([]);
2284
+ const [imageAttachments, setImageAttachments] = (0, import_react8.useState)([]);
2285
+ const [clipboardNotice, setClipboardNotice] = (0, import_react8.useState)();
2286
+ const [history, setHistory] = (0, import_react8.useState)([]);
2287
+ const [historyCursor, setHistoryCursor] = (0, import_react8.useState)(0);
2288
+ const [approvalExpanded, setApprovalExpanded] = (0, import_react8.useState)(false);
2289
+ const [expandedOutput, setExpandedOutput] = (0, import_react8.useState)(false);
2290
+ const [promptCursor, setPromptCursor] = (0, import_react8.useState)(0);
2291
+ const [slashCandidates, setSlashCandidates] = (0, import_react8.useState)(
2177
2292
  () => buildSlashCandidates(BUILTIN_SLASH_CANDIDATES, [], [])
2178
2293
  );
2179
- const [slashSelection, setSlashSelection] = useState2(0);
2180
- const [dismissedSlashInput, setDismissedSlashInput] = useState2();
2181
- const [mentionCandidates, setMentionCandidates] = useState2([]);
2182
- const [mentionSelection, setMentionSelection] = useState2(0);
2183
- const [dismissedMentionInput, setDismissedMentionInput] = useState2();
2184
- const [pendingPrompts, setPendingPrompts] = useState2([]);
2185
- const [revision, setRevision] = useState2(0);
2186
- const [ideContext, setIdeContext] = useState2();
2187
- const [questionIndex, setQuestionIndex] = useState2(0);
2188
- const [questionAnswers, setQuestionAnswers] = useState2({});
2189
- const [customQuestionActive, setCustomQuestionActive] = useState2(false);
2190
- const [columns, setColumns] = useState2(stdout?.columns ?? 80);
2191
- const [rows, setRows] = useState2(stdout?.rows ?? 24);
2192
- const [updateTo, setUpdateTo] = useState2();
2193
- const [transcript, dispatch] = useReducer(transcriptReducer, void 0, createTranscriptState);
2194
- const scrollRef = useRef4(null);
2195
- const mainTaskScrollRef = useRef4(null);
2196
- const subagentTaskScrollRef = useRef4(null);
2197
- const hoveredTaskTrack = useRef4(null);
2198
- const runtimeRef = useRef4(void 0);
2199
- const pendingPromptRef = useRef4(void 0);
2294
+ const [slashSelection, setSlashSelection] = (0, import_react8.useState)(0);
2295
+ const [dismissedSlashInput, setDismissedSlashInput] = (0, import_react8.useState)();
2296
+ const [mentionCandidates, setMentionCandidates] = (0, import_react8.useState)([]);
2297
+ const [mentionSelection, setMentionSelection] = (0, import_react8.useState)(0);
2298
+ const [dismissedMentionInput, setDismissedMentionInput] = (0, import_react8.useState)();
2299
+ const [pendingPrompts, setPendingPrompts] = (0, import_react8.useState)([]);
2300
+ const [revision, setRevision] = (0, import_react8.useState)(0);
2301
+ const [ideContext, setIdeContext] = (0, import_react8.useState)();
2302
+ const [questionIndex, setQuestionIndex] = (0, import_react8.useState)(0);
2303
+ const [questionAnswers, setQuestionAnswers] = (0, import_react8.useState)({});
2304
+ const [customQuestionActive, setCustomQuestionActive] = (0, import_react8.useState)(false);
2305
+ const [columns, setColumns] = (0, import_react8.useState)(stdout?.columns ?? 80);
2306
+ const [rows, setRows] = (0, import_react8.useState)(stdout?.rows ?? 24);
2307
+ const [updateTo, setUpdateTo] = (0, import_react8.useState)();
2308
+ const [transcript, dispatch] = (0, import_react8.useReducer)(transcriptReducer, void 0, createTranscriptState);
2309
+ const scrollRef = (0, import_react8.useRef)(null);
2310
+ const mainTaskScrollRef = (0, import_react8.useRef)(null);
2311
+ const subagentTaskScrollRef = (0, import_react8.useRef)(null);
2312
+ const hoveredTaskTrack = (0, import_react8.useRef)(null);
2313
+ const runtimeRef = (0, import_react8.useRef)(void 0);
2314
+ const pendingPromptRef = (0, import_react8.useRef)(void 0);
2200
2315
  pendingPromptRef.current ??= new PendingPromptQueue();
2201
- const closing = useRef4(false);
2202
- const clipboardBusy = useRef4(false);
2203
- const textBuf = useRef4({ pending: "", timer: null });
2204
- const thinkingBuf = useRef4({ pending: "", timer: null });
2205
- const promptDraftRef = useRef4({
2316
+ const closing = (0, import_react8.useRef)(false);
2317
+ const clipboardBusy = (0, import_react8.useRef)(false);
2318
+ const clipboardFallbackTimer = (0, import_react8.useRef)(null);
2319
+ const terminalTextPasteRevision = (0, import_react8.useRef)(0);
2320
+ const textBuf = (0, import_react8.useRef)({ pending: "", timer: null });
2321
+ const thinkingBuf = (0, import_react8.useRef)({ pending: "", timer: null });
2322
+ const promptDraftRef = (0, import_react8.useRef)({
2206
2323
  text: input,
2207
2324
  cursor: promptCursor,
2208
2325
  pastedBlocks,
2209
2326
  imageAttachments
2210
2327
  });
2211
- const promptEditHistory = useRef4(new PromptEditHistory());
2212
- const historyRef = useRef4([]);
2213
- const historyCursorRef = useRef4(0);
2214
- const historyDraftRef = useRef4(void 0);
2215
- const reverseSearchRef = useRef4(void 0);
2216
- const promptHistoryStoreRef = useRef4(void 0);
2328
+ const promptEditHistory = (0, import_react8.useRef)(new PromptEditHistory());
2329
+ const historyRef = (0, import_react8.useRef)([]);
2330
+ const historyCursorRef = (0, import_react8.useRef)(0);
2331
+ const historyDraftRef = (0, import_react8.useRef)(void 0);
2332
+ const reverseSearchRef = (0, import_react8.useRef)(void 0);
2333
+ const promptHistoryStoreRef = (0, import_react8.useRef)(void 0);
2217
2334
  promptHistoryStoreRef.current ??= new PromptHistoryStore({ home: home ?? homedir(), workspace, maxEntries: HISTORY_CAP });
2218
2335
  promptDraftRef.current = { text: input, cursor: promptCursor, pastedBlocks, imageAttachments };
2336
+ (0, import_react8.useEffect)(() => () => {
2337
+ if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
2338
+ }, []);
2219
2339
  const commitPromptDraft = (next, recordHistory = true) => {
2220
2340
  const current = promptDraftRef.current;
2221
2341
  const resolved = {
@@ -2232,7 +2352,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2232
2352
  if (next.imageAttachments !== void 0) setImageAttachments(next.imageAttachments);
2233
2353
  };
2234
2354
  useTerminalTitle("Flavor Code");
2235
- useEffect3(() => {
2355
+ (0, import_react8.useEffect)(() => {
2236
2356
  let disposed = false;
2237
2357
  void promptHistoryStoreRef.current.load().then((entries) => {
2238
2358
  if (disposed) return;
@@ -2277,18 +2397,18 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2277
2397
  closing.current = true;
2278
2398
  await shutdownRuntime(active, exit, (error) => {
2279
2399
  dispatch({ type: "submit-error", message: error });
2280
- });
2400
+ }, { ...onSessionEnd === void 0 ? {} : { onSessionEnd } });
2281
2401
  };
2282
- const shutdownRef = useRef4(shutdown);
2402
+ const shutdownRef = (0, import_react8.useRef)(shutdown);
2283
2403
  shutdownRef.current = shutdown;
2284
- const interruptRef = useRef4(void 0);
2404
+ const interruptRef = (0, import_react8.useRef)(void 0);
2285
2405
  interruptRef.current ??= createSessionInterruptHandler(
2286
2406
  () => runtimeRef.current?.session,
2287
2407
  () => shutdownRef.current(runtimeRef.current),
2288
2408
  { forceExit: () => process.exit(1) }
2289
2409
  );
2290
2410
  const interrupt = interruptRef.current;
2291
- useEffect3(() => {
2411
+ (0, import_react8.useEffect)(() => {
2292
2412
  let disposed = false;
2293
2413
  const FLUSH_MS = 100;
2294
2414
  const receive = (event) => {
@@ -2361,7 +2481,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2361
2481
  `));
2362
2482
  };
2363
2483
  }, [workspace, home, resumeSession, instanceId, palAlias]);
2364
- useEffect3(() => {
2484
+ (0, import_react8.useEffect)(() => {
2365
2485
  if (runtime === void 0) return;
2366
2486
  let disposed = false;
2367
2487
  void runtime.services.skills().then((skills) => {
@@ -2383,8 +2503,8 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2383
2503
  disposed = true;
2384
2504
  };
2385
2505
  }, [runtime, revision]);
2386
- useEffect3(() => installSigintHandler(process, interrupt), [interrupt]);
2387
- useEffect3(() => {
2506
+ (0, import_react8.useEffect)(() => installSigintHandler(process, interrupt), [interrupt]);
2507
+ (0, import_react8.useEffect)(() => {
2388
2508
  let disposed = false;
2389
2509
  void checkForUpdate(packageVersion()).then((version) => {
2390
2510
  if (version !== void 0 && !disposed) setUpdateTo(version);
@@ -2393,7 +2513,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2393
2513
  disposed = true;
2394
2514
  };
2395
2515
  }, []);
2396
- useEffect3(() => {
2516
+ (0, import_react8.useEffect)(() => {
2397
2517
  if (runtime?.services.ideContext === void 0) {
2398
2518
  setIdeContext(void 0);
2399
2519
  return;
@@ -2423,7 +2543,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2423
2543
  clearInterval(timer);
2424
2544
  };
2425
2545
  }, [runtime]);
2426
- useEffect3(() => {
2546
+ (0, import_react8.useEffect)(() => {
2427
2547
  const controller = new AbortController();
2428
2548
  let disposed = false;
2429
2549
  void createGlobTool(workspace, { defaultLimit: 1e4 }).execute({ pattern: "**", limit: 1e4 }, controller.signal).then((result) => {
@@ -2437,7 +2557,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2437
2557
  controller.abort();
2438
2558
  };
2439
2559
  }, [workspace]);
2440
- useEffect3(() => {
2560
+ (0, import_react8.useEffect)(() => {
2441
2561
  if (!stdout || typeof stdout.on !== "function") return;
2442
2562
  const onResize = () => {
2443
2563
  setColumns(stdout.columns ?? 80);
@@ -2453,13 +2573,16 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2453
2573
  const questions = runtime?.services.questions.pending;
2454
2574
  const memoryReviews = runtime?.memoryReviews.pending ?? [];
2455
2575
  const memoryAutoDismissSeconds = runtime?.memoryReviews.autoDismissSeconds ?? 0;
2456
- useEffect3(() => {
2576
+ (0, import_react8.useEffect)(() => {
2457
2577
  setQuestionIndex(0);
2458
2578
  setQuestionAnswers({});
2459
2579
  setCustomQuestionActive(false);
2460
2580
  }, [questions]);
2461
- useEffect3(() => setApprovalExpanded(false), [approval?.id]);
2462
- const derivedSlashCompletion = deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection);
2581
+ (0, import_react8.useEffect)(() => setApprovalExpanded(false), [approval?.id]);
2582
+ const derivedSlashCompletion = (0, import_react8.useMemo)(
2583
+ () => deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection),
2584
+ [input, promptCursor, slashCandidates, slashSelection]
2585
+ );
2463
2586
  const slashCompletion = canShowSlashCompletion(
2464
2587
  transcript.active !== void 0,
2465
2588
  input,
@@ -2477,27 +2600,43 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2477
2600
  setMentionSelection(0);
2478
2601
  setDismissedMentionInput(next.text);
2479
2602
  };
2480
- const pasteClipboardImage = async () => {
2481
- const active = runtimeRef.current;
2482
- if (active === void 0) {
2483
- setClipboardNotice("Flavor is still starting; try pasting the image again.");
2484
- return;
2485
- }
2486
- if (promptDraftRef.current.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
2487
- setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
2488
- return;
2489
- }
2603
+ const pasteClipboardContent = async (imageOnly = false) => {
2490
2604
  if (clipboardBusy.current) return;
2491
2605
  clipboardBusy.current = true;
2492
- setClipboardNotice("Reading image from clipboard...");
2606
+ const pasteRevision = terminalTextPasteRevision.current;
2607
+ setClipboardNotice(imageOnly ? "Reading clipboard image..." : "Reading clipboard...");
2493
2608
  try {
2494
- const attachment = await readClipboardImage();
2495
- if (attachment === void 0) {
2496
- setClipboardNotice("Clipboard does not contain an image.");
2609
+ const content = imageOnly ? await readClipboardImage().then((attachment2) => attachment2 === void 0 ? void 0 : { kind: "image", attachment: attachment2 }) : await readClipboardContent();
2610
+ if (pasteRevision !== terminalTextPasteRevision.current) {
2611
+ setClipboardNotice(void 0);
2612
+ return;
2613
+ }
2614
+ if (content === void 0) {
2615
+ setClipboardNotice(imageOnly ? "Clipboard does not contain an image." : "Clipboard does not contain pasteable text or an image.");
2616
+ return;
2617
+ }
2618
+ if (content.kind === "text") {
2619
+ const currentDraft2 = promptDraftRef.current;
2620
+ const nextPastedBlocks = /[\r\n]/u.test(content.text) ? [...currentDraft2.pastedBlocks, { id: currentDraft2.pastedBlocks.length + 1, text: content.text }] : currentDraft2.pastedBlocks;
2621
+ commitPromptDraft({
2622
+ ...editPrompt({ text: currentDraft2.text, cursor: currentDraft2.cursor }, { type: "insert", value: content.text }),
2623
+ pastedBlocks: nextPastedBlocks
2624
+ });
2625
+ setClipboardNotice(void 0);
2626
+ return;
2627
+ }
2628
+ const active = runtimeRef.current;
2629
+ if (active === void 0) {
2630
+ setClipboardNotice("Flavor is still starting; try pasting the image again.");
2497
2631
  return;
2498
2632
  }
2499
- const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
2500
2633
  const currentDraft = promptDraftRef.current;
2634
+ if (currentDraft.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
2635
+ setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
2636
+ return;
2637
+ }
2638
+ const attachment = content.attachment;
2639
+ const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
2501
2640
  const currentBytes = currentDraft.imageAttachments.reduce((sum, image) => sum + image.bytes, 0);
2502
2641
  if (currentBytes + incomingBytes > DEFAULT_MAX_TOTAL_IMAGE_BYTES) {
2503
2642
  throw new Error(`Image attachments exceed the maximum total size of ${DEFAULT_MAX_TOTAL_IMAGE_BYTES} bytes`);
@@ -2513,7 +2652,10 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2513
2652
  }
2514
2653
  };
2515
2654
  use_input_default((character, key, event) => {
2516
- const terminalAction = classifyTerminalInput(key);
2655
+ const terminalAction = classifyTerminalInput(
2656
+ key,
2657
+ transcript.active !== void 0 && slashCompletion === null && mentionCompletion === null
2658
+ );
2517
2659
  if (terminalAction?.type === "scroll") {
2518
2660
  const scroll = selectWheelScrollTarget(
2519
2661
  scrollRef.current,
@@ -2534,7 +2676,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2534
2676
  }
2535
2677
  const active = runtimeRef.current;
2536
2678
  if (isCopyShortcut(character, key)) {
2537
- if (selection.hasSelection()) selection.copySelection();
2679
+ if (selection.hasSelection()) selection.copySelectionNoClear();
2538
2680
  else if (process.platform !== "darwin") interrupt();
2539
2681
  return;
2540
2682
  }
@@ -2542,13 +2684,30 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2542
2684
  interrupt();
2543
2685
  return;
2544
2686
  }
2545
- if (isPlatformShortcut(character, key, "o")) {
2687
+ if (isOutputToggleShortcut(character, key)) {
2546
2688
  setExpandedOutput((value) => !value);
2547
- scrollRef.current?.scrollToBottom();
2548
2689
  return;
2549
2690
  }
2550
- if (shouldReadClipboardImage(character, key, event.keypress.isPasted)) {
2551
- void pasteClipboardImage();
2691
+ if (event.keypress.isPasted && character.length > 0) {
2692
+ terminalTextPasteRevision.current += 1;
2693
+ if (clipboardFallbackTimer.current !== null) {
2694
+ clearTimeout(clipboardFallbackTimer.current);
2695
+ clipboardFallbackTimer.current = null;
2696
+ }
2697
+ }
2698
+ const pasteIntent = clipboardPasteIntent(character, key, event.keypress.isPasted);
2699
+ if (pasteIntent === "immediate") {
2700
+ if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
2701
+ clipboardFallbackTimer.current = null;
2702
+ void pasteClipboardContent();
2703
+ return;
2704
+ }
2705
+ if (pasteIntent === "deferred") {
2706
+ if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
2707
+ clipboardFallbackTimer.current = setTimeout(() => {
2708
+ clipboardFallbackTimer.current = null;
2709
+ void pasteClipboardContent();
2710
+ }, CLIPBOARD_SHORTCUT_FALLBACK_MS);
2552
2711
  return;
2553
2712
  }
2554
2713
  if (active?.approvals.pending !== void 0) {
@@ -2706,8 +2865,19 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2706
2865
  return;
2707
2866
  }
2708
2867
  if (key.return) {
2868
+ if (/^\/paste-image\s*$/iu.test(input)) {
2869
+ setInput("");
2870
+ setPromptCursor(0);
2871
+ setPastedBlocks([]);
2872
+ promptDraftRef.current = { text: "", cursor: 0, pastedBlocks: [], imageAttachments };
2873
+ promptEditHistory.current.reset();
2874
+ setSlashSelection(0);
2875
+ setDismissedSlashInput(void 0);
2876
+ void pasteClipboardContent(true);
2877
+ return;
2878
+ }
2709
2879
  const images = [...imageAttachments];
2710
- const prepared = prepareCliSubmission(input, images);
2880
+ const prepared = prepareCliSubmission(input, images, slashCandidates.map(({ name }) => name));
2711
2881
  if (prepared.kind === "empty" || active === void 0) return;
2712
2882
  if (prepared.kind === "error") {
2713
2883
  setClipboardNotice(prepared.message);
@@ -2833,7 +3003,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2833
3003
  setDismissedMentionInput(void 0);
2834
3004
  }
2835
3005
  });
2836
- if (runtime === void 0) return /* @__PURE__ */ jsx5(
3006
+ if (runtime === void 0) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2837
3007
  StartingLayout,
2838
3008
  {
2839
3009
  workspaceName: basename3(workspace),
@@ -2845,7 +3015,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2845
3015
  }
2846
3016
  );
2847
3017
  const llmServiceName = runtime.services.llmServiceName?.();
2848
- return /* @__PURE__ */ jsx5(
3018
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2849
3019
  TerminalLayout,
2850
3020
  {
2851
3021
  model: runtime.services.mainModel(),
@@ -2894,7 +3064,7 @@ function StartingLayout({
2894
3064
  columns,
2895
3065
  rows
2896
3066
  }) {
2897
- return /* @__PURE__ */ jsx5(
3067
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2898
3068
  TerminalLayout,
2899
3069
  {
2900
3070
  model: "starting",
@@ -2914,6 +3084,33 @@ var CLI_VISIBLE_TURN_LIMIT = 40;
2914
3084
  var CLI_VISIBLE_BLOCK_LIMIT = 320;
2915
3085
  var CLI_VISIBLE_BLOCKS_PER_TURN = 80;
2916
3086
  var CLI_VISIBLE_TEXT_CHARS = 32e3;
3087
+ function cliRenderBudget(rows, columns, expanded = false) {
3088
+ if (expanded) {
3089
+ return {
3090
+ turns: Number.POSITIVE_INFINITY,
3091
+ blocks: Number.POSITIVE_INFINITY,
3092
+ blocksPerTurn: Number.POSITIVE_INFINITY,
3093
+ textChars: Number.POSITIVE_INFINITY
3094
+ };
3095
+ }
3096
+ const viewportRows = Math.max(8, Math.floor(rows));
3097
+ const viewportColumns = Math.max(20, Math.floor(columns));
3098
+ const screenMultiplier = 4;
3099
+ const blockMultiplier = 2;
3100
+ const blocks = Math.min(
3101
+ CLI_VISIBLE_BLOCK_LIMIT,
3102
+ Math.max(24, viewportRows * blockMultiplier)
3103
+ );
3104
+ return {
3105
+ turns: Math.min(16, Math.max(4, Math.ceil(viewportRows / 4))),
3106
+ blocks,
3107
+ blocksPerTurn: Math.min(CLI_VISIBLE_BLOCKS_PER_TURN, blocks),
3108
+ textChars: Math.min(
3109
+ 12e3,
3110
+ Math.max(4e3, viewportRows * viewportColumns * screenMultiplier)
3111
+ )
3112
+ };
3113
+ }
2917
3114
  function approvalDetailLines(approval) {
2918
3115
  const lines = [];
2919
3116
  if (approval.agent !== "main") lines.push(`Agent: ${approval.agent}`);
@@ -2963,51 +3160,61 @@ function boundedCliDisplayText(text, limit = CLI_VISIBLE_TEXT_CHARS) {
2963
3160
 
2964
3161
  ${text.slice(-half)}`;
2965
3162
  }
2966
- function boundedCliPresentation(presentation) {
3163
+ function boundedCliPresentation(presentation, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
2967
3164
  if (presentation.kind === "terminal") return {
2968
3165
  ...presentation,
2969
- ...presentation.stdout === void 0 ? {} : { stdout: boundedCliDisplayText(presentation.stdout) },
2970
- ...presentation.stderr === void 0 ? {} : { stderr: boundedCliDisplayText(presentation.stderr) }
3166
+ ...presentation.stdout === void 0 ? {} : { stdout: boundedCliDisplayText(presentation.stdout, maxTextChars) },
3167
+ ...presentation.stderr === void 0 ? {} : { stderr: boundedCliDisplayText(presentation.stderr, maxTextChars) }
2971
3168
  };
2972
3169
  if (presentation.kind === "job" && presentation.output !== void 0) return {
2973
3170
  ...presentation,
2974
- output: boundedCliDisplayText(presentation.output)
3171
+ output: boundedCliDisplayText(presentation.output, maxTextChars)
2975
3172
  };
2976
3173
  return presentation;
2977
3174
  }
2978
- function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN) {
3175
+ function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
3176
+ const uncapped = !Number.isFinite(maxTextChars);
3177
+ const toolTextLimit = uncapped ? maxTextChars : CLI_VISIBLE_TEXT_CHARS;
3178
+ const promptLimit = uncapped ? maxTextChars : 16e3;
2979
3179
  const blockLimit = Math.max(1, Math.floor(maxBlocks));
2980
3180
  const hiddenBlocks = Math.max(0, turn.blocks.length - blockLimit);
2981
- const visible = turn.blocks.slice(-blockLimit).map((block) => block.kind === "text" ? { ...block, text: boundedCliDisplayText(block.text) } : {
3181
+ const visible = turn.blocks.slice(-blockLimit).map((block) => block.kind === "text" ? { ...block, text: boundedCliDisplayText(block.text, maxTextChars) } : {
2982
3182
  ...block,
2983
- ...block.details === void 0 ? {} : { details: boundedCliDisplayText(block.details) },
2984
- ...block.presentation === void 0 ? {} : { presentation: boundedCliPresentation(block.presentation) }
3183
+ ...block.details === void 0 ? {} : {
3184
+ details: boundedCliDisplayText(
3185
+ block.details,
3186
+ block.tool !== void 0 || block.presentation !== void 0 ? toolTextLimit : maxTextChars
3187
+ )
3188
+ },
3189
+ ...block.presentation === void 0 ? {} : {
3190
+ presentation: boundedCliPresentation(block.presentation, toolTextLimit)
3191
+ }
2985
3192
  });
2986
3193
  const blocks = hiddenBlocks === 0 ? visible : [{
2987
3194
  kind: "status",
2988
3195
  id: `display-window:${turn.id}`,
2989
3196
  state: "info",
2990
- text: `\xB7 ${hiddenBlocks} earlier output items hidden to keep the terminal responsive`
3197
+ text: `\xB7 ${hiddenBlocks} earlier output items hidden to keep the terminal responsive \xB7 ${outputToggleShortcut()} to view all`
2991
3198
  }, ...visible];
2992
3199
  return {
2993
3200
  hiddenBlocks,
2994
3201
  turn: {
2995
3202
  ...turn,
2996
- prompt: boundedCliDisplayText(turn.prompt, 16e3),
3203
+ prompt: boundedCliDisplayText(turn.prompt, promptLimit),
2997
3204
  blocks,
2998
3205
  statusLines: blocks.filter((block) => block.kind === "status").map((block) => block.text)
2999
3206
  }
3000
3207
  };
3001
3208
  }
3002
- function cliTranscriptWindow(completed, maxTurns = CLI_VISIBLE_TURN_LIMIT, maxBlocks = CLI_VISIBLE_BLOCK_LIMIT) {
3209
+ function cliTranscriptWindow(completed, maxTurns = CLI_VISIBLE_TURN_LIMIT, maxBlocks = CLI_VISIBLE_BLOCK_LIMIT, maxTextChars = CLI_VISIBLE_TEXT_CHARS, maxBlocksPerTurn = CLI_VISIBLE_BLOCKS_PER_TURN) {
3003
3210
  const turns = [];
3004
3211
  let remainingBlocks = Math.max(1, Math.floor(maxBlocks));
3005
3212
  let hiddenBlocks = 0;
3006
3213
  for (let index = completed.length - 1; index >= 0 && turns.length < Math.max(1, Math.floor(maxTurns)); index -= 1) {
3007
3214
  const source = completed[index];
3008
3215
  if (remainingBlocks <= 0) break;
3009
- const allowance = Math.min(CLI_VISIBLE_BLOCKS_PER_TURN, remainingBlocks);
3010
- const bounded = boundedCliTurn(source, allowance);
3216
+ const allowance = Math.min(maxBlocksPerTurn, remainingBlocks);
3217
+ const bounded = boundedCliTurn(source, allowance, maxTextChars);
3011
3218
  turns.push(bounded.turn);
3012
3219
  hiddenBlocks += bounded.hiddenBlocks;
3013
3220
  remainingBlocks -= Math.min(source.blocks.length, allowance);
@@ -3054,54 +3261,63 @@ function TerminalLayout({
3054
3261
  ideContext
3055
3262
  }) {
3056
3263
  const dividerWidth = Math.max(1, columns - 1);
3264
+ const outputShortcut = outputToggleShortcut();
3057
3265
  const showWelcome = completed.length === 0 && active === void 0;
3058
- const activeCompletion = completion ?? mentionCompletion;
3059
- const menuRows = activeCompletion === void 0 ? 0 : Math.min(6, activeCompletion.items.length - activeCompletion.windowStart);
3060
- const activeTaskBlocks = active?.blocks.filter(
3266
+ const budget = (0, import_react8.useMemo)(
3267
+ () => cliRenderBudget(rows, columns, expandedOutput),
3268
+ [rows, columns, expandedOutput]
3269
+ );
3270
+ const activeTaskBlocks = (0, import_react8.useMemo)(() => active?.blocks.filter(
3061
3271
  (block) => block.kind === "status" && block.task !== void 0
3062
- ) ?? [];
3063
- const rawActiveWithoutTasks = active === void 0 ? void 0 : {
3064
- ...active,
3065
- blocks: active.blocks.filter(
3066
- (block) => !(block.kind === "status" && block.task !== void 0)
3067
- )
3068
- };
3069
- const activeWithoutTasks = rawActiveWithoutTasks === void 0 ? void 0 : expandedOutput ? rawActiveWithoutTasks : boundedCliTurn(rawActiveWithoutTasks).turn;
3070
- const completedWindow = expandedOutput ? { turns: completed, hiddenTurns: 0, hiddenBlocks: 0 } : cliTranscriptWindow(completed);
3272
+ ) ?? [], [active]);
3273
+ const activeWithoutTasks = (0, import_react8.useMemo)(() => {
3274
+ if (active === void 0) return void 0;
3275
+ const raw = {
3276
+ ...active,
3277
+ blocks: active.blocks.filter((block) => !(block.kind === "status" && block.task !== void 0))
3278
+ };
3279
+ return boundedCliTurn(raw, budget.blocksPerTurn, budget.textChars).turn;
3280
+ }, [active, budget]);
3281
+ const completedWindow = (0, import_react8.useMemo)(
3282
+ () => cliTranscriptWindow(completed, budget.turns, budget.blocks, budget.textChars, budget.blocksPerTurn),
3283
+ [completed, budget]
3284
+ );
3071
3285
  const questionRows = questions === void 0 ? 0 : 4 + (questions[questionIndex]?.options.length ?? 0) + questions.length * 2;
3072
3286
  const memoryReviewRows = memoryReviews.length === 0 ? 0 : 5;
3073
3287
  const approvalRows = approval === void 0 ? 0 : 3 + (approvalExpanded ? approvalDetailLines(approval).length : 0);
3074
- const fixedBottomRows = approvalRows + questionRows + memoryReviewRows + menuRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
3288
+ const fixedBottomRows = approvalRows + questionRows + memoryReviewRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
3075
3289
  const taskPanelRows = taskPanelViewportRows(rows, fixedBottomRows, activeTaskBlocks.length > 0);
3076
3290
  const availableBottomRows = Math.max(1, rows - taskPanelRows - 1);
3077
3291
  const bottomMaxRows = Math.min(availableBottomRows, Math.max(Math.floor(rows / 2), fixedBottomRows + 1));
3078
3292
  const promptMaxLines = Math.max(1, bottomMaxRows - fixedBottomRows);
3079
- return /* @__PURE__ */ jsxs4(Box_default, { height: rows, width: "100%", flexDirection: "column", overflow: "hidden", children: [
3080
- /* @__PURE__ */ jsxs4(ScrollBox_default, { ...scrollRef === void 0 ? {} : { ref: scrollRef }, flexGrow: 1, flexDirection: "column", stickyScroll: true, children: [
3081
- showWelcome ? /* @__PURE__ */ jsx5(WelcomeCard, { model, ...serviceName === void 0 ? {} : { serviceName }, workspaceName, ...updateTo === void 0 ? {} : { updateTo }, columns }) : /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
3293
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { height: rows, width: "100%", flexDirection: "column", overflow: "hidden", children: [
3294
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(ScrollBox_default, { ...scrollRef === void 0 ? {} : { ref: scrollRef }, flexGrow: 1, flexDirection: "column", stickyScroll: true, children: [
3295
+ showWelcome ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WelcomeCard, { model, ...serviceName === void 0 ? {} : { serviceName }, workspaceName, ...updateTo === void 0 ? {} : { updateTo }, columns }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3082
3296
  "flavor \xB7 ",
3083
3297
  model,
3084
3298
  " \xB7 ",
3085
3299
  workspaceName
3086
3300
  ] }),
3087
- /* @__PURE__ */ jsx5(Box_default, { height: 1 }),
3088
- completedWindow.hiddenTurns > 0 || completedWindow.hiddenBlocks > 0 ? /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
3301
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { height: 1 }),
3302
+ completedWindow.hiddenTurns > 0 || completedWindow.hiddenBlocks > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3089
3303
  "\u2026 ",
3090
3304
  completedWindow.hiddenTurns,
3091
3305
  " earlier turns and ",
3092
3306
  completedWindow.hiddenBlocks,
3093
- " output items hidden \xB7 Ctrl/Cmd+O expand all"
3307
+ " output items hidden to keep the terminal responsive \xB7 ",
3308
+ outputShortcut,
3309
+ " to view all"
3094
3310
  ] }) : null,
3095
- completedWindow.turns.map((turn, index) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
3096
- index > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
3097
- /* @__PURE__ */ jsx5(TurnView, { turn, interactive: false, workspaceName, expandedOutput })
3311
+ completedWindow.turns.map((turn, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
3312
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TurnSeparator, { width: columns }) : null,
3313
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TurnView, { turn, interactive: false, workspaceName, expandedOutput })
3098
3314
  ] }, turn.id)),
3099
- activeWithoutTasks === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
3100
- completedWindow.turns.length > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
3101
- /* @__PURE__ */ jsx5(TurnView, { turn: activeWithoutTasks, interactive: activeSession, workspaceName, expandedOutput })
3315
+ activeWithoutTasks === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
3316
+ completedWindow.turns.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TurnSeparator, { width: columns }) : null,
3317
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TurnView, { turn: activeWithoutTasks, interactive: activeSession, workspaceName, expandedOutput })
3102
3318
  ] })
3103
3319
  ] }),
3104
- /* @__PURE__ */ jsx5(
3320
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3105
3321
  TaskProgressPanel,
3106
3322
  {
3107
3323
  blocks: activeTaskBlocks,
@@ -3113,82 +3329,86 @@ function TerminalLayout({
3113
3329
  ...onTaskPanelHoverChange === void 0 ? {} : { onHoverChange: onTaskPanelHoverChange }
3114
3330
  }
3115
3331
  ),
3116
- /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", flexShrink: 0, maxHeight: bottomMaxRows, width: "100%", overflowY: "hidden", children: [
3117
- approval === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3118
- /* @__PURE__ */ jsxs4(Text, { color: "magenta", children: [
3119
- "\u250C\u2500 approval \xB7 ",
3120
- approval.tool
3332
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { position: "relative", flexShrink: 0, width: "100%", children: [
3333
+ completion === void 0 && mentionCompletion === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { position: "absolute", bottom: "100%", left: 0, right: 0, flexDirection: "column", opaque: true, children: [
3334
+ completion === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SlashMenu, { completion }),
3335
+ mentionCompletion === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } })
3336
+ ] }),
3337
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", flexShrink: 0, maxHeight: bottomMaxRows, width: "100%", overflowY: "hidden", children: [
3338
+ approval === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3339
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "magenta", children: [
3340
+ "\u250C\u2500 approval \xB7 ",
3341
+ approval.tool
3342
+ ] }),
3343
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { wrap: "truncate-end", color: "magentaBright", children: [
3344
+ "\u2502 ",
3345
+ approval.reason ?? "This action needs permission."
3346
+ ] }),
3347
+ approvalExpanded ? approvalDetailLines(approval).map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "magentaBright", wrap: "truncate-end", children: [
3348
+ "\u2502 ",
3349
+ line
3350
+ ] }, `${approval.id}:detail:${index}`)) : null,
3351
+ isDestructiveTool(approval.tool) || approval.allowAlways === false ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { bold: true, color: "magenta", children: [
3352
+ "\u2514\u2500 ",
3353
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: "v" }),
3354
+ "=details / ",
3355
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "green", children: "y" }),
3356
+ "=once / ",
3357
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: "e" }),
3358
+ "=accept edits / ",
3359
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "red", children: "n" }),
3360
+ "=deny"
3361
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { bold: true, color: "magenta", children: [
3362
+ "\u2514\u2500 ",
3363
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: "v" }),
3364
+ "=details / ",
3365
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "green", children: "y" }),
3366
+ "=once / ",
3367
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: "a" }),
3368
+ "=same-type / ",
3369
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "cyan", children: "e" }),
3370
+ "=accept edits / ",
3371
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "red", children: "n" }),
3372
+ "=deny"
3373
+ ] })
3121
3374
  ] }),
3122
- /* @__PURE__ */ jsxs4(Text, { wrap: "truncate-end", color: "magentaBright", children: [
3123
- "\u2502 ",
3124
- approval.reason ?? "This action needs permission."
3375
+ !questions || questions.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionCards, { questions, activeIndex: questionIndex, answers: questionAnswers, customActive: customQuestionActive }),
3376
+ memoryReviews.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
3377
+ pendingPrompts.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "yellow", wrap: "truncate-end", children: [
3378
+ "Pending (",
3379
+ pendingPrompts.length,
3380
+ ") \xB7 ",
3381
+ queuedPromptLabel(pendingPrompts.at(-1)),
3382
+ " \xB7 Esc edit latest"
3125
3383
  ] }),
3126
- approvalExpanded ? approvalDetailLines(approval).map((line, index) => /* @__PURE__ */ jsxs4(Text, { color: "magentaBright", wrap: "truncate-end", children: [
3127
- "\u2502 ",
3128
- line
3129
- ] }, `${approval.id}:detail:${index}`)) : null,
3130
- isDestructiveTool(approval.tool) || approval.allowAlways === false ? /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
3131
- "\u2514\u2500 ",
3132
- /* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
3133
- "=details / ",
3134
- /* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
3135
- "=once / ",
3136
- /* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
3137
- "=accept edits / ",
3138
- /* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
3139
- "=deny"
3140
- ] }) : /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
3141
- "\u2514\u2500 ",
3142
- /* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
3143
- "=details / ",
3144
- /* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
3145
- "=once / ",
3146
- /* @__PURE__ */ jsx5(Text, { color: "yellow", children: "a" }),
3147
- "=same-type / ",
3148
- /* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
3149
- "=accept edits / ",
3150
- /* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
3151
- "=deny"
3152
- ] })
3153
- ] }),
3154
- !questions || questions.length === 0 ? null : /* @__PURE__ */ jsx5(QuestionCards, { questions, activeIndex: questionIndex, answers: questionAnswers, customActive: customQuestionActive }),
3155
- memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
3156
- completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
3157
- mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } }),
3158
- pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
3159
- "Pending (",
3160
- pendingPrompts.length,
3161
- ") \xB7 ",
3162
- queuedPromptLabel(pendingPrompts.at(-1)),
3163
- " \xB7 Esc edit latest"
3164
- ] }),
3165
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
3166
- imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
3167
- "[Image #",
3168
- index + 1,
3169
- "] ",
3170
- image.name ?? basename3(image.source.path)
3171
- ] }, `${image.sha256}:${index}`)),
3172
- clipboardNotice === void 0 ? null : /* @__PURE__ */ jsx5(Text, { color: "yellow", wrap: "truncate-end", children: clipboardNotice }),
3173
- /* @__PURE__ */ jsx5(
3174
- PromptLine,
3175
- {
3176
- input,
3177
- pastedBlocks,
3178
- cursor: promptCursor,
3179
- columns,
3180
- maxVisibleLines: promptMaxLines,
3181
- completedSlashTokenLength: tokenLength,
3182
- ...onPromptCursorChange === void 0 ? {} : { onCursorChange: onPromptCursorChange }
3183
- }
3184
- ),
3185
- /* @__PURE__ */ jsx5(
3186
- FooterStatus,
3187
- {
3188
- hint: activeSession ? `Esc ${pendingPrompts.length > 0 ? "edit latest" : "stop"} \xB7 Ctrl+C cancel \xB7 Enter queue \xB7 Ctrl/Cmd+R history \xB7 Ctrl/Cmd+O ${expandedOutput ? "collapse" : "expand"} output` : completion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 Esc close" : mentionCompletion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 click choose \xB7 Esc close" : `Enter send \xB7 \u2191\u2193/Ctrl/Cmd+R history \xB7 Ctrl/Cmd+O ${expandedOutput ? "collapse" : "expand"} output \xB7 Ctrl+C exit`,
3189
- ...ideContext === void 0 ? {} : { ideContext }
3190
- }
3191
- )
3384
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
3385
+ imageAttachments.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "cyan", wrap: "truncate-end", children: [
3386
+ "[Image #",
3387
+ index + 1,
3388
+ "] ",
3389
+ image.name ?? basename3(image.source.path)
3390
+ ] }, `${image.sha256}:${index}`)),
3391
+ clipboardNotice === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", wrap: "truncate-end", children: clipboardNotice }),
3392
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3393
+ PromptLine,
3394
+ {
3395
+ input,
3396
+ pastedBlocks,
3397
+ cursor: promptCursor,
3398
+ columns,
3399
+ maxVisibleLines: promptMaxLines,
3400
+ completedSlashTokenLength: tokenLength,
3401
+ ...onPromptCursorChange === void 0 ? {} : { onCursorChange: onPromptCursorChange }
3402
+ }
3403
+ ),
3404
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3405
+ FooterStatus,
3406
+ {
3407
+ hint: completion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 Esc close" : mentionCompletion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 click choose \xB7 Esc close" : activeSession ? `Esc ${pendingPrompts.length > 0 ? "edit latest" : "stop"} \xB7 Ctrl+C cancel \xB7 Enter queue \xB7 Ctrl/Cmd+R history \xB7 ${outputShortcut} ${expandedOutput ? "collapse all output" : "expand all output"}` : `Enter send \xB7 \u2191\u2193/Ctrl/Cmd+R history \xB7 ${outputShortcut} ${expandedOutput ? "collapse all output" : "expand all output"} \xB7 Ctrl+C exit`,
3408
+ ...ideContext === void 0 ? {} : { ideContext }
3409
+ }
3410
+ )
3411
+ ] })
3192
3412
  ] })
3193
3413
  ] });
3194
3414
  }
@@ -3197,9 +3417,9 @@ function FooterStatus({
3197
3417
  ideContext
3198
3418
  }) {
3199
3419
  const ide = ideFooterPresentation(ideContext);
3200
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", width: "100%", justifyContent: "space-between", children: [
3201
- /* @__PURE__ */ jsx5(Box_default, { flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ jsx5(Text, { dimColor: true, wrap: "truncate-end", children: hint }) }),
3202
- ide === void 0 ? null : /* @__PURE__ */ jsx5(Box_default, { flexShrink: 0, marginLeft: 1, children: /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
3420
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "row", width: "100%", justifyContent: "space-between", children: [
3421
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, wrap: "truncate-end", children: hint }) }),
3422
+ ide === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexShrink: 0, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "cyan", wrap: "truncate-end", children: [
3203
3423
  "\u29C9 ",
3204
3424
  ide
3205
3425
  ] }) })
@@ -3213,36 +3433,36 @@ function ideFooterPresentation(context) {
3213
3433
  return `${count} ${count === 1 ? "line" : "lines"} selected`;
3214
3434
  }
3215
3435
  function QuestionCards({ questions, activeIndex, answers, customActive }) {
3216
- return /* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", marginBottom: 1, children: questions.map((q, qi) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: qi < questions.length - 1 ? 1 : 0, children: [
3217
- /* @__PURE__ */ jsxs4(Text, { bold: true, color: "cyan", children: [
3436
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", marginBottom: 1, children: questions.map((q, qi) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginBottom: qi < questions.length - 1 ? 1 : 0, children: [
3437
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { bold: true, color: "cyan", children: [
3218
3438
  "\u250C\u2500 ",
3219
3439
  q.header
3220
3440
  ] }),
3221
- /* @__PURE__ */ jsxs4(Text, { wrap: "truncate-end", color: "cyanBright", children: [
3441
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { wrap: "truncate-end", color: "cyanBright", children: [
3222
3442
  "\u2502 ",
3223
3443
  q.question
3224
3444
  ] }),
3225
- qi < activeIndex ? /* @__PURE__ */ jsxs4(Text, { color: "green", children: [
3445
+ qi < activeIndex ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "green", children: [
3226
3446
  "\u2502 \u2713 ",
3227
3447
  answers[qi]
3228
- ] }) : qi > activeIndex ? null : q.options.map((opt, oi) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", children: [
3448
+ ] }) : qi > activeIndex ? null : q.options.map((opt, oi) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "cyan", children: [
3229
3449
  "\u2502 ",
3230
- /* @__PURE__ */ jsx5(Text, { bold: true, color: "green", children: oi + 1 }),
3450
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, color: "green", children: oi + 1 }),
3231
3451
  ". ",
3232
3452
  opt.label,
3233
- /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
3453
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3234
3454
  " ",
3235
3455
  opt.description
3236
3456
  ] })
3237
3457
  ] }, oi)),
3238
- qi === activeIndex ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
3239
- /* @__PURE__ */ jsxs4(Text, { color: "cyan", children: [
3458
+ qi === activeIndex ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3459
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "cyan", children: [
3240
3460
  "\u2502 ",
3241
- /* @__PURE__ */ jsx5(Text, { bold: true, color: "green", children: q.options.length + 1 }),
3461
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, color: "green", children: q.options.length + 1 }),
3242
3462
  ". Custom input",
3243
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: " Type your own answer" })
3463
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: " Type your own answer" })
3244
3464
  ] }),
3245
- /* @__PURE__ */ jsxs4(Text, { dimColor: true, color: "cyan", children: [
3465
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, color: "cyan", children: [
3246
3466
  "\u2514\u2500 ",
3247
3467
  customActive ? "Type below and press Enter; Esc returns to choices" : `Press 1-${q.options.length + 1} to choose; Esc dismisses`
3248
3468
  ] })
@@ -3251,46 +3471,46 @@ function QuestionCards({ questions, activeIndex, answers, customActive }) {
3251
3471
  }
3252
3472
  function MemoryReviewCards({ reviews, autoDismissSeconds }) {
3253
3473
  const review = reviews[0];
3254
- const [remaining, setRemaining] = useState2(autoDismissSeconds);
3255
- useEffect3(() => {
3474
+ const [remaining, setRemaining] = (0, import_react8.useState)(autoDismissSeconds);
3475
+ (0, import_react8.useEffect)(() => {
3256
3476
  if (autoDismissSeconds <= 0) return;
3257
3477
  setRemaining(autoDismissSeconds);
3258
3478
  const timer = setInterval(() => setRemaining((current) => Math.max(0, current - 1)), 1e3);
3259
3479
  return () => clearInterval(timer);
3260
3480
  }, [review.id, autoDismissSeconds]);
3261
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3262
- /* @__PURE__ */ jsxs4(Text, { bold: true, color: "yellow", children: [
3481
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3482
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { bold: true, color: "yellow", children: [
3263
3483
  "\u250C\u2500 Long-term memory requires confirmation (",
3264
3484
  reviews.length,
3265
3485
  ")"
3266
3486
  ] }),
3267
- /* @__PURE__ */ jsxs4(Text, { color: "yellowBright", wrap: "truncate-end", children: [
3487
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "yellowBright", wrap: "truncate-end", children: [
3268
3488
  "\u2502 [",
3269
3489
  review.type,
3270
3490
  "] ",
3271
3491
  review.content
3272
3492
  ] }),
3273
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2502 Model-generated content is not stored until you approve it." }),
3274
- /* @__PURE__ */ jsxs4(Text, { color: "yellow", children: [
3493
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "\u2502 Model-generated content is not stored until you approve it." }),
3494
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "yellow", children: [
3275
3495
  "\u2514\u2500 ",
3276
- /* @__PURE__ */ jsx5(Text, { bold: true, children: "Ctrl+Y" }),
3496
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: "Ctrl+Y" }),
3277
3497
  " save / ",
3278
- /* @__PURE__ */ jsx5(Text, { bold: true, children: "Ctrl+N" }),
3498
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: "Ctrl+N" }),
3279
3499
  " ignore",
3280
- autoDismissSeconds > 0 ? /* @__PURE__ */ jsx5(Text, { bold: true, color: "cyanBright", children: ` (auto-dismiss in ${remaining}s)` }) : " (conversation remains available)"
3500
+ autoDismissSeconds > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, color: "cyanBright", children: ` (auto-dismiss in ${remaining}s)` }) : " (conversation remains available)"
3281
3501
  ] })
3282
3502
  ] });
3283
3503
  }
3284
3504
  function SlashMenu({ completion }) {
3285
3505
  const visible = completion.items.slice(completion.windowStart, completion.windowStart + 6);
3286
- return /* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", width: "100%", children: visible.map((candidate, visibleIndex) => {
3506
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", width: "100%", children: visible.map((candidate, visibleIndex) => {
3287
3507
  const index = completion.windowStart + visibleIndex;
3288
3508
  const presentation = slashCandidatePresentation(index === completion.selectedIndex);
3289
- return /* @__PURE__ */ jsxs4(Text, { ...presentation.rowStyle, wrap: "truncate-end", children: [
3509
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { ...presentation.rowStyle, wrap: "truncate-end", children: [
3290
3510
  presentation.marker,
3291
- /* @__PURE__ */ jsx5(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
3292
- candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ jsx5(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
3293
- candidate.description === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` ${candidate.description}` })
3511
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
3512
+ candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
3513
+ candidate.description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: ` ${normalizeSlashDescription(candidate.description)}` })
3294
3514
  ] }, `${candidate.kind}:${candidate.name}`);
3295
3515
  }) });
3296
3516
  }
@@ -3299,19 +3519,19 @@ function MentionMenu({
3299
3519
  onSelect
3300
3520
  }) {
3301
3521
  const visible = completion.items.slice(completion.windowStart, completion.windowStart + 6);
3302
- return /* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", width: "100%", children: visible.map((path, visibleIndex) => {
3522
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", width: "100%", children: visible.map((path, visibleIndex) => {
3303
3523
  const index = completion.windowStart + visibleIndex;
3304
3524
  const presentation = mentionCandidatePresentation(index === completion.selectedIndex);
3305
- return /* @__PURE__ */ jsx5(
3525
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3306
3526
  Box_default,
3307
3527
  {
3308
3528
  width: "100%",
3309
3529
  onClick: (event) => {
3310
3530
  if (!event.cellIsBlank) onSelect?.(path);
3311
3531
  },
3312
- children: /* @__PURE__ */ jsxs4(Text, { ...presentation.textStyle, wrap: "truncate-end", children: [
3532
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { ...presentation.textStyle, wrap: "truncate-end", children: [
3313
3533
  presentation.marker,
3314
- presentation.highlightMatches ? /* @__PURE__ */ jsx5(HighlightedName, { name: path, query: completion.query, matchStyle: presentation.matchStyle }) : path
3534
+ presentation.highlightMatches ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HighlightedName, { name: path, query: completion.query, matchStyle: presentation.matchStyle }) : path
3315
3535
  ] })
3316
3536
  },
3317
3537
  path
@@ -3324,16 +3544,16 @@ function HighlightedName({
3324
3544
  matchStyle
3325
3545
  }) {
3326
3546
  const ranges = matchRanges(name, query);
3327
- if (ranges.length === 0) return /* @__PURE__ */ jsx5(Text, { children: name });
3547
+ if (ranges.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: name });
3328
3548
  const parts = [];
3329
3549
  let cursor = 0;
3330
3550
  for (const [start, end] of ranges) {
3331
3551
  if (start > cursor) parts.push(name.slice(cursor, start));
3332
- parts.push(/* @__PURE__ */ jsx5(Text, { ...matchStyle, children: name.slice(start, end) }, `${start}:${end}`));
3552
+ parts.push(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { ...matchStyle, children: name.slice(start, end) }, `${start}:${end}`));
3333
3553
  cursor = end;
3334
3554
  }
3335
3555
  if (cursor < name.length) parts.push(name.slice(cursor));
3336
- return /* @__PURE__ */ jsx5(Text, { children: parts });
3556
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: parts });
3337
3557
  }
3338
3558
  function jumpScroll(scroll, delta) {
3339
3559
  const maximum = Math.max(0, scroll.getScrollHeight() - scroll.getViewportHeight());
@@ -3367,25 +3587,25 @@ function scrollUp(scroll, amount) {
3367
3587
  else scroll.scrollBy(-amount);
3368
3588
  }
3369
3589
  function TurnSeparator({ width }) {
3370
- return /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(Math.max(1, width - 1)) });
3590
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.max(1, width - 1)) });
3371
3591
  }
3372
- function TurnView({
3592
+ var TurnView = import_react8.default.memo(function TurnView2({
3373
3593
  turn,
3374
3594
  interactive,
3375
3595
  workspaceName,
3376
3596
  expandedOutput
3377
3597
  }) {
3378
3598
  if (turn.kind === "compaction") {
3379
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, borderStyle: "round", borderColor: "ansi:yellowBright", paddingX: 1, children: [
3380
- /* @__PURE__ */ jsx5(Text, { color: "ansi:yellowBright", bold: true, children: turn.prompt }),
3381
- turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`))
3599
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, borderStyle: "round", borderColor: "ansi:yellowBright", paddingX: 1, children: [
3600
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:yellowBright", bold: true, children: turn.prompt }),
3601
+ turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`))
3382
3602
  ] });
3383
3603
  }
3384
3604
  if (turn.source?.kind === "pal") {
3385
3605
  const context = turn.source.context === void 0 ? "" : ` \xB7 ${turn.source.context}`;
3386
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3387
- /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
3388
- /* @__PURE__ */ jsxs4(Text, { color: "cyanBright", bold: true, children: [
3606
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3607
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
3608
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "cyanBright", bold: true, children: [
3389
3609
  "PAL \xB7 ",
3390
3610
  turn.source.alias,
3391
3611
  " (",
@@ -3393,33 +3613,33 @@ function TurnView({
3393
3613
  ")",
3394
3614
  context
3395
3615
  ] }),
3396
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", children: turn.prompt })
3616
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", children: turn.prompt })
3397
3617
  ] }),
3398
- /* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
3618
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
3399
3619
  ] });
3400
3620
  }
3401
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3402
- /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", backgroundColor: "#3a3a3a", paddingX: 1, paddingY: 0, children: [
3403
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", bold: true, backgroundColor: "#3a3a3a", children: "\u276F" }),
3404
- /* @__PURE__ */ jsxs4(Text, { color: "ansi:whiteBright", bold: true, backgroundColor: "#3a3a3a", children: [
3621
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
3622
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "row", backgroundColor: "#3a3a3a", paddingX: 1, paddingY: 0, children: [
3623
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", bold: true, backgroundColor: "#3a3a3a", children: "\u276F" }),
3624
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "ansi:whiteBright", bold: true, backgroundColor: "#3a3a3a", children: [
3405
3625
  " ",
3406
3626
  turn.prompt
3407
3627
  ] })
3408
3628
  ] }),
3409
- /* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
3629
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
3410
3630
  ] });
3411
- }
3631
+ });
3412
3632
  var DIFF_CONTENT = fileDiffLineStyle("context").contentColor;
3413
3633
  var DIFF_REMOVED_MARKER = fileDiffLineStyle("removed").markerColor;
3414
3634
  var DIFF_ADDED_MARKER = fileDiffLineStyle("added").markerColor;
3415
- function FileDiffView({ presentation }) {
3635
+ function FileDiffView({ presentation, expanded }) {
3416
3636
  const operation = presentation.operation === "create" ? "Create" : presentation.operation === "delete" ? "Delete" : "Update";
3417
3637
  if (presentation.operation === "delete") {
3418
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", children: [
3419
- /* @__PURE__ */ jsx5(Text, { color: DIFF_REMOVED_MARKER, children: "\u25CF" }),
3420
- /* @__PURE__ */ jsxs4(Text, { color: DIFF_CONTENT, children: [
3638
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "row", children: [
3639
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: DIFF_REMOVED_MARKER, children: "\u25CF" }),
3640
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: DIFF_CONTENT, children: [
3421
3641
  " ",
3422
- /* @__PURE__ */ jsx5(Text, { bold: true, children: operation }),
3642
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: operation }),
3423
3643
  "(",
3424
3644
  basename3(presentation.path),
3425
3645
  ")"
@@ -3427,29 +3647,29 @@ function FileDiffView({ presentation }) {
3427
3647
  ] });
3428
3648
  }
3429
3649
  const lineWidth = Math.max(1, ...presentation.lines.map((line) => Math.max(line.oldLine ?? 0, line.newLine ?? 0))).toString().length;
3430
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", width: "100%", children: [
3431
- /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", children: [
3432
- /* @__PURE__ */ jsx5(Text, { color: DIFF_ADDED_MARKER, children: "\u25CF" }),
3433
- /* @__PURE__ */ jsxs4(Text, { color: DIFF_CONTENT, children: [
3650
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", width: "100%", children: [
3651
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "row", children: [
3652
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: DIFF_ADDED_MARKER, children: "\u25CF" }),
3653
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: DIFF_CONTENT, children: [
3434
3654
  " ",
3435
- /* @__PURE__ */ jsx5(Text, { bold: true, children: operation }),
3655
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: operation }),
3436
3656
  "(",
3437
3657
  basename3(presentation.path),
3438
3658
  ")"
3439
3659
  ] })
3440
3660
  ] }),
3441
- /* @__PURE__ */ jsxs4(Text, { color: DIFF_CONTENT, children: [
3661
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: DIFF_CONTENT, children: [
3442
3662
  " \u2514 Added ",
3443
3663
  lineCount(presentation.added),
3444
3664
  ", removed ",
3445
3665
  lineCount(presentation.removed)
3446
3666
  ] }),
3447
- presentation.lines.map((line, index) => /* @__PURE__ */ jsx5(FileDiffRow, { line, lineWidth }, `${line.kind}:${line.oldLine ?? ""}:${line.newLine ?? ""}:${index}`))
3667
+ (expanded ? presentation.lines : []).map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FileDiffRow, { line, lineWidth }, `${line.kind}:${line.oldLine ?? ""}:${line.newLine ?? ""}:${index}`))
3448
3668
  ] });
3449
3669
  }
3450
3670
  function FileDiffRow({ line, lineWidth }) {
3451
3671
  if (line.kind === "omitted") {
3452
- return /* @__PURE__ */ jsxs4(Text, { color: DIFF_CONTENT, dimColor: true, children: [
3672
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: DIFF_CONTENT, dimColor: true, children: [
3453
3673
  " ".repeat(lineWidth + 4),
3454
3674
  line.text
3455
3675
  ] });
@@ -3458,14 +3678,14 @@ function FileDiffRow({ line, lineWidth }) {
3458
3678
  const marker = line.kind === "removed" ? "-" : line.kind === "added" ? "+" : " ";
3459
3679
  const { backgroundColor, markerColor, contentColor } = fileDiffLineStyle(line.kind);
3460
3680
  const prefix = `${String(number ?? "").padStart(lineWidth)} ${marker}| `;
3461
- return /* @__PURE__ */ jsxs4(
3681
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3462
3682
  Box_default,
3463
3683
  {
3464
3684
  flexDirection: "row",
3465
3685
  width: "100%",
3466
3686
  ...backgroundColor === void 0 ? {} : { backgroundColor },
3467
3687
  children: [
3468
- /* @__PURE__ */ jsx5(
3688
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3469
3689
  Text,
3470
3690
  {
3471
3691
  color: markerColor,
@@ -3474,7 +3694,7 @@ function FileDiffRow({ line, lineWidth }) {
3474
3694
  children: prefix
3475
3695
  }
3476
3696
  ),
3477
- /* @__PURE__ */ jsx5(
3697
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3478
3698
  Text,
3479
3699
  {
3480
3700
  color: contentColor,
@@ -3490,18 +3710,18 @@ function lineCount(count) {
3490
3710
  return `${count} ${count === 1 ? "line" : "lines"}`;
3491
3711
  }
3492
3712
  function StatusLine({ block, interactive }) {
3493
- if (block.progress !== void 0) return /* @__PURE__ */ jsx5(CompactProgressLine, { progress: block.progress });
3713
+ if (block.progress !== void 0) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CompactProgressLine, { progress: block.progress });
3494
3714
  const running = block.state === "running";
3495
3715
  const [ref, time] = useAnimationFrame(running && interactive ? 120 : null);
3496
3716
  const color = statusLineColor(block);
3497
3717
  const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
3498
3718
  const spinner = running && interactive ? frames[Math.floor(Math.max(0, time) / 120) % frames.length] + " " : "";
3499
- return /* @__PURE__ */ jsxs4(Box_default, { ref, flexDirection: "row", children: [
3500
- /* @__PURE__ */ jsxs4(Text, { ...color === void 0 ? { dimColor: true } : { color }, children: [
3719
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { ref, flexDirection: "row", children: [
3720
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { ...color === void 0 ? { dimColor: true } : { color }, children: [
3501
3721
  spinner,
3502
3722
  block.text
3503
3723
  ] }),
3504
- block.hint === void 0 ? null : /* @__PURE__ */ jsxs4(Text, { dimColor: true, wrap: "truncate-end", children: [
3724
+ block.hint === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, wrap: "truncate-end", children: [
3505
3725
  " (",
3506
3726
  block.hint,
3507
3727
  ")"
@@ -3517,13 +3737,13 @@ function statusLineColor(block) {
3517
3737
  }
3518
3738
  function CompactProgressLine({ progress }) {
3519
3739
  const presentation = compactProgressPresentation(progress);
3520
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", children: [
3521
- /* @__PURE__ */ jsx5(Text, { children: "Compacting context " }),
3522
- presentation.cells.map((cell, index) => /* @__PURE__ */ jsxs4(Text, { color: cell.color, children: [
3740
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "row", children: [
3741
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: "Compacting context " }),
3742
+ presentation.cells.map((cell, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: cell.color, children: [
3523
3743
  "\u25A0",
3524
3744
  index === presentation.cells.length - 1 ? "" : " "
3525
3745
  ] }, index)),
3526
- /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
3746
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3527
3747
  " ",
3528
3748
  presentation.progress,
3529
3749
  "%"
@@ -3554,13 +3774,13 @@ function PromptLine({
3554
3774
  lineStarts.push(nextLineStart);
3555
3775
  nextLineStart += [...line].length;
3556
3776
  }
3557
- return /* @__PURE__ */ jsx5(Box_default, { width: "100%", flexDirection: "column", paddingX: PROMPT_HORIZONTAL_PADDING, children: visibleLines.map((line, visibleIndex) => {
3777
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { width: "100%", flexDirection: "column", paddingX: PROMPT_HORIZONTAL_PADDING, children: visibleLines.map((line, visibleIndex) => {
3558
3778
  const lineIndex = windowStart + visibleIndex;
3559
3779
  const isCursorLine = lineIndex === wrap.cursor.line;
3560
3780
  const points = [...line];
3561
3781
  const cursorCol = wrap.cursor.column;
3562
3782
  const styledCount = Math.max(0, Math.min(points.length, tokenLength - (lineStarts[lineIndex] ?? 0)));
3563
- return /* @__PURE__ */ jsxs4(
3783
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3564
3784
  Box_default,
3565
3785
  {
3566
3786
  ...onCursorChange === void 0 ? {} : {
@@ -3574,8 +3794,8 @@ function PromptLine({
3574
3794
  }
3575
3795
  },
3576
3796
  children: [
3577
- /* @__PURE__ */ jsx5(Text, { color: "yellow", bold: true, children: lineIndex === 0 ? "\u276F " : " " }),
3578
- /* @__PURE__ */ jsx5(PromptLineContent, { points, cursor: cursorCol, cursorVisible: isCursorLine, styledCount })
3797
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", bold: true, children: lineIndex === 0 ? "\u276F " : " " }),
3798
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PromptLineContent, { points, cursor: cursorCol, cursorVisible: isCursorLine, styledCount })
3579
3799
  ]
3580
3800
  },
3581
3801
  lineIndex
@@ -3590,14 +3810,15 @@ function StatusBlockView({
3590
3810
  }) {
3591
3811
  const visibleBlock = cliToolTitle(block);
3592
3812
  const outcome = cliToolOutcome(block);
3593
- const primary = visibleBlock.activity === "model" || visibleBlock.task !== void 0 ? /* @__PURE__ */ jsx5(TaskStatusLine, { block: visibleBlock, interactive }) : visibleBlock.state === "completed" && visibleBlock.presentation !== void 0 ? /* @__PURE__ */ jsx5(ToolPresentationView, { presentation: visibleBlock.presentation, workspaceName, expandedOutput }) : /* @__PURE__ */ jsx5(StatusLine, { block: visibleBlock, interactive });
3594
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
3813
+ const toolOutput = block.tool !== void 0 || block.presentation !== void 0;
3814
+ const primary = visibleBlock.activity === "model" || visibleBlock.task !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TaskStatusLine, { block: visibleBlock, interactive }) : visibleBlock.state === "completed" && visibleBlock.presentation !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToolPresentationView, { presentation: visibleBlock.presentation, workspaceName, expandedOutput }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusLine, { block: visibleBlock, interactive });
3815
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
3595
3816
  primary,
3596
- outcome === void 0 ? null : /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
3817
+ outcome === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3597
3818
  "\u2514 ",
3598
3819
  outcome
3599
3820
  ] }) }),
3600
- block.details === void 0 || block.presentation?.kind === "changeset" ? null : /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.details }) })
3821
+ block.details === void 0 || block.presentation?.kind === "changeset" || toolOutput && !expandedOutput ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantText, { text: block.details }) })
3601
3822
  ] });
3602
3823
  }
3603
3824
  function ToolPresentationView({
@@ -3605,32 +3826,34 @@ function ToolPresentationView({
3605
3826
  workspaceName,
3606
3827
  expandedOutput
3607
3828
  }) {
3608
- if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName, expanded: expandedOutput });
3609
- if (presentation.kind === "file-change") return /* @__PURE__ */ jsx5(FileDiffView, { presentation });
3610
- if (presentation.kind === "terminal") return /* @__PURE__ */ jsx5(CommandPresentationView, { presentation, expanded: expandedOutput });
3611
- if (presentation.kind === "web") return /* @__PURE__ */ jsx5(WebPresentationView, { presentation, expanded: expandedOutput });
3612
- if (presentation.kind === "job") return /* @__PURE__ */ jsx5(JobPresentationView, { presentation, expanded: expandedOutput });
3613
- return /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsxs4(Text, { children: [
3614
- presentation.title,
3615
- presentation.summary ? ` \xB7 ${presentation.summary}` : ""
3616
- ] }) });
3829
+ if (presentation.kind === "changeset") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChangeSetPresentationView, { presentation, workspaceName, expanded: expandedOutput });
3830
+ if (presentation.kind === "file-change") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FileDiffView, { presentation, expanded: expandedOutput });
3831
+ if (presentation.kind === "terminal") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CommandPresentationView, { presentation, expanded: expandedOutput });
3832
+ if (presentation.kind === "web") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WebPresentationView, { presentation, expanded: expandedOutput });
3833
+ if (presentation.kind === "job") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(JobPresentationView, { presentation, expanded: expandedOutput });
3834
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, children: [
3835
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
3836
+ presentation.title,
3837
+ presentation.summary ? ` \xB7 ${presentation.summary}` : ""
3838
+ ] }),
3839
+ !expandedOutput || presentation.details === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantText, { text: presentation.details })
3840
+ ] });
3617
3841
  }
3618
- var CLI_CHANGESET_FILE_LIMIT = 8;
3619
3842
  var CHANGESET_TONE = "#b99bf8";
3620
3843
  function ChangeSetPresentationView({
3621
3844
  presentation,
3622
3845
  workspaceName,
3623
3846
  expanded
3624
3847
  }) {
3625
- const visibleFiles = expanded ? presentation.files : presentation.files.slice(0, CLI_CHANGESET_FILE_LIMIT);
3848
+ const visibleFiles = expanded ? presentation.files : [];
3626
3849
  const added = presentation.files.reduce((total, file) => total + file.added, 0);
3627
3850
  const removed = presentation.files.reduce((total, file) => total + file.removed, 0);
3628
3851
  const fileLabel = presentation.files.length === 1 ? "FILE" : "FILES";
3629
3852
  const showing = presentation.files.length > visibleFiles.length ? ` \xB7 Showing ${visibleFiles.length} of ${presentation.files.length}` : "";
3630
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3631
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3632
- /* @__PURE__ */ jsx5(Text, { color: CHANGESET_TONE, children: "\u250C\u2500 " }),
3633
- /* @__PURE__ */ jsxs4(Text, { color: CHANGESET_TONE, bold: true, children: [
3853
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3854
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3855
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: CHANGESET_TONE, children: "\u250C\u2500 " }),
3856
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: CHANGESET_TONE, bold: true, children: [
3634
3857
  "CHANGESET \xB7 ",
3635
3858
  presentation.files.length,
3636
3859
  " ",
@@ -3640,37 +3863,37 @@ function ChangeSetPresentationView({
3640
3863
  visibleFiles.map((file) => {
3641
3864
  const operation = file.operation.toUpperCase();
3642
3865
  const stats = `+${file.added} -${file.removed}`;
3643
- return /* @__PURE__ */ jsxs4(Box_default, { children: [
3644
- /* @__PURE__ */ jsx5(Text, { color: CHANGESET_TONE, children: "\u2502 " }),
3645
- /* @__PURE__ */ jsx5(Text, { color: changeSetOperationColor(file.operation), bold: true, children: operation.padEnd(8) }),
3646
- /* @__PURE__ */ jsxs4(Text, { children: [
3647
- /* @__PURE__ */ jsxs4(Text, { color: "ansi:green", children: [
3866
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3867
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: CHANGESET_TONE, children: "\u2502 " }),
3868
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: changeSetOperationColor(file.operation), bold: true, children: operation.padEnd(8) }),
3869
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
3870
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "ansi:green", children: [
3648
3871
  "+",
3649
3872
  file.added
3650
3873
  ] }),
3651
3874
  " ",
3652
- /* @__PURE__ */ jsxs4(Text, { color: "#e06c50", children: [
3875
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "#e06c50", children: [
3653
3876
  "-",
3654
3877
  file.removed
3655
3878
  ] }),
3656
3879
  " ".repeat(Math.max(1, 9 - stats.length))
3657
3880
  ] }),
3658
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: workspaceRelativePath(file.path, workspaceName) })
3881
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: workspaceRelativePath(file.path, workspaceName) })
3659
3882
  ] }, `${file.operation}:${file.path}`);
3660
3883
  }),
3661
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3662
- /* @__PURE__ */ jsx5(Text, { color: CHANGESET_TONE, children: "\u2514\u2500 " }),
3663
- /* @__PURE__ */ jsxs4(Text, { children: [
3664
- /* @__PURE__ */ jsxs4(Text, { color: "ansi:green", children: [
3884
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3885
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: CHANGESET_TONE, children: "\u2514\u2500 " }),
3886
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
3887
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "ansi:green", children: [
3665
3888
  "+",
3666
3889
  added
3667
3890
  ] }),
3668
3891
  " ",
3669
- /* @__PURE__ */ jsxs4(Text, { color: "#e06c50", children: [
3892
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "#e06c50", children: [
3670
3893
  "-",
3671
3894
  removed
3672
3895
  ] }),
3673
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: showing })
3896
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: showing })
3674
3897
  ] })
3675
3898
  ] })
3676
3899
  ] });
@@ -3689,7 +3912,6 @@ function workspaceRelativePath(value, workspaceName) {
3689
3912
  if (normalized.toLocaleLowerCase().startsWith(rootPrefix.toLocaleLowerCase())) return normalized.slice(rootPrefix.length);
3690
3913
  return normalized;
3691
3914
  }
3692
- var CLI_COMMAND_OUTPUT_LINE_LIMIT = 16;
3693
3915
  function CommandPresentationView({
3694
3916
  presentation,
3695
3917
  expanded
@@ -3697,33 +3919,31 @@ function CommandPresentationView({
3697
3919
  const state = presentation.state ?? commandState(presentation.exitCode);
3698
3920
  const tone = jobStateColor(state);
3699
3921
  const label = presentation.variant === "terminal" ? "TERMINAL" : "COMMAND";
3700
- const hasStdout = jobOutputLines(presentation.stdout ?? "").length > 0;
3701
- const hasStderr = jobOutputLines(presentation.stderr ?? "").length > 0;
3702
- const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : hasStdout && hasStderr ? Math.floor(CLI_COMMAND_OUTPUT_LINE_LIMIT / 2) : CLI_COMMAND_OUTPUT_LINE_LIMIT;
3922
+ const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : 0;
3703
3923
  const stdout = boundedCommandLines(presentation.stdout ?? "", perStreamLimit);
3704
3924
  const stderr = boundedCommandLines(presentation.stderr ?? "", perStreamLimit);
3705
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3706
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3707
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u250C\u2500 " }),
3708
- /* @__PURE__ */ jsxs4(Text, { color: tone, bold: true, children: [
3925
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3926
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3927
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u250C\u2500 " }),
3928
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: tone, bold: true, children: [
3709
3929
  label,
3710
3930
  " \xB7 ",
3711
3931
  state.toUpperCase()
3712
3932
  ] })
3713
3933
  ] }),
3714
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3715
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3716
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", bold: true, wrap: "truncate-end", children: presentation.command ?? presentation.title })
3934
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3935
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
3936
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", bold: true, wrap: "truncate-end", children: presentation.command ?? presentation.title })
3717
3937
  ] }),
3718
- stdout.total === 0 ? null : /* @__PURE__ */ jsx5(CommandOutputSection, { label: "OUTPUT", value: stdout, tone, error: false }),
3719
- stderr.total === 0 ? null : /* @__PURE__ */ jsx5(CommandOutputSection, { label: "ERROR", value: stderr, tone, error: true }),
3720
- presentation.diagnostic === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
3721
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3722
- /* @__PURE__ */ jsx5(Text, { color: tone, children: presentation.diagnostic })
3938
+ stdout.total === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CommandOutputSection, { label: "OUTPUT", value: stdout, tone, error: false }),
3939
+ stderr.total === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CommandOutputSection, { label: "ERROR", value: stderr, tone, error: true }),
3940
+ !expanded || presentation.diagnostic === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3941
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
3942
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: presentation.diagnostic })
3723
3943
  ] }),
3724
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3725
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2514\u2500 " }),
3726
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: commandFooter(presentation, state) })
3944
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3945
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2514\u2500 " }),
3946
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: commandFooter(presentation, state) })
3727
3947
  ] })
3728
3948
  ] });
3729
3949
  }
@@ -3733,16 +3953,17 @@ function CommandOutputSection({
3733
3953
  tone,
3734
3954
  error
3735
3955
  }) {
3736
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
3737
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3738
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u251C\u2500 " }),
3739
- /* @__PURE__ */ jsx5(Text, { color: error ? "#e06c50" : tone, bold: true, children: label }),
3740
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.total} ${value.total === 1 ? "LINE" : "LINES"}` })
3956
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3957
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3958
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u251C\u2500 " }),
3959
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: error ? "#e06c50" : tone, bold: true, children: label }),
3960
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: ` \xB7 ${value.total} ${value.total === 1 ? "LINE" : "LINES"}` }),
3961
+ value.hidden === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: ` \xB7 ${value.head.length + value.tail.length} SHOWN` })
3741
3962
  ] }),
3742
- value.head.map((line, index) => /* @__PURE__ */ jsx5(CommandOutputLine, { line, tone, error }, `head:${index}`)),
3743
- value.hidden === 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
3744
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3745
- /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
3963
+ value.head.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CommandOutputLine, { line, tone, error }, `head:${index}`)),
3964
+ value.hidden === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3965
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
3966
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3746
3967
  "\u2026 ",
3747
3968
  value.hidden,
3748
3969
  " ",
@@ -3750,20 +3971,21 @@ function CommandOutputSection({
3750
3971
  " hidden"
3751
3972
  ] })
3752
3973
  ] }),
3753
- value.tail.map((line, index) => /* @__PURE__ */ jsx5(CommandOutputLine, { line, tone, error }, `tail:${index}`))
3974
+ value.tail.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CommandOutputLine, { line, tone, error }, `tail:${index}`))
3754
3975
  ] });
3755
3976
  }
3756
3977
  function CommandOutputLine({ line, tone, error }) {
3757
- return /* @__PURE__ */ jsxs4(Box_default, { children: [
3758
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3759
- /* @__PURE__ */ jsx5(Text, { color: error ? "#e06c50" : "#b8bcc2", wrap: "truncate-end", children: line === "" ? " " : line })
3978
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
3979
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
3980
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: error ? "#e06c50" : "#b8bcc2", wrap: "truncate-end", children: line === "" ? " " : line })
3760
3981
  ] });
3761
3982
  }
3762
3983
  function boundedCommandLines(output, limit) {
3763
3984
  const lines = jobOutputLines(output);
3985
+ if (limit <= 0) return { total: lines.length, head: [], tail: [], hidden: lines.length };
3764
3986
  if (lines.length <= limit) return { total: lines.length, head: lines, tail: [], hidden: 0 };
3765
- const headCount = Math.ceil(limit / 2);
3766
- const tailCount = Math.floor(limit / 2);
3987
+ const headCount = Math.ceil(limit * 0.625);
3988
+ const tailCount = Math.max(0, limit - headCount);
3767
3989
  return {
3768
3990
  total: lines.length,
3769
3991
  head: lines.slice(0, headCount),
@@ -3780,57 +4002,56 @@ function commandFooter(presentation, state) {
3780
4002
  if (presentation.truncated === true) parts.push("output truncated");
3781
4003
  return parts.join(" \xB7 ");
3782
4004
  }
3783
- var CLI_WEB_RESULT_LIMIT = 5;
3784
4005
  function WebPresentationView({
3785
4006
  presentation,
3786
4007
  expanded
3787
4008
  }) {
3788
4009
  const items = presentation.items ?? [];
3789
- if (presentation.items === void 0) return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3790
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3791
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u250C\u2500 " }),
3792
- /* @__PURE__ */ jsx5(Text, { color: "ansi:cyanBright", bold: true, children: "WEB FETCH" }),
3793
- presentation.summary === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${presentation.summary}` })
4010
+ if (presentation.items === void 0) return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
4011
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4012
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u250C\u2500 " }),
4013
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:cyanBright", bold: true, children: "WEB FETCH" }),
4014
+ presentation.summary === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: ` \xB7 ${presentation.summary}` })
3794
4015
  ] }),
3795
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3796
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2502 " }),
3797
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: presentation.url ?? presentation.title })
4016
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4017
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2502 " }),
4018
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: presentation.url ?? presentation.title })
3798
4019
  ] }),
3799
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3800
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2514\u2500 " }),
3801
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "Page content added to context" })
4020
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4021
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2514\u2500 " }),
4022
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "Page content added to context" })
3802
4023
  ] })
3803
4024
  ] });
3804
- const visibleItems = expanded ? items : items.slice(0, CLI_WEB_RESULT_LIMIT);
4025
+ const visibleItems = expanded ? items : [];
3805
4026
  const query = presentation.title.replace(/^Search:\s*/iu, "").trim();
3806
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3807
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3808
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u250C\u2500 " }),
3809
- /* @__PURE__ */ jsx5(Text, { color: "ansi:cyanBright", bold: true, children: "WEB SEARCH" }),
3810
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${items.length} ${items.length === 1 ? "RESULT" : "RESULTS"}` })
4027
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
4028
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4029
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u250C\u2500 " }),
4030
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:cyanBright", bold: true, children: "WEB SEARCH" }),
4031
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: ` \xB7 ${items.length} ${items.length === 1 ? "RESULT" : "RESULTS"}` })
3811
4032
  ] }),
3812
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3813
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2502 " }),
3814
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", bold: true, wrap: "truncate-end", children: query })
4033
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4034
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2502 " }),
4035
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", bold: true, wrap: "truncate-end", children: query })
3815
4036
  ] }),
3816
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2502" }),
3817
- visibleItems.map((item, index) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
3818
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3819
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2502 " }),
3820
- /* @__PURE__ */ jsx5(Text, { color: "ansi:cyanBright", bold: true, children: String(index + 1).padStart(2, "0") }),
3821
- /* @__PURE__ */ jsxs4(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: [
4037
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2502" }),
4038
+ visibleItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
4039
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4040
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2502 " }),
4041
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:cyanBright", bold: true, children: String(index + 1).padStart(2, "0") }),
4042
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: [
3822
4043
  " ",
3823
4044
  item.title
3824
4045
  ] })
3825
4046
  ] }),
3826
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3827
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2502 " }),
3828
- /* @__PURE__ */ jsx5(Text, { dimColor: true, wrap: "truncate-end", children: compactWebSource(item.url) })
4047
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4048
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2502 " }),
4049
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, wrap: "truncate-end", children: compactWebSource(item.url) })
3829
4050
  ] })
3830
4051
  ] }, item.url)),
3831
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3832
- /* @__PURE__ */ jsx5(Text, { color: "#5f87af", children: "\u2514\u2500 " }),
3833
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: items.length > visibleItems.length ? `Showing ${visibleItems.length} of ${items.length}` : `${items.length} ${items.length === 1 ? "source" : "sources"}` })
4052
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4053
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#5f87af", children: "\u2514\u2500 " }),
4054
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: items.length > visibleItems.length ? `Showing ${visibleItems.length} of ${items.length}` : `${items.length} ${items.length === 1 ? "source" : "sources"}` })
3834
4055
  ] })
3835
4056
  ] });
3836
4057
  }
@@ -3844,49 +4065,47 @@ function compactWebSource(value) {
3844
4065
  return value;
3845
4066
  }
3846
4067
  }
3847
- var CLI_JOB_LOG_LINE_LIMIT = 12;
3848
- var CLI_JOB_LIST_LIMIT = 8;
3849
4068
  function JobPresentationView({
3850
4069
  presentation,
3851
4070
  expanded
3852
4071
  }) {
3853
- if (presentation.action === "list") return /* @__PURE__ */ jsx5(JobListPresentationView, { presentation, expanded });
4072
+ if (presentation.action === "list") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(JobListPresentationView, { presentation, expanded });
3854
4073
  const state = presentation.state ?? "running";
3855
4074
  const tone = jobStateColor(state);
3856
4075
  const lines = jobOutputLines(presentation.output ?? "");
3857
- const visibleLines = expanded ? lines : lines.slice(-CLI_JOB_LOG_LINE_LIMIT);
4076
+ const visibleLines = expanded ? lines : [];
3858
4077
  const hiddenLines = lines.length - visibleLines.length;
3859
4078
  const showLog = presentation.action === "read" || presentation.action === "kill" || lines.length > 0;
3860
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3861
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3862
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u250C\u2500 " }),
3863
- /* @__PURE__ */ jsxs4(Text, { color: tone, bold: true, children: [
4079
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
4080
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4081
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u250C\u2500 " }),
4082
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: tone, bold: true, children: [
3864
4083
  "JOB \xB7 ",
3865
4084
  state.toUpperCase()
3866
4085
  ] })
3867
4086
  ] }),
3868
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3869
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3870
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", bold: true, children: presentation.id ?? "unknown job" }),
3871
- presentation.jobKind === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${presentation.jobKind}` })
4087
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4088
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
4089
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", bold: true, children: presentation.id ?? "unknown job" }),
4090
+ presentation.jobKind === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: ` \xB7 ${presentation.jobKind}` })
3872
4091
  ] }),
3873
- presentation.label === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
3874
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3875
- /* @__PURE__ */ jsx5(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: presentation.label })
4092
+ presentation.label === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4093
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
4094
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "ansi:whiteBright", wrap: "truncate-end", children: presentation.label })
3876
4095
  ] }),
3877
- presentation.error === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
3878
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3879
- /* @__PURE__ */ jsx5(Text, { color: "#e06c50", wrap: "truncate-end", children: presentation.error })
4096
+ presentation.error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4097
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
4098
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#e06c50", wrap: "truncate-end", children: presentation.error })
3880
4099
  ] }),
3881
- showLog ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
3882
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3883
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u251C\u2500 " }),
3884
- /* @__PURE__ */ jsx5(Text, { color: tone, bold: true, children: "LOG" }),
3885
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: lines.length === 0 ? " \xB7 NO NEW OUTPUT" : ` \xB7 ${lines.length} ${lines.length === 1 ? "LINE" : "LINES"}` })
4100
+ showLog ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4101
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4102
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u251C\u2500 " }),
4103
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, bold: true, children: "LOG" }),
4104
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: lines.length === 0 ? " \xB7 NO NEW OUTPUT" : ` \xB7 ${lines.length} ${lines.length === 1 ? "LINE" : "LINES"}` })
3886
4105
  ] }),
3887
- hiddenLines > 0 ? /* @__PURE__ */ jsxs4(Box_default, { children: [
3888
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3889
- /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
4106
+ hiddenLines > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4107
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
4108
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
3890
4109
  "\u2026 ",
3891
4110
  hiddenLines,
3892
4111
  " earlier ",
@@ -3894,11 +4113,11 @@ function JobPresentationView({
3894
4113
  " hidden"
3895
4114
  ] })
3896
4115
  ] }) : null,
3897
- visibleLines.map((line, index) => /* @__PURE__ */ jsx5(JobLogLine, { line, tone }, `${index}:${line}`))
4116
+ visibleLines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(JobLogLine, { line, tone }, `${index}:${line}`))
3898
4117
  ] }) : null,
3899
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3900
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2514\u2500 " }),
3901
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: jobFooter(presentation) })
4118
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4119
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2514\u2500 " }),
4120
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: jobFooter(presentation) })
3902
4121
  ] })
3903
4122
  ] });
3904
4123
  }
@@ -3907,42 +4126,42 @@ function JobListPresentationView({
3907
4126
  expanded
3908
4127
  }) {
3909
4128
  const jobs = presentation.jobs ?? [];
3910
- const visibleJobs = expanded ? jobs : jobs.slice(0, CLI_JOB_LIST_LIMIT);
3911
- return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
3912
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3913
- /* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u250C\u2500 " }),
3914
- /* @__PURE__ */ jsxs4(Text, { color: "#d7a657", bold: true, children: [
4129
+ const visibleJobs = expanded ? jobs : [];
4130
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
4131
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4132
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#d7a657", children: "\u250C\u2500 " }),
4133
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "#d7a657", bold: true, children: [
3915
4134
  "JOBS \xB7 ",
3916
4135
  jobs.length
3917
4136
  ] })
3918
4137
  ] }),
3919
- jobs.length === 0 ? /* @__PURE__ */ jsxs4(Box_default, { children: [
3920
- /* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u2502 " }),
3921
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "No background jobs" })
3922
- ] }) : visibleJobs.map((job) => /* @__PURE__ */ jsxs4(Box_default, { children: [
3923
- /* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u2502 " }),
3924
- /* @__PURE__ */ jsx5(Text, { color: jobStateColor(job.state), bold: true, children: job.state.toUpperCase().padEnd(9) }),
3925
- /* @__PURE__ */ jsxs4(Text, { color: "ansi:whiteBright", children: [
4138
+ jobs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4139
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#d7a657", children: "\u2502 " }),
4140
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "No background jobs" })
4141
+ ] }) : visibleJobs.map((job) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4142
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#d7a657", children: "\u2502 " }),
4143
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: jobStateColor(job.state), bold: true, children: job.state.toUpperCase().padEnd(9) }),
4144
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "ansi:whiteBright", children: [
3926
4145
  " ",
3927
4146
  job.id
3928
4147
  ] }),
3929
- /* @__PURE__ */ jsxs4(Text, { dimColor: true, wrap: "truncate-end", children: [
4148
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, wrap: "truncate-end", children: [
3930
4149
  " \xB7 ",
3931
4150
  job.label
3932
4151
  ] })
3933
4152
  ] }, job.id)),
3934
- /* @__PURE__ */ jsxs4(Box_default, { children: [
3935
- /* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u2514\u2500 " }),
3936
- /* @__PURE__ */ jsx5(Text, { dimColor: true, children: jobs.length > visibleJobs.length ? `Showing ${visibleJobs.length} of ${jobs.length}` : `${jobs.length} ${jobs.length === 1 ? "job" : "jobs"}` })
4153
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4154
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "#d7a657", children: "\u2514\u2500 " }),
4155
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: jobs.length > visibleJobs.length ? `Showing ${visibleJobs.length} of ${jobs.length}` : `${jobs.length} ${jobs.length === 1 ? "job" : "jobs"}` })
3937
4156
  ] })
3938
4157
  ] });
3939
4158
  }
3940
4159
  function JobLogLine({ line, tone }) {
3941
4160
  const error = /^(?:\[stderr\]|ERR(?:OR)?(?:!|:|\s)|npm ERR!)/iu.test(line.trimStart());
3942
4161
  const stage = /^={3}.*={3}$/u.test(line.trim());
3943
- return /* @__PURE__ */ jsxs4(Box_default, { children: [
3944
- /* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
3945
- /* @__PURE__ */ jsx5(
4162
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
4163
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: tone, children: "\u2502 " }),
4164
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3946
4165
  Text,
3947
4166
  {
3948
4167
  ...error ? { color: "#e06c50" } : stage ? { color: "ansi:cyanBright", bold: true } : { dimColor: true },
@@ -4114,11 +4333,11 @@ function PromptLineContent({
4114
4333
  styledCount
4115
4334
  }) {
4116
4335
  const tokenStyle = completedSlashTokenPresentation();
4117
- return /* @__PURE__ */ jsxs4(Text, { children: [
4336
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
4118
4337
  points.map((point, index) => {
4119
4338
  const styled = index < styledCount;
4120
4339
  const caret = cursorVisible && index === cursor;
4121
- return /* @__PURE__ */ jsx5(
4340
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4122
4341
  Text,
4123
4342
  {
4124
4343
  ...styled ? tokenStyle : {},
@@ -4128,7 +4347,7 @@ function PromptLineContent({
4128
4347
  index
4129
4348
  );
4130
4349
  }),
4131
- cursorVisible && cursor >= points.length ? /* @__PURE__ */ jsx5(Text, { inverse: true, children: " " }) : null
4350
+ cursorVisible && cursor >= points.length ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { inverse: true, children: " " }) : null
4132
4351
  ] });
4133
4352
  }
4134
4353
  function editPrompt(state, edit) {
@@ -4203,6 +4422,13 @@ var FORCE_EXIT_GRACE_MS = 250;
4203
4422
  async function shutdownRuntime(runtime, exit, report, options = {}) {
4204
4423
  const timeoutMs = options.shutdownTimeoutMs ?? SHUTDOWN_TIMEOUT_MS;
4205
4424
  let timedOut = false;
4425
+ if (runtime?.sessionId !== void 0 && options.onSessionEnd !== void 0) {
4426
+ try {
4427
+ options.onSessionEnd(runtime.sessionId);
4428
+ } catch (error) {
4429
+ safeReport(report, safeUiError(error));
4430
+ }
4431
+ }
4206
4432
  try {
4207
4433
  const outcome = await withTimeout(closeAndDisposeRuntime(runtime, report), timeoutMs);
4208
4434
  timedOut = outcome.timedOut;
@@ -4259,6 +4485,7 @@ export {
4259
4485
  boundedCliTurn,
4260
4486
  canShowSlashCompletion,
4261
4487
  classifyTerminalInput,
4488
+ cliRenderBudget,
4262
4489
  cliTranscriptWindow,
4263
4490
  closeAndDisposeRuntime,
4264
4491
  completionKeyAction,
@@ -4266,9 +4493,12 @@ export {
4266
4493
  editPromptWithPastedBlocks,
4267
4494
  ideFooterPresentation,
4268
4495
  isCopyShortcut,
4496
+ isOutputToggleShortcut,
4269
4497
  isPlatformShortcut,
4498
+ jumpScroll,
4270
4499
  navigateHistory,
4271
4500
  navigatePromptHistory,
4501
+ outputToggleShortcut,
4272
4502
  pastedDraftPresentation,
4273
4503
  prepareCliSubmission,
4274
4504
  promptCursorFromClick,
@@ -4281,6 +4511,8 @@ export {
4281
4511
  reverseSearchHistory,
4282
4512
  runTerminalSubmissionChain,
4283
4513
  runningEscapeAction,
4514
+ scrollDown,
4515
+ scrollUp,
4284
4516
  selectWheelScrollTarget,
4285
4517
  shutdownRuntime,
4286
4518
  slashKeyAction,