@claude-code-kit/ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31,61 +31,230 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ AgentContext: () => AgentContext,
35
+ AgentProvider: () => AgentProvider,
36
+ AgentREPL: () => AgentREPL,
37
+ AuthFlowUI: () => AuthFlowUI,
38
+ BashPermissionContent: () => BashPermissionContent,
39
+ Byline: () => Byline,
40
+ ClawdLogo: () => ClawdLogo,
34
41
  CommandRegistry: () => CommandRegistry,
35
42
  DEFAULT_BINDINGS: () => DEFAULT_BINDINGS,
43
+ Dialog: () => Dialog,
44
+ DiffView: () => DiffView,
36
45
  Divider: () => Divider,
46
+ FileEditPermissionContent: () => FileEditPermissionContent,
47
+ FuzzyPicker: () => FuzzyPicker,
37
48
  KeybindingSetup: () => KeybindingSetup,
49
+ KeyboardShortcutHint: () => KeyboardShortcutHint,
50
+ ListItem: () => ListItem,
51
+ LoadingState: () => LoadingState,
52
+ Markdown: () => Markdown,
53
+ MarkdownTable: () => MarkdownTable,
38
54
  MessageList: () => MessageList,
39
55
  MultiSelect: () => MultiSelect,
56
+ Pane: () => Pane,
57
+ PermissionRequest: () => PermissionRequest,
40
58
  ProgressBar: () => ProgressBar,
41
59
  PromptInput: () => PromptInput,
42
60
  REPL: () => REPL,
61
+ Ratchet: () => Ratchet,
62
+ SearchOverlay: () => SearchOverlay,
43
63
  Select: () => Select,
44
64
  Spinner: () => Spinner,
45
65
  StatusIcon: () => StatusIcon,
46
66
  StatusLine: () => StatusLine,
67
+ StreamingMarkdown: () => StreamingMarkdown,
47
68
  StreamingText: () => StreamingText,
69
+ Tab: () => Tab,
70
+ Tabs: () => Tabs,
71
+ TextHoverColorContext: () => TextHoverColorContext,
72
+ ThemeProvider: () => ThemeProvider,
73
+ ThemedBox: () => ThemedBox_default,
74
+ ThemedText: () => ThemedText,
75
+ VirtualList: () => VirtualList,
76
+ WelcomeScreen: () => WelcomeScreen,
48
77
  clearCommand: () => clearCommand,
78
+ color: () => color,
49
79
  createCommandRegistry: () => createCommandRegistry,
50
80
  defineCommand: () => defineCommand,
51
81
  defineJSXCommand: () => defineJSXCommand,
52
82
  defineLocalCommand: () => defineLocalCommand,
53
83
  exitCommand: () => exitCommand,
84
+ getTheme: () => getTheme,
54
85
  helpCommand: () => helpCommand,
86
+ parseUnifiedDiff: () => parseUnifiedDiff,
87
+ useAgent: () => useAgent,
88
+ useAgentContext: () => useAgentContext,
89
+ useDoublePress: () => useDoublePress,
55
90
  useKeybinding: () => useKeybinding,
56
91
  useKeybindings: () => useKeybindings,
57
- useStatusLine: () => useStatusLine
92
+ usePreviewTheme: () => usePreviewTheme,
93
+ useSearch: () => useSearch,
94
+ useStatusLine: () => useStatusLine,
95
+ useTabsWidth: () => useTabsWidth,
96
+ useTerminalSize: () => useTerminalSize,
97
+ useTheme: () => useTheme,
98
+ useThemeSetting: () => useThemeSetting,
99
+ useVirtualScroll: () => useVirtualScroll
58
100
  });
59
101
  module.exports = __toCommonJS(index_exports);
60
102
  __reExport(index_exports, require("@claude-code-kit/ink-renderer"), module.exports);
61
103
 
62
- // src/Divider.tsx
104
+ // src/DiffView.tsx
63
105
  var import_react = require("react");
64
106
  var import_ink_renderer = require("@claude-code-kit/ink-renderer");
65
107
  var import_jsx_runtime = require("react/jsx-runtime");
66
- function Divider({ width, color, char = "\u2500", padding = 0, title }) {
67
- const terminalSize = (0, import_react.useContext)(import_ink_renderer.TerminalSizeContext);
108
+ function parseUnifiedDiff(diff) {
109
+ const rawLines = diff.split("\n");
110
+ let filename = "";
111
+ const lines = [];
112
+ let oldLine = 0;
113
+ let newLine = 0;
114
+ for (const line of rawLines) {
115
+ if (line.startsWith("+++ ")) {
116
+ const path = line.slice(4).trim();
117
+ filename = path.startsWith("b/") ? path.slice(2) : path;
118
+ continue;
119
+ }
120
+ if (line.startsWith("--- ")) continue;
121
+ const hunkMatch = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
122
+ if (hunkMatch) {
123
+ oldLine = parseInt(hunkMatch[1], 10);
124
+ newLine = parseInt(hunkMatch[2], 10);
125
+ continue;
126
+ }
127
+ if (line.startsWith("diff ") || line.startsWith("index ") || line.startsWith("\\")) {
128
+ continue;
129
+ }
130
+ if (oldLine === 0 && newLine === 0) continue;
131
+ if (line.startsWith("+")) {
132
+ lines.push({
133
+ type: "added",
134
+ content: line.slice(1),
135
+ newLineNumber: newLine
136
+ });
137
+ newLine++;
138
+ } else if (line.startsWith("-")) {
139
+ lines.push({
140
+ type: "removed",
141
+ content: line.slice(1),
142
+ oldLineNumber: oldLine
143
+ });
144
+ oldLine++;
145
+ } else {
146
+ lines.push({
147
+ type: "context",
148
+ content: line.startsWith(" ") ? line.slice(1) : line,
149
+ oldLineNumber: oldLine,
150
+ newLineNumber: newLine
151
+ });
152
+ oldLine++;
153
+ newLine++;
154
+ }
155
+ }
156
+ return { filename: filename || "unknown", lines };
157
+ }
158
+ function DiffView({
159
+ filename,
160
+ lines: propLines,
161
+ diff,
162
+ showLineNumbers = true,
163
+ maxHeight,
164
+ color: colorOverrides
165
+ }) {
166
+ const parsed = (0, import_react.useMemo)(() => {
167
+ if (diff) return parseUnifiedDiff(diff);
168
+ return null;
169
+ }, [diff]);
170
+ const resolvedFilename = parsed?.filename ?? filename;
171
+ const resolvedLines = parsed?.lines ?? propLines;
172
+ const addedColor = colorOverrides?.added ?? "green";
173
+ const removedColor = colorOverrides?.removed ?? "red";
174
+ const headerColor = colorOverrides?.header ?? "cyan";
175
+ const contextColor = colorOverrides?.context;
176
+ const maxLineNum = (0, import_react.useMemo)(() => {
177
+ let max = 0;
178
+ for (const line of resolvedLines) {
179
+ if (line.oldLineNumber !== void 0 && line.oldLineNumber > max) max = line.oldLineNumber;
180
+ if (line.newLineNumber !== void 0 && line.newLineNumber > max) max = line.newLineNumber;
181
+ }
182
+ return max;
183
+ }, [resolvedLines]);
184
+ const gutterWidth = Math.max(2, String(maxLineNum).length);
185
+ const visibleLines = maxHeight && resolvedLines.length > maxHeight ? resolvedLines.slice(0, maxHeight) : resolvedLines;
186
+ const truncated = maxHeight && resolvedLines.length > maxHeight ? resolvedLines.length - maxHeight : 0;
187
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Box, { flexDirection: "column", children: [
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Text, { bold: true, color: headerColor, children: [
189
+ " ",
190
+ resolvedFilename
191
+ ] }),
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Text, { dimColor: true, children: [
193
+ " ",
194
+ "\u2500".repeat(30)
195
+ ] }),
196
+ visibleLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
197
+ DiffLineRow,
198
+ {
199
+ line,
200
+ gutterWidth,
201
+ showLineNumbers,
202
+ addedColor,
203
+ removedColor,
204
+ contextColor
205
+ },
206
+ i
207
+ )),
208
+ truncated > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Text, { dimColor: true, children: [
209
+ " ... ",
210
+ truncated,
211
+ " more lines"
212
+ ] })
213
+ ] });
214
+ }
215
+ function DiffLineRow({ line, gutterWidth, showLineNumbers, addedColor, removedColor, contextColor }) {
216
+ const lineNum = line.type === "removed" ? line.oldLineNumber : line.newLineNumber ?? line.oldLineNumber;
217
+ const prefix = line.type === "added" ? "+ " : line.type === "removed" ? "- " : " ";
218
+ const gutterStr = showLineNumbers && lineNum !== void 0 ? String(lineNum).padStart(gutterWidth) : " ".repeat(gutterWidth);
219
+ const contentColor = line.type === "added" ? addedColor : line.type === "removed" ? removedColor : contextColor;
220
+ const dim = line.type === "context" && !contextColor;
221
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Text, { children: [
222
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink_renderer.Text, { dimColor: true, children: gutterStr }),
223
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink_renderer.Text, { dimColor: true, children: " \u2502 " }),
224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Text, { dimColor: dim, color: contentColor, children: [
225
+ prefix,
226
+ line.content
227
+ ] })
228
+ ] });
229
+ }
230
+
231
+ // src/Divider.tsx
232
+ var import_react2 = require("react");
233
+ var import_ink_renderer2 = require("@claude-code-kit/ink-renderer");
234
+ var import_jsx_runtime2 = require("react/jsx-runtime");
235
+ function Divider({ width, color: color2, char = "\u2500", padding = 0, title }) {
236
+ const terminalSize = (0, import_react2.useContext)(import_ink_renderer2.TerminalSizeContext);
68
237
  const terminalWidth = terminalSize?.columns ?? 80;
69
238
  const effectiveWidth = Math.max(0, (width ?? terminalWidth - 2) - padding);
70
239
  if (title) {
71
- const titleWidth = (0, import_ink_renderer.stringWidth)(title) + 2;
240
+ const titleWidth = (0, import_ink_renderer2.stringWidth)(title) + 2;
72
241
  const sideWidth = Math.max(0, effectiveWidth - titleWidth);
73
242
  const leftWidth = Math.floor(sideWidth / 2);
74
243
  const rightWidth = sideWidth - leftWidth;
75
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink_renderer.Text, { color, dimColor: !color, children: [
244
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink_renderer2.Text, { color: color2, dimColor: !color2, children: [
76
245
  char.repeat(leftWidth),
77
246
  " ",
78
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink_renderer.Text, { dimColor: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink_renderer.Ansi, { children: title }) }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink_renderer2.Text, { dimColor: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink_renderer2.Ansi, { children: title }) }),
79
248
  " ",
80
249
  char.repeat(rightWidth)
81
250
  ] });
82
251
  }
83
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink_renderer.Text, { color, dimColor: !color, children: char.repeat(effectiveWidth) });
252
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink_renderer2.Text, { color: color2, dimColor: !color2, children: char.repeat(effectiveWidth) });
84
253
  }
85
254
 
86
255
  // src/ProgressBar.tsx
87
- var import_ink_renderer2 = require("@claude-code-kit/ink-renderer");
88
- var import_jsx_runtime2 = require("react/jsx-runtime");
256
+ var import_ink_renderer3 = require("@claude-code-kit/ink-renderer");
257
+ var import_jsx_runtime3 = require("react/jsx-runtime");
89
258
  var BLOCKS = [" ", "\u258F", "\u258E", "\u258D", "\u258C", "\u258B", "\u258A", "\u2589", "\u2588"];
90
259
  function ProgressBar({ ratio: inputRatio, width, fillColor, emptyColor }) {
91
260
  const ratio = Math.min(1, Math.max(0, inputRatio));
@@ -100,13 +269,13 @@ function ProgressBar({ ratio: inputRatio, width, fillColor, emptyColor }) {
100
269
  segments.push(BLOCKS[0].repeat(empty));
101
270
  }
102
271
  }
103
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink_renderer2.Text, { color: fillColor, backgroundColor: emptyColor, children: segments.join("") });
272
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink_renderer3.Text, { color: fillColor, backgroundColor: emptyColor, children: segments.join("") });
104
273
  }
105
274
 
106
275
  // src/StatusIcon.tsx
107
276
  var import_figures = __toESM(require("figures"));
108
- var import_ink_renderer3 = require("@claude-code-kit/ink-renderer");
109
- var import_jsx_runtime3 = require("react/jsx-runtime");
277
+ var import_ink_renderer4 = require("@claude-code-kit/ink-renderer");
278
+ var import_jsx_runtime4 = require("react/jsx-runtime");
110
279
  var STATUS_CONFIG = {
111
280
  success: { icon: import_figures.default.tick, color: "green" },
112
281
  error: { icon: import_figures.default.cross, color: "red" },
@@ -117,16 +286,16 @@ var STATUS_CONFIG = {
117
286
  };
118
287
  function StatusIcon({ status, withSpace = false }) {
119
288
  const config = STATUS_CONFIG[status];
120
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ink_renderer3.Text, { color: config.color, dimColor: !config.color, children: [
289
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ink_renderer4.Text, { color: config.color, dimColor: !config.color, children: [
121
290
  config.icon,
122
291
  withSpace && " "
123
292
  ] });
124
293
  }
125
294
 
126
295
  // src/StatusLine.tsx
127
- var import_react2 = require("react");
128
- var import_ink_renderer4 = require("@claude-code-kit/ink-renderer");
129
- var import_jsx_runtime4 = require("react/jsx-runtime");
296
+ var import_react3 = __toESM(require("react"));
297
+ var import_ink_renderer5 = require("@claude-code-kit/ink-renderer");
298
+ var import_jsx_runtime5 = require("react/jsx-runtime");
130
299
  function hasAnsi(s) {
131
300
  return /\x1b\[/.test(s);
132
301
  }
@@ -134,28 +303,31 @@ function StatusLine({
134
303
  segments,
135
304
  text,
136
305
  paddingX = 1,
137
- gap = 1,
306
+ separator = " \xB7 ",
138
307
  borderStyle = "none",
139
308
  borderColor
140
309
  }) {
141
310
  const border = borderStyle === "none" ? void 0 : borderStyle;
142
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
143
- import_ink_renderer4.Box,
311
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
312
+ import_ink_renderer5.Box,
144
313
  {
145
314
  flexDirection: "row",
146
315
  paddingX,
147
316
  borderStyle: border,
148
317
  borderColor,
149
- children: text !== void 0 ? hasAnsi(text) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink_renderer4.Ansi, { children: text }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink_renderer4.Text, { dimColor: true, children: text }) : segments?.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink_renderer4.Box, { flexGrow: seg.flex ? 1 : 0, marginRight: i < segments.length - 1 ? gap : 0, children: hasAnsi(seg.content) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink_renderer4.Ansi, { children: seg.content }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink_renderer4.Text, { dimColor: true, color: seg.color, children: seg.content }) }, i))
318
+ children: text !== void 0 ? hasAnsi(text) ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink_renderer5.Ansi, { children: text }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink_renderer5.Text, { dimColor: true, children: text }) : segments?.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react3.default.Fragment, { children: [
319
+ i > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink_renderer5.Text, { dimColor: true, children: separator }),
320
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink_renderer5.Box, { flexGrow: seg.flex ? 1 : 0, children: hasAnsi(seg.content) ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink_renderer5.Ansi, { children: seg.content }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink_renderer5.Text, { dimColor: true, color: seg.color, children: seg.content }) })
321
+ ] }, i))
150
322
  }
151
323
  );
152
324
  }
153
325
  function useStatusLine(updater, deps, intervalMs) {
154
- const [value, setValue] = (0, import_react2.useState)(() => updater());
155
- (0, import_react2.useEffect)(() => {
326
+ const [value, setValue] = (0, import_react3.useState)(() => updater());
327
+ (0, import_react3.useEffect)(() => {
156
328
  setValue(updater());
157
329
  }, deps);
158
- (0, import_react2.useEffect)(() => {
330
+ (0, import_react3.useEffect)(() => {
159
331
  if (!intervalMs) return;
160
332
  const id = setInterval(() => setValue(updater()), intervalMs);
161
333
  return () => clearInterval(id);
@@ -260,11 +432,11 @@ var clearCommand = {
260
432
  };
261
433
 
262
434
  // src/keybindings/useKeybinding.ts
263
- var import_react4 = require("react");
264
- var import_ink_renderer5 = require("@claude-code-kit/ink-renderer");
435
+ var import_react5 = require("react");
436
+ var import_ink_renderer6 = require("@claude-code-kit/ink-renderer");
265
437
 
266
438
  // src/keybindings/KeybindingContext.tsx
267
- var import_react3 = require("react");
439
+ var import_react4 = require("react");
268
440
 
269
441
  // src/keybindings/match.ts
270
442
  function getKeyName(input, key) {
@@ -418,10 +590,13 @@ function parseBindings(blocks) {
418
590
 
419
591
  // src/keybindings/resolver.ts
420
592
  function getBindingDisplayText(action, context, bindings) {
421
- const binding = bindings.findLast(
422
- (b) => b.action === action && b.context === context
423
- );
424
- return binding ? chordToString(binding.chord) : void 0;
593
+ for (let i = bindings.length - 1; i >= 0; i--) {
594
+ const binding = bindings[i];
595
+ if (binding && binding.action === action && binding.context === context) {
596
+ return chordToString(binding.chord);
597
+ }
598
+ }
599
+ return void 0;
425
600
  }
426
601
  function buildKeystroke(input, key) {
427
602
  const keyName = getKeyName(input, key);
@@ -508,8 +683,8 @@ function resolveKeyWithChordState(input, key, activeContexts, bindings, pending)
508
683
  }
509
684
 
510
685
  // src/keybindings/KeybindingContext.tsx
511
- var import_jsx_runtime5 = require("react/jsx-runtime");
512
- var KeybindingContext = (0, import_react3.createContext)(null);
686
+ var import_jsx_runtime6 = require("react/jsx-runtime");
687
+ var KeybindingContext = (0, import_react4.createContext)(null);
513
688
  function KeybindingProvider({
514
689
  bindings,
515
690
  pendingChordRef,
@@ -521,11 +696,11 @@ function KeybindingProvider({
521
696
  handlerRegistryRef,
522
697
  children
523
698
  }) {
524
- const getDisplayText = (0, import_react3.useMemo)(
699
+ const getDisplayText = (0, import_react4.useMemo)(
525
700
  () => (action, context) => getBindingDisplayText(action, context, bindings),
526
701
  [bindings]
527
702
  );
528
- const registerHandler = (0, import_react3.useMemo)(
703
+ const registerHandler = (0, import_react4.useMemo)(
529
704
  () => (registration) => {
530
705
  const registry = handlerRegistryRef.current;
531
706
  if (!registry) return () => {
@@ -546,7 +721,7 @@ function KeybindingProvider({
546
721
  },
547
722
  [handlerRegistryRef]
548
723
  );
549
- const invokeAction = (0, import_react3.useMemo)(
724
+ const invokeAction = (0, import_react4.useMemo)(
550
725
  () => (action) => {
551
726
  const registry = handlerRegistryRef.current;
552
727
  if (!registry) return false;
@@ -562,7 +737,7 @@ function KeybindingProvider({
562
737
  },
563
738
  [activeContexts, handlerRegistryRef]
564
739
  );
565
- const resolve = (0, import_react3.useMemo)(
740
+ const resolve = (0, import_react4.useMemo)(
566
741
  () => (input, key, contexts) => resolveKeyWithChordState(
567
742
  input,
568
743
  key,
@@ -572,7 +747,7 @@ function KeybindingProvider({
572
747
  ),
573
748
  [bindings, pendingChordRef]
574
749
  );
575
- const value = (0, import_react3.useMemo)(
750
+ const value = (0, import_react4.useMemo)(
576
751
  () => ({
577
752
  resolve,
578
753
  setPendingChord,
@@ -598,21 +773,21 @@ function KeybindingProvider({
598
773
  invokeAction
599
774
  ]
600
775
  );
601
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(KeybindingContext.Provider, { value, children });
776
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(KeybindingContext.Provider, { value, children });
602
777
  }
603
778
  function useOptionalKeybindingContext() {
604
- return (0, import_react3.useContext)(KeybindingContext);
779
+ return (0, import_react4.useContext)(KeybindingContext);
605
780
  }
606
781
 
607
782
  // src/keybindings/useKeybinding.ts
608
783
  function useKeybinding(action, handler, options = {}) {
609
784
  const { context = "Global", isActive = true } = options;
610
785
  const keybindingContext = useOptionalKeybindingContext();
611
- (0, import_react4.useEffect)(() => {
786
+ (0, import_react5.useEffect)(() => {
612
787
  if (!keybindingContext || !isActive) return;
613
788
  return keybindingContext.registerHandler({ action, context, handler });
614
789
  }, [action, context, handler, keybindingContext, isActive]);
615
- const handleInput = (0, import_react4.useCallback)(
790
+ const handleInput = (0, import_react5.useCallback)(
616
791
  (input, key, event) => {
617
792
  if (!keybindingContext) return;
618
793
  const contextsToCheck = [
@@ -648,12 +823,12 @@ function useKeybinding(action, handler, options = {}) {
648
823
  },
649
824
  [action, context, handler, keybindingContext]
650
825
  );
651
- (0, import_ink_renderer5.useInput)(handleInput, { isActive });
826
+ (0, import_ink_renderer6.useInput)(handleInput, { isActive });
652
827
  }
653
828
  function useKeybindings(handlers, options = {}) {
654
829
  const { context = "Global", isActive = true } = options;
655
830
  const keybindingContext = useOptionalKeybindingContext();
656
- (0, import_react4.useEffect)(() => {
831
+ (0, import_react5.useEffect)(() => {
657
832
  if (!keybindingContext || !isActive) return;
658
833
  const unregisterFns = [];
659
834
  for (const [action, handler] of Object.entries(handlers)) {
@@ -667,7 +842,7 @@ function useKeybindings(handlers, options = {}) {
667
842
  }
668
843
  };
669
844
  }, [context, handlers, keybindingContext, isActive]);
670
- const handleInput = (0, import_react4.useCallback)(
845
+ const handleInput = (0, import_react5.useCallback)(
671
846
  (input, key, event) => {
672
847
  if (!keybindingContext) return;
673
848
  const contextsToCheck = [
@@ -704,12 +879,12 @@ function useKeybindings(handlers, options = {}) {
704
879
  },
705
880
  [context, handlers, keybindingContext]
706
881
  );
707
- (0, import_ink_renderer5.useInput)(handleInput, { isActive });
882
+ (0, import_ink_renderer6.useInput)(handleInput, { isActive });
708
883
  }
709
884
 
710
885
  // src/keybindings/KeybindingProviderSetup.tsx
711
- var import_react5 = require("react");
712
- var import_ink_renderer6 = require("@claude-code-kit/ink-renderer");
886
+ var import_react6 = require("react");
887
+ var import_ink_renderer7 = require("@claude-code-kit/ink-renderer");
713
888
 
714
889
  // src/keybindings/loadUserBindings.ts
715
890
  var import_chokidar = __toESM(require("chokidar"));
@@ -1577,22 +1752,22 @@ function handleDelete(path) {
1577
1752
  }
1578
1753
 
1579
1754
  // src/keybindings/KeybindingProviderSetup.tsx
1580
- var import_jsx_runtime6 = require("react/jsx-runtime");
1755
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1581
1756
  var plural = (n, s) => n === 1 ? s : s + "s";
1582
1757
  function logForDebugging2(msg) {
1583
1758
  if (process.env.DEBUG_KEYBINDINGS) console.error(msg);
1584
1759
  }
1585
1760
  var CHORD_TIMEOUT_MS = 1e3;
1586
1761
  function KeybindingSetup({ children, onWarnings }) {
1587
- const [{ bindings, warnings }, setLoadResult] = (0, import_react5.useState)(() => {
1762
+ const [{ bindings, warnings }, setLoadResult] = (0, import_react6.useState)(() => {
1588
1763
  const result = loadKeybindingsSyncWithWarnings();
1589
1764
  logForDebugging2(
1590
1765
  `[keybindings] KeybindingSetup initialized with ${result.bindings.length} bindings, ${result.warnings.length} warnings`
1591
1766
  );
1592
1767
  return result;
1593
1768
  });
1594
- const [isReload, setIsReload] = (0, import_react5.useState)(false);
1595
- (0, import_react5.useEffect)(() => {
1769
+ const [isReload, setIsReload] = (0, import_react6.useState)(false);
1770
+ (0, import_react6.useEffect)(() => {
1596
1771
  if (!onWarnings || warnings.length === 0) return;
1597
1772
  const errorCount = warnings.filter((w) => w.severity === "error").length;
1598
1773
  const warnCount = warnings.filter((w) => w.severity === "warning").length;
@@ -1606,29 +1781,29 @@ function KeybindingSetup({ children, onWarnings }) {
1606
1781
  }
1607
1782
  onWarnings(message + " \xB7 /doctor for details", errorCount > 0);
1608
1783
  }, [warnings, isReload, onWarnings]);
1609
- const pendingChordRef = (0, import_react5.useRef)(null);
1610
- const [pendingChord, setPendingChordState] = (0, import_react5.useState)(null);
1611
- const chordTimeoutRef = (0, import_react5.useRef)(null);
1612
- const handlerRegistryRef = (0, import_react5.useRef)(
1784
+ const pendingChordRef = (0, import_react6.useRef)(null);
1785
+ const [pendingChord, setPendingChordState] = (0, import_react6.useState)(null);
1786
+ const chordTimeoutRef = (0, import_react6.useRef)(null);
1787
+ const handlerRegistryRef = (0, import_react6.useRef)(
1613
1788
  /* @__PURE__ */ new Map()
1614
1789
  );
1615
- const activeContextsRef = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
1616
- const registerActiveContext = (0, import_react5.useCallback)((context) => {
1790
+ const activeContextsRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
1791
+ const registerActiveContext = (0, import_react6.useCallback)((context) => {
1617
1792
  activeContextsRef.current.add(context);
1618
1793
  }, []);
1619
- const unregisterActiveContext = (0, import_react5.useCallback)(
1794
+ const unregisterActiveContext = (0, import_react6.useCallback)(
1620
1795
  (context) => {
1621
1796
  activeContextsRef.current.delete(context);
1622
1797
  },
1623
1798
  []
1624
1799
  );
1625
- const clearChordTimeout = (0, import_react5.useCallback)(() => {
1800
+ const clearChordTimeout = (0, import_react6.useCallback)(() => {
1626
1801
  if (chordTimeoutRef.current) {
1627
1802
  clearTimeout(chordTimeoutRef.current);
1628
1803
  chordTimeoutRef.current = null;
1629
1804
  }
1630
1805
  }, []);
1631
- const setPendingChord = (0, import_react5.useCallback)(
1806
+ const setPendingChord = (0, import_react6.useCallback)(
1632
1807
  (pending) => {
1633
1808
  clearChordTimeout();
1634
1809
  if (pending !== null) {
@@ -1643,7 +1818,7 @@ function KeybindingSetup({ children, onWarnings }) {
1643
1818
  },
1644
1819
  [clearChordTimeout]
1645
1820
  );
1646
- (0, import_react5.useEffect)(() => {
1821
+ (0, import_react6.useEffect)(() => {
1647
1822
  void initializeKeybindingWatcher();
1648
1823
  const unsubscribe = subscribeToKeybindingChanges((result) => {
1649
1824
  setIsReload(true);
@@ -1657,7 +1832,7 @@ function KeybindingSetup({ children, onWarnings }) {
1657
1832
  clearChordTimeout();
1658
1833
  };
1659
1834
  }, [clearChordTimeout]);
1660
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1835
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1661
1836
  KeybindingProvider,
1662
1837
  {
1663
1838
  bindings,
@@ -1669,7 +1844,7 @@ function KeybindingSetup({ children, onWarnings }) {
1669
1844
  unregisterActiveContext,
1670
1845
  handlerRegistryRef,
1671
1846
  children: [
1672
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1847
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1673
1848
  ChordInterceptor,
1674
1849
  {
1675
1850
  bindings,
@@ -1691,7 +1866,7 @@ function ChordInterceptor({
1691
1866
  activeContexts,
1692
1867
  handlerRegistryRef
1693
1868
  }) {
1694
- const handleInput = (0, import_react5.useCallback)(
1869
+ const handleInput = (0, import_react6.useCallback)(
1695
1870
  (input, key, event) => {
1696
1871
  if ((key.wheelUp || key.wheelDown) && pendingChordRef.current === null) {
1697
1872
  return;
@@ -1755,14 +1930,102 @@ function ChordInterceptor({
1755
1930
  },
1756
1931
  [bindings, pendingChordRef, setPendingChord, activeContexts, handlerRegistryRef]
1757
1932
  );
1758
- (0, import_ink_renderer6.useInput)(handleInput);
1933
+ (0, import_ink_renderer7.useInput)(handleInput);
1759
1934
  return null;
1760
1935
  }
1761
1936
 
1937
+ // src/hooks/useDoublePress.ts
1938
+ var import_react7 = require("react");
1939
+ var DOUBLE_PRESS_TIMEOUT_MS = 800;
1940
+ function useDoublePress(setPending, onDoublePress, onFirstPress) {
1941
+ const lastPressRef = (0, import_react7.useRef)(0);
1942
+ const timeoutRef = (0, import_react7.useRef)(void 0);
1943
+ const clearTimeoutSafe = (0, import_react7.useCallback)(() => {
1944
+ if (timeoutRef.current) {
1945
+ clearTimeout(timeoutRef.current);
1946
+ timeoutRef.current = void 0;
1947
+ }
1948
+ }, []);
1949
+ (0, import_react7.useEffect)(() => {
1950
+ return () => {
1951
+ clearTimeoutSafe();
1952
+ };
1953
+ }, [clearTimeoutSafe]);
1954
+ return (0, import_react7.useCallback)(() => {
1955
+ const now = Date.now();
1956
+ const timeSinceLastPress = now - lastPressRef.current;
1957
+ const isDoublePress = timeSinceLastPress <= DOUBLE_PRESS_TIMEOUT_MS && timeoutRef.current !== void 0;
1958
+ if (isDoublePress) {
1959
+ clearTimeoutSafe();
1960
+ setPending(false);
1961
+ onDoublePress();
1962
+ } else {
1963
+ onFirstPress?.();
1964
+ setPending(true);
1965
+ clearTimeoutSafe();
1966
+ timeoutRef.current = setTimeout(
1967
+ (setPending2, timeoutRef2) => {
1968
+ setPending2(false);
1969
+ timeoutRef2.current = void 0;
1970
+ },
1971
+ DOUBLE_PRESS_TIMEOUT_MS,
1972
+ setPending,
1973
+ timeoutRef
1974
+ );
1975
+ }
1976
+ lastPressRef.current = now;
1977
+ }, [setPending, onDoublePress, onFirstPress, clearTimeoutSafe]);
1978
+ }
1979
+
1980
+ // src/hooks/useTerminalSize.ts
1981
+ var import_react8 = require("react");
1982
+ var import_ink_renderer8 = require("@claude-code-kit/ink-renderer");
1983
+ function useTerminalSize() {
1984
+ const size = (0, import_react8.useContext)(import_ink_renderer8.TerminalSizeContext);
1985
+ if (!size) {
1986
+ throw new Error("useTerminalSize must be used within an Ink App component");
1987
+ }
1988
+ return size;
1989
+ }
1990
+
1762
1991
  // src/PromptInput.tsx
1763
- var import_react6 = require("react");
1764
- var import_ink_renderer7 = require("@claude-code-kit/ink-renderer");
1765
- var import_jsx_runtime7 = require("react/jsx-runtime");
1992
+ var import_react9 = require("react");
1993
+ var import_ink_renderer9 = require("@claude-code-kit/ink-renderer");
1994
+
1995
+ // src/utils/promptInputLogic.ts
1996
+ function wordFwd(s, p) {
1997
+ let i = p;
1998
+ while (i < s.length && s[i] !== " ") i++;
1999
+ while (i < s.length && s[i] === " ") i++;
2000
+ return i;
2001
+ }
2002
+ function wordBwd(s, p) {
2003
+ let i = p;
2004
+ if (i > 0) i--;
2005
+ while (i > 0 && s[i] === " ") i--;
2006
+ while (i > 0 && s[i - 1] !== " ") i--;
2007
+ return i;
2008
+ }
2009
+ function lineOffset(lines, line) {
2010
+ let pos = 0;
2011
+ for (let i = 0; i < line; i++) pos += lines[i].length + 1;
2012
+ return pos;
2013
+ }
2014
+ function cursorLineIndex(lines, cursor) {
2015
+ let pos = 0;
2016
+ for (let i = 0; i < lines.length; i++) {
2017
+ if (cursor <= pos + lines[i].length) return i;
2018
+ pos += lines[i].length + 1;
2019
+ }
2020
+ return lines.length - 1;
2021
+ }
2022
+ function filterCommands(commands, value) {
2023
+ if (!value.startsWith("/")) return [];
2024
+ return commands.filter((cmd) => `/${cmd.name}`.startsWith(value));
2025
+ }
2026
+
2027
+ // src/PromptInput.tsx
2028
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1766
2029
  function PromptInput({
1767
2030
  value,
1768
2031
  onChange,
@@ -1773,186 +2036,302 @@ function PromptInput({
1773
2036
  disabled = false,
1774
2037
  commands = [],
1775
2038
  onCommandSelect,
1776
- history = []
2039
+ history = [],
2040
+ vimMode = false,
2041
+ multiline = false
1777
2042
  }) {
1778
- const [cursor, setCursor] = (0, import_react6.useState)(0);
1779
- const [historyIndex, setHistoryIndex] = (0, import_react6.useState)(-1);
1780
- const [suggestionIndex, setSuggestionIndex] = (0, import_react6.useState)(0);
1781
- const [showSuggestions, setShowSuggestions] = (0, import_react6.useState)(false);
1782
- const suggestions = value.startsWith("/") && commands.length > 0 ? commands.filter((cmd) => `/${cmd.name}`.startsWith(value)) : [];
2043
+ const [cursor, setCursor] = (0, import_react9.useState)(0);
2044
+ const [historyIndex, setHistoryIndex] = (0, import_react9.useState)(-1);
2045
+ const [suggestionIndex, setSuggestionIndex] = (0, import_react9.useState)(0);
2046
+ const [showSuggestions, setShowSuggestions] = (0, import_react9.useState)(false);
2047
+ const [vim, setVim] = (0, import_react9.useState)("INSERT");
2048
+ const [pendingD, setPendingD] = (0, import_react9.useState)(false);
2049
+ const isVimNormal = vimMode && vim === "NORMAL";
2050
+ const suggestions = commands.length > 0 ? filterCommands(commands, value) : [];
1783
2051
  const hasSuggestions = showSuggestions && suggestions.length > 0;
1784
- const updateValue = (0, import_react6.useCallback)(
1785
- (newValue, newCursor) => {
1786
- onChange(newValue);
1787
- setCursor(newCursor ?? newValue.length);
2052
+ const lines = multiline ? value.split("\n") : [value];
2053
+ const cursorLine = multiline ? cursorLineIndex(lines, cursor) : 0;
2054
+ const lineOffset2 = (line) => lineOffset(lines, line);
2055
+ const updateValue = (0, import_react9.useCallback)((nv, nc) => {
2056
+ onChange(nv);
2057
+ setCursor(nc ?? nv.length);
2058
+ setHistoryIndex(-1);
2059
+ setShowSuggestions(nv.startsWith("/"));
2060
+ setSuggestionIndex(0);
2061
+ }, [onChange]);
2062
+ const insertNewline = () => {
2063
+ updateValue(value.slice(0, cursor) + "\n" + value.slice(cursor), cursor + 1);
2064
+ };
2065
+ const moveLine = (dir) => {
2066
+ const target = cursorLine + dir;
2067
+ if (multiline && target >= 0 && target < lines.length) {
2068
+ const col = cursor - lineOffset2(cursorLine);
2069
+ setCursor(lineOffset2(target) + Math.min(col, lines[target].length));
2070
+ return true;
2071
+ }
2072
+ return false;
2073
+ };
2074
+ const historyUp = () => {
2075
+ if (history.length > 0 && historyIndex + 1 < history.length) {
2076
+ const ni = historyIndex + 1;
2077
+ setHistoryIndex(ni);
2078
+ const hv = history[ni];
2079
+ onChange(hv);
2080
+ setCursor(hv.length);
2081
+ }
2082
+ };
2083
+ const historyDown = () => {
2084
+ if (historyIndex > 0) {
2085
+ const ni = historyIndex - 1;
2086
+ setHistoryIndex(ni);
2087
+ const hv = history[ni];
2088
+ onChange(hv);
2089
+ setCursor(hv.length);
2090
+ } else if (historyIndex === 0) {
1788
2091
  setHistoryIndex(-1);
1789
- setShowSuggestions(newValue.startsWith("/"));
1790
- setSuggestionIndex(0);
1791
- },
1792
- [onChange]
1793
- );
1794
- (0, import_ink_renderer7.useInput)(
1795
- (input, key) => {
1796
- if (disabled) return;
1797
- if (key.return) {
1798
- if (hasSuggestions) {
1799
- const cmd = suggestions[suggestionIndex];
1800
- const cmdValue = `/${cmd.name}`;
1801
- onCommandSelect?.(cmd.name);
1802
- onChange(cmdValue);
1803
- setCursor(cmdValue.length);
1804
- setShowSuggestions(false);
1805
- return;
1806
- }
1807
- if (value.length > 0) {
1808
- onSubmit(value);
1809
- }
2092
+ onChange("");
2093
+ setCursor(0);
2094
+ }
2095
+ };
2096
+ (0, import_ink_renderer9.useInput)((input, key) => {
2097
+ if (disabled) return;
2098
+ if (isVimNormal) {
2099
+ if (input !== "d") setPendingD(false);
2100
+ if (input === "i") {
2101
+ setVim("INSERT");
1810
2102
  return;
1811
2103
  }
1812
- if (key.escape) {
1813
- if (hasSuggestions) {
1814
- setShowSuggestions(false);
1815
- }
2104
+ if (input === "a") {
2105
+ setVim("INSERT");
2106
+ setCursor((c) => Math.min(value.length, c + 1));
1816
2107
  return;
1817
2108
  }
1818
- if (key.tab) {
1819
- if (hasSuggestions) {
1820
- const cmd = suggestions[suggestionIndex];
1821
- const cmdValue = `/${cmd.name} `;
1822
- updateValue(cmdValue);
1823
- }
2109
+ if (input === "h" || key.leftArrow) {
2110
+ setCursor((c) => Math.max(0, c - 1));
1824
2111
  return;
1825
2112
  }
1826
- if (key.upArrow) {
1827
- if (hasSuggestions) {
1828
- setSuggestionIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
1829
- return;
2113
+ if (input === "l" || key.rightArrow) {
2114
+ setCursor((c) => Math.min(Math.max(0, value.length - 1), c + 1));
2115
+ return;
2116
+ }
2117
+ if (input === "0" || key.home) {
2118
+ setCursor(multiline ? lineOffset2(cursorLine) : 0);
2119
+ return;
2120
+ }
2121
+ if (input === "$" || key.end) {
2122
+ if (multiline) {
2123
+ const endOfLine = lineOffset2(cursorLine) + lines[cursorLine].length;
2124
+ setCursor(Math.max(lineOffset2(cursorLine), endOfLine - 1));
2125
+ } else {
2126
+ setCursor(Math.max(0, value.length - 1));
1830
2127
  }
1831
- if (history.length > 0) {
1832
- const nextIndex = historyIndex + 1;
1833
- if (nextIndex < history.length) {
1834
- setHistoryIndex(nextIndex);
1835
- const histValue = history[nextIndex];
1836
- onChange(histValue);
1837
- setCursor(histValue.length);
1838
- }
2128
+ return;
2129
+ }
2130
+ if (input === "w") {
2131
+ setCursor(wordFwd(value, cursor));
2132
+ return;
2133
+ }
2134
+ if (input === "b") {
2135
+ setCursor(wordBwd(value, cursor));
2136
+ return;
2137
+ }
2138
+ if (input === "x") {
2139
+ if (cursor < value.length) {
2140
+ const nv = value.slice(0, cursor) + value.slice(cursor + 1);
2141
+ updateValue(nv, Math.min(cursor, Math.max(0, nv.length - 1)));
1839
2142
  }
1840
2143
  return;
1841
2144
  }
1842
- if (key.downArrow) {
1843
- if (hasSuggestions) {
1844
- setSuggestionIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
2145
+ if (input === "d") {
2146
+ if (!pendingD) {
2147
+ setPendingD(true);
1845
2148
  return;
1846
2149
  }
1847
- if (historyIndex > 0) {
1848
- const nextIndex = historyIndex - 1;
1849
- setHistoryIndex(nextIndex);
1850
- const histValue = history[nextIndex];
1851
- onChange(histValue);
1852
- setCursor(histValue.length);
1853
- } else if (historyIndex === 0) {
1854
- setHistoryIndex(-1);
1855
- onChange("");
1856
- setCursor(0);
2150
+ setPendingD(false);
2151
+ if (multiline && lines.length > 1) {
2152
+ const pos = lineOffset2(cursorLine);
2153
+ const end = pos + lines[cursorLine].length;
2154
+ const from = cursorLine === 0 ? pos : pos - 1;
2155
+ const to = cursorLine === 0 ? Math.min(end + 1, value.length) : end;
2156
+ const nv = value.slice(0, from) + value.slice(to);
2157
+ updateValue(nv, Math.min(from, Math.max(0, nv.length - 1)));
2158
+ } else {
2159
+ updateValue("", 0);
1857
2160
  }
1858
2161
  return;
1859
2162
  }
1860
- if (key.leftArrow) {
1861
- setCursor((c) => Math.max(0, c - 1));
2163
+ if (key.upArrow || input === "k" && !key.ctrl) {
2164
+ if (!moveLine(-1)) historyUp();
1862
2165
  return;
1863
2166
  }
1864
- if (key.rightArrow) {
1865
- setCursor((c) => Math.min(value.length, c + 1));
2167
+ if (key.downArrow || input === "j" && !key.ctrl) {
2168
+ if (!moveLine(1)) historyDown();
1866
2169
  return;
1867
2170
  }
1868
- if (key.home || key.ctrl && input === "a") {
1869
- setCursor(0);
2171
+ if (key.return && value.length > 0) {
2172
+ onSubmit(value);
1870
2173
  return;
1871
2174
  }
1872
- if (key.end || key.ctrl && input === "e") {
1873
- setCursor(value.length);
2175
+ return;
2176
+ }
2177
+ if (key.return) {
2178
+ if (hasSuggestions) {
2179
+ const cmd = suggestions[suggestionIndex];
2180
+ const cv = `/${cmd.name}`;
2181
+ onCommandSelect?.(cmd.name);
2182
+ onChange(cv);
2183
+ setCursor(cv.length);
2184
+ setShowSuggestions(false);
1874
2185
  return;
1875
2186
  }
1876
- if (key.ctrl && input === "w") {
1877
- if (cursor > 0) {
1878
- let i = cursor - 1;
1879
- while (i > 0 && value[i - 1] === " ") i--;
1880
- while (i > 0 && value[i - 1] !== " ") i--;
1881
- const newValue = value.slice(0, i) + value.slice(cursor);
1882
- updateValue(newValue, i);
1883
- }
2187
+ if (multiline && key.shift) {
2188
+ insertNewline();
1884
2189
  return;
1885
2190
  }
1886
- if (key.ctrl && input === "u") {
1887
- const newValue = value.slice(cursor);
1888
- updateValue(newValue, 0);
2191
+ if (value.length > 0) onSubmit(value);
2192
+ return;
2193
+ }
2194
+ if (key.escape) {
2195
+ if (hasSuggestions) {
2196
+ setShowSuggestions(false);
1889
2197
  return;
1890
2198
  }
1891
- if (key.backspace) {
1892
- if (cursor > 0) {
1893
- const newValue = value.slice(0, cursor - 1) + value.slice(cursor);
1894
- updateValue(newValue, cursor - 1);
1895
- }
2199
+ if (vimMode) {
2200
+ setVim("NORMAL");
1896
2201
  return;
1897
2202
  }
1898
- if (key.delete) {
1899
- if (cursor < value.length) {
1900
- const newValue = value.slice(0, cursor) + value.slice(cursor + 1);
1901
- updateValue(newValue, cursor);
1902
- }
2203
+ return;
2204
+ }
2205
+ if (multiline && key.ctrl && input === "j") {
2206
+ insertNewline();
2207
+ return;
2208
+ }
2209
+ if (key.tab) {
2210
+ if (hasSuggestions) {
2211
+ updateValue(`/${suggestions[suggestionIndex].name} `);
2212
+ }
2213
+ ;
2214
+ return;
2215
+ }
2216
+ if (key.upArrow) {
2217
+ if (hasSuggestions) {
2218
+ setSuggestionIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
1903
2219
  return;
1904
2220
  }
1905
- if (key.ctrl || key.meta) return;
1906
- if (input.length > 0) {
1907
- const newValue = value.slice(0, cursor) + input + value.slice(cursor);
1908
- updateValue(newValue, cursor + input.length);
2221
+ if (!moveLine(-1)) historyUp();
2222
+ return;
2223
+ }
2224
+ if (key.downArrow) {
2225
+ if (hasSuggestions) {
2226
+ setSuggestionIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
2227
+ return;
1909
2228
  }
1910
- },
1911
- { isActive: !disabled }
1912
- );
1913
- const renderTextWithCursor = () => {
1914
- if (value.length === 0 && placeholder) {
1915
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink_renderer7.Text, { children: [
1916
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink_renderer7.Text, { inverse: true, children: " " }),
1917
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink_renderer7.Text, { dimColor: true, children: placeholder })
2229
+ if (!moveLine(1)) historyDown();
2230
+ return;
2231
+ }
2232
+ if (key.leftArrow) {
2233
+ setCursor((c) => Math.max(0, c - 1));
2234
+ return;
2235
+ }
2236
+ if (key.rightArrow) {
2237
+ setCursor((c) => Math.min(value.length, c + 1));
2238
+ return;
2239
+ }
2240
+ if (key.home || key.ctrl && input === "a") {
2241
+ setCursor(0);
2242
+ return;
2243
+ }
2244
+ if (key.end || key.ctrl && input === "e") {
2245
+ setCursor(value.length);
2246
+ return;
2247
+ }
2248
+ if (key.ctrl && input === "w") {
2249
+ if (cursor > 0) {
2250
+ let i = cursor - 1;
2251
+ while (i > 0 && value[i - 1] === " ") i--;
2252
+ while (i > 0 && value[i - 1] !== " ") i--;
2253
+ updateValue(value.slice(0, i) + value.slice(cursor), i);
2254
+ }
2255
+ ;
2256
+ return;
2257
+ }
2258
+ if (key.ctrl && input === "u") {
2259
+ updateValue(value.slice(cursor), 0);
2260
+ return;
2261
+ }
2262
+ if (key.backspace) {
2263
+ if (cursor > 0) updateValue(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
2264
+ return;
2265
+ }
2266
+ if (key.delete) {
2267
+ if (cursor < value.length) updateValue(value.slice(0, cursor) + value.slice(cursor + 1), cursor);
2268
+ return;
2269
+ }
2270
+ if (key.ctrl || key.meta) return;
2271
+ if (input.length > 0) updateValue(value.slice(0, cursor) + input + value.slice(cursor), cursor + input.length);
2272
+ }, { isActive: !disabled });
2273
+ const renderCursor = (text, cur) => {
2274
+ if (text.length === 0 && placeholder && cursor === 0) {
2275
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Text, { children: [
2276
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { inverse: true, children: " " }),
2277
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { dimColor: true, children: placeholder })
1918
2278
  ] });
1919
2279
  }
1920
- const before = value.slice(0, cursor);
1921
- const atCursor = cursor < value.length ? value[cursor] : " ";
1922
- const after = cursor < value.length ? value.slice(cursor + 1) : "";
1923
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink_renderer7.Text, { children: [
2280
+ const before = text.slice(0, cur);
2281
+ const at = cur < text.length ? text[cur] : " ";
2282
+ const after = cur < text.length ? text.slice(cur + 1) : "";
2283
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Text, { children: [
1924
2284
  before,
1925
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink_renderer7.Text, { inverse: true, children: atCursor }),
2285
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { inverse: true, children: at }),
1926
2286
  after
1927
2287
  ] });
1928
2288
  };
1929
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink_renderer7.Box, { flexDirection: "column", children: [
1930
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink_renderer7.Box, { children: [
1931
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink_renderer7.Text, { color: prefixColor, children: [
1932
- prefix,
1933
- " "
1934
- ] }),
1935
- renderTextWithCursor()
1936
- ] }),
1937
- hasSuggestions && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink_renderer7.Box, { flexDirection: "column", marginLeft: 2, children: suggestions.map((cmd, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink_renderer7.Box, { children: [
1938
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1939
- import_ink_renderer7.Text,
1940
- {
1941
- inverse: i === suggestionIndex,
1942
- color: i === suggestionIndex ? "cyan" : void 0,
1943
- children: ` /${cmd.name}`
1944
- }
1945
- ),
1946
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink_renderer7.Text, { dimColor: true, children: ` ${cmd.description}` })
1947
- ] }, cmd.name)) })
2289
+ const vimTag = vimMode ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { dimColor: true, children: ` -- ${vim} --` }) : null;
2290
+ const renderContent = () => {
2291
+ if (!multiline || lines.length <= 1) {
2292
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Box, { children: [
2293
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Text, { color: prefixColor, children: [
2294
+ prefix,
2295
+ " "
2296
+ ] }),
2297
+ renderCursor(value, cursor),
2298
+ vimTag
2299
+ ] });
2300
+ }
2301
+ let off = 0;
2302
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Box, { flexDirection: "column", children: lines.map((line, i) => {
2303
+ const ls = off;
2304
+ off += line.length + 1;
2305
+ const active = i === cursorLine;
2306
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Box, { children: [
2307
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { color: prefixColor, children: i === 0 ? `${prefix} ` : "\u2219 " }),
2308
+ active ? renderCursor(line, cursor - ls) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { children: line }),
2309
+ i === lines.length - 1 && vimTag
2310
+ ] }, i);
2311
+ }) });
2312
+ };
2313
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Box, { flexDirection: "column", children: [
2314
+ renderContent(),
2315
+ hasSuggestions && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Box, { flexDirection: "column", marginLeft: 2, children: suggestions.map((cmd, i) => {
2316
+ const isFocused = i === suggestionIndex;
2317
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Box, { children: [
2318
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer9.Text, { color: isFocused ? "cyan" : void 0, children: [
2319
+ isFocused ? "\u276F" : " ",
2320
+ " "
2321
+ ] }),
2322
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { color: isFocused ? "cyan" : void 0, bold: isFocused, children: `/${cmd.name}` }),
2323
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer9.Text, { dimColor: true, children: ` ${cmd.description}` })
2324
+ ] }, cmd.name);
2325
+ }) })
1948
2326
  ] });
1949
2327
  }
1950
2328
 
1951
2329
  // src/Spinner.tsx
1952
- var import_react7 = require("react");
1953
- var import_ink_renderer8 = require("@claude-code-kit/ink-renderer");
1954
- var import_jsx_runtime8 = require("react/jsx-runtime");
1955
- var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2330
+ var import_react10 = require("react");
2331
+ var import_ink_renderer10 = require("@claude-code-kit/ink-renderer");
2332
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2333
+ var DEFAULT_CHARACTERS = process.platform === "darwin" ? ["\xB7", "\u2722", "\u2733", "\u2736", "\u273B", "\u273D"] : ["\xB7", "\u2722", "*", "\u2736", "\u273B", "\u273D"];
2334
+ var FRAMES = [...DEFAULT_CHARACTERS, ...[...DEFAULT_CHARACTERS].reverse()];
1956
2335
  var SPINNER_INTERVAL = 80;
1957
2336
  var VERB_ROTATE_INTERVAL = 4e3;
1958
2337
  var ELAPSED_SHOW_AFTER = 1e3;
@@ -1961,22 +2340,22 @@ function Spinner({
1961
2340
  label,
1962
2341
  verb,
1963
2342
  verbs,
1964
- color = DEFAULT_COLOR,
2343
+ color: color2 = DEFAULT_COLOR,
1965
2344
  showElapsed = true
1966
2345
  }) {
1967
- const [frameIndex, setFrameIndex] = (0, import_react7.useState)(0);
1968
- const [verbIndex, setVerbIndex] = (0, import_react7.useState)(0);
1969
- const [elapsed, setElapsed] = (0, import_react7.useState)(0);
1970
- const startRef = (0, import_react7.useRef)(Date.now());
2346
+ const [frameIndex, setFrameIndex] = (0, import_react10.useState)(0);
2347
+ const [verbIndex, setVerbIndex] = (0, import_react10.useState)(0);
2348
+ const [elapsed, setElapsed] = (0, import_react10.useState)(0);
2349
+ const startRef = (0, import_react10.useRef)(Date.now());
1971
2350
  const allVerbs = verbs ?? (verb ? [verb] : ["Thinking"]);
1972
- (0, import_react7.useEffect)(() => {
2351
+ (0, import_react10.useEffect)(() => {
1973
2352
  const id = setInterval(() => {
1974
2353
  setFrameIndex((i) => (i + 1) % FRAMES.length);
1975
2354
  setElapsed(Date.now() - startRef.current);
1976
2355
  }, SPINNER_INTERVAL);
1977
2356
  return () => clearInterval(id);
1978
2357
  }, []);
1979
- (0, import_react7.useEffect)(() => {
2358
+ (0, import_react10.useEffect)(() => {
1980
2359
  if (allVerbs.length <= 1) return;
1981
2360
  const id = setInterval(() => {
1982
2361
  setVerbIndex((i) => (i + 1) % allVerbs.length);
@@ -1987,18 +2366,18 @@ function Spinner({
1987
2366
  const currentVerb = allVerbs[verbIndex % allVerbs.length];
1988
2367
  const elapsedSec = Math.floor(elapsed / 1e3);
1989
2368
  const showTime = showElapsed && elapsed >= ELAPSED_SHOW_AFTER;
1990
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer8.Box, { children: [
1991
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink_renderer8.Text, { color, children: frame }),
1992
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer8.Text, { children: [
2369
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer10.Box, { children: [
2370
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer10.Text, { color: color2, children: frame }),
2371
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer10.Text, { children: [
1993
2372
  " ",
1994
2373
  currentVerb,
1995
2374
  "..."
1996
2375
  ] }),
1997
- label && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer8.Text, { children: [
2376
+ label && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer10.Text, { children: [
1998
2377
  " ",
1999
2378
  label
2000
2379
  ] }),
2001
- showTime && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink_renderer8.Text, { dimColor: true, children: [
2380
+ showTime && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer10.Text, { dimColor: true, children: [
2002
2381
  " (",
2003
2382
  elapsedSec,
2004
2383
  "s)"
@@ -2006,50 +2385,902 @@ function Spinner({
2006
2385
  ] });
2007
2386
  }
2008
2387
 
2009
- // src/Select.tsx
2010
- var import_react8 = require("react");
2011
- var import_ink_renderer9 = require("@claude-code-kit/ink-renderer");
2012
- var import_jsx_runtime9 = require("react/jsx-runtime");
2013
- function useListNavigation(opts) {
2014
- const { options, maxVisible, onCancel, onSelect, extraHandler } = opts;
2015
- const [focusIndex, setFocusIndex] = (0, import_react8.useState)(0);
2016
- const focusRef = (0, import_react8.useRef)(focusIndex);
2017
- focusRef.current = focusIndex;
2018
- const total = options.length;
2019
- const max = maxVisible ?? total;
2020
- const scrollOffset = (0, import_react8.useMemo)(() => {
2021
- if (total <= max) return 0;
2022
- const half = Math.floor(max / 2);
2023
- if (focusIndex <= half) return 0;
2024
- if (focusIndex >= total - max + half) return total - max;
2025
- return focusIndex - half;
2026
- }, [focusIndex, total, max]);
2027
- const visibleOptions = (0, import_react8.useMemo)(
2028
- () => options.slice(scrollOffset, scrollOffset + max),
2029
- [options, scrollOffset, max]
2030
- );
2031
- const moveFocus = (0, import_react8.useCallback)(
2032
- (dir) => {
2033
- setFocusIndex((prev) => {
2034
- let next = prev;
2035
- for (let i = 0; i < total; i++) {
2036
- next = (next + dir + total) % total;
2037
- if (!options[next].disabled) return next;
2388
+ // src/Markdown.tsx
2389
+ var import_marked2 = require("marked");
2390
+ var import_react13 = require("react");
2391
+ var import_ink_renderer17 = require("@claude-code-kit/ink-renderer");
2392
+
2393
+ // src/design-system/ThemeProvider.tsx
2394
+ var import_react11 = require("react");
2395
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2396
+ var themes = {
2397
+ dark: {
2398
+ text: "#E0E0E0",
2399
+ dimText: "#666666",
2400
+ border: "#444444",
2401
+ accent: "#5B9BD5",
2402
+ success: "#6BC76B",
2403
+ warning: "#E5C07B",
2404
+ error: "#E06C75",
2405
+ assistant: "#DA7756",
2406
+ inactive: "#666666",
2407
+ inverseText: "#1E1E1E",
2408
+ permission: "#5B9BD5",
2409
+ diffAdded: "#1a3a1a",
2410
+ diffRemoved: "#3a1a1a",
2411
+ diffAddedWord: "#2d5a2d",
2412
+ diffRemovedWord: "#5a2d2d",
2413
+ diffHeader: "#1e2d3d",
2414
+ userMessage: "#2B4A6F",
2415
+ assistantMessage: "#3D2614",
2416
+ systemMessage: "#2D2D2D",
2417
+ toolUseMessage: "#1E3A2D",
2418
+ permissionAllow: "#1B4332",
2419
+ permissionDeny: "#3B1014",
2420
+ permissionAlways: "#1B2F4D",
2421
+ focus: "#5B9BD5",
2422
+ selection: "#264F78",
2423
+ placeholder: "#555555",
2424
+ link: "#79B8FF",
2425
+ code: "#F8BFB0",
2426
+ codeBackground: "#2D2D2D",
2427
+ blockquote: "#444444",
2428
+ info: "#5B9BD5",
2429
+ spinnerColor: "#DA7756",
2430
+ shimmer: "#3A3A3A"
2431
+ },
2432
+ light: {
2433
+ text: "#1E1E1E",
2434
+ dimText: "#999999",
2435
+ border: "#CCCCCC",
2436
+ accent: "#0066CC",
2437
+ success: "#2E7D32",
2438
+ warning: "#F57C00",
2439
+ error: "#C62828",
2440
+ assistant: "#DA7756",
2441
+ inactive: "#999999",
2442
+ inverseText: "#FFFFFF",
2443
+ permission: "#0066CC",
2444
+ diffAdded: "#E6FFEC",
2445
+ diffRemoved: "#FFEBE9",
2446
+ diffAddedWord: "#CCFFD8",
2447
+ diffRemovedWord: "#FFD7D5",
2448
+ diffHeader: "#DDF4FF",
2449
+ userMessage: "#E8F0FE",
2450
+ assistantMessage: "#FDF2EE",
2451
+ systemMessage: "#F5F5F5",
2452
+ toolUseMessage: "#EAF5EE",
2453
+ permissionAllow: "#E6F4EA",
2454
+ permissionDeny: "#FCE8E6",
2455
+ permissionAlways: "#E8F0FE",
2456
+ focus: "#0066CC",
2457
+ selection: "#B3D4FF",
2458
+ placeholder: "#AAAAAA",
2459
+ link: "#0066CC",
2460
+ code: "#C7522A",
2461
+ codeBackground: "#F5F5F5",
2462
+ blockquote: "#EEEEEE",
2463
+ info: "#0066CC",
2464
+ spinnerColor: "#DA7756",
2465
+ shimmer: "#E8E8E8"
2466
+ },
2467
+ "light-high-contrast": {
2468
+ text: "#000000",
2469
+ dimText: "#595959",
2470
+ border: "#767676",
2471
+ accent: "#0000EE",
2472
+ success: "#006400",
2473
+ warning: "#7A4000",
2474
+ error: "#AE1818",
2475
+ assistant: "#B55530",
2476
+ inactive: "#767676",
2477
+ inverseText: "#FFFFFF",
2478
+ permission: "#0000EE",
2479
+ diffAdded: "#CCF0D0",
2480
+ diffRemoved: "#F5C6C6",
2481
+ diffAddedWord: "#99E0A0",
2482
+ diffRemovedWord: "#EBA0A0",
2483
+ diffHeader: "#B8DEFF",
2484
+ userMessage: "#C8DCFF",
2485
+ assistantMessage: "#FCDAC8",
2486
+ systemMessage: "#E0E0E0",
2487
+ toolUseMessage: "#C4EED0",
2488
+ permissionAllow: "#C4EED0",
2489
+ permissionDeny: "#F5C6C6",
2490
+ permissionAlways: "#C8DCFF",
2491
+ focus: "#0000EE",
2492
+ selection: "#80BFFF",
2493
+ placeholder: "#767676",
2494
+ link: "#0000EE",
2495
+ code: "#8B0000",
2496
+ codeBackground: "#E8E8E8",
2497
+ blockquote: "#D0D0D0",
2498
+ info: "#0000EE",
2499
+ spinnerColor: "#B55530",
2500
+ shimmer: "#D0D0D0"
2501
+ },
2502
+ "dark-dimmed": {
2503
+ text: "#ADBAC7",
2504
+ dimText: "#545D68",
2505
+ border: "#373E47",
2506
+ accent: "#539BF5",
2507
+ success: "#57AB5A",
2508
+ warning: "#C69026",
2509
+ error: "#E5534B",
2510
+ assistant: "#DA7756",
2511
+ inactive: "#545D68",
2512
+ inverseText: "#22272E",
2513
+ permission: "#539BF5",
2514
+ diffAdded: "#1B2F23",
2515
+ diffRemoved: "#2F1B1E",
2516
+ diffAddedWord: "#264D30",
2517
+ diffRemovedWord: "#4D2628",
2518
+ diffHeader: "#1C2B3A",
2519
+ userMessage: "#1C2B3A",
2520
+ assistantMessage: "#2F211A",
2521
+ systemMessage: "#2D333B",
2522
+ toolUseMessage: "#1B2B23",
2523
+ permissionAllow: "#1B2B23",
2524
+ permissionDeny: "#2F1B1E",
2525
+ permissionAlways: "#1C2B3A",
2526
+ focus: "#539BF5",
2527
+ selection: "#1C4066",
2528
+ placeholder: "#545D68",
2529
+ link: "#6CB6FF",
2530
+ code: "#F0A070",
2531
+ codeBackground: "#2D333B",
2532
+ blockquote: "#373E47",
2533
+ info: "#539BF5",
2534
+ spinnerColor: "#DA7756",
2535
+ shimmer: "#373E47"
2536
+ }
2537
+ };
2538
+ function getTheme(name) {
2539
+ return themes[name] ?? themes.dark;
2540
+ }
2541
+ var DEFAULT_THEME = "dark";
2542
+ var ThemeContext = (0, import_react11.createContext)({
2543
+ themeSetting: DEFAULT_THEME,
2544
+ setThemeSetting: () => {
2545
+ },
2546
+ setPreviewTheme: () => {
2547
+ },
2548
+ savePreview: () => {
2549
+ },
2550
+ cancelPreview: () => {
2551
+ },
2552
+ currentTheme: DEFAULT_THEME
2553
+ });
2554
+ function ThemeProvider({
2555
+ children,
2556
+ initialState = "dark",
2557
+ onThemeSave
2558
+ }) {
2559
+ const [themeSetting, setThemeSetting] = (0, import_react11.useState)(initialState);
2560
+ const [previewTheme, setPreviewTheme] = (0, import_react11.useState)(null);
2561
+ const activeSetting = previewTheme ?? themeSetting;
2562
+ const currentTheme = activeSetting === "auto" ? "dark" : activeSetting;
2563
+ const value = (0, import_react11.useMemo)(
2564
+ () => ({
2565
+ themeSetting,
2566
+ setThemeSetting: (newSetting) => {
2567
+ setThemeSetting(newSetting);
2568
+ setPreviewTheme(null);
2569
+ onThemeSave?.(newSetting);
2570
+ },
2571
+ setPreviewTheme: (newSetting) => {
2572
+ setPreviewTheme(newSetting);
2573
+ },
2574
+ savePreview: () => {
2575
+ if (previewTheme !== null) {
2576
+ setThemeSetting(previewTheme);
2577
+ setPreviewTheme(null);
2578
+ onThemeSave?.(previewTheme);
2038
2579
  }
2039
- return prev;
2040
- });
2041
- },
2042
- [options, total]
2580
+ },
2581
+ cancelPreview: () => {
2582
+ if (previewTheme !== null) {
2583
+ setPreviewTheme(null);
2584
+ }
2585
+ },
2586
+ currentTheme
2587
+ }),
2588
+ [themeSetting, previewTheme, currentTheme, onThemeSave]
2043
2589
  );
2044
- (0, import_ink_renderer9.useInput)((input, key) => {
2045
- if (extraHandler?.(input, key, focusRef.current)) return;
2046
- if (key.upArrow || input === "k") {
2047
- moveFocus(-1);
2048
- } else if (key.downArrow || input === "j") {
2049
- moveFocus(1);
2050
- } else if (key.return) {
2051
- if (!options[focusRef.current]?.disabled) {
2052
- onSelect(focusRef.current);
2590
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ThemeContext.Provider, { value, children });
2591
+ }
2592
+ function useTheme() {
2593
+ const { currentTheme, setThemeSetting } = (0, import_react11.useContext)(ThemeContext);
2594
+ return [currentTheme, setThemeSetting];
2595
+ }
2596
+ function useThemeSetting() {
2597
+ return (0, import_react11.useContext)(ThemeContext).themeSetting;
2598
+ }
2599
+ function usePreviewTheme() {
2600
+ const { setPreviewTheme, savePreview, cancelPreview } = (0, import_react11.useContext)(ThemeContext);
2601
+ return { setPreviewTheme, savePreview, cancelPreview };
2602
+ }
2603
+
2604
+ // src/utils/optional/cliHighlight.ts
2605
+ var cliHighlightPromise;
2606
+ async function loadCliHighlight() {
2607
+ try {
2608
+ const mod = await import("cli-highlight");
2609
+ const cliHighlight = mod;
2610
+ return {
2611
+ highlight: cliHighlight.highlight,
2612
+ supportsLanguage: cliHighlight.supportsLanguage
2613
+ };
2614
+ } catch {
2615
+ return null;
2616
+ }
2617
+ }
2618
+ function getCliHighlightPromise() {
2619
+ cliHighlightPromise ?? (cliHighlightPromise = loadCliHighlight());
2620
+ return cliHighlightPromise;
2621
+ }
2622
+
2623
+ // src/utils/hash.ts
2624
+ function hashContent(content) {
2625
+ let h = 2166136261 | 0;
2626
+ for (let i = 0; i < content.length; i++) {
2627
+ h ^= content.charCodeAt(i);
2628
+ h = Math.imul(h, 16777619);
2629
+ }
2630
+ let h2 = 26499749718 | 0;
2631
+ for (let i = 0; i < content.length; i++) {
2632
+ h2 ^= content.charCodeAt(i);
2633
+ h2 = Math.imul(h2, 16777619);
2634
+ }
2635
+ return ((h >>> 0) * 1048576 + (h2 >>> 0)).toString(36) + content.length.toString(36);
2636
+ }
2637
+
2638
+ // src/utils/markdown.ts
2639
+ var import_chalk = __toESM(require("chalk"));
2640
+ var import_marked = require("marked");
2641
+ var import_strip_ansi = __toESM(require("strip-ansi"));
2642
+ var import_ink_renderer12 = require("@claude-code-kit/ink-renderer");
2643
+
2644
+ // src/design-system/color.ts
2645
+ var import_ink_renderer11 = require("@claude-code-kit/ink-renderer");
2646
+ function color(c, theme, type = "foreground") {
2647
+ return (text) => {
2648
+ if (!c) {
2649
+ return text;
2650
+ }
2651
+ if (c.startsWith("rgb(") || c.startsWith("#") || c.startsWith("ansi256(") || c.startsWith("ansi:")) {
2652
+ return (0, import_ink_renderer11.colorize)(text, c, type);
2653
+ }
2654
+ return (0, import_ink_renderer11.colorize)(text, getTheme(theme)[c], type);
2655
+ };
2656
+ }
2657
+
2658
+ // src/utils/markdown.ts
2659
+ function logForDebugging3(...args) {
2660
+ if (process.env["DEBUG"]) {
2661
+ console.debug(...args);
2662
+ }
2663
+ }
2664
+ var EOL = "\n";
2665
+ var BLOCKQUOTE_BAR = "\u258E";
2666
+ var OSC8_START = "\x1B]8;;";
2667
+ var OSC8_END = "\x07";
2668
+ function supportsHyperlinks() {
2669
+ const termProgram = process.env["TERM_PROGRAM"];
2670
+ const lcTerminal = process.env["LC_TERMINAL"];
2671
+ const term = process.env["TERM"];
2672
+ const supported = ["ghostty", "Hyper", "kitty", "alacritty", "iTerm.app", "iTerm2"];
2673
+ return !!(termProgram && supported.includes(termProgram)) || !!(lcTerminal && supported.includes(lcTerminal)) || !!term?.includes("kitty");
2674
+ }
2675
+ function createHyperlink(url, content) {
2676
+ if (!supportsHyperlinks()) {
2677
+ return url;
2678
+ }
2679
+ const displayText = content ?? url;
2680
+ const coloredText = import_chalk.default.blue(displayText);
2681
+ return `${OSC8_START}${url}${OSC8_END}${coloredText}${OSC8_START}${OSC8_END}`;
2682
+ }
2683
+ var markedConfigured = false;
2684
+ function configureMarked() {
2685
+ if (markedConfigured) return;
2686
+ markedConfigured = true;
2687
+ import_marked.marked.use({
2688
+ tokenizer: {
2689
+ del() {
2690
+ return void 0;
2691
+ }
2692
+ }
2693
+ });
2694
+ }
2695
+ function formatToken(token, theme, listDepth = 0, orderedListNumber = null, parent = null, highlight = null) {
2696
+ switch (token.type) {
2697
+ case "blockquote": {
2698
+ const inner = (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, null, highlight)).join("");
2699
+ const bar = import_chalk.default.dim(BLOCKQUOTE_BAR);
2700
+ return inner.split(EOL).map(
2701
+ (line) => (0, import_strip_ansi.default)(line).trim() ? `${bar} ${import_chalk.default.italic(line)}` : line
2702
+ ).join(EOL);
2703
+ }
2704
+ case "code": {
2705
+ if (!highlight) {
2706
+ return token.text + EOL;
2707
+ }
2708
+ let language = "plaintext";
2709
+ if (token.lang) {
2710
+ if (highlight.supportsLanguage(token.lang)) {
2711
+ language = token.lang;
2712
+ } else {
2713
+ logForDebugging3(
2714
+ `Language not supported while highlighting code, falling back to plaintext: ${token.lang}`
2715
+ );
2716
+ }
2717
+ }
2718
+ return highlight.highlight(token.text, { language }) + EOL;
2719
+ }
2720
+ case "codespan": {
2721
+ return color("permission", theme)(token.text);
2722
+ }
2723
+ case "em":
2724
+ return import_chalk.default.italic(
2725
+ (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, parent, highlight)).join("")
2726
+ );
2727
+ case "strong":
2728
+ return import_chalk.default.bold(
2729
+ (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, parent, highlight)).join("")
2730
+ );
2731
+ case "heading":
2732
+ switch (token.depth) {
2733
+ case 1:
2734
+ return import_chalk.default.bold.italic.underline(
2735
+ (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, null, highlight)).join("")
2736
+ ) + EOL + EOL;
2737
+ case 2:
2738
+ return import_chalk.default.bold(
2739
+ (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, null, highlight)).join("")
2740
+ ) + EOL + EOL;
2741
+ default:
2742
+ return import_chalk.default.bold(
2743
+ (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, null, highlight)).join("")
2744
+ ) + EOL + EOL;
2745
+ }
2746
+ case "hr":
2747
+ return "---";
2748
+ case "image":
2749
+ return token.href;
2750
+ case "link": {
2751
+ if (token.href.startsWith("mailto:")) {
2752
+ const email = token.href.replace(/^mailto:/, "");
2753
+ return email;
2754
+ }
2755
+ const linkText = (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, token, highlight)).join("");
2756
+ const plainLinkText = (0, import_strip_ansi.default)(linkText);
2757
+ if (plainLinkText && plainLinkText !== token.href) {
2758
+ return createHyperlink(token.href, linkText);
2759
+ }
2760
+ return createHyperlink(token.href);
2761
+ }
2762
+ case "list": {
2763
+ return token.items.map(
2764
+ (_, index) => formatToken(
2765
+ _,
2766
+ theme,
2767
+ listDepth,
2768
+ token.ordered ? token.start + index : null,
2769
+ token,
2770
+ highlight
2771
+ )
2772
+ ).join("");
2773
+ }
2774
+ case "list_item":
2775
+ return (token.tokens ?? []).map(
2776
+ (_) => `${" ".repeat(listDepth)}${formatToken(_, theme, listDepth + 1, orderedListNumber, token, highlight)}`
2777
+ ).join("");
2778
+ case "paragraph":
2779
+ return (token.tokens ?? []).map((_) => formatToken(_, theme, 0, null, null, highlight)).join("") + EOL;
2780
+ case "space":
2781
+ return EOL;
2782
+ case "br":
2783
+ return EOL;
2784
+ case "text":
2785
+ if (parent?.type === "link") {
2786
+ return token.text;
2787
+ }
2788
+ if (parent?.type === "list_item") {
2789
+ return `${orderedListNumber === null ? "-" : getListNumber(listDepth, orderedListNumber) + "."} ${token.tokens ? token.tokens.map((_) => formatToken(_, theme, listDepth, orderedListNumber, token, highlight)).join("") : linkifyIssueReferences(token.text)}${EOL}`;
2790
+ }
2791
+ return linkifyIssueReferences(token.text);
2792
+ case "table": {
2793
+ let getDisplayText2 = function(tokens) {
2794
+ return (0, import_strip_ansi.default)(
2795
+ tokens?.map((_) => formatToken(_, theme, 0, null, null, highlight)).join("") ?? ""
2796
+ );
2797
+ };
2798
+ var getDisplayText = getDisplayText2;
2799
+ const tableToken = token;
2800
+ const columnWidths = tableToken.header.map((header, index) => {
2801
+ let maxWidth = (0, import_ink_renderer12.stringWidth)(getDisplayText2(header.tokens));
2802
+ for (const row of tableToken.rows) {
2803
+ const cellLength = (0, import_ink_renderer12.stringWidth)(getDisplayText2(row[index]?.tokens));
2804
+ maxWidth = Math.max(maxWidth, cellLength);
2805
+ }
2806
+ return Math.max(maxWidth, 3);
2807
+ });
2808
+ let tableOutput = "| ";
2809
+ tableToken.header.forEach((header, index) => {
2810
+ const content = header.tokens?.map((_) => formatToken(_, theme, 0, null, null, highlight)).join("") ?? "";
2811
+ const displayText = getDisplayText2(header.tokens);
2812
+ const width = columnWidths[index];
2813
+ const align = tableToken.align?.[index];
2814
+ tableOutput += padAligned(content, (0, import_ink_renderer12.stringWidth)(displayText), width, align) + " | ";
2815
+ });
2816
+ tableOutput = tableOutput.trimEnd() + EOL;
2817
+ tableOutput += "|";
2818
+ columnWidths.forEach((width) => {
2819
+ const separator = "-".repeat(width + 2);
2820
+ tableOutput += separator + "|";
2821
+ });
2822
+ tableOutput += EOL;
2823
+ tableToken.rows.forEach((row) => {
2824
+ tableOutput += "| ";
2825
+ row.forEach((cell, index) => {
2826
+ const content = cell.tokens?.map((_) => formatToken(_, theme, 0, null, null, highlight)).join("") ?? "";
2827
+ const displayText = getDisplayText2(cell.tokens);
2828
+ const width = columnWidths[index];
2829
+ const align = tableToken.align?.[index];
2830
+ tableOutput += padAligned(content, (0, import_ink_renderer12.stringWidth)(displayText), width, align) + " | ";
2831
+ });
2832
+ tableOutput = tableOutput.trimEnd() + EOL;
2833
+ });
2834
+ return tableOutput + EOL;
2835
+ }
2836
+ case "escape":
2837
+ return token.text;
2838
+ case "def":
2839
+ case "del":
2840
+ case "html":
2841
+ return "";
2842
+ }
2843
+ return "";
2844
+ }
2845
+ var ISSUE_REF_PATTERN = /(^|[^\w./-])([A-Za-z0-9][\w-]*\/[A-Za-z0-9][\w.-]*)#(\d+)\b/g;
2846
+ function linkifyIssueReferences(text) {
2847
+ if (!supportsHyperlinks()) {
2848
+ return text;
2849
+ }
2850
+ return text.replace(
2851
+ ISSUE_REF_PATTERN,
2852
+ (_match, prefix, repo, num) => prefix + createHyperlink(
2853
+ `https://github.com/${repo}/issues/${num}`,
2854
+ `${repo}#${num}`
2855
+ )
2856
+ );
2857
+ }
2858
+ function numberToLetter(n) {
2859
+ let result = "";
2860
+ while (n > 0) {
2861
+ n--;
2862
+ result = String.fromCharCode(97 + n % 26) + result;
2863
+ n = Math.floor(n / 26);
2864
+ }
2865
+ return result;
2866
+ }
2867
+ var ROMAN_VALUES = [
2868
+ [1e3, "m"],
2869
+ [900, "cm"],
2870
+ [500, "d"],
2871
+ [400, "cd"],
2872
+ [100, "c"],
2873
+ [90, "xc"],
2874
+ [50, "l"],
2875
+ [40, "xl"],
2876
+ [10, "x"],
2877
+ [9, "ix"],
2878
+ [5, "v"],
2879
+ [4, "iv"],
2880
+ [1, "i"]
2881
+ ];
2882
+ function numberToRoman(n) {
2883
+ let result = "";
2884
+ for (const [value, numeral] of ROMAN_VALUES) {
2885
+ while (n >= value) {
2886
+ result += numeral;
2887
+ n -= value;
2888
+ }
2889
+ }
2890
+ return result;
2891
+ }
2892
+ function getListNumber(listDepth, orderedListNumber) {
2893
+ switch (listDepth) {
2894
+ case 0:
2895
+ case 1:
2896
+ return orderedListNumber.toString();
2897
+ case 2:
2898
+ return numberToLetter(orderedListNumber);
2899
+ case 3:
2900
+ return numberToRoman(orderedListNumber);
2901
+ default:
2902
+ return orderedListNumber.toString();
2903
+ }
2904
+ }
2905
+ function padAligned(content, displayWidth, targetWidth, align) {
2906
+ const padding = Math.max(0, targetWidth - displayWidth);
2907
+ if (align === "center") {
2908
+ const leftPad = Math.floor(padding / 2);
2909
+ return " ".repeat(leftPad) + content + " ".repeat(padding - leftPad);
2910
+ }
2911
+ if (align === "right") {
2912
+ return " ".repeat(padding) + content;
2913
+ }
2914
+ return content + " ".repeat(padding);
2915
+ }
2916
+
2917
+ // src/MarkdownTable.tsx
2918
+ var import_react12 = require("react");
2919
+ var import_strip_ansi2 = __toESM(require("strip-ansi"));
2920
+ var import_ink_renderer13 = require("@claude-code-kit/ink-renderer");
2921
+ var import_ink_renderer14 = require("@claude-code-kit/ink-renderer");
2922
+ var import_ink_renderer15 = require("@claude-code-kit/ink-renderer");
2923
+ var import_ink_renderer16 = require("@claude-code-kit/ink-renderer");
2924
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2925
+ var SAFETY_MARGIN = 4;
2926
+ var MIN_COLUMN_WIDTH = 3;
2927
+ var MAX_ROW_LINES = 4;
2928
+ var ANSI_BOLD_START = "\x1B[1m";
2929
+ var ANSI_BOLD_END = "\x1B[22m";
2930
+ function wrapText(text, width, options) {
2931
+ if (width <= 0) return [text];
2932
+ const trimmedText = text.trimEnd();
2933
+ const wrapped = (0, import_ink_renderer15.wrapAnsi)(trimmedText, width, {
2934
+ hard: options?.hard ?? false,
2935
+ trim: false,
2936
+ wordWrap: true
2937
+ });
2938
+ const lines = wrapped.split("\n").filter((line) => line.length > 0);
2939
+ return lines.length > 0 ? lines : [""];
2940
+ }
2941
+ function MarkdownTable({
2942
+ token,
2943
+ highlight,
2944
+ forceWidth
2945
+ }) {
2946
+ const [theme] = useTheme();
2947
+ const terminalSize = (0, import_react12.useContext)(import_ink_renderer13.TerminalSizeContext);
2948
+ const actualTerminalWidth = terminalSize?.columns ?? 80;
2949
+ const terminalWidth = forceWidth ?? actualTerminalWidth;
2950
+ function formatCell(tokens) {
2951
+ return tokens?.map((_) => formatToken(_, theme, 0, null, null, highlight)).join("") ?? "";
2952
+ }
2953
+ function getPlainText(tokens_0) {
2954
+ return (0, import_strip_ansi2.default)(formatCell(tokens_0));
2955
+ }
2956
+ function getMinWidth(tokens_1) {
2957
+ const text = getPlainText(tokens_1);
2958
+ const words = text.split(/\s+/).filter((w) => w.length > 0);
2959
+ if (words.length === 0) return MIN_COLUMN_WIDTH;
2960
+ return Math.max(...words.map((w_0) => (0, import_ink_renderer14.stringWidth)(w_0)), MIN_COLUMN_WIDTH);
2961
+ }
2962
+ function getIdealWidth(tokens_2) {
2963
+ return Math.max((0, import_ink_renderer14.stringWidth)(getPlainText(tokens_2)), MIN_COLUMN_WIDTH);
2964
+ }
2965
+ const minWidths = token.header.map((header, colIndex) => {
2966
+ let maxMinWidth = getMinWidth(header.tokens);
2967
+ for (const row of token.rows) {
2968
+ maxMinWidth = Math.max(maxMinWidth, getMinWidth(row[colIndex]?.tokens));
2969
+ }
2970
+ return maxMinWidth;
2971
+ });
2972
+ const idealWidths = token.header.map((header_0, colIndex_0) => {
2973
+ let maxIdeal = getIdealWidth(header_0.tokens);
2974
+ for (const row_0 of token.rows) {
2975
+ maxIdeal = Math.max(maxIdeal, getIdealWidth(row_0[colIndex_0]?.tokens));
2976
+ }
2977
+ return maxIdeal;
2978
+ });
2979
+ const numCols = token.header.length;
2980
+ const borderOverhead = 1 + numCols * 3;
2981
+ const availableWidth = Math.max(terminalWidth - borderOverhead - SAFETY_MARGIN, numCols * MIN_COLUMN_WIDTH);
2982
+ const totalMin = minWidths.reduce((sum, w_1) => sum + w_1, 0);
2983
+ const totalIdeal = idealWidths.reduce((sum_0, w_2) => sum_0 + w_2, 0);
2984
+ let needsHardWrap = false;
2985
+ let columnWidths;
2986
+ if (totalIdeal <= availableWidth) {
2987
+ columnWidths = idealWidths;
2988
+ } else if (totalMin <= availableWidth) {
2989
+ const extraSpace = availableWidth - totalMin;
2990
+ const overflows = idealWidths.map((ideal, i) => ideal - minWidths[i]);
2991
+ const totalOverflow = overflows.reduce((sum_1, o) => sum_1 + o, 0);
2992
+ columnWidths = minWidths.map((min, i_0) => {
2993
+ if (totalOverflow === 0) return min;
2994
+ const extra = Math.floor(overflows[i_0] / totalOverflow * extraSpace);
2995
+ return min + extra;
2996
+ });
2997
+ } else {
2998
+ needsHardWrap = true;
2999
+ const scaleFactor = availableWidth / totalMin;
3000
+ columnWidths = minWidths.map((w_3) => Math.max(Math.floor(w_3 * scaleFactor), MIN_COLUMN_WIDTH));
3001
+ }
3002
+ function calculateMaxRowLines() {
3003
+ let maxLines = 1;
3004
+ for (let i_1 = 0; i_1 < token.header.length; i_1++) {
3005
+ const content = formatCell(token.header[i_1].tokens);
3006
+ const wrapped = wrapText(content, columnWidths[i_1], {
3007
+ hard: needsHardWrap
3008
+ });
3009
+ maxLines = Math.max(maxLines, wrapped.length);
3010
+ }
3011
+ for (const row_1 of token.rows) {
3012
+ for (let i_2 = 0; i_2 < row_1.length; i_2++) {
3013
+ const content_0 = formatCell(row_1[i_2]?.tokens);
3014
+ const wrapped_0 = wrapText(content_0, columnWidths[i_2], {
3015
+ hard: needsHardWrap
3016
+ });
3017
+ maxLines = Math.max(maxLines, wrapped_0.length);
3018
+ }
3019
+ }
3020
+ return maxLines;
3021
+ }
3022
+ const maxRowLines = calculateMaxRowLines();
3023
+ const useVerticalFormat = maxRowLines > MAX_ROW_LINES;
3024
+ function renderRowLines(cells, isHeader) {
3025
+ const cellLines = cells.map((cell, colIndex_1) => {
3026
+ const formattedText = formatCell(cell.tokens);
3027
+ const width = columnWidths[colIndex_1];
3028
+ return wrapText(formattedText, width, {
3029
+ hard: needsHardWrap
3030
+ });
3031
+ });
3032
+ const maxLines_0 = Math.max(...cellLines.map((lines) => lines.length), 1);
3033
+ const verticalOffsets = cellLines.map((lines_0) => Math.floor((maxLines_0 - lines_0.length) / 2));
3034
+ const result = [];
3035
+ for (let lineIdx = 0; lineIdx < maxLines_0; lineIdx++) {
3036
+ let line = "\u2502";
3037
+ for (let colIndex_2 = 0; colIndex_2 < cells.length; colIndex_2++) {
3038
+ const lines_1 = cellLines[colIndex_2];
3039
+ const offset = verticalOffsets[colIndex_2];
3040
+ const contentLineIdx = lineIdx - offset;
3041
+ const lineText = contentLineIdx >= 0 && contentLineIdx < lines_1.length ? lines_1[contentLineIdx] : "";
3042
+ const width_0 = columnWidths[colIndex_2];
3043
+ const align = isHeader ? "center" : token.align?.[colIndex_2] ?? "left";
3044
+ line += " " + padAligned(lineText, (0, import_ink_renderer14.stringWidth)(lineText), width_0, align) + " \u2502";
3045
+ }
3046
+ result.push(line);
3047
+ }
3048
+ return result;
3049
+ }
3050
+ function renderBorderLine(type) {
3051
+ const [left, mid, cross, right] = {
3052
+ top: ["\u250C", "\u2500", "\u252C", "\u2510"],
3053
+ middle: ["\u251C", "\u2500", "\u253C", "\u2524"],
3054
+ bottom: ["\u2514", "\u2500", "\u2534", "\u2518"]
3055
+ }[type];
3056
+ let line_0 = left;
3057
+ columnWidths.forEach((width_1, colIndex_3) => {
3058
+ line_0 += mid.repeat(width_1 + 2);
3059
+ line_0 += colIndex_3 < columnWidths.length - 1 ? cross : right;
3060
+ });
3061
+ return line_0;
3062
+ }
3063
+ function renderVerticalFormat() {
3064
+ const lines_2 = [];
3065
+ const headers = token.header.map((h) => getPlainText(h.tokens));
3066
+ const separatorWidth = Math.min(terminalWidth - 1, 40);
3067
+ const separator = "\u2500".repeat(separatorWidth);
3068
+ const wrapIndent = " ";
3069
+ token.rows.forEach((row_2, rowIndex) => {
3070
+ if (rowIndex > 0) {
3071
+ lines_2.push(separator);
3072
+ }
3073
+ row_2.forEach((cell_0, colIndex_4) => {
3074
+ const label = headers[colIndex_4] || `Column ${colIndex_4 + 1}`;
3075
+ const rawValue = formatCell(cell_0.tokens).trimEnd();
3076
+ const value = rawValue.replace(/\n+/g, " ").replace(/\s+/g, " ").trim();
3077
+ const firstLineWidth = terminalWidth - (0, import_ink_renderer14.stringWidth)(label) - 3;
3078
+ const subsequentLineWidth = terminalWidth - wrapIndent.length - 1;
3079
+ const firstPassLines = wrapText(value, Math.max(firstLineWidth, 10));
3080
+ const firstLine = firstPassLines[0] || "";
3081
+ let wrappedValue;
3082
+ if (firstPassLines.length <= 1 || subsequentLineWidth <= firstLineWidth) {
3083
+ wrappedValue = firstPassLines;
3084
+ } else {
3085
+ const remainingText = firstPassLines.slice(1).map((l) => l.trim()).join(" ");
3086
+ const rewrapped = wrapText(remainingText, subsequentLineWidth);
3087
+ wrappedValue = [firstLine, ...rewrapped];
3088
+ }
3089
+ lines_2.push(`${ANSI_BOLD_START}${label}:${ANSI_BOLD_END} ${wrappedValue[0] || ""}`);
3090
+ for (let i_3 = 1; i_3 < wrappedValue.length; i_3++) {
3091
+ const line_1 = wrappedValue[i_3];
3092
+ if (!line_1.trim()) continue;
3093
+ lines_2.push(`${wrapIndent}${line_1}`);
3094
+ }
3095
+ });
3096
+ });
3097
+ return lines_2.join("\n");
3098
+ }
3099
+ if (useVerticalFormat) {
3100
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink_renderer16.Ansi, { children: renderVerticalFormat() });
3101
+ }
3102
+ const tableLines = [];
3103
+ tableLines.push(renderBorderLine("top"));
3104
+ tableLines.push(...renderRowLines(token.header, true));
3105
+ tableLines.push(renderBorderLine("middle"));
3106
+ token.rows.forEach((row_3, rowIndex_0) => {
3107
+ tableLines.push(...renderRowLines(row_3, false));
3108
+ if (rowIndex_0 < token.rows.length - 1) {
3109
+ tableLines.push(renderBorderLine("middle"));
3110
+ }
3111
+ });
3112
+ tableLines.push(renderBorderLine("bottom"));
3113
+ const maxLineWidth = Math.max(...tableLines.map((line_2) => (0, import_ink_renderer14.stringWidth)((0, import_strip_ansi2.default)(line_2))));
3114
+ if (maxLineWidth > terminalWidth - SAFETY_MARGIN) {
3115
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink_renderer16.Ansi, { children: renderVerticalFormat() });
3116
+ }
3117
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink_renderer16.Ansi, { children: tableLines.join("\n") });
3118
+ }
3119
+
3120
+ // src/Markdown.tsx
3121
+ var import_jsx_runtime12 = require("react/jsx-runtime");
3122
+ var TOKEN_CACHE_MAX = 500;
3123
+ var tokenCache = /* @__PURE__ */ new Map();
3124
+ var MD_SYNTAX_RE = /[#*`|[>\-_~]|\n\n|^\d+\. |\n\d+\. /;
3125
+ function hasMarkdownSyntax(s) {
3126
+ return MD_SYNTAX_RE.test(s.length > 500 ? s.slice(0, 500) : s);
3127
+ }
3128
+ function stripPromptXMLTags(content) {
3129
+ return content.replace(/<(commit_analysis|context|function_analysis|pr_analysis)>.*?<\/\1>\n?/gs, "").trim();
3130
+ }
3131
+ function cachedLexer(content) {
3132
+ if (!hasMarkdownSyntax(content)) {
3133
+ return [
3134
+ {
3135
+ type: "paragraph",
3136
+ raw: content,
3137
+ text: content,
3138
+ tokens: [{ type: "text", raw: content, text: content }]
3139
+ }
3140
+ ];
3141
+ }
3142
+ const key = hashContent(content);
3143
+ const hit = tokenCache.get(key);
3144
+ if (hit) {
3145
+ tokenCache.delete(key);
3146
+ tokenCache.set(key, hit);
3147
+ return hit;
3148
+ }
3149
+ const tokens = import_marked2.marked.lexer(content);
3150
+ if (tokenCache.size >= TOKEN_CACHE_MAX) {
3151
+ const first = tokenCache.keys().next().value;
3152
+ if (first !== void 0) tokenCache.delete(first);
3153
+ }
3154
+ tokenCache.set(key, tokens);
3155
+ return tokens;
3156
+ }
3157
+ function Markdown(props) {
3158
+ const settings = {};
3159
+ if (settings.syntaxHighlightingDisabled) {
3160
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkdownBody, { ...props, highlight: null });
3161
+ }
3162
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react13.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkdownBody, { ...props, highlight: null }), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkdownWithHighlight, { ...props }) });
3163
+ }
3164
+ function MarkdownWithHighlight(props) {
3165
+ const highlight = (0, import_react13.use)(getCliHighlightPromise());
3166
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkdownBody, { ...props, highlight });
3167
+ }
3168
+ function MarkdownBody({
3169
+ children,
3170
+ dimColor,
3171
+ highlight
3172
+ }) {
3173
+ const [theme] = useTheme();
3174
+ configureMarked();
3175
+ const elements = (0, import_react13.useMemo)(() => {
3176
+ const tokens = cachedLexer(stripPromptXMLTags(children));
3177
+ const elements2 = [];
3178
+ let nonTableContent = "";
3179
+ function flushNonTableContent() {
3180
+ if (nonTableContent) {
3181
+ elements2.push(
3182
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink_renderer17.Ansi, { dimColor, children: nonTableContent.trim() }, elements2.length)
3183
+ );
3184
+ nonTableContent = "";
3185
+ }
3186
+ }
3187
+ for (const token of tokens) {
3188
+ if (token.type === "table") {
3189
+ flushNonTableContent();
3190
+ elements2.push(
3191
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3192
+ MarkdownTable,
3193
+ {
3194
+ token,
3195
+ highlight
3196
+ },
3197
+ elements2.length
3198
+ )
3199
+ );
3200
+ } else {
3201
+ nonTableContent += formatToken(token, theme, 0, null, null, highlight);
3202
+ }
3203
+ }
3204
+ flushNonTableContent();
3205
+ return elements2;
3206
+ }, [children, dimColor, highlight, theme]);
3207
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink_renderer17.Box, { flexDirection: "column", gap: 1, children: elements });
3208
+ }
3209
+ function StreamingMarkdown({
3210
+ children
3211
+ }) {
3212
+ "use no memo";
3213
+ configureMarked();
3214
+ const stripped = stripPromptXMLTags(children);
3215
+ const stablePrefixRef = (0, import_react13.useRef)("");
3216
+ if (!stripped.startsWith(stablePrefixRef.current)) {
3217
+ stablePrefixRef.current = "";
3218
+ }
3219
+ const boundary = stablePrefixRef.current.length;
3220
+ const tokens = import_marked2.marked.lexer(stripped.substring(boundary));
3221
+ let lastContentIdx = tokens.length - 1;
3222
+ while (lastContentIdx >= 0 && tokens[lastContentIdx].type === "space") {
3223
+ lastContentIdx--;
3224
+ }
3225
+ let advance = 0;
3226
+ for (let i = 0; i < lastContentIdx; i++) {
3227
+ advance += tokens[i].raw.length;
3228
+ }
3229
+ if (advance > 0) {
3230
+ stablePrefixRef.current = stripped.substring(0, boundary + advance);
3231
+ }
3232
+ const stablePrefix = stablePrefixRef.current;
3233
+ const unstableSuffix = stripped.substring(stablePrefix.length);
3234
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink_renderer17.Box, { flexDirection: "column", gap: 1, children: [
3235
+ stablePrefix && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Markdown, { children: stablePrefix }),
3236
+ unstableSuffix && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Markdown, { children: unstableSuffix })
3237
+ ] });
3238
+ }
3239
+
3240
+ // src/Select.tsx
3241
+ var import_react14 = require("react");
3242
+ var import_ink_renderer18 = require("@claude-code-kit/ink-renderer");
3243
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3244
+ function useListNavigation(opts) {
3245
+ const { options, maxVisible, onCancel, onSelect, extraHandler } = opts;
3246
+ const [focusIndex, setFocusIndex] = (0, import_react14.useState)(0);
3247
+ const focusRef = (0, import_react14.useRef)(focusIndex);
3248
+ focusRef.current = focusIndex;
3249
+ const total = options.length;
3250
+ const max = maxVisible ?? total;
3251
+ const scrollOffset = (0, import_react14.useMemo)(() => {
3252
+ if (total <= max) return 0;
3253
+ const half = Math.floor(max / 2);
3254
+ if (focusIndex <= half) return 0;
3255
+ if (focusIndex >= total - max + half) return total - max;
3256
+ return focusIndex - half;
3257
+ }, [focusIndex, total, max]);
3258
+ const visibleOptions = (0, import_react14.useMemo)(
3259
+ () => options.slice(scrollOffset, scrollOffset + max),
3260
+ [options, scrollOffset, max]
3261
+ );
3262
+ const moveFocus = (0, import_react14.useCallback)(
3263
+ (dir) => {
3264
+ setFocusIndex((prev) => {
3265
+ let next = prev;
3266
+ for (let i = 0; i < total; i++) {
3267
+ next = (next + dir + total) % total;
3268
+ if (!options[next].disabled) return next;
3269
+ }
3270
+ return prev;
3271
+ });
3272
+ },
3273
+ [options, total]
3274
+ );
3275
+ (0, import_ink_renderer18.useInput)((input, key) => {
3276
+ if (extraHandler?.(input, key, focusRef.current)) return;
3277
+ if (key.upArrow || input === "k") {
3278
+ moveFocus(-1);
3279
+ } else if (key.downArrow || input === "j") {
3280
+ moveFocus(1);
3281
+ } else if (key.return) {
3282
+ if (!options[focusRef.current]?.disabled) {
3283
+ onSelect(focusRef.current);
2053
3284
  }
2054
3285
  } else if (key.escape) {
2055
3286
  onCancel?.();
@@ -2064,7 +3295,7 @@ function useListNavigation(opts) {
2064
3295
  return { focusIndex, scrollOffset, visibleOptions, max, total };
2065
3296
  }
2066
3297
  function ScrollHint({ count, direction }) {
2067
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Text, { dimColor: true, children: [
3298
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Text, { dimColor: true, children: [
2068
3299
  " ",
2069
3300
  direction === "up" ? "\u2191" : "\u2193",
2070
3301
  " ",
@@ -2080,26 +3311,26 @@ function Select({
2080
3311
  title,
2081
3312
  maxVisible
2082
3313
  }) {
2083
- const handleSelect = (0, import_react8.useCallback)(
3314
+ const handleSelect = (0, import_react14.useCallback)(
2084
3315
  (index) => onChange(options[index].value),
2085
3316
  [onChange, options]
2086
3317
  );
2087
3318
  const { focusIndex, scrollOffset, visibleOptions, max, total } = useListNavigation({ options, maxVisible, onCancel, onSelect: handleSelect });
2088
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Box, { flexDirection: "column", children: [
2089
- title && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Text, { bold: true, children: title }) }),
2090
- scrollOffset > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollHint, { count: scrollOffset, direction: "up" }),
3319
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Box, { flexDirection: "column", children: [
3320
+ title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Text, { bold: true, children: title }) }),
3321
+ scrollOffset > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollHint, { count: scrollOffset, direction: "up" }),
2091
3322
  visibleOptions.map((opt, i) => {
2092
3323
  const realIndex = scrollOffset + i;
2093
3324
  const isFocused = realIndex === focusIndex;
2094
3325
  const isSelected = opt.value === defaultValue;
2095
3326
  const isDisabled = opt.disabled === true;
2096
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Box, { children: [
2097
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Text, { color: isFocused ? "cyan" : void 0, children: [
3327
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Box, { children: [
3328
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Text, { color: isFocused ? "cyan" : void 0, children: [
2098
3329
  isFocused ? "\u276F" : " ",
2099
3330
  " "
2100
3331
  ] }),
2101
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2102
- import_ink_renderer9.Text,
3332
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3333
+ import_ink_renderer18.Text,
2103
3334
  {
2104
3335
  color: isDisabled ? "gray" : isFocused ? "cyan" : void 0,
2105
3336
  bold: isFocused,
@@ -2111,15 +3342,15 @@ function Select({
2111
3342
  ]
2112
3343
  }
2113
3344
  ),
2114
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Text, { color: "green", children: " \u2713" }),
2115
- opt.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Text, { dimColor: true, children: [
3345
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Text, { color: "green", children: " \u2713" }),
3346
+ opt.description && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Text, { dimColor: true, children: [
2116
3347
  " ",
2117
3348
  opt.description
2118
3349
  ] })
2119
3350
  ] }, realIndex);
2120
3351
  }),
2121
- scrollOffset + max < total && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
2122
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Text, { dimColor: true, children: "Enter to confirm \xB7 Esc to exit" }) })
3352
+ scrollOffset + max < total && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
3353
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Text, { dimColor: true, children: "Enter to confirm \xB7 Esc to exit" }) })
2123
3354
  ] });
2124
3355
  }
2125
3356
  function MultiSelect({
@@ -2131,12 +3362,12 @@ function MultiSelect({
2131
3362
  title,
2132
3363
  maxVisible
2133
3364
  }) {
2134
- const [selected, setSelected] = (0, import_react8.useState)(() => new Set(selectedValues));
2135
- const handleConfirm = (0, import_react8.useCallback)(
3365
+ const [selected, setSelected] = (0, import_react14.useState)(() => new Set(selectedValues));
3366
+ const handleConfirm = (0, import_react14.useCallback)(
2136
3367
  () => onConfirm(Array.from(selected)),
2137
3368
  [onConfirm, selected]
2138
3369
  );
2139
- const handleSpace = (0, import_react8.useCallback)(
3370
+ const handleSpace = (0, import_react14.useCallback)(
2140
3371
  (input, _key, focusIndex2) => {
2141
3372
  if (input !== " ") return false;
2142
3373
  const opt = options[focusIndex2];
@@ -2159,21 +3390,21 @@ function MultiSelect({
2159
3390
  onSelect: handleConfirm,
2160
3391
  extraHandler: handleSpace
2161
3392
  });
2162
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Box, { flexDirection: "column", children: [
2163
- title && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Text, { bold: true, children: title }) }),
2164
- scrollOffset > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollHint, { count: scrollOffset, direction: "up" }),
3393
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Box, { flexDirection: "column", children: [
3394
+ title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Text, { bold: true, children: title }) }),
3395
+ scrollOffset > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollHint, { count: scrollOffset, direction: "up" }),
2165
3396
  visibleOptions.map((opt, i) => {
2166
3397
  const realIndex = scrollOffset + i;
2167
3398
  const isFocused = realIndex === focusIndex;
2168
3399
  const isChecked = selected.has(opt.value);
2169
3400
  const isDisabled = opt.disabled === true;
2170
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Box, { children: [
2171
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Text, { color: isFocused ? "cyan" : void 0, children: [
3401
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Box, { children: [
3402
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Text, { color: isFocused ? "cyan" : void 0, children: [
2172
3403
  isFocused ? "\u276F" : " ",
2173
3404
  " "
2174
3405
  ] }),
2175
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2176
- import_ink_renderer9.Text,
3406
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3407
+ import_ink_renderer18.Text,
2177
3408
  {
2178
3409
  color: isDisabled ? "gray" : isFocused ? "cyan" : void 0,
2179
3410
  bold: isFocused,
@@ -2187,83 +3418,330 @@ function MultiSelect({
2187
3418
  ]
2188
3419
  }
2189
3420
  ),
2190
- opt.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink_renderer9.Text, { dimColor: true, children: [
3421
+ opt.description && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink_renderer18.Text, { dimColor: true, children: [
2191
3422
  " ",
2192
3423
  opt.description
2193
3424
  ] })
2194
3425
  ] }, realIndex);
2195
3426
  }),
2196
- scrollOffset + max < total && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
2197
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink_renderer9.Text, { dimColor: true, children: "Space to toggle \xB7 Enter to confirm \xB7 Esc to exit" }) })
3427
+ scrollOffset + max < total && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
3428
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink_renderer18.Text, { dimColor: true, children: "Space to toggle \xB7 Enter to confirm \xB7 Esc to exit" }) })
3429
+ ] });
3430
+ }
3431
+
3432
+ // src/PermissionRequest.tsx
3433
+ var import_react15 = __toESM(require("react"));
3434
+ var import_ink_renderer19 = require("@claude-code-kit/ink-renderer");
3435
+ var import_jsx_runtime14 = require("react/jsx-runtime");
3436
+ function PermissionHeader({ toolName, width }) {
3437
+ const label = ` ${toolName} `;
3438
+ const labelLen = toolName.length + 2;
3439
+ const leftLen = 3;
3440
+ const rightLen = Math.max(0, width - leftLen - labelLen);
3441
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Text, { children: [
3442
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { dimColor: true, children: "\u2500".repeat(leftLen) }),
3443
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { bold: true, color: "cyan", children: label }),
3444
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { dimColor: true, children: "\u2500".repeat(rightLen) })
3445
+ ] });
3446
+ }
3447
+ function HorizontalRule({ width }) {
3448
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { dimColor: true, children: "\u2500".repeat(width) });
3449
+ }
3450
+ function BashPermissionContent({ command }) {
3451
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Box, { flexDirection: "column", children: [
3452
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { children: "Run command:" }),
3453
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { color: "yellow", children: command }) })
3454
+ ] });
3455
+ }
3456
+ function FileEditPermissionContent({
3457
+ filename,
3458
+ diff
3459
+ }) {
3460
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Box, { flexDirection: "column", children: [
3461
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Text, { children: [
3462
+ "Edit file: ",
3463
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { color: "cyan", bold: true, children: filename })
3464
+ ] }),
3465
+ diff && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, flexDirection: "column", children: diff.split("\n").map((line, i) => {
3466
+ let color2;
3467
+ if (line.startsWith("+")) color2 = "green";
3468
+ else if (line.startsWith("-")) color2 = "red";
3469
+ else if (line.startsWith("@")) color2 = "cyan";
3470
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { color: color2, dimColor: !color2 && !line.startsWith("+"), children: line }, i);
3471
+ }) })
3472
+ ] });
3473
+ }
3474
+ function PermissionRequest({
3475
+ toolName,
3476
+ description,
3477
+ details,
3478
+ showAlwaysAllow = true,
3479
+ onDecision,
3480
+ children,
3481
+ preview
3482
+ }) {
3483
+ const terminalSize = (0, import_react15.useContext)(import_ink_renderer19.TerminalSizeContext);
3484
+ const terminalWidth = Math.min((terminalSize?.columns ?? 80) - 2, 80);
3485
+ const options = (0, import_react15.useMemo)(() => {
3486
+ const opts = [
3487
+ { value: "allow", label: "Yes, allow this action" }
3488
+ ];
3489
+ if (showAlwaysAllow) {
3490
+ opts.push({ value: "always_allow", label: `Yes, and always allow ${toolName}` });
3491
+ }
3492
+ opts.push({ value: "deny", label: "No, deny" });
3493
+ return opts;
3494
+ }, [showAlwaysAllow, toolName]);
3495
+ const [focusIndex, setFocusIndex] = import_react15.default.useState(0);
3496
+ const focusRef = import_react15.default.useRef(focusIndex);
3497
+ focusRef.current = focusIndex;
3498
+ const decide = (0, import_react15.useCallback)(
3499
+ (action) => {
3500
+ onDecision(action);
3501
+ },
3502
+ [onDecision]
3503
+ );
3504
+ (0, import_ink_renderer19.useInput)((input, key) => {
3505
+ if (input === "y") {
3506
+ decide("allow");
3507
+ return;
3508
+ }
3509
+ if (input === "a" && showAlwaysAllow) {
3510
+ decide("always_allow");
3511
+ return;
3512
+ }
3513
+ if (input === "n" || key.escape) {
3514
+ decide("deny");
3515
+ return;
3516
+ }
3517
+ if (key.upArrow || input === "k") {
3518
+ setFocusIndex((prev) => (prev - 1 + options.length) % options.length);
3519
+ } else if (key.downArrow || input === "j") {
3520
+ setFocusIndex((prev) => (prev + 1) % options.length);
3521
+ } else if (key.return) {
3522
+ decide(options[focusRef.current].value);
3523
+ } else if (input >= "1" && input <= "9") {
3524
+ const idx = parseInt(input, 10) - 1;
3525
+ if (idx < options.length) {
3526
+ setFocusIndex(idx);
3527
+ decide(options[idx].value);
3528
+ }
3529
+ }
3530
+ });
3531
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Box, { flexDirection: "column", children: [
3532
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PermissionHeader, { toolName, width: terminalWidth }),
3533
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { children: description }) }),
3534
+ details && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, marginLeft: 4, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { color: "yellow", children: details }) }),
3535
+ children && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, marginLeft: 2, flexDirection: "column", children }),
3536
+ preview && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, marginLeft: 2, flexDirection: "column", children: preview }),
3537
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(HorizontalRule, { width: terminalWidth }) }),
3538
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, flexDirection: "column", children: options.map((opt, i) => {
3539
+ const isFocused = i === focusIndex;
3540
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Box, { children: [
3541
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink_renderer19.Text, { color: isFocused ? "cyan" : void 0, children: [
3542
+ isFocused ? "\u276F" : " ",
3543
+ " "
3544
+ ] }),
3545
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3546
+ import_ink_renderer19.Text,
3547
+ {
3548
+ color: isFocused ? "cyan" : void 0,
3549
+ bold: isFocused,
3550
+ children: [
3551
+ i + 1,
3552
+ ". ",
3553
+ opt.label
3554
+ ]
3555
+ }
3556
+ )
3557
+ ] }, opt.value);
3558
+ }) }),
3559
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink_renderer19.Text, { dimColor: true, children: "Enter to confirm \xB7 Esc to deny" }) })
2198
3560
  ] });
2199
3561
  }
2200
3562
 
2201
3563
  // src/MessageList.tsx
2202
- var import_ink_renderer10 = require("@claude-code-kit/ink-renderer");
2203
- var import_jsx_runtime10 = require("react/jsx-runtime");
3564
+ var import_react16 = require("react");
3565
+ var import_ink_renderer20 = require("@claude-code-kit/ink-renderer");
3566
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2204
3567
  var ROLE_CONFIG = {
2205
3568
  user: { icon: "\u276F", label: "You", color: "cyan" },
2206
3569
  assistant: { icon: "\u25CF", label: "Claude", color: "#DA7756" },
2207
3570
  system: { icon: "\u273B", label: "System", color: void 0 }
2208
3571
  };
2209
- function MessageItem({
2210
- message,
2211
- renderMessage
2212
- }) {
2213
- if (renderMessage) {
2214
- return renderMessage(message);
2215
- }
2216
- const config = ROLE_CONFIG[message.role];
2217
- const isSystem = message.role === "system";
2218
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Box, { flexDirection: "column", children: [
2219
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Box, { children: [
2220
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Text, { color: config.color, dimColor: isSystem, children: config.icon }),
2221
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Text, { color: config.color, dimColor: isSystem, bold: !isSystem, children: [
2222
- " ",
2223
- config.label
2224
- ] })
2225
- ] }),
2226
- message.content.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Text, { dimColor: isSystem, children: line }) }, i))
2227
- ] });
3572
+ var GUTTER = "\u23BF";
3573
+ function TextBlock({ text, dim }) {
3574
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: text.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { dimColor: dim, children: line }) }, i)) });
2228
3575
  }
2229
- function MessageList({
2230
- messages,
2231
- streamingContent,
2232
- renderMessage
2233
- }) {
2234
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Box, { flexDirection: "column", children: [
2235
- messages.map((message, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Box, { flexDirection: "column", marginTop: i > 0 ? 1 : 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageItem, { message, renderMessage }) }, message.id)),
2236
- streamingContent != null && streamingContent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Box, { flexDirection: "column", marginTop: messages.length > 0 ? 1 : 0, children: [
2237
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Box, { children: [
2238
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Text, { color: "#DA7756", children: "\u25CF" }),
2239
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Text, { color: "#DA7756", bold: true, children: [
2240
- " ",
2241
- "Claude"
3576
+ function ToolUseBlock({ content }) {
3577
+ const statusColor = content.status === "error" ? "red" : content.status === "success" ? "green" : void 0;
3578
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginLeft: 2, children: [
3579
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3580
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { dimColor: true, children: [
3581
+ GUTTER,
3582
+ " "
3583
+ ] }),
3584
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { bold: true, children: content.toolName })
3585
+ ] }),
3586
+ content.input.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 4, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { dimColor: true, children: line }) }, i)),
3587
+ content.status === "running" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 4, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Spinner, { label: content.toolName, showElapsed: true }) }),
3588
+ content.result != null && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginLeft: 4, children: [
3589
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3590
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { dimColor: true, children: [
3591
+ GUTTER,
3592
+ " "
3593
+ ] }),
3594
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { color: statusColor, children: [
3595
+ "result (",
3596
+ content.status ?? "done",
3597
+ ")"
2242
3598
  ] })
2243
3599
  ] }),
2244
- streamingContent.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink_renderer10.Text, { children: [
2245
- line,
2246
- i === streamingContent.split("\n").length - 1 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink_renderer10.Text, { color: "#DA7756", children: "\u2588" })
2247
- ] }) }, i))
3600
+ content.result.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 6, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: statusColor, dimColor: !statusColor, children: line }) }, i))
2248
3601
  ] })
2249
3602
  ] });
2250
3603
  }
2251
-
3604
+ function ThinkingBlock({ content }) {
3605
+ const [collapsed, setCollapsed] = (0, import_react16.useState)(content.collapsed ?? true);
3606
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginLeft: 2, children: [
3607
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { onClick: () => setCollapsed((c) => !c), children: [
3608
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { color: "#DA7756", children: [
3609
+ "\u273B",
3610
+ " "
3611
+ ] }),
3612
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { dimColor: true, children: [
3613
+ "Thinking...",
3614
+ collapsed ? " (click to expand)" : ""
3615
+ ] })
3616
+ ] }),
3617
+ !collapsed && content.text.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 4, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { dimColor: true, children: line }) }, i))
3618
+ ] });
3619
+ }
3620
+ function DiffBlock({ content }) {
3621
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginLeft: 2, children: [
3622
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3623
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { dimColor: true, children: [
3624
+ GUTTER,
3625
+ " "
3626
+ ] }),
3627
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { bold: true, children: content.filename })
3628
+ ] }),
3629
+ content.diff.split("\n").map((line, i) => {
3630
+ let color2;
3631
+ if (line.startsWith("+")) color2 = "green";
3632
+ else if (line.startsWith("-")) color2 = "red";
3633
+ else if (line.startsWith("@")) color2 = "cyan";
3634
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 4, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: color2, dimColor: !color2, children: line }) }, i);
3635
+ })
3636
+ ] });
3637
+ }
3638
+ function CodeBlock({ content }) {
3639
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginLeft: 2, children: [
3640
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { dimColor: true, children: [
3641
+ "```",
3642
+ content.language ?? ""
3643
+ ] }),
3644
+ content.code.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { children: line }) }, i)),
3645
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { dimColor: true, children: "```" })
3646
+ ] });
3647
+ }
3648
+ function ErrorBlock({ content }) {
3649
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginLeft: 2, children: [
3650
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3651
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { color: "red", children: [
3652
+ "\u2716",
3653
+ " Error: "
3654
+ ] }),
3655
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: "red", children: content.message })
3656
+ ] }),
3657
+ content.details?.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 4, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: "red", dimColor: true, children: line }) }, i))
3658
+ ] });
3659
+ }
3660
+ function ContentBlock({ block }) {
3661
+ switch (block.type) {
3662
+ case "text":
3663
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TextBlock, { text: block.text });
3664
+ case "tool_use":
3665
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ToolUseBlock, { content: block });
3666
+ case "thinking":
3667
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ThinkingBlock, { content: block });
3668
+ case "diff":
3669
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DiffBlock, { content: block });
3670
+ case "code":
3671
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CodeBlock, { content: block });
3672
+ case "error":
3673
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ErrorBlock, { content: block });
3674
+ default:
3675
+ return null;
3676
+ }
3677
+ }
3678
+ function MessageItem({
3679
+ message,
3680
+ renderMessage
3681
+ }) {
3682
+ if (renderMessage) {
3683
+ return renderMessage(message);
3684
+ }
3685
+ const config = ROLE_CONFIG[message.role];
3686
+ const isSystem = message.role === "system";
3687
+ if (typeof message.content === "string") {
3688
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", children: [
3689
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3690
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: config.color, dimColor: isSystem, children: config.icon }),
3691
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { color: config.color, dimColor: isSystem, bold: !isSystem, children: [
3692
+ " ",
3693
+ config.label
3694
+ ] })
3695
+ ] }),
3696
+ message.content.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { dimColor: isSystem, children: line }) }, i))
3697
+ ] });
3698
+ }
3699
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", children: [
3700
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3701
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: config.color, dimColor: isSystem, children: config.icon }),
3702
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { color: config.color, dimColor: isSystem, bold: !isSystem, children: [
3703
+ " ",
3704
+ config.label
3705
+ ] })
3706
+ ] }),
3707
+ message.content.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ContentBlock, { block }, i))
3708
+ ] });
3709
+ }
3710
+ function MessageList({
3711
+ messages,
3712
+ streamingContent,
3713
+ renderMessage
3714
+ }) {
3715
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", children: [
3716
+ messages.map((message, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { flexDirection: "column", marginTop: i > 0 ? 1 : 0, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MessageItem, { message, renderMessage }) }, message.id)),
3717
+ streamingContent != null && streamingContent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { flexDirection: "column", marginTop: messages.length > 0 ? 1 : 0, children: [
3718
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Box, { children: [
3719
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: "#DA7756", children: "\u25CF" }),
3720
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: "#DA7756", bold: true, children: " Claude" })
3721
+ ] }),
3722
+ streamingContent.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink_renderer20.Text, { children: [
3723
+ line,
3724
+ i === streamingContent.split("\n").length - 1 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink_renderer20.Text, { color: "#DA7756", children: "\u2588" })
3725
+ ] }) }, i))
3726
+ ] })
3727
+ ] });
3728
+ }
3729
+
2252
3730
  // src/StreamingText.tsx
2253
- var import_react9 = require("react");
2254
- var import_ink_renderer11 = require("@claude-code-kit/ink-renderer");
2255
- var import_jsx_runtime11 = require("react/jsx-runtime");
3731
+ var import_react17 = require("react");
3732
+ var import_ink_renderer21 = require("@claude-code-kit/ink-renderer");
3733
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2256
3734
  function StreamingText({
2257
3735
  text,
2258
3736
  speed = 3,
2259
3737
  interval = 20,
2260
3738
  onComplete,
2261
- color
3739
+ color: color2
2262
3740
  }) {
2263
- const [revealed, setRevealed] = (0, import_react9.useState)(0);
2264
- const onCompleteRef = (0, import_react9.useRef)(onComplete);
3741
+ const [revealed, setRevealed] = (0, import_react17.useState)(0);
3742
+ const onCompleteRef = (0, import_react17.useRef)(onComplete);
2265
3743
  onCompleteRef.current = onComplete;
2266
- (0, import_react9.useEffect)(() => {
3744
+ (0, import_react17.useEffect)(() => {
2267
3745
  if (revealed >= text.length) return;
2268
3746
  const id = setInterval(() => {
2269
3747
  setRevealed((prev) => {
@@ -2276,19 +3754,171 @@ function StreamingText({
2276
3754
  }, interval);
2277
3755
  return () => clearInterval(id);
2278
3756
  }, [text.length, speed, interval, revealed >= text.length]);
2279
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink_renderer11.Text, { color, children: text.slice(0, revealed) });
3757
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink_renderer21.Text, { color: color2, children: text.slice(0, revealed) });
2280
3758
  }
2281
3759
 
2282
3760
  // src/REPL.tsx
2283
- var import_react10 = require("react");
2284
- var import_ink_renderer12 = require("@claude-code-kit/ink-renderer");
2285
- var import_jsx_runtime12 = require("react/jsx-runtime");
3761
+ var import_react19 = require("react");
3762
+ var import_ink_renderer23 = require("@claude-code-kit/ink-renderer");
3763
+
3764
+ // src/SearchOverlay.tsx
3765
+ var import_react18 = require("react");
3766
+ var import_ink_renderer22 = require("@claude-code-kit/ink-renderer");
3767
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3768
+ function computeMatches(content, query) {
3769
+ if (!query) return [];
3770
+ const lower = query.toLowerCase();
3771
+ const found = [];
3772
+ for (let i = 0; i < content.length; i++) {
3773
+ const text = content[i] ?? "";
3774
+ let offset = 0;
3775
+ let pos = text.toLowerCase().indexOf(lower, offset);
3776
+ while (pos !== -1) {
3777
+ found.push({ index: i, offset: pos, length: query.length });
3778
+ offset = pos + 1;
3779
+ pos = text.toLowerCase().indexOf(lower, offset);
3780
+ }
3781
+ }
3782
+ return found;
3783
+ }
3784
+ function useSearch({ content, isActive }) {
3785
+ const [query, setQueryState] = (0, import_react18.useState)("");
3786
+ const [matches, setMatches] = (0, import_react18.useState)([]);
3787
+ const [currentIndex, setCurrentIndex] = (0, import_react18.useState)(0);
3788
+ const setQuery = (0, import_react18.useCallback)((q) => {
3789
+ setQueryState(q);
3790
+ const found = computeMatches(content, q);
3791
+ setMatches(found);
3792
+ setCurrentIndex(found.length > 0 ? 0 : -1);
3793
+ }, [content]);
3794
+ const next = (0, import_react18.useCallback)(() => {
3795
+ if (matches.length === 0) return;
3796
+ setCurrentIndex((i) => (i + 1) % matches.length);
3797
+ }, [matches.length]);
3798
+ const previous = (0, import_react18.useCallback)(() => {
3799
+ if (matches.length === 0) return;
3800
+ setCurrentIndex((i) => (i - 1 + matches.length) % matches.length);
3801
+ }, [matches.length]);
3802
+ (0, import_react18.useEffect)(() => {
3803
+ if (!isActive) {
3804
+ setQueryState("");
3805
+ setMatches([]);
3806
+ setCurrentIndex(0);
3807
+ }
3808
+ }, [isActive]);
3809
+ return { query, matches, currentIndex, next, previous, setQuery };
3810
+ }
3811
+ function SearchOverlay({
3812
+ isOpen,
3813
+ onClose,
3814
+ onSearch,
3815
+ onNavigate
3816
+ }) {
3817
+ const [query, setQueryState] = (0, import_react18.useState)("");
3818
+ const [cursor, setCursor] = (0, import_react18.useState)(0);
3819
+ const [matches, setMatches] = (0, import_react18.useState)([]);
3820
+ const matchIndexRef = (0, import_react18.useRef)(0);
3821
+ const [matchIndex, setMatchIndexState] = (0, import_react18.useState)(0);
3822
+ const setMatchIndex = (0, import_react18.useCallback)((next) => {
3823
+ matchIndexRef.current = next;
3824
+ setMatchIndexState(next);
3825
+ }, []);
3826
+ (0, import_react18.useEffect)(() => {
3827
+ if (!isOpen) {
3828
+ setQueryState("");
3829
+ setCursor(0);
3830
+ setMatches([]);
3831
+ setMatchIndex(0);
3832
+ }
3833
+ }, [isOpen, setMatchIndex]);
3834
+ const runSearch = (0, import_react18.useCallback)((q) => {
3835
+ const found = onSearch(q);
3836
+ setMatches(found);
3837
+ setMatchIndex(0);
3838
+ if (found.length > 0) onNavigate(found[0]);
3839
+ }, [onSearch, onNavigate, setMatchIndex]);
3840
+ const navigate = (0, import_react18.useCallback)((delta) => {
3841
+ setMatches((currentMatches) => {
3842
+ if (currentMatches.length === 0) return currentMatches;
3843
+ const next = (matchIndexRef.current + delta + currentMatches.length) % currentMatches.length;
3844
+ setMatchIndex(next);
3845
+ onNavigate(currentMatches[next]);
3846
+ return currentMatches;
3847
+ });
3848
+ }, [onNavigate, setMatchIndex]);
3849
+ (0, import_ink_renderer22.useInput)(
3850
+ (input, key) => {
3851
+ if (key.escape) {
3852
+ onClose();
3853
+ return;
3854
+ }
3855
+ if (key.return) {
3856
+ navigate(1);
3857
+ return;
3858
+ }
3859
+ if (input === "n" && key.ctrl) {
3860
+ navigate(1);
3861
+ return;
3862
+ }
3863
+ if (input === "p" && key.ctrl) {
3864
+ navigate(-1);
3865
+ return;
3866
+ }
3867
+ if (key.backspace) {
3868
+ if (cursor > 0) {
3869
+ const next = query.slice(0, cursor - 1) + query.slice(cursor);
3870
+ setQueryState(next);
3871
+ setCursor(cursor - 1);
3872
+ runSearch(next);
3873
+ }
3874
+ return;
3875
+ }
3876
+ if (key.leftArrow) {
3877
+ setCursor((c) => Math.max(0, c - 1));
3878
+ return;
3879
+ }
3880
+ if (key.rightArrow) {
3881
+ setCursor((c) => Math.min(query.length, c + 1));
3882
+ return;
3883
+ }
3884
+ if (key.ctrl || key.meta) return;
3885
+ if (input.length > 0) {
3886
+ const next = query.slice(0, cursor) + input + query.slice(cursor);
3887
+ setQueryState(next);
3888
+ setCursor(cursor + input.length);
3889
+ runSearch(next);
3890
+ }
3891
+ },
3892
+ { isActive: isOpen }
3893
+ );
3894
+ if (!isOpen) return null;
3895
+ const total = matches.length;
3896
+ const current = total > 0 ? matchIndex + 1 : 0;
3897
+ const countLabel = total > 0 ? `${current}/${total} matches` : "no matches";
3898
+ const before = query.slice(0, cursor);
3899
+ const atCursor = cursor < query.length ? query[cursor] : " ";
3900
+ const after = cursor < query.length ? query.slice(cursor + 1) : "";
3901
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_ink_renderer22.Box, { flexDirection: "row", paddingX: 1, children: [
3902
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_ink_renderer22.Text, { color: "cyan", children: "Search: " }),
3903
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_ink_renderer22.Box, { flexGrow: 1, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_ink_renderer22.Text, { children: [
3904
+ before,
3905
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_ink_renderer22.Text, { inverse: true, children: atCursor }),
3906
+ after
3907
+ ] }) }),
3908
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_ink_renderer22.Text, { dimColor: true, children: countLabel })
3909
+ ] });
3910
+ }
3911
+
3912
+ // src/REPL.tsx
3913
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2286
3914
  function REPL({
2287
3915
  onSubmit,
2288
3916
  onExit,
2289
3917
  messages,
2290
3918
  isLoading = false,
2291
3919
  streamingContent,
3920
+ welcome,
3921
+ permissionRequest,
2292
3922
  commands = [],
2293
3923
  model,
2294
3924
  statusSegments,
@@ -2298,16 +3928,20 @@ function REPL({
2298
3928
  renderMessage,
2299
3929
  spinner
2300
3930
  }) {
2301
- const { exit } = (0, import_ink_renderer12.useApp)();
2302
- const [inputValue, setInputValue] = (0, import_react10.useState)("");
2303
- const [internalHistory, setInternalHistory] = (0, import_react10.useState)([]);
2304
- const submittingRef = (0, import_react10.useRef)(false);
3931
+ const { exit } = (0, import_ink_renderer23.useApp)();
3932
+ const [inputValue, setInputValue] = (0, import_react19.useState)("");
3933
+ const [internalHistory, setInternalHistory] = (0, import_react19.useState)([]);
3934
+ const [searchOpen, setSearchOpen] = (0, import_react19.useState)(false);
3935
+ const submittingRef = (0, import_react19.useRef)(false);
2305
3936
  const history = externalHistory ?? internalHistory;
3937
+ const messageContents = messages.map(
3938
+ (m) => typeof m.content === "string" ? m.content : m.content.map((b) => "text" in b ? b.text : "").join(" ")
3939
+ );
2306
3940
  const promptCommands = commands.map((c) => ({
2307
3941
  name: c.name,
2308
3942
  description: c.description
2309
3943
  }));
2310
- const handleSubmit = (0, import_react10.useCallback)(
3944
+ const handleSubmit = (0, import_react19.useCallback)(
2311
3945
  (value) => {
2312
3946
  if (submittingRef.current) return;
2313
3947
  const trimmed = value.trim();
@@ -2339,7 +3973,7 @@ function REPL({
2339
3973
  },
2340
3974
  [commands, onSubmit, externalHistory]
2341
3975
  );
2342
- (0, import_ink_renderer12.useInput)(
3976
+ (0, import_ink_renderer23.useInput)(
2343
3977
  (_input, key) => {
2344
3978
  if (key.ctrl && _input === "c" && isLoading) {
2345
3979
  return;
@@ -2351,13 +3985,20 @@ function REPL({
2351
3985
  exit();
2352
3986
  }
2353
3987
  }
3988
+ if (key.ctrl && _input === "f") {
3989
+ setSearchOpen(true);
3990
+ }
2354
3991
  },
2355
- { isActive: true }
3992
+ // Deactivate when search overlay is open so only SearchOverlay handles input.
3993
+ { isActive: !searchOpen }
2356
3994
  );
2357
3995
  const resolvedSegments = statusSegments ?? buildDefaultSegments(model);
2358
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink_renderer12.Box, { flexDirection: "column", flexGrow: 1, children: [
2359
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink_renderer12.Box, { flexDirection: "column", flexGrow: 1, children: [
2360
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3996
+ const showWelcome = welcome && messages.length === 0 && !isLoading;
3997
+ const showPermission = !!permissionRequest;
3998
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_ink_renderer23.Box, { flexDirection: "column", flexGrow: 1, children: [
3999
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_ink_renderer23.Box, { flexDirection: "column", flexGrow: 1, children: [
4000
+ showWelcome && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_ink_renderer23.Box, { marginBottom: 1, children: welcome }),
4001
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2361
4002
  MessageList,
2362
4003
  {
2363
4004
  messages,
@@ -2365,10 +4006,29 @@ function REPL({
2365
4006
  renderMessage
2366
4007
  }
2367
4008
  ),
2368
- isLoading && !streamingContent && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink_renderer12.Box, { marginTop: messages.length > 0 ? 1 : 0, children: spinner ?? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Spinner, {}) })
4009
+ isLoading && !streamingContent && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_ink_renderer23.Box, { marginTop: messages.length > 0 ? 1 : 0, children: spinner ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Spinner, {}) })
2369
4010
  ] }),
2370
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Divider, {}),
2371
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4011
+ searchOpen && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4012
+ SearchOverlay,
4013
+ {
4014
+ isOpen: searchOpen,
4015
+ onClose: () => setSearchOpen(false),
4016
+ onSearch: (q) => computeMatches(messageContents, q),
4017
+ onNavigate: () => {
4018
+ }
4019
+ }
4020
+ ),
4021
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Divider, {}),
4022
+ showPermission ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4023
+ PermissionRequest,
4024
+ {
4025
+ toolName: permissionRequest.toolName,
4026
+ description: permissionRequest.description,
4027
+ details: permissionRequest.details,
4028
+ preview: permissionRequest.preview,
4029
+ onDecision: permissionRequest.onDecision
4030
+ }
4031
+ ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2372
4032
  PromptInput,
2373
4033
  {
2374
4034
  value: inputValue,
@@ -2376,44 +4036,1367 @@ function REPL({
2376
4036
  onSubmit: handleSubmit,
2377
4037
  prefix,
2378
4038
  placeholder,
2379
- disabled: isLoading,
4039
+ disabled: isLoading || searchOpen,
2380
4040
  commands: promptCommands,
2381
4041
  history
2382
4042
  }
2383
4043
  ),
2384
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Divider, {}),
2385
- resolvedSegments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(StatusLine, { segments: resolvedSegments })
4044
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Divider, {}),
4045
+ resolvedSegments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StatusLine, { segments: resolvedSegments })
2386
4046
  ] });
2387
4047
  }
2388
4048
  function buildDefaultSegments(model) {
2389
4049
  if (!model) return [];
2390
4050
  return [{ content: model, color: "green" }];
2391
4051
  }
4052
+
4053
+ // src/design-system/ThemedBox.tsx
4054
+ var import_ink_renderer24 = require("@claude-code-kit/ink-renderer");
4055
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4056
+ function resolveColor(color2, theme) {
4057
+ if (!color2) return void 0;
4058
+ if (color2.startsWith("rgb(") || color2.startsWith("#") || color2.startsWith("ansi256(") || color2.startsWith("ansi:")) {
4059
+ return color2;
4060
+ }
4061
+ return theme[color2];
4062
+ }
4063
+ function ThemedBox({
4064
+ borderColor,
4065
+ borderTopColor,
4066
+ borderBottomColor,
4067
+ borderLeftColor,
4068
+ borderRightColor,
4069
+ backgroundColor,
4070
+ children,
4071
+ ref,
4072
+ ...rest
4073
+ }) {
4074
+ const [themeName] = useTheme();
4075
+ const theme = getTheme(themeName);
4076
+ const resolvedBorderColor = resolveColor(borderColor, theme);
4077
+ const resolvedBorderTopColor = resolveColor(borderTopColor, theme);
4078
+ const resolvedBorderBottomColor = resolveColor(borderBottomColor, theme);
4079
+ const resolvedBorderLeftColor = resolveColor(borderLeftColor, theme);
4080
+ const resolvedBorderRightColor = resolveColor(borderRightColor, theme);
4081
+ const resolvedBackgroundColor = resolveColor(backgroundColor, theme);
4082
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4083
+ import_ink_renderer24.Box,
4084
+ {
4085
+ ref,
4086
+ borderColor: resolvedBorderColor,
4087
+ borderTopColor: resolvedBorderTopColor,
4088
+ borderBottomColor: resolvedBorderBottomColor,
4089
+ borderLeftColor: resolvedBorderLeftColor,
4090
+ borderRightColor: resolvedBorderRightColor,
4091
+ backgroundColor: resolvedBackgroundColor,
4092
+ ...rest,
4093
+ children
4094
+ }
4095
+ );
4096
+ }
4097
+ var ThemedBox_default = ThemedBox;
4098
+
4099
+ // src/design-system/ThemedText.tsx
4100
+ var import_react20 = __toESM(require("react"));
4101
+ var import_ink_renderer25 = require("@claude-code-kit/ink-renderer");
4102
+ var import_jsx_runtime20 = require("react/jsx-runtime");
4103
+ var TextHoverColorContext = import_react20.default.createContext(void 0);
4104
+ function resolveColor2(color2, theme) {
4105
+ if (!color2) return void 0;
4106
+ if (color2.startsWith("rgb(") || color2.startsWith("#") || color2.startsWith("ansi256(") || color2.startsWith("ansi:")) {
4107
+ return color2;
4108
+ }
4109
+ return theme[color2];
4110
+ }
4111
+ function ThemedText({
4112
+ color: color2,
4113
+ backgroundColor,
4114
+ dimColor = false,
4115
+ bold = false,
4116
+ italic = false,
4117
+ underline = false,
4118
+ strikethrough = false,
4119
+ inverse = false,
4120
+ wrap = "wrap",
4121
+ children
4122
+ }) {
4123
+ const [themeName] = useTheme();
4124
+ const theme = getTheme(themeName);
4125
+ const hoverColor = (0, import_react20.useContext)(TextHoverColorContext);
4126
+ const resolvedColor = !color2 && hoverColor ? resolveColor2(hoverColor, theme) : dimColor ? theme.inactive : resolveColor2(color2, theme);
4127
+ const resolvedBackgroundColor = backgroundColor ? theme[backgroundColor] : void 0;
4128
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4129
+ import_ink_renderer25.Text,
4130
+ {
4131
+ color: resolvedColor,
4132
+ backgroundColor: resolvedBackgroundColor,
4133
+ bold,
4134
+ italic,
4135
+ underline,
4136
+ strikethrough,
4137
+ inverse,
4138
+ wrap,
4139
+ children
4140
+ }
4141
+ );
4142
+ }
4143
+
4144
+ // src/design-system/Dialog.tsx
4145
+ var import_react22 = require("react");
4146
+ var import_ink_renderer29 = require("@claude-code-kit/ink-renderer");
4147
+
4148
+ // src/design-system/Byline.tsx
4149
+ var import_react21 = __toESM(require("react"));
4150
+ var import_ink_renderer26 = require("@claude-code-kit/ink-renderer");
4151
+ var import_jsx_runtime21 = require("react/jsx-runtime");
4152
+ function Byline({ children }) {
4153
+ const validChildren = import_react21.Children.toArray(children);
4154
+ if (validChildren.length === 0) {
4155
+ return null;
4156
+ }
4157
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_jsx_runtime21.Fragment, { children: validChildren.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4158
+ import_react21.default.Fragment,
4159
+ {
4160
+ children: [
4161
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink_renderer26.Text, { dimColor: true, children: " \xB7 " }),
4162
+ child
4163
+ ]
4164
+ },
4165
+ (0, import_react21.isValidElement)(child) ? child.key ?? index : index
4166
+ )) });
4167
+ }
4168
+
4169
+ // src/design-system/KeyboardShortcutHint.tsx
4170
+ var import_ink_renderer27 = require("@claude-code-kit/ink-renderer");
4171
+ var import_jsx_runtime22 = require("react/jsx-runtime");
4172
+ function KeyboardShortcutHint({
4173
+ shortcut,
4174
+ action,
4175
+ parens = false,
4176
+ bold = false
4177
+ }) {
4178
+ const shortcutText = bold ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink_renderer27.Text, { bold: true, children: shortcut }) : shortcut;
4179
+ if (parens) {
4180
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_ink_renderer27.Text, { children: [
4181
+ "(",
4182
+ shortcutText,
4183
+ " to ",
4184
+ action,
4185
+ ")"
4186
+ ] });
4187
+ }
4188
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_ink_renderer27.Text, { children: [
4189
+ shortcutText,
4190
+ " to ",
4191
+ action
4192
+ ] });
4193
+ }
4194
+
4195
+ // src/design-system/Pane.tsx
4196
+ var import_ink_renderer28 = require("@claude-code-kit/ink-renderer");
4197
+ var import_jsx_runtime23 = require("react/jsx-runtime");
4198
+ function Pane({ children, color: color2 }) {
4199
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_ink_renderer28.Box, { flexDirection: "column", paddingTop: 1, children: [
4200
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Divider, { color: color2 }),
4201
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_ink_renderer28.Box, { flexDirection: "column", paddingX: 2, children })
4202
+ ] });
4203
+ }
4204
+
4205
+ // src/design-system/Dialog.tsx
4206
+ var import_jsx_runtime24 = require("react/jsx-runtime");
4207
+ function Dialog({
4208
+ title,
4209
+ subtitle,
4210
+ children,
4211
+ onCancel,
4212
+ color: color2 = "permission",
4213
+ hideInputGuide,
4214
+ hideBorder
4215
+ }) {
4216
+ (0, import_ink_renderer29.useInput)(
4217
+ (0, import_react22.useCallback)(
4218
+ (_input, key) => {
4219
+ if (key.escape) {
4220
+ onCancel();
4221
+ }
4222
+ },
4223
+ [onCancel]
4224
+ )
4225
+ );
4226
+ const defaultInputGuide = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Byline, { children: [
4227
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(KeyboardShortcutHint, { shortcut: "Enter", action: "confirm" }),
4228
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(KeyboardShortcutHint, { shortcut: "Esc", action: "cancel" })
4229
+ ] });
4230
+ const content = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
4231
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_ink_renderer29.Box, { flexDirection: "column", gap: 1, children: [
4232
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_ink_renderer29.Box, { flexDirection: "column", children: [
4233
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink_renderer29.Text, { bold: true, color: color2, children: title }),
4234
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink_renderer29.Text, { dimColor: true, children: subtitle })
4235
+ ] }),
4236
+ children
4237
+ ] }),
4238
+ !hideInputGuide && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink_renderer29.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink_renderer29.Text, { dimColor: true, italic: true, children: defaultInputGuide }) })
4239
+ ] });
4240
+ if (hideBorder) {
4241
+ return content;
4242
+ }
4243
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Pane, { color: color2, children: content });
4244
+ }
4245
+
4246
+ // src/design-system/FuzzyPicker.tsx
4247
+ var import_react23 = require("react");
4248
+ var import_ink_renderer32 = require("@claude-code-kit/ink-renderer");
4249
+
4250
+ // src/design-system/ListItem.tsx
4251
+ var import_figures2 = __toESM(require("figures"));
4252
+ var import_ink_renderer30 = require("@claude-code-kit/ink-renderer");
4253
+ var import_ink_renderer31 = require("@claude-code-kit/ink-renderer");
4254
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4255
+ function ListItem({
4256
+ isFocused,
4257
+ isSelected = false,
4258
+ children,
4259
+ description,
4260
+ showScrollDown,
4261
+ showScrollUp,
4262
+ styled = true,
4263
+ disabled = false,
4264
+ declareCursor
4265
+ }) {
4266
+ function renderIndicator() {
4267
+ if (disabled) {
4268
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { children: " " });
4269
+ }
4270
+ if (isFocused) {
4271
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { color: "cyan", children: import_figures2.default.pointer });
4272
+ }
4273
+ if (showScrollDown) {
4274
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { dimColor: true, children: import_figures2.default.arrowDown });
4275
+ }
4276
+ if (showScrollUp) {
4277
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { dimColor: true, children: import_figures2.default.arrowUp });
4278
+ }
4279
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { children: " " });
4280
+ }
4281
+ function getTextColor() {
4282
+ if (disabled) {
4283
+ return void 0;
4284
+ }
4285
+ if (!styled) {
4286
+ return void 0;
4287
+ }
4288
+ if (isSelected) {
4289
+ return "green";
4290
+ }
4291
+ if (isFocused) {
4292
+ return "cyan";
4293
+ }
4294
+ return void 0;
4295
+ }
4296
+ const textColor = getTextColor();
4297
+ const cursorRef = (0, import_ink_renderer30.useDeclaredCursor)({
4298
+ line: 0,
4299
+ column: 0,
4300
+ active: isFocused && !disabled && declareCursor !== false
4301
+ });
4302
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_ink_renderer31.Box, { ref: cursorRef, flexDirection: "column", children: [
4303
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_ink_renderer31.Box, { flexDirection: "row", gap: 1, children: [
4304
+ renderIndicator(),
4305
+ styled ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { color: textColor, dimColor: disabled, children }) : children,
4306
+ isSelected && !disabled && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { color: "green", children: import_figures2.default.tick })
4307
+ ] }),
4308
+ description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Box, { paddingLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_ink_renderer31.Text, { dimColor: true, children: description }) })
4309
+ ] });
4310
+ }
4311
+
4312
+ // src/design-system/FuzzyPicker.tsx
4313
+ var import_jsx_runtime26 = require("react/jsx-runtime");
4314
+ var DEFAULT_VISIBLE = 8;
4315
+ var CHROME_ROWS = 10;
4316
+ var MIN_VISIBLE = 2;
4317
+ function FuzzyPicker({
4318
+ title,
4319
+ placeholder = "Type to search...",
4320
+ initialQuery,
4321
+ items,
4322
+ getKey,
4323
+ renderItem,
4324
+ renderPreview,
4325
+ previewPosition = "bottom",
4326
+ visibleCount: requestedVisible = DEFAULT_VISIBLE,
4327
+ direction = "down",
4328
+ onQueryChange,
4329
+ onSelect,
4330
+ onTab,
4331
+ onShiftTab,
4332
+ onFocus,
4333
+ onCancel,
4334
+ emptyMessage = "No results",
4335
+ matchLabel,
4336
+ selectAction = "select",
4337
+ extraHints
4338
+ }) {
4339
+ const terminalSize = (0, import_react23.useContext)(import_ink_renderer32.TerminalSizeContext);
4340
+ const rows = terminalSize?.rows ?? 24;
4341
+ const columns = terminalSize?.columns ?? 80;
4342
+ const [focusedIndex, setFocusedIndex] = (0, import_react23.useState)(0);
4343
+ const [query, setQuery] = (0, import_react23.useState)(initialQuery ?? "");
4344
+ const visibleCount = Math.max(
4345
+ MIN_VISIBLE,
4346
+ Math.min(requestedVisible, rows - CHROME_ROWS - (matchLabel ? 1 : 0))
4347
+ );
4348
+ const compact = columns < 120;
4349
+ const step = (0, import_react23.useCallback)(
4350
+ (delta) => {
4351
+ setFocusedIndex((i) => (0, import_ink_renderer32.clamp)(i + delta, 0, items.length - 1));
4352
+ },
4353
+ [items.length]
4354
+ );
4355
+ (0, import_ink_renderer32.useInput)(
4356
+ (0, import_react23.useCallback)(
4357
+ (input, key) => {
4358
+ if (key.escape) {
4359
+ onCancel();
4360
+ return;
4361
+ }
4362
+ if (key.upArrow || key.ctrl && input === "p") {
4363
+ step(direction === "up" ? 1 : -1);
4364
+ return;
4365
+ }
4366
+ if (key.downArrow || key.ctrl && input === "n") {
4367
+ step(direction === "up" ? -1 : 1);
4368
+ return;
4369
+ }
4370
+ if (key.return) {
4371
+ const selected = items[focusedIndex];
4372
+ if (selected) onSelect(selected);
4373
+ return;
4374
+ }
4375
+ if (key.tab) {
4376
+ const selected = items[focusedIndex];
4377
+ if (!selected) return;
4378
+ const tabAction = key.shift ? onShiftTab ?? onTab : onTab;
4379
+ if (tabAction) {
4380
+ tabAction.handler(selected);
4381
+ } else {
4382
+ onSelect(selected);
4383
+ }
4384
+ return;
4385
+ }
4386
+ if (key.backspace) {
4387
+ setQuery((q) => q.slice(0, -1));
4388
+ return;
4389
+ }
4390
+ if (input && !key.ctrl) {
4391
+ setQuery((q) => q + input);
4392
+ }
4393
+ },
4394
+ [onCancel, step, direction, items, focusedIndex, onSelect, onShiftTab, onTab]
4395
+ )
4396
+ );
4397
+ (0, import_react23.useEffect)(() => {
4398
+ onQueryChange(query);
4399
+ setFocusedIndex(0);
4400
+ }, [query]);
4401
+ (0, import_react23.useEffect)(() => {
4402
+ setFocusedIndex((i) => (0, import_ink_renderer32.clamp)(i, 0, items.length - 1));
4403
+ }, [items.length]);
4404
+ const focused = items[focusedIndex];
4405
+ (0, import_react23.useEffect)(() => {
4406
+ onFocus?.(focused);
4407
+ }, [focused]);
4408
+ const windowStart = (0, import_ink_renderer32.clamp)(
4409
+ focusedIndex - visibleCount + 1,
4410
+ 0,
4411
+ items.length - visibleCount
4412
+ );
4413
+ const visible = items.slice(windowStart, windowStart + visibleCount);
4414
+ const emptyText = typeof emptyMessage === "function" ? emptyMessage(query) : emptyMessage;
4415
+ const searchInput = /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Box, { borderStyle: "round", paddingX: 1, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Text, { dimColor: !query, children: query || placeholder }) });
4416
+ const listBlock = /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4417
+ List,
4418
+ {
4419
+ visible,
4420
+ windowStart,
4421
+ visibleCount,
4422
+ total: items.length,
4423
+ focusedIndex,
4424
+ direction,
4425
+ getKey,
4426
+ renderItem,
4427
+ emptyText
4428
+ }
4429
+ );
4430
+ const preview = renderPreview && focused ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Box, { flexDirection: "column", flexGrow: 1, children: renderPreview(focused) }) : null;
4431
+ const listGroup = renderPreview && previewPosition === "right" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4432
+ import_ink_renderer32.Box,
4433
+ {
4434
+ flexDirection: "row",
4435
+ gap: 2,
4436
+ height: visibleCount + (matchLabel ? 1 : 0),
4437
+ children: [
4438
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_ink_renderer32.Box, { flexDirection: "column", flexShrink: 0, children: [
4439
+ listBlock,
4440
+ matchLabel && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Text, { dimColor: true, children: matchLabel })
4441
+ ] }),
4442
+ preview ?? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Box, { flexGrow: 1 })
4443
+ ]
4444
+ }
4445
+ ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_ink_renderer32.Box, { flexDirection: "column", children: [
4446
+ listBlock,
4447
+ matchLabel && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Text, { dimColor: true, children: matchLabel }),
4448
+ preview
4449
+ ] });
4450
+ const inputAbove = direction !== "up";
4451
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Pane, { color: "permission", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_ink_renderer32.Box, { flexDirection: "column", gap: 1, children: [
4452
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Text, { bold: true, color: "permission", children: title }),
4453
+ inputAbove && searchInput,
4454
+ listGroup,
4455
+ !inputAbove && searchInput,
4456
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Text, { dimColor: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Byline, { children: [
4457
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4458
+ KeyboardShortcutHint,
4459
+ {
4460
+ shortcut: "up/dn",
4461
+ action: compact ? "nav" : "navigate"
4462
+ }
4463
+ ),
4464
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(KeyboardShortcutHint, { shortcut: "Enter", action: selectAction }),
4465
+ onTab && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(KeyboardShortcutHint, { shortcut: "Tab", action: onTab.action }),
4466
+ onShiftTab && !compact && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4467
+ KeyboardShortcutHint,
4468
+ {
4469
+ shortcut: "shift+tab",
4470
+ action: onShiftTab.action
4471
+ }
4472
+ ),
4473
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(KeyboardShortcutHint, { shortcut: "Esc", action: "cancel" }),
4474
+ extraHints
4475
+ ] }) })
4476
+ ] }) });
4477
+ }
4478
+ function List({
4479
+ visible,
4480
+ windowStart,
4481
+ visibleCount,
4482
+ total,
4483
+ focusedIndex,
4484
+ direction,
4485
+ getKey,
4486
+ renderItem,
4487
+ emptyText
4488
+ }) {
4489
+ if (visible.length === 0) {
4490
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Box, { height: visibleCount, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ink_renderer32.Text, { dimColor: true, children: emptyText }) });
4491
+ }
4492
+ const rows = visible.map((item, i) => {
4493
+ const actualIndex = windowStart + i;
4494
+ const isFocused = actualIndex === focusedIndex;
4495
+ const atLowEdge = i === 0 && windowStart > 0;
4496
+ const atHighEdge = i === visible.length - 1 && windowStart + visibleCount < total;
4497
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4498
+ ListItem,
4499
+ {
4500
+ isFocused,
4501
+ showScrollUp: direction === "up" ? atHighEdge : atLowEdge,
4502
+ showScrollDown: direction === "up" ? atLowEdge : atHighEdge,
4503
+ styled: false,
4504
+ children: renderItem(item, isFocused)
4505
+ },
4506
+ getKey(item)
4507
+ );
4508
+ });
4509
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4510
+ import_ink_renderer32.Box,
4511
+ {
4512
+ height: visibleCount,
4513
+ flexShrink: 0,
4514
+ flexDirection: direction === "up" ? "column-reverse" : "column",
4515
+ children: rows
4516
+ }
4517
+ );
4518
+ }
4519
+
4520
+ // src/design-system/LoadingState.tsx
4521
+ var import_ink_renderer33 = require("@claude-code-kit/ink-renderer");
4522
+ var import_jsx_runtime27 = require("react/jsx-runtime");
4523
+ function LoadingState({
4524
+ message,
4525
+ bold = false,
4526
+ dimColor = false,
4527
+ subtitle
4528
+ }) {
4529
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_ink_renderer33.Box, { flexDirection: "column", children: [
4530
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_ink_renderer33.Box, { flexDirection: "row", children: [
4531
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Spinner, {}),
4532
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_ink_renderer33.Text, { bold, dimColor, children: [
4533
+ " ",
4534
+ message
4535
+ ] })
4536
+ ] }),
4537
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ink_renderer33.Text, { dimColor: true, children: subtitle })
4538
+ ] });
4539
+ }
4540
+
4541
+ // src/design-system/Ratchet.tsx
4542
+ var import_react24 = require("react");
4543
+ var import_ink_renderer34 = require("@claude-code-kit/ink-renderer");
4544
+ var import_ink_renderer35 = require("@claude-code-kit/ink-renderer");
4545
+ var import_ink_renderer36 = require("@claude-code-kit/ink-renderer");
4546
+ var import_jsx_runtime28 = require("react/jsx-runtime");
4547
+ function Ratchet({
4548
+ children,
4549
+ lock = "always"
4550
+ }) {
4551
+ const [viewportRef, { isVisible }] = (0, import_ink_renderer35.useTerminalViewport)();
4552
+ const terminalSize = (0, import_react24.useContext)(import_ink_renderer34.TerminalSizeContext);
4553
+ const rows = terminalSize?.rows ?? 24;
4554
+ const innerRef = (0, import_react24.useRef)(null);
4555
+ const maxHeight = (0, import_react24.useRef)(0);
4556
+ const [minHeight, setMinHeight] = (0, import_react24.useState)(0);
4557
+ const outerRef = (0, import_react24.useCallback)(
4558
+ (el) => {
4559
+ viewportRef(el);
4560
+ },
4561
+ [viewportRef]
4562
+ );
4563
+ const engaged = lock === "always" || !isVisible;
4564
+ (0, import_react24.useLayoutEffect)(() => {
4565
+ if (!innerRef.current) {
4566
+ return;
4567
+ }
4568
+ const { height } = (0, import_ink_renderer36.measureElement)(innerRef.current);
4569
+ if (height > maxHeight.current) {
4570
+ maxHeight.current = Math.min(height, rows);
4571
+ setMinHeight(maxHeight.current);
4572
+ }
4573
+ });
4574
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ink_renderer36.Box, { minHeight: engaged ? minHeight : void 0, ref: outerRef, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ink_renderer36.Box, { ref: innerRef, flexDirection: "column", children }) });
4575
+ }
4576
+
4577
+ // src/design-system/Tabs.tsx
4578
+ var import_react25 = require("react");
4579
+ var import_ink_renderer37 = require("@claude-code-kit/ink-renderer");
4580
+ var import_ink_renderer38 = require("@claude-code-kit/ink-renderer");
4581
+ var import_ink_renderer39 = require("@claude-code-kit/ink-renderer");
4582
+ var import_jsx_runtime29 = require("react/jsx-runtime");
4583
+ var TabsContext = (0, import_react25.createContext)({
4584
+ selectedTab: void 0,
4585
+ width: void 0
4586
+ });
4587
+ function Tabs({
4588
+ title,
4589
+ color: color2,
4590
+ defaultTab,
4591
+ children,
4592
+ hidden,
4593
+ useFullWidth,
4594
+ selectedTab: controlledSelectedTab,
4595
+ onTabChange,
4596
+ banner,
4597
+ disableNavigation
4598
+ }) {
4599
+ const terminalSize = (0, import_react25.useContext)(import_ink_renderer37.TerminalSizeContext);
4600
+ const terminalWidth = terminalSize?.columns ?? 80;
4601
+ const tabs = children.map((child) => [
4602
+ child.props.id ?? child.props.title,
4603
+ child.props.title
4604
+ ]);
4605
+ const defaultTabIndex = defaultTab ? tabs.findIndex((tab) => defaultTab === tab[0]) : 0;
4606
+ const isControlled = controlledSelectedTab !== void 0;
4607
+ const [internalSelectedTab, setInternalSelectedTab] = (0, import_react25.useState)(
4608
+ defaultTabIndex !== -1 ? defaultTabIndex : 0
4609
+ );
4610
+ const controlledTabIndex = isControlled ? tabs.findIndex((tab) => tab[0] === controlledSelectedTab) : -1;
4611
+ const selectedTabIndex = isControlled ? controlledTabIndex !== -1 ? controlledTabIndex : 0 : internalSelectedTab;
4612
+ const handleTabChange = (0, import_react25.useCallback)(
4613
+ (offset) => {
4614
+ const newIndex = (selectedTabIndex + tabs.length + offset) % tabs.length;
4615
+ const newTabId = tabs[newIndex]?.[0];
4616
+ if (isControlled && onTabChange && newTabId) {
4617
+ onTabChange(newTabId);
4618
+ } else {
4619
+ setInternalSelectedTab(newIndex);
4620
+ }
4621
+ },
4622
+ [selectedTabIndex, tabs, isControlled, onTabChange]
4623
+ );
4624
+ (0, import_ink_renderer39.useInput)(
4625
+ (0, import_react25.useCallback)(
4626
+ (_input, key) => {
4627
+ if (hidden || disableNavigation) return;
4628
+ if (key.tab && !key.shift) {
4629
+ handleTabChange(1);
4630
+ } else if (key.tab && key.shift) {
4631
+ handleTabChange(-1);
4632
+ } else if (key.leftArrow) {
4633
+ handleTabChange(-1);
4634
+ } else if (key.rightArrow) {
4635
+ handleTabChange(1);
4636
+ }
4637
+ },
4638
+ [hidden, disableNavigation, handleTabChange]
4639
+ )
4640
+ );
4641
+ const titleWidth = title ? (0, import_ink_renderer38.stringWidth)(title) + 1 : 0;
4642
+ const tabsWidth = tabs.reduce(
4643
+ (sum, [, tabTitle]) => sum + (tabTitle ? (0, import_ink_renderer38.stringWidth)(tabTitle) : 0) + 3,
4644
+ 0
4645
+ );
4646
+ const usedWidth = titleWidth + tabsWidth;
4647
+ const spacerWidth = useFullWidth ? Math.max(0, terminalWidth - usedWidth) : 0;
4648
+ const contentWidth = useFullWidth ? terminalWidth : void 0;
4649
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4650
+ TabsContext.Provider,
4651
+ {
4652
+ value: {
4653
+ selectedTab: tabs[selectedTabIndex]?.[0],
4654
+ width: contentWidth
4655
+ },
4656
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_ink_renderer39.Box, { flexDirection: "column", children: [
4657
+ !hidden && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_ink_renderer39.Box, { flexDirection: "row", gap: 1, children: [
4658
+ title !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ink_renderer39.Text, { bold: true, color: color2, children: title }),
4659
+ tabs.map(([id, tabTitle], i) => {
4660
+ const isCurrent = selectedTabIndex === i;
4661
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
4662
+ import_ink_renderer39.Text,
4663
+ {
4664
+ inverse: isCurrent,
4665
+ bold: isCurrent,
4666
+ children: [
4667
+ " ",
4668
+ tabTitle,
4669
+ " "
4670
+ ]
4671
+ },
4672
+ id
4673
+ );
4674
+ }),
4675
+ spacerWidth > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ink_renderer39.Text, { children: " ".repeat(spacerWidth) })
4676
+ ] }),
4677
+ banner,
4678
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4679
+ import_ink_renderer39.Box,
4680
+ {
4681
+ width: contentWidth,
4682
+ marginTop: hidden ? 0 : 1,
4683
+ children
4684
+ }
4685
+ )
4686
+ ] })
4687
+ }
4688
+ );
4689
+ }
4690
+ function Tab({ title, id, children }) {
4691
+ const { selectedTab, width } = (0, import_react25.useContext)(TabsContext);
4692
+ if (selectedTab !== (id ?? title)) {
4693
+ return null;
4694
+ }
4695
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ink_renderer39.Box, { width, children });
4696
+ }
4697
+ function useTabsWidth() {
4698
+ const { width } = (0, import_react25.useContext)(TabsContext);
4699
+ return width;
4700
+ }
4701
+
4702
+ // src/useVirtualScroll.ts
4703
+ var import_react26 = __toESM(require("react"));
4704
+ var import_ink_renderer40 = require("@claude-code-kit/ink-renderer");
4705
+ function clamp2(value, min, max) {
4706
+ return Math.max(min, Math.min(max, value));
4707
+ }
4708
+ function useVirtualScroll(options) {
4709
+ const {
4710
+ itemCount,
4711
+ estimatedItemHeight = 3,
4712
+ overscan = 20,
4713
+ viewportHeight
4714
+ } = options;
4715
+ const totalHeight = itemCount * estimatedItemHeight;
4716
+ const maxOffset = Math.max(0, totalHeight - viewportHeight);
4717
+ const [scrollOffset, setScrollOffset] = (0, import_react26.useState)(0);
4718
+ const clampedOffset = clamp2(scrollOffset, 0, maxOffset);
4719
+ const rawStart = Math.floor(clampedOffset / estimatedItemHeight);
4720
+ const rawEnd = Math.ceil((clampedOffset + viewportHeight) / estimatedItemHeight);
4721
+ const startIndex = clamp2(rawStart - overscan, 0, itemCount);
4722
+ const endIndex = clamp2(rawEnd + overscan, 0, itemCount);
4723
+ const visibleItems = endIndex - startIndex;
4724
+ const scrollTo = (0, import_react26.useCallback)(
4725
+ (index) => {
4726
+ const targetOffset = clamp2(index * estimatedItemHeight, 0, maxOffset);
4727
+ setScrollOffset(targetOffset);
4728
+ },
4729
+ [estimatedItemHeight, maxOffset]
4730
+ );
4731
+ const scrollToEnd = (0, import_react26.useCallback)(() => {
4732
+ setScrollOffset(maxOffset);
4733
+ }, [maxOffset]);
4734
+ const onScroll = (0, import_react26.useCallback)(
4735
+ (delta) => {
4736
+ setScrollOffset((prev) => clamp2(prev + delta * estimatedItemHeight, 0, maxOffset));
4737
+ },
4738
+ [estimatedItemHeight, maxOffset]
4739
+ );
4740
+ const isAtTop = clampedOffset <= 0;
4741
+ const isAtEnd = clampedOffset >= maxOffset;
4742
+ return (0, import_react26.useMemo)(
4743
+ () => ({
4744
+ startIndex,
4745
+ endIndex,
4746
+ visibleItems,
4747
+ totalHeight,
4748
+ scrollOffset: clampedOffset,
4749
+ scrollTo,
4750
+ scrollToEnd,
4751
+ onScroll,
4752
+ isAtTop,
4753
+ isAtEnd
4754
+ }),
4755
+ [
4756
+ startIndex,
4757
+ endIndex,
4758
+ visibleItems,
4759
+ totalHeight,
4760
+ clampedOffset,
4761
+ scrollTo,
4762
+ scrollToEnd,
4763
+ onScroll,
4764
+ isAtTop,
4765
+ isAtEnd
4766
+ ]
4767
+ );
4768
+ }
4769
+ function VirtualList(props) {
4770
+ const { items, renderItem, viewportHeight, estimatedItemHeight = 3, overscan = 20 } = props;
4771
+ const { startIndex, endIndex, totalHeight } = useVirtualScroll({
4772
+ itemCount: items.length,
4773
+ estimatedItemHeight,
4774
+ overscan,
4775
+ viewportHeight
4776
+ });
4777
+ const topPad = startIndex * estimatedItemHeight;
4778
+ const renderedHeight = (endIndex - startIndex) * estimatedItemHeight;
4779
+ const bottomPad = Math.max(0, totalHeight - topPad - renderedHeight);
4780
+ const visibleSlice = [];
4781
+ for (let i = startIndex; i < endIndex && i < items.length; i++) {
4782
+ visibleSlice.push(renderItem(items[i], i));
4783
+ }
4784
+ return import_react26.default.createElement(
4785
+ import_ink_renderer40.Box,
4786
+ {
4787
+ flexDirection: "column",
4788
+ height: viewportHeight,
4789
+ overflow: "hidden"
4790
+ },
4791
+ topPad > 0 ? import_react26.default.createElement(import_ink_renderer40.Box, { height: topPad, key: "__virtual-top" }) : null,
4792
+ ...visibleSlice,
4793
+ bottomPad > 0 ? import_react26.default.createElement(import_ink_renderer40.Box, { height: bottomPad, key: "__virtual-bottom" }) : null
4794
+ );
4795
+ }
4796
+
4797
+ // src/WelcomeScreen.tsx
4798
+ var import_ink_renderer41 = require("@claude-code-kit/ink-renderer");
4799
+ var import_jsx_runtime30 = require("react/jsx-runtime");
4800
+ var DEFAULT_COLOR2 = "#DA7756";
4801
+ function ClawdLogo({ color: color2 = DEFAULT_COLOR2 }) {
4802
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_ink_renderer41.Box, { flexDirection: "column", children: [
4803
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { color: color2, children: " \u2590\u259B\u2588\u2588\u2588\u259C\u258C" }),
4804
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { color: color2, children: "\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598" }),
4805
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { color: color2, children: " \u2598\u2598 \u259D\u259D " })
4806
+ ] });
4807
+ }
4808
+ function WelcomeScreen({
4809
+ appName,
4810
+ subtitle,
4811
+ version,
4812
+ tips,
4813
+ logo,
4814
+ model,
4815
+ color: color2 = DEFAULT_COLOR2
4816
+ }) {
4817
+ const logoNode = logo ?? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ClawdLogo, { color: color2 });
4818
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_ink_renderer41.Box, { flexDirection: "column", gap: 1, marginTop: 1, marginLeft: 1, children: [
4819
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_ink_renderer41.Box, { flexDirection: "row", gap: 2, alignItems: "flex-start", children: [
4820
+ logoNode,
4821
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_ink_renderer41.Box, { flexDirection: "column", justifyContent: "center", children: [
4822
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_ink_renderer41.Box, { flexDirection: "row", gap: 1, children: [
4823
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { bold: true, color: color2, children: appName }),
4824
+ version && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { dimColor: true, children: `v${version}` })
4825
+ ] }),
4826
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { dimColor: true, children: subtitle }),
4827
+ model && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { dimColor: true, children: model })
4828
+ ] })
4829
+ ] }),
4830
+ tips && tips.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_ink_renderer41.Box, { flexDirection: "column", gap: 0, children: [
4831
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { dimColor: true, children: "Tips:" }),
4832
+ tips.map((tip, i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ink_renderer41.Text, { dimColor: true, children: ` - ${tip}` }, i))
4833
+ ] })
4834
+ ] });
4835
+ }
4836
+
4837
+ // src/agent/useAgent.ts
4838
+ var import_react27 = require("react");
4839
+ var _msgId = 0;
4840
+ function nextId() {
4841
+ return `msg-${++_msgId}-${Date.now()}`;
4842
+ }
4843
+ function toolCallToContent(tc) {
4844
+ return {
4845
+ type: "tool_use",
4846
+ toolName: tc.name,
4847
+ input: JSON.stringify(tc.input, null, 2),
4848
+ status: "running"
4849
+ };
4850
+ }
4851
+ function useAgent({ agent, onError }) {
4852
+ const [messages, setMessages] = (0, import_react27.useState)([]);
4853
+ const [isLoading, setIsLoading] = (0, import_react27.useState)(false);
4854
+ const [streamingContent, setStreamingContent] = (0, import_react27.useState)(null);
4855
+ const [permissionRequest, setPermissionRequest] = (0, import_react27.useState)(null);
4856
+ const isRunningRef = (0, import_react27.useRef)(false);
4857
+ const toolMsgMap = (0, import_react27.useRef)(/* @__PURE__ */ new Map());
4858
+ (0, import_react27.useEffect)(() => {
4859
+ agent.setPermissionHandler(async (request) => {
4860
+ return new Promise((resolve) => {
4861
+ setPermissionRequest({
4862
+ toolName: request.tool,
4863
+ description: `Tool "${request.tool}" wants to execute`,
4864
+ details: JSON.stringify(request.input, null, 2),
4865
+ resolve: (decision) => {
4866
+ setPermissionRequest(null);
4867
+ resolve({ decision });
4868
+ }
4869
+ });
4870
+ });
4871
+ });
4872
+ }, [agent]);
4873
+ const cancel = (0, import_react27.useCallback)(() => {
4874
+ agent.abort();
4875
+ isRunningRef.current = false;
4876
+ setIsLoading(false);
4877
+ setStreamingContent(null);
4878
+ setPermissionRequest(null);
4879
+ }, [agent]);
4880
+ const clearMessages = (0, import_react27.useCallback)(() => {
4881
+ agent.clearMessages();
4882
+ setMessages([]);
4883
+ setStreamingContent(null);
4884
+ setPermissionRequest(null);
4885
+ }, [agent]);
4886
+ const submit = (0, import_react27.useCallback)(
4887
+ (input) => {
4888
+ if (isRunningRef.current) return;
4889
+ const trimmed = input.trim();
4890
+ if (!trimmed) return;
4891
+ const userMsg = {
4892
+ id: nextId(),
4893
+ role: "user",
4894
+ content: trimmed,
4895
+ timestamp: Date.now()
4896
+ };
4897
+ setMessages((prev) => [...prev, userMsg]);
4898
+ isRunningRef.current = true;
4899
+ setIsLoading(true);
4900
+ setStreamingContent(null);
4901
+ (async () => {
4902
+ let accumulated = "";
4903
+ try {
4904
+ for await (const event of agent.run(trimmed)) {
4905
+ switch (event.type) {
4906
+ case "text": {
4907
+ accumulated += event.text;
4908
+ setStreamingContent(accumulated);
4909
+ break;
4910
+ }
4911
+ case "tool_call": {
4912
+ const msgId = nextId();
4913
+ toolMsgMap.current.set(event.toolCall.id, msgId);
4914
+ const toolMsg = {
4915
+ id: msgId,
4916
+ role: "assistant",
4917
+ content: [toolCallToContent(event.toolCall)],
4918
+ timestamp: Date.now()
4919
+ };
4920
+ setMessages((prev) => [...prev, toolMsg]);
4921
+ break;
4922
+ }
4923
+ case "tool_result": {
4924
+ const targetId = toolMsgMap.current.get(event.toolCallId);
4925
+ if (targetId) {
4926
+ setMessages(
4927
+ (prev) => prev.map((m) => {
4928
+ if (m.id !== targetId) return m;
4929
+ const contents = Array.isArray(m.content) ? m.content : [];
4930
+ return {
4931
+ ...m,
4932
+ content: contents.map((c) => {
4933
+ if (c.type !== "tool_use") return c;
4934
+ return {
4935
+ ...c,
4936
+ result: event.result.content,
4937
+ status: event.result.isError ? "error" : "success"
4938
+ };
4939
+ })
4940
+ };
4941
+ })
4942
+ );
4943
+ toolMsgMap.current.delete(event.toolCallId);
4944
+ }
4945
+ break;
4946
+ }
4947
+ case "error": {
4948
+ onError?.(event.error);
4949
+ break;
4950
+ }
4951
+ case "done": {
4952
+ if (accumulated.length > 0) {
4953
+ const assistantMsg = {
4954
+ id: nextId(),
4955
+ role: "assistant",
4956
+ content: accumulated,
4957
+ timestamp: Date.now()
4958
+ };
4959
+ setMessages((prev) => [...prev, assistantMsg]);
4960
+ }
4961
+ accumulated = "";
4962
+ setStreamingContent(null);
4963
+ break;
4964
+ }
4965
+ }
4966
+ }
4967
+ } catch (err) {
4968
+ const error = err instanceof Error ? err : new Error(String(err));
4969
+ onError?.(error);
4970
+ } finally {
4971
+ isRunningRef.current = false;
4972
+ setIsLoading(false);
4973
+ setStreamingContent(null);
4974
+ }
4975
+ })();
4976
+ },
4977
+ [agent, onError]
4978
+ );
4979
+ return {
4980
+ messages,
4981
+ isLoading,
4982
+ streamingContent,
4983
+ permissionRequest,
4984
+ submit,
4985
+ cancel,
4986
+ clearMessages
4987
+ };
4988
+ }
4989
+
4990
+ // src/agent/AgentProvider.tsx
4991
+ var import_react28 = require("react");
4992
+ var import_jsx_runtime31 = require("react/jsx-runtime");
4993
+ var AgentContext = (0, import_react28.createContext)(null);
4994
+ function AgentProvider({
4995
+ agent,
4996
+ model = "unknown",
4997
+ onError,
4998
+ children
4999
+ }) {
5000
+ const agentState = useAgent({ agent, onError });
5001
+ const value = (0, import_react28.useMemo)(
5002
+ () => ({
5003
+ ...agentState,
5004
+ agent,
5005
+ model
5006
+ }),
5007
+ [agentState, agent, model]
5008
+ );
5009
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AgentContext.Provider, { value, children });
5010
+ }
5011
+ function useAgentContext() {
5012
+ const ctx = (0, import_react28.useContext)(AgentContext);
5013
+ if (!ctx) {
5014
+ throw new Error(
5015
+ "useAgentContext must be used within an <AgentProvider>. Wrap your component tree with <AgentProvider agent={agent}>."
5016
+ );
5017
+ }
5018
+ return ctx;
5019
+ }
5020
+
5021
+ // src/agent/AgentREPL.tsx
5022
+ var import_react29 = require("react");
5023
+ var import_jsx_runtime32 = require("react/jsx-runtime");
5024
+ function AgentREPLInner({
5025
+ commands,
5026
+ welcome,
5027
+ placeholder,
5028
+ onExit
5029
+ }) {
5030
+ const {
5031
+ messages,
5032
+ isLoading,
5033
+ streamingContent,
5034
+ permissionRequest,
5035
+ submit,
5036
+ model,
5037
+ clearMessages
5038
+ } = useAgentContext();
5039
+ const permissionState = (0, import_react29.useMemo)(() => {
5040
+ if (!permissionRequest) return void 0;
5041
+ return {
5042
+ toolName: permissionRequest.toolName,
5043
+ description: permissionRequest.description,
5044
+ details: permissionRequest.details,
5045
+ onDecision: (action) => {
5046
+ permissionRequest.resolve(action === "deny" ? "deny" : "allow");
5047
+ }
5048
+ };
5049
+ }, [permissionRequest]);
5050
+ const allCommands = (0, import_react29.useMemo)(() => {
5051
+ const builtIn = [
5052
+ {
5053
+ name: "clear",
5054
+ description: "Clear conversation history",
5055
+ onExecute: () => clearMessages()
5056
+ }
5057
+ ];
5058
+ return [...builtIn, ...commands ?? []];
5059
+ }, [commands, clearMessages]);
5060
+ const handleSubmit = (0, import_react29.useCallback)(
5061
+ async (input) => {
5062
+ submit(input);
5063
+ },
5064
+ [submit]
5065
+ );
5066
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5067
+ REPL,
5068
+ {
5069
+ onSubmit: handleSubmit,
5070
+ onExit,
5071
+ messages,
5072
+ isLoading,
5073
+ streamingContent,
5074
+ permissionRequest: permissionState,
5075
+ commands: allCommands,
5076
+ model,
5077
+ welcome,
5078
+ placeholder
5079
+ }
5080
+ );
5081
+ }
5082
+ function AgentREPL({
5083
+ agent,
5084
+ model,
5085
+ commands,
5086
+ welcome,
5087
+ placeholder,
5088
+ onError,
5089
+ onExit
5090
+ }) {
5091
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AgentProvider, { agent, model, onError, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5092
+ AgentREPLInner,
5093
+ {
5094
+ commands,
5095
+ welcome,
5096
+ placeholder,
5097
+ onExit
5098
+ }
5099
+ ) });
5100
+ }
5101
+
5102
+ // src/AuthFlow.tsx
5103
+ var import_react30 = require("react");
5104
+ var import_ink_renderer42 = require("@claude-code-kit/ink-renderer");
5105
+ var import_jsx_runtime33 = require("react/jsx-runtime");
5106
+ function CredentialInput({
5107
+ label,
5108
+ masked,
5109
+ onSubmit,
5110
+ onCancel
5111
+ }) {
5112
+ const [value, setValue] = (0, import_react30.useState)("");
5113
+ const [cursor, setCursor] = (0, import_react30.useState)(0);
5114
+ (0, import_ink_renderer42.useInput)((input, key) => {
5115
+ if (key.escape) {
5116
+ onCancel?.();
5117
+ return;
5118
+ }
5119
+ if (key.return) {
5120
+ if (value.length > 0) onSubmit(value);
5121
+ return;
5122
+ }
5123
+ if (key.backspace) {
5124
+ if (cursor > 0) {
5125
+ setValue((v) => v.slice(0, cursor - 1) + v.slice(cursor));
5126
+ setCursor((c) => c - 1);
5127
+ }
5128
+ return;
5129
+ }
5130
+ if (key.leftArrow) {
5131
+ setCursor((c) => Math.max(0, c - 1));
5132
+ return;
5133
+ }
5134
+ if (key.rightArrow) {
5135
+ setCursor((c) => Math.min(value.length, c + 1));
5136
+ return;
5137
+ }
5138
+ if (key.ctrl || key.meta) return;
5139
+ if (input.length > 0) {
5140
+ setValue((v) => v.slice(0, cursor) + input + v.slice(cursor));
5141
+ setCursor((c) => c + input.length);
5142
+ }
5143
+ });
5144
+ const display = masked ? "*".repeat(value.length) : value;
5145
+ const before = display.slice(0, cursor);
5146
+ const at = cursor < display.length ? display[cursor] : " ";
5147
+ const after = cursor < display.length ? display.slice(cursor + 1) : "";
5148
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Box, { flexDirection: "column", children: [
5149
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Text, { bold: true, children: label }),
5150
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Box, { children: [
5151
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Text, { color: "cyan", children: "> " }),
5152
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Text, { children: [
5153
+ before,
5154
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Text, { inverse: true, children: at }),
5155
+ after
5156
+ ] })
5157
+ ] }),
5158
+ value.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Text, { dimColor: true, children: " Type your credential and press Enter" })
5159
+ ] });
5160
+ }
5161
+ function AuthFlowUI({
5162
+ auth,
5163
+ onComplete,
5164
+ onCancel,
5165
+ title = "Authentication"
5166
+ }) {
5167
+ const [phase, setPhase] = (0, import_react30.useState)({ type: "select-provider" });
5168
+ const [baseURL, setBaseURL] = (0, import_react30.useState)();
5169
+ const [error, setError] = (0, import_react30.useState)();
5170
+ const flowState = auth.interactive();
5171
+ const providerOptions = (flowState.providers ?? []).map((p) => ({
5172
+ value: p.name,
5173
+ label: `${p.displayName}`,
5174
+ description: p.description
5175
+ }));
5176
+ const handleProviderSelect = (0, import_react30.useCallback)((providerName) => {
5177
+ setError(void 0);
5178
+ try {
5179
+ const state = auth.selectProvider(providerName);
5180
+ if (state.step === "done" && state.result) {
5181
+ onComplete(state.result.provider, state.result.providerName, state.result.model);
5182
+ setPhase({ type: "done" });
5183
+ return;
5184
+ }
5185
+ if (state.step === "input-credentials" && state.currentAuthMethod) {
5186
+ const method = state.currentAuthMethod;
5187
+ const needsBaseURL = method.type === "base-url-key" && !method.defaultBaseURL;
5188
+ setPhase({
5189
+ type: "input-credentials",
5190
+ providerName,
5191
+ method,
5192
+ needsBaseURL
5193
+ });
5194
+ return;
5195
+ }
5196
+ if (state.step === "select-model" && state.models) {
5197
+ setPhase({
5198
+ type: "select-model",
5199
+ providerName,
5200
+ method: state.currentAuthMethod,
5201
+ models: state.models,
5202
+ defaultModel: state.currentModel
5203
+ });
5204
+ return;
5205
+ }
5206
+ if (state.step === "select-auth-method" && state.authMethods) {
5207
+ const method = state.authMethods[0];
5208
+ const needsBaseURL = method.type === "base-url-key" && !("defaultBaseURL" in method && method.defaultBaseURL);
5209
+ setPhase({
5210
+ type: "input-credentials",
5211
+ providerName,
5212
+ method,
5213
+ needsBaseURL: needsBaseURL && method.type === "base-url-key"
5214
+ });
5215
+ return;
5216
+ }
5217
+ } catch (err) {
5218
+ setError(err instanceof Error ? err.message : String(err));
5219
+ }
5220
+ }, [auth, onComplete]);
5221
+ const handleBaseURLSubmit = (0, import_react30.useCallback)((url) => {
5222
+ setBaseURL(url);
5223
+ }, []);
5224
+ const handleCredentialSubmit = (0, import_react30.useCallback)(async (apiKey) => {
5225
+ if (phase.type !== "input-credentials") return;
5226
+ setError(void 0);
5227
+ try {
5228
+ const credentials = {
5229
+ apiKey,
5230
+ baseURL: baseURL || (phase.method.type === "base-url-key" ? phase.method.defaultBaseURL : void 0)
5231
+ };
5232
+ const state = await auth.inputCredentials(phase.providerName, phase.method, credentials);
5233
+ if (state.step === "done" && state.result) {
5234
+ onComplete(state.result.provider, state.result.providerName, state.result.model);
5235
+ setPhase({ type: "done" });
5236
+ return;
5237
+ }
5238
+ if (state.step === "select-model" && state.models) {
5239
+ setPhase({
5240
+ type: "select-model",
5241
+ providerName: phase.providerName,
5242
+ method: phase.method,
5243
+ models: state.models,
5244
+ defaultModel: state.currentModel
5245
+ });
5246
+ return;
5247
+ }
5248
+ } catch (err) {
5249
+ setError(err instanceof Error ? err.message : String(err));
5250
+ }
5251
+ }, [auth, phase, baseURL, onComplete]);
5252
+ const handleModelSelect = (0, import_react30.useCallback)(async (model) => {
5253
+ if (phase.type !== "select-model") return;
5254
+ setError(void 0);
5255
+ try {
5256
+ const state = await auth.selectModel(phase.providerName, phase.method, model);
5257
+ if (state.step === "done" && state.result) {
5258
+ onComplete(state.result.provider, state.result.providerName, state.result.model);
5259
+ setPhase({ type: "done" });
5260
+ }
5261
+ } catch (err) {
5262
+ setError(err instanceof Error ? err.message : String(err));
5263
+ }
5264
+ }, [auth, phase, onComplete]);
5265
+ const handleCancel = (0, import_react30.useCallback)(() => {
5266
+ if (phase.type === "select-provider") {
5267
+ onCancel?.();
5268
+ } else {
5269
+ setPhase({ type: "select-provider" });
5270
+ setBaseURL(void 0);
5271
+ setError(void 0);
5272
+ }
5273
+ }, [phase, onCancel]);
5274
+ if (phase.type === "done") {
5275
+ return null;
5276
+ }
5277
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Box, { flexDirection: "column", marginTop: 1, marginLeft: 1, children: [
5278
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Text, { bold: true, color: "#DA7756", children: title }) }),
5279
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Divider, {}),
5280
+ error && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Text, { color: "red", children: [
5281
+ "Error: ",
5282
+ error
5283
+ ] }) }),
5284
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Box, { marginTop: 1, children: [
5285
+ phase.type === "select-provider" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5286
+ Select,
5287
+ {
5288
+ title: "Select a provider:",
5289
+ options: providerOptions,
5290
+ onChange: handleProviderSelect,
5291
+ onCancel: handleCancel
5292
+ }
5293
+ ),
5294
+ phase.type === "input-credentials" && phase.method.type === "base-url-key" && phase.needsBaseURL && !baseURL && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5295
+ CredentialInput,
5296
+ {
5297
+ label: "Enter Base URL:",
5298
+ masked: false,
5299
+ onSubmit: handleBaseURLSubmit,
5300
+ onCancel: handleCancel
5301
+ }
5302
+ ),
5303
+ phase.type === "input-credentials" && !(phase.method.type === "base-url-key" && phase.needsBaseURL && !baseURL) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5304
+ CredentialInput,
5305
+ {
5306
+ label: phase.method.type === "api-key" || phase.method.type === "base-url-key" ? phase.method.inputLabel ?? "Enter API Key:" : "Enter API Key:",
5307
+ masked: true,
5308
+ onSubmit: handleCredentialSubmit,
5309
+ onCancel: handleCancel
5310
+ }
5311
+ ),
5312
+ phase.type === "select-model" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5313
+ Select,
5314
+ {
5315
+ title: "Select a model:",
5316
+ options: phase.models.map((m) => ({
5317
+ value: m,
5318
+ label: m,
5319
+ description: m === phase.defaultModel ? "(default)" : void 0
5320
+ })),
5321
+ defaultValue: phase.defaultModel,
5322
+ onChange: handleModelSelect,
5323
+ onCancel: handleCancel
5324
+ }
5325
+ )
5326
+ ] }),
5327
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ink_renderer42.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_ink_renderer42.Text, { dimColor: true, children: [
5328
+ "Esc to ",
5329
+ phase.type === "select-provider" ? "cancel" : "go back"
5330
+ ] }) })
5331
+ ] });
5332
+ }
2392
5333
  // Annotate the CommonJS export names for ESM import in node:
2393
5334
  0 && (module.exports = {
5335
+ AgentContext,
5336
+ AgentProvider,
5337
+ AgentREPL,
5338
+ AuthFlowUI,
5339
+ BashPermissionContent,
5340
+ Byline,
5341
+ ClawdLogo,
2394
5342
  CommandRegistry,
2395
5343
  DEFAULT_BINDINGS,
5344
+ Dialog,
5345
+ DiffView,
2396
5346
  Divider,
5347
+ FileEditPermissionContent,
5348
+ FuzzyPicker,
2397
5349
  KeybindingSetup,
5350
+ KeyboardShortcutHint,
5351
+ ListItem,
5352
+ LoadingState,
5353
+ Markdown,
5354
+ MarkdownTable,
2398
5355
  MessageList,
2399
5356
  MultiSelect,
5357
+ Pane,
5358
+ PermissionRequest,
2400
5359
  ProgressBar,
2401
5360
  PromptInput,
2402
5361
  REPL,
5362
+ Ratchet,
5363
+ SearchOverlay,
2403
5364
  Select,
2404
5365
  Spinner,
2405
5366
  StatusIcon,
2406
5367
  StatusLine,
5368
+ StreamingMarkdown,
2407
5369
  StreamingText,
5370
+ Tab,
5371
+ Tabs,
5372
+ TextHoverColorContext,
5373
+ ThemeProvider,
5374
+ ThemedBox,
5375
+ ThemedText,
5376
+ VirtualList,
5377
+ WelcomeScreen,
2408
5378
  clearCommand,
5379
+ color,
2409
5380
  createCommandRegistry,
2410
5381
  defineCommand,
2411
5382
  defineJSXCommand,
2412
5383
  defineLocalCommand,
2413
5384
  exitCommand,
5385
+ getTheme,
2414
5386
  helpCommand,
5387
+ parseUnifiedDiff,
5388
+ useAgent,
5389
+ useAgentContext,
5390
+ useDoublePress,
2415
5391
  useKeybinding,
2416
5392
  useKeybindings,
5393
+ usePreviewTheme,
5394
+ useSearch,
2417
5395
  useStatusLine,
5396
+ useTabsWidth,
5397
+ useTerminalSize,
5398
+ useTheme,
5399
+ useThemeSetting,
5400
+ useVirtualScroll,
2418
5401
  ...require("@claude-code-kit/ink-renderer")
2419
5402
  });