@claude-code-kit/ui 0.1.1 → 0.3.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.mjs CHANGED
@@ -1,10 +1,137 @@
1
1
  // src/index.ts
2
2
  export * from "@claude-code-kit/ink-renderer";
3
3
 
4
+ // src/DiffView.tsx
5
+ import { useMemo } from "react";
6
+ import { Box, Text } from "@claude-code-kit/ink-renderer";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ function parseUnifiedDiff(diff) {
9
+ const rawLines = diff.split("\n");
10
+ let filename = "";
11
+ const lines = [];
12
+ let oldLine = 0;
13
+ let newLine = 0;
14
+ for (const line of rawLines) {
15
+ if (line.startsWith("+++ ")) {
16
+ const path = line.slice(4).trim();
17
+ filename = path.startsWith("b/") ? path.slice(2) : path;
18
+ continue;
19
+ }
20
+ if (line.startsWith("--- ")) continue;
21
+ const hunkMatch = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
22
+ if (hunkMatch) {
23
+ oldLine = parseInt(hunkMatch[1], 10);
24
+ newLine = parseInt(hunkMatch[2], 10);
25
+ continue;
26
+ }
27
+ if (line.startsWith("diff ") || line.startsWith("index ") || line.startsWith("\\")) {
28
+ continue;
29
+ }
30
+ if (oldLine === 0 && newLine === 0) continue;
31
+ if (line.startsWith("+")) {
32
+ lines.push({
33
+ type: "added",
34
+ content: line.slice(1),
35
+ newLineNumber: newLine
36
+ });
37
+ newLine++;
38
+ } else if (line.startsWith("-")) {
39
+ lines.push({
40
+ type: "removed",
41
+ content: line.slice(1),
42
+ oldLineNumber: oldLine
43
+ });
44
+ oldLine++;
45
+ } else {
46
+ lines.push({
47
+ type: "context",
48
+ content: line.startsWith(" ") ? line.slice(1) : line,
49
+ oldLineNumber: oldLine,
50
+ newLineNumber: newLine
51
+ });
52
+ oldLine++;
53
+ newLine++;
54
+ }
55
+ }
56
+ return { filename: filename || "unknown", lines };
57
+ }
58
+ function DiffView({
59
+ filename,
60
+ lines: propLines,
61
+ diff,
62
+ showLineNumbers = true,
63
+ maxHeight,
64
+ color: colorOverrides
65
+ }) {
66
+ const parsed = useMemo(() => {
67
+ if (diff) return parseUnifiedDiff(diff);
68
+ return null;
69
+ }, [diff]);
70
+ const resolvedFilename = parsed?.filename ?? filename;
71
+ const resolvedLines = parsed?.lines ?? propLines;
72
+ const addedColor = colorOverrides?.added ?? "green";
73
+ const removedColor = colorOverrides?.removed ?? "red";
74
+ const headerColor = colorOverrides?.header ?? "cyan";
75
+ const contextColor = colorOverrides?.context;
76
+ const maxLineNum = useMemo(() => {
77
+ let max = 0;
78
+ for (const line of resolvedLines) {
79
+ if (line.oldLineNumber !== void 0 && line.oldLineNumber > max) max = line.oldLineNumber;
80
+ if (line.newLineNumber !== void 0 && line.newLineNumber > max) max = line.newLineNumber;
81
+ }
82
+ return max;
83
+ }, [resolvedLines]);
84
+ const gutterWidth = Math.max(2, String(maxLineNum).length);
85
+ const visibleLines = maxHeight && resolvedLines.length > maxHeight ? resolvedLines.slice(0, maxHeight) : resolvedLines;
86
+ const truncated = maxHeight && resolvedLines.length > maxHeight ? resolvedLines.length - maxHeight : 0;
87
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
88
+ /* @__PURE__ */ jsxs(Text, { bold: true, color: headerColor, children: [
89
+ " ",
90
+ resolvedFilename
91
+ ] }),
92
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
93
+ " ",
94
+ "\u2500".repeat(30)
95
+ ] }),
96
+ visibleLines.map((line, i) => /* @__PURE__ */ jsx(
97
+ DiffLineRow,
98
+ {
99
+ line,
100
+ gutterWidth,
101
+ showLineNumbers,
102
+ addedColor,
103
+ removedColor,
104
+ contextColor
105
+ },
106
+ i
107
+ )),
108
+ truncated > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
109
+ " ... ",
110
+ truncated,
111
+ " more lines"
112
+ ] })
113
+ ] });
114
+ }
115
+ function DiffLineRow({ line, gutterWidth, showLineNumbers, addedColor, removedColor, contextColor }) {
116
+ const lineNum = line.type === "removed" ? line.oldLineNumber : line.newLineNumber ?? line.oldLineNumber;
117
+ const prefix = line.type === "added" ? "+ " : line.type === "removed" ? "- " : " ";
118
+ const gutterStr = showLineNumbers && lineNum !== void 0 ? String(lineNum).padStart(gutterWidth) : " ".repeat(gutterWidth);
119
+ const contentColor = line.type === "added" ? addedColor : line.type === "removed" ? removedColor : contextColor;
120
+ const dim = line.type === "context" && !contextColor;
121
+ return /* @__PURE__ */ jsxs(Text, { children: [
122
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: gutterStr }),
123
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
124
+ /* @__PURE__ */ jsxs(Text, { dimColor: dim, color: contentColor, children: [
125
+ prefix,
126
+ line.content
127
+ ] })
128
+ ] });
129
+ }
130
+
4
131
  // src/Divider.tsx
5
132
  import { useContext } from "react";
6
- import { Text, Ansi, TerminalSizeContext, stringWidth } from "@claude-code-kit/ink-renderer";
7
- import { jsx, jsxs } from "react/jsx-runtime";
133
+ import { Text as Text2, Ansi, TerminalSizeContext, stringWidth } from "@claude-code-kit/ink-renderer";
134
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
8
135
  function Divider({ width, color: color2, char = "\u2500", padding = 0, title }) {
9
136
  const terminalSize = useContext(TerminalSizeContext);
10
137
  const terminalWidth = terminalSize?.columns ?? 80;
@@ -14,20 +141,20 @@ function Divider({ width, color: color2, char = "\u2500", padding = 0, title })
14
141
  const sideWidth = Math.max(0, effectiveWidth - titleWidth);
15
142
  const leftWidth = Math.floor(sideWidth / 2);
16
143
  const rightWidth = sideWidth - leftWidth;
17
- return /* @__PURE__ */ jsxs(Text, { color: color2, dimColor: !color2, children: [
144
+ return /* @__PURE__ */ jsxs2(Text2, { color: color2, dimColor: !color2, children: [
18
145
  char.repeat(leftWidth),
19
146
  " ",
20
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: /* @__PURE__ */ jsx(Ansi, { children: title }) }),
147
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: /* @__PURE__ */ jsx2(Ansi, { children: title }) }),
21
148
  " ",
22
149
  char.repeat(rightWidth)
23
150
  ] });
24
151
  }
25
- return /* @__PURE__ */ jsx(Text, { color: color2, dimColor: !color2, children: char.repeat(effectiveWidth) });
152
+ return /* @__PURE__ */ jsx2(Text2, { color: color2, dimColor: !color2, children: char.repeat(effectiveWidth) });
26
153
  }
27
154
 
28
155
  // src/ProgressBar.tsx
29
- import { Text as Text2 } from "@claude-code-kit/ink-renderer";
30
- import { jsx as jsx2 } from "react/jsx-runtime";
156
+ import { Text as Text3 } from "@claude-code-kit/ink-renderer";
157
+ import { jsx as jsx3 } from "react/jsx-runtime";
31
158
  var BLOCKS = [" ", "\u258F", "\u258E", "\u258D", "\u258C", "\u258B", "\u258A", "\u2589", "\u2588"];
32
159
  function ProgressBar({ ratio: inputRatio, width, fillColor, emptyColor }) {
33
160
  const ratio = Math.min(1, Math.max(0, inputRatio));
@@ -42,13 +169,13 @@ function ProgressBar({ ratio: inputRatio, width, fillColor, emptyColor }) {
42
169
  segments.push(BLOCKS[0].repeat(empty));
43
170
  }
44
171
  }
45
- return /* @__PURE__ */ jsx2(Text2, { color: fillColor, backgroundColor: emptyColor, children: segments.join("") });
172
+ return /* @__PURE__ */ jsx3(Text3, { color: fillColor, backgroundColor: emptyColor, children: segments.join("") });
46
173
  }
47
174
 
48
175
  // src/StatusIcon.tsx
49
176
  import figures from "figures";
50
- import { Text as Text3 } from "@claude-code-kit/ink-renderer";
51
- import { jsxs as jsxs2 } from "react/jsx-runtime";
177
+ import { Text as Text4 } from "@claude-code-kit/ink-renderer";
178
+ import { jsxs as jsxs3 } from "react/jsx-runtime";
52
179
  var STATUS_CONFIG = {
53
180
  success: { icon: figures.tick, color: "green" },
54
181
  error: { icon: figures.cross, color: "red" },
@@ -59,16 +186,16 @@ var STATUS_CONFIG = {
59
186
  };
60
187
  function StatusIcon({ status, withSpace = false }) {
61
188
  const config = STATUS_CONFIG[status];
62
- return /* @__PURE__ */ jsxs2(Text3, { color: config.color, dimColor: !config.color, children: [
189
+ return /* @__PURE__ */ jsxs3(Text4, { color: config.color, dimColor: !config.color, children: [
63
190
  config.icon,
64
191
  withSpace && " "
65
192
  ] });
66
193
  }
67
194
 
68
195
  // src/StatusLine.tsx
69
- import { useEffect, useState } from "react";
70
- import { Box, Text as Text4, Ansi as Ansi2 } from "@claude-code-kit/ink-renderer";
71
- import { jsx as jsx3 } from "react/jsx-runtime";
196
+ import React3, { useEffect, useState } from "react";
197
+ import { Box as Box2, Text as Text5, Ansi as Ansi2 } from "@claude-code-kit/ink-renderer";
198
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
72
199
  function hasAnsi(s) {
73
200
  return /\x1b\[/.test(s);
74
201
  }
@@ -76,19 +203,22 @@ function StatusLine({
76
203
  segments,
77
204
  text,
78
205
  paddingX = 1,
79
- gap = 1,
206
+ separator = " \xB7 ",
80
207
  borderStyle = "none",
81
208
  borderColor
82
209
  }) {
83
210
  const border = borderStyle === "none" ? void 0 : borderStyle;
84
- return /* @__PURE__ */ jsx3(
85
- Box,
211
+ return /* @__PURE__ */ jsx4(
212
+ Box2,
86
213
  {
87
214
  flexDirection: "row",
88
215
  paddingX,
89
216
  borderStyle: border,
90
217
  borderColor,
91
- children: text !== void 0 ? hasAnsi(text) ? /* @__PURE__ */ jsx3(Ansi2, { children: text }) : /* @__PURE__ */ jsx3(Text4, { dimColor: true, children: text }) : segments?.map((seg, i) => /* @__PURE__ */ jsx3(Box, { flexGrow: seg.flex ? 1 : 0, marginRight: i < segments.length - 1 ? gap : 0, children: hasAnsi(seg.content) ? /* @__PURE__ */ jsx3(Ansi2, { children: seg.content }) : /* @__PURE__ */ jsx3(Text4, { dimColor: true, color: seg.color, children: seg.content }) }, i))
218
+ children: text !== void 0 ? hasAnsi(text) ? /* @__PURE__ */ jsx4(Ansi2, { children: text }) : /* @__PURE__ */ jsx4(Text5, { dimColor: true, children: text }) : segments?.map((seg, i) => /* @__PURE__ */ jsxs4(React3.Fragment, { children: [
219
+ i > 0 && /* @__PURE__ */ jsx4(Text5, { dimColor: true, children: separator }),
220
+ /* @__PURE__ */ jsx4(Box2, { flexGrow: seg.flex ? 1 : 0, children: hasAnsi(seg.content) ? /* @__PURE__ */ jsx4(Ansi2, { children: seg.content }) : /* @__PURE__ */ jsx4(Text5, { dimColor: true, color: seg.color, children: seg.content }) })
221
+ ] }, i))
92
222
  }
93
223
  );
94
224
  }
@@ -210,7 +340,7 @@ import {
210
340
  createContext,
211
341
  useContext as useContext2,
212
342
  useLayoutEffect,
213
- useMemo
343
+ useMemo as useMemo2
214
344
  } from "react";
215
345
 
216
346
  // src/keybindings/match.ts
@@ -458,7 +588,7 @@ function resolveKeyWithChordState(input, key, activeContexts, bindings, pending)
458
588
  }
459
589
 
460
590
  // src/keybindings/KeybindingContext.tsx
461
- import { jsx as jsx4 } from "react/jsx-runtime";
591
+ import { jsx as jsx5 } from "react/jsx-runtime";
462
592
  var KeybindingContext = createContext(null);
463
593
  function KeybindingProvider({
464
594
  bindings,
@@ -471,11 +601,11 @@ function KeybindingProvider({
471
601
  handlerRegistryRef,
472
602
  children
473
603
  }) {
474
- const getDisplayText = useMemo(
604
+ const getDisplayText = useMemo2(
475
605
  () => (action, context) => getBindingDisplayText(action, context, bindings),
476
606
  [bindings]
477
607
  );
478
- const registerHandler = useMemo(
608
+ const registerHandler = useMemo2(
479
609
  () => (registration) => {
480
610
  const registry = handlerRegistryRef.current;
481
611
  if (!registry) return () => {
@@ -496,7 +626,7 @@ function KeybindingProvider({
496
626
  },
497
627
  [handlerRegistryRef]
498
628
  );
499
- const invokeAction = useMemo(
629
+ const invokeAction = useMemo2(
500
630
  () => (action) => {
501
631
  const registry = handlerRegistryRef.current;
502
632
  if (!registry) return false;
@@ -512,7 +642,7 @@ function KeybindingProvider({
512
642
  },
513
643
  [activeContexts, handlerRegistryRef]
514
644
  );
515
- const resolve = useMemo(
645
+ const resolve = useMemo2(
516
646
  () => (input, key, contexts) => resolveKeyWithChordState(
517
647
  input,
518
648
  key,
@@ -522,7 +652,7 @@ function KeybindingProvider({
522
652
  ),
523
653
  [bindings, pendingChordRef]
524
654
  );
525
- const value = useMemo(
655
+ const value = useMemo2(
526
656
  () => ({
527
657
  resolve,
528
658
  setPendingChord,
@@ -548,7 +678,7 @@ function KeybindingProvider({
548
678
  invokeAction
549
679
  ]
550
680
  );
551
- return /* @__PURE__ */ jsx4(KeybindingContext.Provider, { value, children });
681
+ return /* @__PURE__ */ jsx5(KeybindingContext.Provider, { value, children });
552
682
  }
553
683
  function useOptionalKeybindingContext() {
554
684
  return useContext2(KeybindingContext);
@@ -1527,7 +1657,7 @@ function handleDelete(path) {
1527
1657
  }
1528
1658
 
1529
1659
  // src/keybindings/KeybindingProviderSetup.tsx
1530
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1660
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1531
1661
  var plural = (n, s) => n === 1 ? s : s + "s";
1532
1662
  function logForDebugging2(msg) {
1533
1663
  if (process.env.DEBUG_KEYBINDINGS) console.error(msg);
@@ -1607,7 +1737,7 @@ function KeybindingSetup({ children, onWarnings }) {
1607
1737
  clearChordTimeout();
1608
1738
  };
1609
1739
  }, [clearChordTimeout]);
1610
- return /* @__PURE__ */ jsxs3(
1740
+ return /* @__PURE__ */ jsxs5(
1611
1741
  KeybindingProvider,
1612
1742
  {
1613
1743
  bindings,
@@ -1619,7 +1749,7 @@ function KeybindingSetup({ children, onWarnings }) {
1619
1749
  unregisterActiveContext,
1620
1750
  handlerRegistryRef,
1621
1751
  children: [
1622
- /* @__PURE__ */ jsx5(
1752
+ /* @__PURE__ */ jsx6(
1623
1753
  ChordInterceptor,
1624
1754
  {
1625
1755
  bindings,
@@ -1765,8 +1895,42 @@ function useTerminalSize() {
1765
1895
 
1766
1896
  // src/PromptInput.tsx
1767
1897
  import { useState as useState3, useCallback as useCallback4 } from "react";
1768
- import { Text as Text5, Box as Box2, useInput as useInput3 } from "@claude-code-kit/ink-renderer";
1769
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1898
+ import { Text as Text6, Box as Box3, useInput as useInput3 } from "@claude-code-kit/ink-renderer";
1899
+
1900
+ // src/utils/promptInputLogic.ts
1901
+ function wordFwd(s, p) {
1902
+ let i = p;
1903
+ while (i < s.length && s[i] !== " ") i++;
1904
+ while (i < s.length && s[i] === " ") i++;
1905
+ return i;
1906
+ }
1907
+ function wordBwd(s, p) {
1908
+ let i = p;
1909
+ if (i > 0) i--;
1910
+ while (i > 0 && s[i] === " ") i--;
1911
+ while (i > 0 && s[i - 1] !== " ") i--;
1912
+ return i;
1913
+ }
1914
+ function lineOffset(lines, line) {
1915
+ let pos = 0;
1916
+ for (let i = 0; i < line; i++) pos += lines[i].length + 1;
1917
+ return pos;
1918
+ }
1919
+ function cursorLineIndex(lines, cursor) {
1920
+ let pos = 0;
1921
+ for (let i = 0; i < lines.length; i++) {
1922
+ if (cursor <= pos + lines[i].length) return i;
1923
+ pos += lines[i].length + 1;
1924
+ }
1925
+ return lines.length - 1;
1926
+ }
1927
+ function filterCommands(commands, value) {
1928
+ if (!value.startsWith("/")) return [];
1929
+ return commands.filter((cmd) => `/${cmd.name}`.startsWith(value));
1930
+ }
1931
+
1932
+ // src/PromptInput.tsx
1933
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1770
1934
  function PromptInput({
1771
1935
  value,
1772
1936
  onChange,
@@ -1777,186 +1941,302 @@ function PromptInput({
1777
1941
  disabled = false,
1778
1942
  commands = [],
1779
1943
  onCommandSelect,
1780
- history = []
1944
+ history = [],
1945
+ vimMode = false,
1946
+ multiline = false
1781
1947
  }) {
1782
1948
  const [cursor, setCursor] = useState3(0);
1783
1949
  const [historyIndex, setHistoryIndex] = useState3(-1);
1784
1950
  const [suggestionIndex, setSuggestionIndex] = useState3(0);
1785
1951
  const [showSuggestions, setShowSuggestions] = useState3(false);
1786
- const suggestions = value.startsWith("/") && commands.length > 0 ? commands.filter((cmd) => `/${cmd.name}`.startsWith(value)) : [];
1952
+ const [vim, setVim] = useState3("INSERT");
1953
+ const [pendingD, setPendingD] = useState3(false);
1954
+ const isVimNormal = vimMode && vim === "NORMAL";
1955
+ const suggestions = commands.length > 0 ? filterCommands(commands, value) : [];
1787
1956
  const hasSuggestions = showSuggestions && suggestions.length > 0;
1788
- const updateValue = useCallback4(
1789
- (newValue, newCursor) => {
1790
- onChange(newValue);
1791
- setCursor(newCursor ?? newValue.length);
1957
+ const lines = multiline ? value.split("\n") : [value];
1958
+ const cursorLine = multiline ? cursorLineIndex(lines, cursor) : 0;
1959
+ const lineOffset2 = (line) => lineOffset(lines, line);
1960
+ const updateValue = useCallback4((nv, nc) => {
1961
+ onChange(nv);
1962
+ setCursor(nc ?? nv.length);
1963
+ setHistoryIndex(-1);
1964
+ setShowSuggestions(nv.startsWith("/"));
1965
+ setSuggestionIndex(0);
1966
+ }, [onChange]);
1967
+ const insertNewline = () => {
1968
+ updateValue(value.slice(0, cursor) + "\n" + value.slice(cursor), cursor + 1);
1969
+ };
1970
+ const moveLine = (dir) => {
1971
+ const target = cursorLine + dir;
1972
+ if (multiline && target >= 0 && target < lines.length) {
1973
+ const col = cursor - lineOffset2(cursorLine);
1974
+ setCursor(lineOffset2(target) + Math.min(col, lines[target].length));
1975
+ return true;
1976
+ }
1977
+ return false;
1978
+ };
1979
+ const historyUp = () => {
1980
+ if (history.length > 0 && historyIndex + 1 < history.length) {
1981
+ const ni = historyIndex + 1;
1982
+ setHistoryIndex(ni);
1983
+ const hv = history[ni];
1984
+ onChange(hv);
1985
+ setCursor(hv.length);
1986
+ }
1987
+ };
1988
+ const historyDown = () => {
1989
+ if (historyIndex > 0) {
1990
+ const ni = historyIndex - 1;
1991
+ setHistoryIndex(ni);
1992
+ const hv = history[ni];
1993
+ onChange(hv);
1994
+ setCursor(hv.length);
1995
+ } else if (historyIndex === 0) {
1792
1996
  setHistoryIndex(-1);
1793
- setShowSuggestions(newValue.startsWith("/"));
1794
- setSuggestionIndex(0);
1795
- },
1796
- [onChange]
1797
- );
1798
- useInput3(
1799
- (input, key) => {
1800
- if (disabled) return;
1801
- if (key.return) {
1802
- if (hasSuggestions) {
1803
- const cmd = suggestions[suggestionIndex];
1804
- const cmdValue = `/${cmd.name}`;
1805
- onCommandSelect?.(cmd.name);
1806
- onChange(cmdValue);
1807
- setCursor(cmdValue.length);
1808
- setShowSuggestions(false);
1809
- return;
1810
- }
1811
- if (value.length > 0) {
1812
- onSubmit(value);
1813
- }
1997
+ onChange("");
1998
+ setCursor(0);
1999
+ }
2000
+ };
2001
+ useInput3((input, key) => {
2002
+ if (disabled) return;
2003
+ if (isVimNormal) {
2004
+ if (input !== "d") setPendingD(false);
2005
+ if (input === "i") {
2006
+ setVim("INSERT");
1814
2007
  return;
1815
2008
  }
1816
- if (key.escape) {
1817
- if (hasSuggestions) {
1818
- setShowSuggestions(false);
1819
- }
2009
+ if (input === "a") {
2010
+ setVim("INSERT");
2011
+ setCursor((c) => Math.min(value.length, c + 1));
1820
2012
  return;
1821
2013
  }
1822
- if (key.tab) {
1823
- if (hasSuggestions) {
1824
- const cmd = suggestions[suggestionIndex];
1825
- const cmdValue = `/${cmd.name} `;
1826
- updateValue(cmdValue);
1827
- }
2014
+ if (input === "h" || key.leftArrow) {
2015
+ setCursor((c) => Math.max(0, c - 1));
1828
2016
  return;
1829
2017
  }
1830
- if (key.upArrow) {
1831
- if (hasSuggestions) {
1832
- setSuggestionIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
1833
- return;
2018
+ if (input === "l" || key.rightArrow) {
2019
+ setCursor((c) => Math.min(Math.max(0, value.length - 1), c + 1));
2020
+ return;
2021
+ }
2022
+ if (input === "0" || key.home) {
2023
+ setCursor(multiline ? lineOffset2(cursorLine) : 0);
2024
+ return;
2025
+ }
2026
+ if (input === "$" || key.end) {
2027
+ if (multiline) {
2028
+ const endOfLine = lineOffset2(cursorLine) + lines[cursorLine].length;
2029
+ setCursor(Math.max(lineOffset2(cursorLine), endOfLine - 1));
2030
+ } else {
2031
+ setCursor(Math.max(0, value.length - 1));
1834
2032
  }
1835
- if (history.length > 0) {
1836
- const nextIndex = historyIndex + 1;
1837
- if (nextIndex < history.length) {
1838
- setHistoryIndex(nextIndex);
1839
- const histValue = history[nextIndex];
1840
- onChange(histValue);
1841
- setCursor(histValue.length);
1842
- }
2033
+ return;
2034
+ }
2035
+ if (input === "w") {
2036
+ setCursor(wordFwd(value, cursor));
2037
+ return;
2038
+ }
2039
+ if (input === "b") {
2040
+ setCursor(wordBwd(value, cursor));
2041
+ return;
2042
+ }
2043
+ if (input === "x") {
2044
+ if (cursor < value.length) {
2045
+ const nv = value.slice(0, cursor) + value.slice(cursor + 1);
2046
+ updateValue(nv, Math.min(cursor, Math.max(0, nv.length - 1)));
1843
2047
  }
1844
2048
  return;
1845
2049
  }
1846
- if (key.downArrow) {
1847
- if (hasSuggestions) {
1848
- setSuggestionIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
2050
+ if (input === "d") {
2051
+ if (!pendingD) {
2052
+ setPendingD(true);
1849
2053
  return;
1850
2054
  }
1851
- if (historyIndex > 0) {
1852
- const nextIndex = historyIndex - 1;
1853
- setHistoryIndex(nextIndex);
1854
- const histValue = history[nextIndex];
1855
- onChange(histValue);
1856
- setCursor(histValue.length);
1857
- } else if (historyIndex === 0) {
1858
- setHistoryIndex(-1);
1859
- onChange("");
1860
- setCursor(0);
2055
+ setPendingD(false);
2056
+ if (multiline && lines.length > 1) {
2057
+ const pos = lineOffset2(cursorLine);
2058
+ const end = pos + lines[cursorLine].length;
2059
+ const from = cursorLine === 0 ? pos : pos - 1;
2060
+ const to = cursorLine === 0 ? Math.min(end + 1, value.length) : end;
2061
+ const nv = value.slice(0, from) + value.slice(to);
2062
+ updateValue(nv, Math.min(from, Math.max(0, nv.length - 1)));
2063
+ } else {
2064
+ updateValue("", 0);
1861
2065
  }
1862
2066
  return;
1863
2067
  }
1864
- if (key.leftArrow) {
1865
- setCursor((c) => Math.max(0, c - 1));
2068
+ if (key.upArrow || input === "k" && !key.ctrl) {
2069
+ if (!moveLine(-1)) historyUp();
1866
2070
  return;
1867
2071
  }
1868
- if (key.rightArrow) {
1869
- setCursor((c) => Math.min(value.length, c + 1));
2072
+ if (key.downArrow || input === "j" && !key.ctrl) {
2073
+ if (!moveLine(1)) historyDown();
1870
2074
  return;
1871
2075
  }
1872
- if (key.home || key.ctrl && input === "a") {
1873
- setCursor(0);
2076
+ if (key.return && value.length > 0) {
2077
+ onSubmit(value);
1874
2078
  return;
1875
2079
  }
1876
- if (key.end || key.ctrl && input === "e") {
1877
- setCursor(value.length);
2080
+ return;
2081
+ }
2082
+ if (key.return) {
2083
+ if (hasSuggestions) {
2084
+ const cmd = suggestions[suggestionIndex];
2085
+ const cv = `/${cmd.name}`;
2086
+ onCommandSelect?.(cmd.name);
2087
+ onChange(cv);
2088
+ setCursor(cv.length);
2089
+ setShowSuggestions(false);
1878
2090
  return;
1879
2091
  }
1880
- if (key.ctrl && input === "w") {
1881
- if (cursor > 0) {
1882
- let i = cursor - 1;
1883
- while (i > 0 && value[i - 1] === " ") i--;
1884
- while (i > 0 && value[i - 1] !== " ") i--;
1885
- const newValue = value.slice(0, i) + value.slice(cursor);
1886
- updateValue(newValue, i);
1887
- }
2092
+ if (multiline && key.shift) {
2093
+ insertNewline();
1888
2094
  return;
1889
2095
  }
1890
- if (key.ctrl && input === "u") {
1891
- const newValue = value.slice(cursor);
1892
- updateValue(newValue, 0);
2096
+ if (value.length > 0) onSubmit(value);
2097
+ return;
2098
+ }
2099
+ if (key.escape) {
2100
+ if (hasSuggestions) {
2101
+ setShowSuggestions(false);
1893
2102
  return;
1894
2103
  }
1895
- if (key.backspace) {
1896
- if (cursor > 0) {
1897
- const newValue = value.slice(0, cursor - 1) + value.slice(cursor);
1898
- updateValue(newValue, cursor - 1);
1899
- }
2104
+ if (vimMode) {
2105
+ setVim("NORMAL");
1900
2106
  return;
1901
2107
  }
1902
- if (key.delete) {
1903
- if (cursor < value.length) {
1904
- const newValue = value.slice(0, cursor) + value.slice(cursor + 1);
1905
- updateValue(newValue, cursor);
1906
- }
2108
+ return;
2109
+ }
2110
+ if (multiline && key.ctrl && input === "j") {
2111
+ insertNewline();
2112
+ return;
2113
+ }
2114
+ if (key.tab) {
2115
+ if (hasSuggestions) {
2116
+ updateValue(`/${suggestions[suggestionIndex].name} `);
2117
+ }
2118
+ ;
2119
+ return;
2120
+ }
2121
+ if (key.upArrow) {
2122
+ if (hasSuggestions) {
2123
+ setSuggestionIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
1907
2124
  return;
1908
2125
  }
1909
- if (key.ctrl || key.meta) return;
1910
- if (input.length > 0) {
1911
- const newValue = value.slice(0, cursor) + input + value.slice(cursor);
1912
- updateValue(newValue, cursor + input.length);
2126
+ if (!moveLine(-1)) historyUp();
2127
+ return;
2128
+ }
2129
+ if (key.downArrow) {
2130
+ if (hasSuggestions) {
2131
+ setSuggestionIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
2132
+ return;
1913
2133
  }
1914
- },
1915
- { isActive: !disabled }
1916
- );
1917
- const renderTextWithCursor = () => {
1918
- if (value.length === 0 && placeholder) {
1919
- return /* @__PURE__ */ jsxs4(Text5, { children: [
1920
- /* @__PURE__ */ jsx6(Text5, { inverse: true, children: " " }),
1921
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: placeholder })
2134
+ if (!moveLine(1)) historyDown();
2135
+ return;
2136
+ }
2137
+ if (key.leftArrow) {
2138
+ setCursor((c) => Math.max(0, c - 1));
2139
+ return;
2140
+ }
2141
+ if (key.rightArrow) {
2142
+ setCursor((c) => Math.min(value.length, c + 1));
2143
+ return;
2144
+ }
2145
+ if (key.home || key.ctrl && input === "a") {
2146
+ setCursor(0);
2147
+ return;
2148
+ }
2149
+ if (key.end || key.ctrl && input === "e") {
2150
+ setCursor(value.length);
2151
+ return;
2152
+ }
2153
+ if (key.ctrl && input === "w") {
2154
+ if (cursor > 0) {
2155
+ let i = cursor - 1;
2156
+ while (i > 0 && value[i - 1] === " ") i--;
2157
+ while (i > 0 && value[i - 1] !== " ") i--;
2158
+ updateValue(value.slice(0, i) + value.slice(cursor), i);
2159
+ }
2160
+ ;
2161
+ return;
2162
+ }
2163
+ if (key.ctrl && input === "u") {
2164
+ updateValue(value.slice(cursor), 0);
2165
+ return;
2166
+ }
2167
+ if (key.backspace) {
2168
+ if (cursor > 0) updateValue(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
2169
+ return;
2170
+ }
2171
+ if (key.delete) {
2172
+ if (cursor < value.length) updateValue(value.slice(0, cursor) + value.slice(cursor + 1), cursor);
2173
+ return;
2174
+ }
2175
+ if (key.ctrl || key.meta) return;
2176
+ if (input.length > 0) updateValue(value.slice(0, cursor) + input + value.slice(cursor), cursor + input.length);
2177
+ }, { isActive: !disabled });
2178
+ const renderCursor = (text, cur) => {
2179
+ if (text.length === 0 && placeholder && cursor === 0) {
2180
+ return /* @__PURE__ */ jsxs6(Text6, { children: [
2181
+ /* @__PURE__ */ jsx7(Text6, { inverse: true, children: " " }),
2182
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: placeholder })
1922
2183
  ] });
1923
2184
  }
1924
- const before = value.slice(0, cursor);
1925
- const atCursor = cursor < value.length ? value[cursor] : " ";
1926
- const after = cursor < value.length ? value.slice(cursor + 1) : "";
1927
- return /* @__PURE__ */ jsxs4(Text5, { children: [
2185
+ const before = text.slice(0, cur);
2186
+ const at = cur < text.length ? text[cur] : " ";
2187
+ const after = cur < text.length ? text.slice(cur + 1) : "";
2188
+ return /* @__PURE__ */ jsxs6(Text6, { children: [
1928
2189
  before,
1929
- /* @__PURE__ */ jsx6(Text5, { inverse: true, children: atCursor }),
2190
+ /* @__PURE__ */ jsx7(Text6, { inverse: true, children: at }),
1930
2191
  after
1931
2192
  ] });
1932
2193
  };
1933
- return /* @__PURE__ */ jsxs4(Box2, { flexDirection: "column", children: [
1934
- /* @__PURE__ */ jsxs4(Box2, { children: [
1935
- /* @__PURE__ */ jsxs4(Text5, { color: prefixColor, children: [
1936
- prefix,
1937
- " "
1938
- ] }),
1939
- renderTextWithCursor()
1940
- ] }),
1941
- hasSuggestions && /* @__PURE__ */ jsx6(Box2, { flexDirection: "column", marginLeft: 2, children: suggestions.map((cmd, i) => /* @__PURE__ */ jsxs4(Box2, { children: [
1942
- /* @__PURE__ */ jsx6(
1943
- Text5,
1944
- {
1945
- inverse: i === suggestionIndex,
1946
- color: i === suggestionIndex ? "cyan" : void 0,
1947
- children: ` /${cmd.name}`
1948
- }
1949
- ),
1950
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: ` ${cmd.description}` })
1951
- ] }, cmd.name)) })
2194
+ const vimTag = vimMode ? /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: ` -- ${vim} --` }) : null;
2195
+ const renderContent = () => {
2196
+ if (!multiline || lines.length <= 1) {
2197
+ return /* @__PURE__ */ jsxs6(Box3, { children: [
2198
+ /* @__PURE__ */ jsxs6(Text6, { color: prefixColor, children: [
2199
+ prefix,
2200
+ " "
2201
+ ] }),
2202
+ renderCursor(value, cursor),
2203
+ vimTag
2204
+ ] });
2205
+ }
2206
+ let off = 0;
2207
+ return /* @__PURE__ */ jsx7(Box3, { flexDirection: "column", children: lines.map((line, i) => {
2208
+ const ls = off;
2209
+ off += line.length + 1;
2210
+ const active = i === cursorLine;
2211
+ return /* @__PURE__ */ jsxs6(Box3, { children: [
2212
+ /* @__PURE__ */ jsx7(Text6, { color: prefixColor, children: i === 0 ? `${prefix} ` : "\u2219 " }),
2213
+ active ? renderCursor(line, cursor - ls) : /* @__PURE__ */ jsx7(Text6, { children: line }),
2214
+ i === lines.length - 1 && vimTag
2215
+ ] }, i);
2216
+ }) });
2217
+ };
2218
+ return /* @__PURE__ */ jsxs6(Box3, { flexDirection: "column", children: [
2219
+ renderContent(),
2220
+ hasSuggestions && /* @__PURE__ */ jsx7(Box3, { flexDirection: "column", marginLeft: 2, children: suggestions.map((cmd, i) => {
2221
+ const isFocused = i === suggestionIndex;
2222
+ return /* @__PURE__ */ jsxs6(Box3, { children: [
2223
+ /* @__PURE__ */ jsxs6(Text6, { color: isFocused ? "cyan" : void 0, children: [
2224
+ isFocused ? "\u276F" : " ",
2225
+ " "
2226
+ ] }),
2227
+ /* @__PURE__ */ jsx7(Text6, { color: isFocused ? "cyan" : void 0, bold: isFocused, children: `/${cmd.name}` }),
2228
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: ` ${cmd.description}` })
2229
+ ] }, cmd.name);
2230
+ }) })
1952
2231
  ] });
1953
2232
  }
1954
2233
 
1955
2234
  // src/Spinner.tsx
1956
2235
  import { useState as useState4, useEffect as useEffect5, useRef as useRef3 } from "react";
1957
- import { Text as Text6, Box as Box3 } from "@claude-code-kit/ink-renderer";
1958
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1959
- var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2236
+ import { Text as Text7, Box as Box4 } from "@claude-code-kit/ink-renderer";
2237
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2238
+ var DEFAULT_CHARACTERS = process.platform === "darwin" ? ["\xB7", "\u2722", "\u2733", "\u2736", "\u273B", "\u273D"] : ["\xB7", "\u2722", "*", "\u2736", "\u273B", "\u273D"];
2239
+ var FRAMES = [...DEFAULT_CHARACTERS, ...[...DEFAULT_CHARACTERS].reverse()];
1960
2240
  var SPINNER_INTERVAL = 80;
1961
2241
  var VERB_ROTATE_INTERVAL = 4e3;
1962
2242
  var ELAPSED_SHOW_AFTER = 1e3;
@@ -1991,18 +2271,18 @@ function Spinner({
1991
2271
  const currentVerb = allVerbs[verbIndex % allVerbs.length];
1992
2272
  const elapsedSec = Math.floor(elapsed / 1e3);
1993
2273
  const showTime = showElapsed && elapsed >= ELAPSED_SHOW_AFTER;
1994
- return /* @__PURE__ */ jsxs5(Box3, { children: [
1995
- /* @__PURE__ */ jsx7(Text6, { color: color2, children: frame }),
1996
- /* @__PURE__ */ jsxs5(Text6, { children: [
2274
+ return /* @__PURE__ */ jsxs7(Box4, { children: [
2275
+ /* @__PURE__ */ jsx8(Text7, { color: color2, children: frame }),
2276
+ /* @__PURE__ */ jsxs7(Text7, { children: [
1997
2277
  " ",
1998
2278
  currentVerb,
1999
2279
  "..."
2000
2280
  ] }),
2001
- label && /* @__PURE__ */ jsxs5(Text6, { children: [
2281
+ label && /* @__PURE__ */ jsxs7(Text7, { children: [
2002
2282
  " ",
2003
2283
  label
2004
2284
  ] }),
2005
- showTime && /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
2285
+ showTime && /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2006
2286
  " (",
2007
2287
  elapsedSec,
2008
2288
  "s)"
@@ -2012,12 +2292,12 @@ function Spinner({
2012
2292
 
2013
2293
  // src/Markdown.tsx
2014
2294
  import { marked as marked2 } from "marked";
2015
- import { Suspense, use, useMemo as useMemo3, useRef as useRef4 } from "react";
2016
- import { Ansi as Ansi4, Box as Box4 } from "@claude-code-kit/ink-renderer";
2295
+ import { Suspense, use, useMemo as useMemo4, useRef as useRef4 } from "react";
2296
+ import { Ansi as Ansi4, Box as Box5 } from "@claude-code-kit/ink-renderer";
2017
2297
 
2018
2298
  // src/design-system/ThemeProvider.tsx
2019
- import { createContext as createContext2, useContext as useContext4, useMemo as useMemo2, useState as useState5 } from "react";
2020
- import { jsx as jsx8 } from "react/jsx-runtime";
2299
+ import { createContext as createContext2, useContext as useContext4, useMemo as useMemo3, useState as useState5 } from "react";
2300
+ import { jsx as jsx9 } from "react/jsx-runtime";
2021
2301
  var themes = {
2022
2302
  dark: {
2023
2303
  text: "#E0E0E0",
@@ -2030,7 +2310,29 @@ var themes = {
2030
2310
  assistant: "#DA7756",
2031
2311
  inactive: "#666666",
2032
2312
  inverseText: "#1E1E1E",
2033
- permission: "#5B9BD5"
2313
+ permission: "#5B9BD5",
2314
+ diffAdded: "#1a3a1a",
2315
+ diffRemoved: "#3a1a1a",
2316
+ diffAddedWord: "#2d5a2d",
2317
+ diffRemovedWord: "#5a2d2d",
2318
+ diffHeader: "#1e2d3d",
2319
+ userMessage: "#2B4A6F",
2320
+ assistantMessage: "#3D2614",
2321
+ systemMessage: "#2D2D2D",
2322
+ toolUseMessage: "#1E3A2D",
2323
+ permissionAllow: "#1B4332",
2324
+ permissionDeny: "#3B1014",
2325
+ permissionAlways: "#1B2F4D",
2326
+ focus: "#5B9BD5",
2327
+ selection: "#264F78",
2328
+ placeholder: "#555555",
2329
+ link: "#79B8FF",
2330
+ code: "#F8BFB0",
2331
+ codeBackground: "#2D2D2D",
2332
+ blockquote: "#444444",
2333
+ info: "#5B9BD5",
2334
+ spinnerColor: "#DA7756",
2335
+ shimmer: "#3A3A3A"
2034
2336
  },
2035
2337
  light: {
2036
2338
  text: "#1E1E1E",
@@ -2043,7 +2345,99 @@ var themes = {
2043
2345
  assistant: "#DA7756",
2044
2346
  inactive: "#999999",
2045
2347
  inverseText: "#FFFFFF",
2046
- permission: "#0066CC"
2348
+ permission: "#0066CC",
2349
+ diffAdded: "#E6FFEC",
2350
+ diffRemoved: "#FFEBE9",
2351
+ diffAddedWord: "#CCFFD8",
2352
+ diffRemovedWord: "#FFD7D5",
2353
+ diffHeader: "#DDF4FF",
2354
+ userMessage: "#E8F0FE",
2355
+ assistantMessage: "#FDF2EE",
2356
+ systemMessage: "#F5F5F5",
2357
+ toolUseMessage: "#EAF5EE",
2358
+ permissionAllow: "#E6F4EA",
2359
+ permissionDeny: "#FCE8E6",
2360
+ permissionAlways: "#E8F0FE",
2361
+ focus: "#0066CC",
2362
+ selection: "#B3D4FF",
2363
+ placeholder: "#AAAAAA",
2364
+ link: "#0066CC",
2365
+ code: "#C7522A",
2366
+ codeBackground: "#F5F5F5",
2367
+ blockquote: "#EEEEEE",
2368
+ info: "#0066CC",
2369
+ spinnerColor: "#DA7756",
2370
+ shimmer: "#E8E8E8"
2371
+ },
2372
+ "light-high-contrast": {
2373
+ text: "#000000",
2374
+ dimText: "#595959",
2375
+ border: "#767676",
2376
+ accent: "#0000EE",
2377
+ success: "#006400",
2378
+ warning: "#7A4000",
2379
+ error: "#AE1818",
2380
+ assistant: "#B55530",
2381
+ inactive: "#767676",
2382
+ inverseText: "#FFFFFF",
2383
+ permission: "#0000EE",
2384
+ diffAdded: "#CCF0D0",
2385
+ diffRemoved: "#F5C6C6",
2386
+ diffAddedWord: "#99E0A0",
2387
+ diffRemovedWord: "#EBA0A0",
2388
+ diffHeader: "#B8DEFF",
2389
+ userMessage: "#C8DCFF",
2390
+ assistantMessage: "#FCDAC8",
2391
+ systemMessage: "#E0E0E0",
2392
+ toolUseMessage: "#C4EED0",
2393
+ permissionAllow: "#C4EED0",
2394
+ permissionDeny: "#F5C6C6",
2395
+ permissionAlways: "#C8DCFF",
2396
+ focus: "#0000EE",
2397
+ selection: "#80BFFF",
2398
+ placeholder: "#767676",
2399
+ link: "#0000EE",
2400
+ code: "#8B0000",
2401
+ codeBackground: "#E8E8E8",
2402
+ blockquote: "#D0D0D0",
2403
+ info: "#0000EE",
2404
+ spinnerColor: "#B55530",
2405
+ shimmer: "#D0D0D0"
2406
+ },
2407
+ "dark-dimmed": {
2408
+ text: "#ADBAC7",
2409
+ dimText: "#545D68",
2410
+ border: "#373E47",
2411
+ accent: "#539BF5",
2412
+ success: "#57AB5A",
2413
+ warning: "#C69026",
2414
+ error: "#E5534B",
2415
+ assistant: "#DA7756",
2416
+ inactive: "#545D68",
2417
+ inverseText: "#22272E",
2418
+ permission: "#539BF5",
2419
+ diffAdded: "#1B2F23",
2420
+ diffRemoved: "#2F1B1E",
2421
+ diffAddedWord: "#264D30",
2422
+ diffRemovedWord: "#4D2628",
2423
+ diffHeader: "#1C2B3A",
2424
+ userMessage: "#1C2B3A",
2425
+ assistantMessage: "#2F211A",
2426
+ systemMessage: "#2D333B",
2427
+ toolUseMessage: "#1B2B23",
2428
+ permissionAllow: "#1B2B23",
2429
+ permissionDeny: "#2F1B1E",
2430
+ permissionAlways: "#1C2B3A",
2431
+ focus: "#539BF5",
2432
+ selection: "#1C4066",
2433
+ placeholder: "#545D68",
2434
+ link: "#6CB6FF",
2435
+ code: "#F0A070",
2436
+ codeBackground: "#2D333B",
2437
+ blockquote: "#373E47",
2438
+ info: "#539BF5",
2439
+ spinnerColor: "#DA7756",
2440
+ shimmer: "#373E47"
2047
2441
  }
2048
2442
  };
2049
2443
  function getTheme(name) {
@@ -2071,7 +2465,7 @@ function ThemeProvider({
2071
2465
  const [previewTheme, setPreviewTheme] = useState5(null);
2072
2466
  const activeSetting = previewTheme ?? themeSetting;
2073
2467
  const currentTheme = activeSetting === "auto" ? "dark" : activeSetting;
2074
- const value = useMemo2(
2468
+ const value = useMemo3(
2075
2469
  () => ({
2076
2470
  themeSetting,
2077
2471
  setThemeSetting: (newSetting) => {
@@ -2098,7 +2492,7 @@ function ThemeProvider({
2098
2492
  }),
2099
2493
  [themeSetting, previewTheme, currentTheme, onThemeSave]
2100
2494
  );
2101
- return /* @__PURE__ */ jsx8(ThemeContext.Provider, { value, children });
2495
+ return /* @__PURE__ */ jsx9(ThemeContext.Provider, { value, children });
2102
2496
  }
2103
2497
  function useTheme() {
2104
2498
  const { currentTheme, setThemeSetting } = useContext4(ThemeContext);
@@ -2116,7 +2510,8 @@ function usePreviewTheme() {
2116
2510
  var cliHighlightPromise;
2117
2511
  async function loadCliHighlight() {
2118
2512
  try {
2119
- const cliHighlight = await import("cli-highlight");
2513
+ const mod = await import("cli-highlight");
2514
+ const cliHighlight = mod;
2120
2515
  return {
2121
2516
  highlight: cliHighlight.highlight,
2122
2517
  supportsLanguage: cliHighlight.supportsLanguage
@@ -2431,7 +2826,7 @@ import { TerminalSizeContext as TerminalSizeContext3 } from "@claude-code-kit/in
2431
2826
  import { stringWidth as stringWidth3 } from "@claude-code-kit/ink-renderer";
2432
2827
  import { wrapAnsi } from "@claude-code-kit/ink-renderer";
2433
2828
  import { Ansi as Ansi3 } from "@claude-code-kit/ink-renderer";
2434
- import { jsx as jsx9 } from "react/jsx-runtime";
2829
+ import { jsx as jsx10 } from "react/jsx-runtime";
2435
2830
  var SAFETY_MARGIN = 4;
2436
2831
  var MIN_COLUMN_WIDTH = 3;
2437
2832
  var MAX_ROW_LINES = 4;
@@ -2607,7 +3002,7 @@ function MarkdownTable({
2607
3002
  return lines_2.join("\n");
2608
3003
  }
2609
3004
  if (useVerticalFormat) {
2610
- return /* @__PURE__ */ jsx9(Ansi3, { children: renderVerticalFormat() });
3005
+ return /* @__PURE__ */ jsx10(Ansi3, { children: renderVerticalFormat() });
2611
3006
  }
2612
3007
  const tableLines = [];
2613
3008
  tableLines.push(renderBorderLine("top"));
@@ -2622,13 +3017,13 @@ function MarkdownTable({
2622
3017
  tableLines.push(renderBorderLine("bottom"));
2623
3018
  const maxLineWidth = Math.max(...tableLines.map((line_2) => stringWidth3(stripAnsi2(line_2))));
2624
3019
  if (maxLineWidth > terminalWidth - SAFETY_MARGIN) {
2625
- return /* @__PURE__ */ jsx9(Ansi3, { children: renderVerticalFormat() });
3020
+ return /* @__PURE__ */ jsx10(Ansi3, { children: renderVerticalFormat() });
2626
3021
  }
2627
- return /* @__PURE__ */ jsx9(Ansi3, { children: tableLines.join("\n") });
3022
+ return /* @__PURE__ */ jsx10(Ansi3, { children: tableLines.join("\n") });
2628
3023
  }
2629
3024
 
2630
3025
  // src/Markdown.tsx
2631
- import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
3026
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2632
3027
  var TOKEN_CACHE_MAX = 500;
2633
3028
  var tokenCache = /* @__PURE__ */ new Map();
2634
3029
  var MD_SYNTAX_RE = /[#*`|[>\-_~]|\n\n|^\d+\. |\n\d+\. /;
@@ -2667,13 +3062,13 @@ function cachedLexer(content) {
2667
3062
  function Markdown(props) {
2668
3063
  const settings = {};
2669
3064
  if (settings.syntaxHighlightingDisabled) {
2670
- return /* @__PURE__ */ jsx10(MarkdownBody, { ...props, highlight: null });
3065
+ return /* @__PURE__ */ jsx11(MarkdownBody, { ...props, highlight: null });
2671
3066
  }
2672
- return /* @__PURE__ */ jsx10(Suspense, { fallback: /* @__PURE__ */ jsx10(MarkdownBody, { ...props, highlight: null }), children: /* @__PURE__ */ jsx10(MarkdownWithHighlight, { ...props }) });
3067
+ return /* @__PURE__ */ jsx11(Suspense, { fallback: /* @__PURE__ */ jsx11(MarkdownBody, { ...props, highlight: null }), children: /* @__PURE__ */ jsx11(MarkdownWithHighlight, { ...props }) });
2673
3068
  }
2674
3069
  function MarkdownWithHighlight(props) {
2675
3070
  const highlight = use(getCliHighlightPromise());
2676
- return /* @__PURE__ */ jsx10(MarkdownBody, { ...props, highlight });
3071
+ return /* @__PURE__ */ jsx11(MarkdownBody, { ...props, highlight });
2677
3072
  }
2678
3073
  function MarkdownBody({
2679
3074
  children,
@@ -2682,14 +3077,14 @@ function MarkdownBody({
2682
3077
  }) {
2683
3078
  const [theme] = useTheme();
2684
3079
  configureMarked();
2685
- const elements = useMemo3(() => {
3080
+ const elements = useMemo4(() => {
2686
3081
  const tokens = cachedLexer(stripPromptXMLTags(children));
2687
3082
  const elements2 = [];
2688
3083
  let nonTableContent = "";
2689
3084
  function flushNonTableContent() {
2690
3085
  if (nonTableContent) {
2691
3086
  elements2.push(
2692
- /* @__PURE__ */ jsx10(Ansi4, { dimColor, children: nonTableContent.trim() }, elements2.length)
3087
+ /* @__PURE__ */ jsx11(Ansi4, { dimColor, children: nonTableContent.trim() }, elements2.length)
2693
3088
  );
2694
3089
  nonTableContent = "";
2695
3090
  }
@@ -2698,7 +3093,7 @@ function MarkdownBody({
2698
3093
  if (token.type === "table") {
2699
3094
  flushNonTableContent();
2700
3095
  elements2.push(
2701
- /* @__PURE__ */ jsx10(
3096
+ /* @__PURE__ */ jsx11(
2702
3097
  MarkdownTable,
2703
3098
  {
2704
3099
  token,
@@ -2714,7 +3109,7 @@ function MarkdownBody({
2714
3109
  flushNonTableContent();
2715
3110
  return elements2;
2716
3111
  }, [children, dimColor, highlight, theme]);
2717
- return /* @__PURE__ */ jsx10(Box4, { flexDirection: "column", gap: 1, children: elements });
3112
+ return /* @__PURE__ */ jsx11(Box5, { flexDirection: "column", gap: 1, children: elements });
2718
3113
  }
2719
3114
  function StreamingMarkdown({
2720
3115
  children
@@ -2741,16 +3136,16 @@ function StreamingMarkdown({
2741
3136
  }
2742
3137
  const stablePrefix = stablePrefixRef.current;
2743
3138
  const unstableSuffix = stripped.substring(stablePrefix.length);
2744
- return /* @__PURE__ */ jsxs6(Box4, { flexDirection: "column", gap: 1, children: [
2745
- stablePrefix && /* @__PURE__ */ jsx10(Markdown, { children: stablePrefix }),
2746
- unstableSuffix && /* @__PURE__ */ jsx10(Markdown, { children: unstableSuffix })
3139
+ return /* @__PURE__ */ jsxs8(Box5, { flexDirection: "column", gap: 1, children: [
3140
+ stablePrefix && /* @__PURE__ */ jsx11(Markdown, { children: stablePrefix }),
3141
+ unstableSuffix && /* @__PURE__ */ jsx11(Markdown, { children: unstableSuffix })
2747
3142
  ] });
2748
3143
  }
2749
3144
 
2750
3145
  // src/Select.tsx
2751
- import { useState as useState6, useRef as useRef5, useMemo as useMemo4, useCallback as useCallback5 } from "react";
2752
- import { Box as Box5, Text as Text7, useInput as useInput4 } from "@claude-code-kit/ink-renderer";
2753
- import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
3146
+ import { useState as useState6, useRef as useRef5, useMemo as useMemo5, useCallback as useCallback5 } from "react";
3147
+ import { Box as Box6, Text as Text8, useInput as useInput4 } from "@claude-code-kit/ink-renderer";
3148
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2754
3149
  function useListNavigation(opts) {
2755
3150
  const { options, maxVisible, onCancel, onSelect, extraHandler } = opts;
2756
3151
  const [focusIndex, setFocusIndex] = useState6(0);
@@ -2758,14 +3153,14 @@ function useListNavigation(opts) {
2758
3153
  focusRef.current = focusIndex;
2759
3154
  const total = options.length;
2760
3155
  const max = maxVisible ?? total;
2761
- const scrollOffset = useMemo4(() => {
3156
+ const scrollOffset = useMemo5(() => {
2762
3157
  if (total <= max) return 0;
2763
3158
  const half = Math.floor(max / 2);
2764
3159
  if (focusIndex <= half) return 0;
2765
3160
  if (focusIndex >= total - max + half) return total - max;
2766
3161
  return focusIndex - half;
2767
3162
  }, [focusIndex, total, max]);
2768
- const visibleOptions = useMemo4(
3163
+ const visibleOptions = useMemo5(
2769
3164
  () => options.slice(scrollOffset, scrollOffset + max),
2770
3165
  [options, scrollOffset, max]
2771
3166
  );
@@ -2805,7 +3200,7 @@ function useListNavigation(opts) {
2805
3200
  return { focusIndex, scrollOffset, visibleOptions, max, total };
2806
3201
  }
2807
3202
  function ScrollHint({ count, direction }) {
2808
- return /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
3203
+ return /* @__PURE__ */ jsxs9(Text8, { dimColor: true, children: [
2809
3204
  " ",
2810
3205
  direction === "up" ? "\u2191" : "\u2193",
2811
3206
  " ",
@@ -2826,21 +3221,21 @@ function Select({
2826
3221
  [onChange, options]
2827
3222
  );
2828
3223
  const { focusIndex, scrollOffset, visibleOptions, max, total } = useListNavigation({ options, maxVisible, onCancel, onSelect: handleSelect });
2829
- return /* @__PURE__ */ jsxs7(Box5, { flexDirection: "column", children: [
2830
- title && /* @__PURE__ */ jsx11(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx11(Text7, { bold: true, children: title }) }),
2831
- scrollOffset > 0 && /* @__PURE__ */ jsx11(ScrollHint, { count: scrollOffset, direction: "up" }),
3224
+ return /* @__PURE__ */ jsxs9(Box6, { flexDirection: "column", children: [
3225
+ title && /* @__PURE__ */ jsx12(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Text8, { bold: true, children: title }) }),
3226
+ scrollOffset > 0 && /* @__PURE__ */ jsx12(ScrollHint, { count: scrollOffset, direction: "up" }),
2832
3227
  visibleOptions.map((opt, i) => {
2833
3228
  const realIndex = scrollOffset + i;
2834
3229
  const isFocused = realIndex === focusIndex;
2835
3230
  const isSelected = opt.value === defaultValue;
2836
3231
  const isDisabled = opt.disabled === true;
2837
- return /* @__PURE__ */ jsxs7(Box5, { children: [
2838
- /* @__PURE__ */ jsxs7(Text7, { color: isFocused ? "cyan" : void 0, children: [
3232
+ return /* @__PURE__ */ jsxs9(Box6, { children: [
3233
+ /* @__PURE__ */ jsxs9(Text8, { color: isFocused ? "cyan" : void 0, children: [
2839
3234
  isFocused ? "\u276F" : " ",
2840
3235
  " "
2841
3236
  ] }),
2842
- /* @__PURE__ */ jsxs7(
2843
- Text7,
3237
+ /* @__PURE__ */ jsxs9(
3238
+ Text8,
2844
3239
  {
2845
3240
  color: isDisabled ? "gray" : isFocused ? "cyan" : void 0,
2846
3241
  bold: isFocused,
@@ -2852,15 +3247,15 @@ function Select({
2852
3247
  ]
2853
3248
  }
2854
3249
  ),
2855
- isSelected && /* @__PURE__ */ jsx11(Text7, { color: "green", children: " \u2713" }),
2856
- opt.description && /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
3250
+ isSelected && /* @__PURE__ */ jsx12(Text8, { color: "green", children: " \u2713" }),
3251
+ opt.description && /* @__PURE__ */ jsxs9(Text8, { dimColor: true, children: [
2857
3252
  " ",
2858
3253
  opt.description
2859
3254
  ] })
2860
3255
  ] }, realIndex);
2861
3256
  }),
2862
- scrollOffset + max < total && /* @__PURE__ */ jsx11(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
2863
- /* @__PURE__ */ jsx11(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text7, { dimColor: true, children: "Enter to confirm \xB7 Esc to exit" }) })
3257
+ scrollOffset + max < total && /* @__PURE__ */ jsx12(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
3258
+ /* @__PURE__ */ jsx12(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text8, { dimColor: true, children: "Enter to confirm \xB7 Esc to exit" }) })
2864
3259
  ] });
2865
3260
  }
2866
3261
  function MultiSelect({
@@ -2900,21 +3295,21 @@ function MultiSelect({
2900
3295
  onSelect: handleConfirm,
2901
3296
  extraHandler: handleSpace
2902
3297
  });
2903
- return /* @__PURE__ */ jsxs7(Box5, { flexDirection: "column", children: [
2904
- title && /* @__PURE__ */ jsx11(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx11(Text7, { bold: true, children: title }) }),
2905
- scrollOffset > 0 && /* @__PURE__ */ jsx11(ScrollHint, { count: scrollOffset, direction: "up" }),
3298
+ return /* @__PURE__ */ jsxs9(Box6, { flexDirection: "column", children: [
3299
+ title && /* @__PURE__ */ jsx12(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Text8, { bold: true, children: title }) }),
3300
+ scrollOffset > 0 && /* @__PURE__ */ jsx12(ScrollHint, { count: scrollOffset, direction: "up" }),
2906
3301
  visibleOptions.map((opt, i) => {
2907
3302
  const realIndex = scrollOffset + i;
2908
3303
  const isFocused = realIndex === focusIndex;
2909
3304
  const isChecked = selected.has(opt.value);
2910
3305
  const isDisabled = opt.disabled === true;
2911
- return /* @__PURE__ */ jsxs7(Box5, { children: [
2912
- /* @__PURE__ */ jsxs7(Text7, { color: isFocused ? "cyan" : void 0, children: [
3306
+ return /* @__PURE__ */ jsxs9(Box6, { children: [
3307
+ /* @__PURE__ */ jsxs9(Text8, { color: isFocused ? "cyan" : void 0, children: [
2913
3308
  isFocused ? "\u276F" : " ",
2914
3309
  " "
2915
3310
  ] }),
2916
- /* @__PURE__ */ jsxs7(
2917
- Text7,
3311
+ /* @__PURE__ */ jsxs9(
3312
+ Text8,
2918
3313
  {
2919
3314
  color: isDisabled ? "gray" : isFocused ? "cyan" : void 0,
2920
3315
  bold: isFocused,
@@ -2928,25 +3323,263 @@ function MultiSelect({
2928
3323
  ]
2929
3324
  }
2930
3325
  ),
2931
- opt.description && /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
3326
+ opt.description && /* @__PURE__ */ jsxs9(Text8, { dimColor: true, children: [
2932
3327
  " ",
2933
3328
  opt.description
2934
3329
  ] })
2935
3330
  ] }, realIndex);
2936
3331
  }),
2937
- scrollOffset + max < total && /* @__PURE__ */ jsx11(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
2938
- /* @__PURE__ */ jsx11(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text7, { dimColor: true, children: "Space to toggle \xB7 Enter to confirm \xB7 Esc to exit" }) })
3332
+ scrollOffset + max < total && /* @__PURE__ */ jsx12(ScrollHint, { count: total - scrollOffset - max, direction: "down" }),
3333
+ /* @__PURE__ */ jsx12(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text8, { dimColor: true, children: "Space to toggle \xB7 Enter to confirm \xB7 Esc to exit" }) })
3334
+ ] });
3335
+ }
3336
+
3337
+ // src/PermissionRequest.tsx
3338
+ import React12, { useMemo as useMemo6, useCallback as useCallback6, useContext as useContext6 } from "react";
3339
+ import { Box as Box7, Text as Text9, useInput as useInput5, TerminalSizeContext as TerminalSizeContext4 } from "@claude-code-kit/ink-renderer";
3340
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
3341
+ function PermissionHeader({ toolName, width }) {
3342
+ const label = ` ${toolName} `;
3343
+ const labelLen = toolName.length + 2;
3344
+ const leftLen = 3;
3345
+ const rightLen = Math.max(0, width - leftLen - labelLen);
3346
+ return /* @__PURE__ */ jsxs10(Text9, { children: [
3347
+ /* @__PURE__ */ jsx13(Text9, { dimColor: true, children: "\u2500".repeat(leftLen) }),
3348
+ /* @__PURE__ */ jsx13(Text9, { bold: true, color: "cyan", children: label }),
3349
+ /* @__PURE__ */ jsx13(Text9, { dimColor: true, children: "\u2500".repeat(rightLen) })
3350
+ ] });
3351
+ }
3352
+ function HorizontalRule({ width }) {
3353
+ return /* @__PURE__ */ jsx13(Text9, { dimColor: true, children: "\u2500".repeat(width) });
3354
+ }
3355
+ function BashPermissionContent({ command }) {
3356
+ return /* @__PURE__ */ jsxs10(Box7, { flexDirection: "column", children: [
3357
+ /* @__PURE__ */ jsx13(Text9, { children: "Run command:" }),
3358
+ /* @__PURE__ */ jsx13(Box7, { marginLeft: 2, children: /* @__PURE__ */ jsx13(Text9, { color: "yellow", children: command }) })
3359
+ ] });
3360
+ }
3361
+ function FileEditPermissionContent({
3362
+ filename,
3363
+ diff
3364
+ }) {
3365
+ return /* @__PURE__ */ jsxs10(Box7, { flexDirection: "column", children: [
3366
+ /* @__PURE__ */ jsxs10(Text9, { children: [
3367
+ "Edit file: ",
3368
+ /* @__PURE__ */ jsx13(Text9, { color: "cyan", bold: true, children: filename })
3369
+ ] }),
3370
+ diff && /* @__PURE__ */ jsx13(Box7, { marginTop: 1, flexDirection: "column", children: diff.split("\n").map((line, i) => {
3371
+ let color2;
3372
+ if (line.startsWith("+")) color2 = "green";
3373
+ else if (line.startsWith("-")) color2 = "red";
3374
+ else if (line.startsWith("@")) color2 = "cyan";
3375
+ return /* @__PURE__ */ jsx13(Text9, { color: color2, dimColor: !color2 && !line.startsWith("+"), children: line }, i);
3376
+ }) })
3377
+ ] });
3378
+ }
3379
+ function PermissionRequest({
3380
+ toolName,
3381
+ description,
3382
+ details,
3383
+ showAlwaysAllow = true,
3384
+ onDecision,
3385
+ children,
3386
+ preview
3387
+ }) {
3388
+ const terminalSize = useContext6(TerminalSizeContext4);
3389
+ const terminalWidth = Math.min((terminalSize?.columns ?? 80) - 2, 80);
3390
+ const options = useMemo6(() => {
3391
+ const opts = [
3392
+ { value: "allow", label: "Yes, allow this action" }
3393
+ ];
3394
+ if (showAlwaysAllow) {
3395
+ opts.push({ value: "always_allow", label: `Yes, and always allow ${toolName}` });
3396
+ }
3397
+ opts.push({ value: "deny", label: "No, deny" });
3398
+ return opts;
3399
+ }, [showAlwaysAllow, toolName]);
3400
+ const [focusIndex, setFocusIndex] = React12.useState(0);
3401
+ const focusRef = React12.useRef(focusIndex);
3402
+ focusRef.current = focusIndex;
3403
+ const decide = useCallback6(
3404
+ (action) => {
3405
+ onDecision(action);
3406
+ },
3407
+ [onDecision]
3408
+ );
3409
+ useInput5((input, key) => {
3410
+ if (input === "y") {
3411
+ decide("allow");
3412
+ return;
3413
+ }
3414
+ if (input === "a" && showAlwaysAllow) {
3415
+ decide("always_allow");
3416
+ return;
3417
+ }
3418
+ if (input === "n" || key.escape) {
3419
+ decide("deny");
3420
+ return;
3421
+ }
3422
+ if (key.upArrow || input === "k") {
3423
+ setFocusIndex((prev) => (prev - 1 + options.length) % options.length);
3424
+ } else if (key.downArrow || input === "j") {
3425
+ setFocusIndex((prev) => (prev + 1) % options.length);
3426
+ } else if (key.return) {
3427
+ decide(options[focusRef.current].value);
3428
+ } else if (input >= "1" && input <= "9") {
3429
+ const idx = parseInt(input, 10) - 1;
3430
+ if (idx < options.length) {
3431
+ setFocusIndex(idx);
3432
+ decide(options[idx].value);
3433
+ }
3434
+ }
3435
+ });
3436
+ return /* @__PURE__ */ jsxs10(Box7, { flexDirection: "column", children: [
3437
+ /* @__PURE__ */ jsx13(PermissionHeader, { toolName, width: terminalWidth }),
3438
+ /* @__PURE__ */ jsx13(Box7, { marginTop: 1, marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx13(Text9, { children: description }) }),
3439
+ details && /* @__PURE__ */ jsx13(Box7, { marginTop: 1, marginLeft: 4, children: /* @__PURE__ */ jsx13(Text9, { color: "yellow", children: details }) }),
3440
+ children && /* @__PURE__ */ jsx13(Box7, { marginTop: 1, marginLeft: 2, flexDirection: "column", children }),
3441
+ preview && /* @__PURE__ */ jsx13(Box7, { marginTop: 1, marginLeft: 2, flexDirection: "column", children: preview }),
3442
+ /* @__PURE__ */ jsx13(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx13(HorizontalRule, { width: terminalWidth }) }),
3443
+ /* @__PURE__ */ jsx13(Box7, { marginTop: 1, flexDirection: "column", children: options.map((opt, i) => {
3444
+ const isFocused = i === focusIndex;
3445
+ return /* @__PURE__ */ jsxs10(Box7, { children: [
3446
+ /* @__PURE__ */ jsxs10(Text9, { color: isFocused ? "cyan" : void 0, children: [
3447
+ isFocused ? "\u276F" : " ",
3448
+ " "
3449
+ ] }),
3450
+ /* @__PURE__ */ jsxs10(
3451
+ Text9,
3452
+ {
3453
+ color: isFocused ? "cyan" : void 0,
3454
+ bold: isFocused,
3455
+ children: [
3456
+ i + 1,
3457
+ ". ",
3458
+ opt.label
3459
+ ]
3460
+ }
3461
+ )
3462
+ ] }, opt.value);
3463
+ }) }),
3464
+ /* @__PURE__ */ jsx13(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text9, { dimColor: true, children: "Enter to confirm \xB7 Esc to deny" }) })
2939
3465
  ] });
2940
3466
  }
2941
3467
 
2942
3468
  // src/MessageList.tsx
2943
- import { Box as Box6, Text as Text8 } from "@claude-code-kit/ink-renderer";
2944
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
3469
+ import { useState as useState7 } from "react";
3470
+ import { Box as Box8, Text as Text10 } from "@claude-code-kit/ink-renderer";
3471
+ import { Fragment, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
2945
3472
  var ROLE_CONFIG = {
2946
3473
  user: { icon: "\u276F", label: "You", color: "cyan" },
2947
3474
  assistant: { icon: "\u25CF", label: "Claude", color: "#DA7756" },
2948
3475
  system: { icon: "\u273B", label: "System", color: void 0 }
2949
3476
  };
3477
+ var GUTTER = "\u23BF";
3478
+ function TextBlock({ text, dim }) {
3479
+ return /* @__PURE__ */ jsx14(Fragment, { children: text.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 2, children: /* @__PURE__ */ jsx14(Text10, { dimColor: dim, children: line }) }, i)) });
3480
+ }
3481
+ function ToolUseBlock({ content }) {
3482
+ const statusColor = content.status === "error" ? "red" : content.status === "success" ? "green" : void 0;
3483
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginLeft: 2, children: [
3484
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3485
+ /* @__PURE__ */ jsxs11(Text10, { dimColor: true, children: [
3486
+ GUTTER,
3487
+ " "
3488
+ ] }),
3489
+ /* @__PURE__ */ jsx14(Text10, { bold: true, children: content.toolName })
3490
+ ] }),
3491
+ content.input.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 4, children: /* @__PURE__ */ jsx14(Text10, { dimColor: true, children: line }) }, i)),
3492
+ content.status === "running" && /* @__PURE__ */ jsx14(Box8, { marginLeft: 4, children: /* @__PURE__ */ jsx14(Spinner, { label: content.toolName, showElapsed: true }) }),
3493
+ content.result != null && /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginLeft: 4, children: [
3494
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3495
+ /* @__PURE__ */ jsxs11(Text10, { dimColor: true, children: [
3496
+ GUTTER,
3497
+ " "
3498
+ ] }),
3499
+ /* @__PURE__ */ jsxs11(Text10, { color: statusColor, children: [
3500
+ "result (",
3501
+ content.status ?? "done",
3502
+ ")"
3503
+ ] })
3504
+ ] }),
3505
+ content.result.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 6, children: /* @__PURE__ */ jsx14(Text10, { color: statusColor, dimColor: !statusColor, children: line }) }, i))
3506
+ ] })
3507
+ ] });
3508
+ }
3509
+ function ThinkingBlock({ content }) {
3510
+ const [collapsed, setCollapsed] = useState7(content.collapsed ?? true);
3511
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginLeft: 2, children: [
3512
+ /* @__PURE__ */ jsxs11(Box8, { onClick: () => setCollapsed((c) => !c), children: [
3513
+ /* @__PURE__ */ jsxs11(Text10, { color: "#DA7756", children: [
3514
+ "\u273B",
3515
+ " "
3516
+ ] }),
3517
+ /* @__PURE__ */ jsxs11(Text10, { dimColor: true, children: [
3518
+ "Thinking...",
3519
+ collapsed ? " (click to expand)" : ""
3520
+ ] })
3521
+ ] }),
3522
+ !collapsed && content.text.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 4, children: /* @__PURE__ */ jsx14(Text10, { dimColor: true, children: line }) }, i))
3523
+ ] });
3524
+ }
3525
+ function DiffBlock({ content }) {
3526
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginLeft: 2, children: [
3527
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3528
+ /* @__PURE__ */ jsxs11(Text10, { dimColor: true, children: [
3529
+ GUTTER,
3530
+ " "
3531
+ ] }),
3532
+ /* @__PURE__ */ jsx14(Text10, { bold: true, children: content.filename })
3533
+ ] }),
3534
+ content.diff.split("\n").map((line, i) => {
3535
+ let color2;
3536
+ if (line.startsWith("+")) color2 = "green";
3537
+ else if (line.startsWith("-")) color2 = "red";
3538
+ else if (line.startsWith("@")) color2 = "cyan";
3539
+ return /* @__PURE__ */ jsx14(Box8, { marginLeft: 4, children: /* @__PURE__ */ jsx14(Text10, { color: color2, dimColor: !color2, children: line }) }, i);
3540
+ })
3541
+ ] });
3542
+ }
3543
+ function CodeBlock({ content }) {
3544
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginLeft: 2, children: [
3545
+ /* @__PURE__ */ jsxs11(Text10, { dimColor: true, children: [
3546
+ "```",
3547
+ content.language ?? ""
3548
+ ] }),
3549
+ content.code.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 2, children: /* @__PURE__ */ jsx14(Text10, { children: line }) }, i)),
3550
+ /* @__PURE__ */ jsx14(Text10, { dimColor: true, children: "```" })
3551
+ ] });
3552
+ }
3553
+ function ErrorBlock({ content }) {
3554
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginLeft: 2, children: [
3555
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3556
+ /* @__PURE__ */ jsxs11(Text10, { color: "red", children: [
3557
+ "\u2716",
3558
+ " Error: "
3559
+ ] }),
3560
+ /* @__PURE__ */ jsx14(Text10, { color: "red", children: content.message })
3561
+ ] }),
3562
+ content.details?.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 4, children: /* @__PURE__ */ jsx14(Text10, { color: "red", dimColor: true, children: line }) }, i))
3563
+ ] });
3564
+ }
3565
+ function ContentBlock({ block }) {
3566
+ switch (block.type) {
3567
+ case "text":
3568
+ return /* @__PURE__ */ jsx14(TextBlock, { text: block.text });
3569
+ case "tool_use":
3570
+ return /* @__PURE__ */ jsx14(ToolUseBlock, { content: block });
3571
+ case "thinking":
3572
+ return /* @__PURE__ */ jsx14(ThinkingBlock, { content: block });
3573
+ case "diff":
3574
+ return /* @__PURE__ */ jsx14(DiffBlock, { content: block });
3575
+ case "code":
3576
+ return /* @__PURE__ */ jsx14(CodeBlock, { content: block });
3577
+ case "error":
3578
+ return /* @__PURE__ */ jsx14(ErrorBlock, { content: block });
3579
+ default:
3580
+ return null;
3581
+ }
3582
+ }
2950
3583
  function MessageItem({
2951
3584
  message,
2952
3585
  renderMessage
@@ -2956,15 +3589,27 @@ function MessageItem({
2956
3589
  }
2957
3590
  const config = ROLE_CONFIG[message.role];
2958
3591
  const isSystem = message.role === "system";
2959
- return /* @__PURE__ */ jsxs8(Box6, { flexDirection: "column", children: [
2960
- /* @__PURE__ */ jsxs8(Box6, { children: [
2961
- /* @__PURE__ */ jsx12(Text8, { color: config.color, dimColor: isSystem, children: config.icon }),
2962
- /* @__PURE__ */ jsxs8(Text8, { color: config.color, dimColor: isSystem, bold: !isSystem, children: [
3592
+ if (typeof message.content === "string") {
3593
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", children: [
3594
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3595
+ /* @__PURE__ */ jsx14(Text10, { color: config.color, dimColor: isSystem, children: config.icon }),
3596
+ /* @__PURE__ */ jsxs11(Text10, { color: config.color, dimColor: isSystem, bold: !isSystem, children: [
3597
+ " ",
3598
+ config.label
3599
+ ] })
3600
+ ] }),
3601
+ message.content.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 2, children: /* @__PURE__ */ jsx14(Text10, { dimColor: isSystem, children: line }) }, i))
3602
+ ] });
3603
+ }
3604
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", children: [
3605
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3606
+ /* @__PURE__ */ jsx14(Text10, { color: config.color, dimColor: isSystem, children: config.icon }),
3607
+ /* @__PURE__ */ jsxs11(Text10, { color: config.color, dimColor: isSystem, bold: !isSystem, children: [
2963
3608
  " ",
2964
3609
  config.label
2965
3610
  ] })
2966
3611
  ] }),
2967
- message.content.split("\n").map((line, i) => /* @__PURE__ */ jsx12(Box6, { marginLeft: 2, children: /* @__PURE__ */ jsx12(Text8, { dimColor: isSystem, children: line }) }, i))
3612
+ message.content.map((block, i) => /* @__PURE__ */ jsx14(ContentBlock, { block }, i))
2968
3613
  ] });
2969
3614
  }
2970
3615
  function MessageList({
@@ -2972,28 +3617,25 @@ function MessageList({
2972
3617
  streamingContent,
2973
3618
  renderMessage
2974
3619
  }) {
2975
- return /* @__PURE__ */ jsxs8(Box6, { flexDirection: "column", children: [
2976
- messages.map((message, i) => /* @__PURE__ */ jsx12(Box6, { flexDirection: "column", marginTop: i > 0 ? 1 : 0, children: /* @__PURE__ */ jsx12(MessageItem, { message, renderMessage }) }, message.id)),
2977
- streamingContent != null && streamingContent.length > 0 && /* @__PURE__ */ jsxs8(Box6, { flexDirection: "column", marginTop: messages.length > 0 ? 1 : 0, children: [
2978
- /* @__PURE__ */ jsxs8(Box6, { children: [
2979
- /* @__PURE__ */ jsx12(Text8, { color: "#DA7756", children: "\u25CF" }),
2980
- /* @__PURE__ */ jsxs8(Text8, { color: "#DA7756", bold: true, children: [
2981
- " ",
2982
- "Claude"
2983
- ] })
3620
+ return /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", children: [
3621
+ messages.map((message, i) => /* @__PURE__ */ jsx14(Box8, { flexDirection: "column", marginTop: i > 0 ? 1 : 0, children: /* @__PURE__ */ jsx14(MessageItem, { message, renderMessage }) }, message.id)),
3622
+ streamingContent != null && streamingContent.length > 0 && /* @__PURE__ */ jsxs11(Box8, { flexDirection: "column", marginTop: messages.length > 0 ? 1 : 0, children: [
3623
+ /* @__PURE__ */ jsxs11(Box8, { children: [
3624
+ /* @__PURE__ */ jsx14(Text10, { color: "#DA7756", children: "\u25CF" }),
3625
+ /* @__PURE__ */ jsx14(Text10, { color: "#DA7756", bold: true, children: " Claude" })
2984
3626
  ] }),
2985
- streamingContent.split("\n").map((line, i) => /* @__PURE__ */ jsx12(Box6, { marginLeft: 2, children: /* @__PURE__ */ jsxs8(Text8, { children: [
3627
+ streamingContent.split("\n").map((line, i) => /* @__PURE__ */ jsx14(Box8, { marginLeft: 2, children: /* @__PURE__ */ jsxs11(Text10, { children: [
2986
3628
  line,
2987
- i === streamingContent.split("\n").length - 1 && /* @__PURE__ */ jsx12(Text8, { color: "#DA7756", children: "\u2588" })
3629
+ i === streamingContent.split("\n").length - 1 && /* @__PURE__ */ jsx14(Text10, { color: "#DA7756", children: "\u2588" })
2988
3630
  ] }) }, i))
2989
3631
  ] })
2990
3632
  ] });
2991
3633
  }
2992
3634
 
2993
3635
  // src/StreamingText.tsx
2994
- import { useState as useState7, useEffect as useEffect6, useRef as useRef6 } from "react";
2995
- import { Text as Text9 } from "@claude-code-kit/ink-renderer";
2996
- import { jsx as jsx13 } from "react/jsx-runtime";
3636
+ import { useState as useState8, useEffect as useEffect6, useRef as useRef6 } from "react";
3637
+ import { Text as Text11 } from "@claude-code-kit/ink-renderer";
3638
+ import { jsx as jsx15 } from "react/jsx-runtime";
2997
3639
  function StreamingText({
2998
3640
  text,
2999
3641
  speed = 3,
@@ -3001,7 +3643,7 @@ function StreamingText({
3001
3643
  onComplete,
3002
3644
  color: color2
3003
3645
  }) {
3004
- const [revealed, setRevealed] = useState7(0);
3646
+ const [revealed, setRevealed] = useState8(0);
3005
3647
  const onCompleteRef = useRef6(onComplete);
3006
3648
  onCompleteRef.current = onComplete;
3007
3649
  useEffect6(() => {
@@ -3017,19 +3659,171 @@ function StreamingText({
3017
3659
  }, interval);
3018
3660
  return () => clearInterval(id);
3019
3661
  }, [text.length, speed, interval, revealed >= text.length]);
3020
- return /* @__PURE__ */ jsx13(Text9, { color: color2, children: text.slice(0, revealed) });
3662
+ return /* @__PURE__ */ jsx15(Text11, { color: color2, children: text.slice(0, revealed) });
3021
3663
  }
3022
3664
 
3023
3665
  // src/REPL.tsx
3024
- import { useState as useState8, useCallback as useCallback6, useRef as useRef7 } from "react";
3025
- import { Box as Box7, useInput as useInput5, useApp } from "@claude-code-kit/ink-renderer";
3026
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
3666
+ import { useState as useState10, useCallback as useCallback8, useRef as useRef8 } from "react";
3667
+ import { Box as Box10, useInput as useInput7, useApp } from "@claude-code-kit/ink-renderer";
3668
+
3669
+ // src/SearchOverlay.tsx
3670
+ import { useState as useState9, useCallback as useCallback7, useEffect as useEffect7, useRef as useRef7 } from "react";
3671
+ import { Box as Box9, Text as Text12, useInput as useInput6 } from "@claude-code-kit/ink-renderer";
3672
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
3673
+ function computeMatches(content, query) {
3674
+ if (!query) return [];
3675
+ const lower = query.toLowerCase();
3676
+ const found = [];
3677
+ for (let i = 0; i < content.length; i++) {
3678
+ const text = content[i] ?? "";
3679
+ let offset = 0;
3680
+ let pos = text.toLowerCase().indexOf(lower, offset);
3681
+ while (pos !== -1) {
3682
+ found.push({ index: i, offset: pos, length: query.length });
3683
+ offset = pos + 1;
3684
+ pos = text.toLowerCase().indexOf(lower, offset);
3685
+ }
3686
+ }
3687
+ return found;
3688
+ }
3689
+ function useSearch({ content, isActive }) {
3690
+ const [query, setQueryState] = useState9("");
3691
+ const [matches, setMatches] = useState9([]);
3692
+ const [currentIndex, setCurrentIndex] = useState9(0);
3693
+ const setQuery = useCallback7((q) => {
3694
+ setQueryState(q);
3695
+ const found = computeMatches(content, q);
3696
+ setMatches(found);
3697
+ setCurrentIndex(found.length > 0 ? 0 : -1);
3698
+ }, [content]);
3699
+ const next = useCallback7(() => {
3700
+ if (matches.length === 0) return;
3701
+ setCurrentIndex((i) => (i + 1) % matches.length);
3702
+ }, [matches.length]);
3703
+ const previous = useCallback7(() => {
3704
+ if (matches.length === 0) return;
3705
+ setCurrentIndex((i) => (i - 1 + matches.length) % matches.length);
3706
+ }, [matches.length]);
3707
+ useEffect7(() => {
3708
+ if (!isActive) {
3709
+ setQueryState("");
3710
+ setMatches([]);
3711
+ setCurrentIndex(0);
3712
+ }
3713
+ }, [isActive]);
3714
+ return { query, matches, currentIndex, next, previous, setQuery };
3715
+ }
3716
+ function SearchOverlay({
3717
+ isOpen,
3718
+ onClose,
3719
+ onSearch,
3720
+ onNavigate
3721
+ }) {
3722
+ const [query, setQueryState] = useState9("");
3723
+ const [cursor, setCursor] = useState9(0);
3724
+ const [matches, setMatches] = useState9([]);
3725
+ const matchIndexRef = useRef7(0);
3726
+ const [matchIndex, setMatchIndexState] = useState9(0);
3727
+ const setMatchIndex = useCallback7((next) => {
3728
+ matchIndexRef.current = next;
3729
+ setMatchIndexState(next);
3730
+ }, []);
3731
+ useEffect7(() => {
3732
+ if (!isOpen) {
3733
+ setQueryState("");
3734
+ setCursor(0);
3735
+ setMatches([]);
3736
+ setMatchIndex(0);
3737
+ }
3738
+ }, [isOpen, setMatchIndex]);
3739
+ const runSearch = useCallback7((q) => {
3740
+ const found = onSearch(q);
3741
+ setMatches(found);
3742
+ setMatchIndex(0);
3743
+ if (found.length > 0) onNavigate(found[0]);
3744
+ }, [onSearch, onNavigate, setMatchIndex]);
3745
+ const navigate = useCallback7((delta) => {
3746
+ setMatches((currentMatches) => {
3747
+ if (currentMatches.length === 0) return currentMatches;
3748
+ const next = (matchIndexRef.current + delta + currentMatches.length) % currentMatches.length;
3749
+ setMatchIndex(next);
3750
+ onNavigate(currentMatches[next]);
3751
+ return currentMatches;
3752
+ });
3753
+ }, [onNavigate, setMatchIndex]);
3754
+ useInput6(
3755
+ (input, key) => {
3756
+ if (key.escape) {
3757
+ onClose();
3758
+ return;
3759
+ }
3760
+ if (key.return) {
3761
+ navigate(1);
3762
+ return;
3763
+ }
3764
+ if (input === "n" && key.ctrl) {
3765
+ navigate(1);
3766
+ return;
3767
+ }
3768
+ if (input === "p" && key.ctrl) {
3769
+ navigate(-1);
3770
+ return;
3771
+ }
3772
+ if (key.backspace) {
3773
+ if (cursor > 0) {
3774
+ const next = query.slice(0, cursor - 1) + query.slice(cursor);
3775
+ setQueryState(next);
3776
+ setCursor(cursor - 1);
3777
+ runSearch(next);
3778
+ }
3779
+ return;
3780
+ }
3781
+ if (key.leftArrow) {
3782
+ setCursor((c) => Math.max(0, c - 1));
3783
+ return;
3784
+ }
3785
+ if (key.rightArrow) {
3786
+ setCursor((c) => Math.min(query.length, c + 1));
3787
+ return;
3788
+ }
3789
+ if (key.ctrl || key.meta) return;
3790
+ if (input.length > 0) {
3791
+ const next = query.slice(0, cursor) + input + query.slice(cursor);
3792
+ setQueryState(next);
3793
+ setCursor(cursor + input.length);
3794
+ runSearch(next);
3795
+ }
3796
+ },
3797
+ { isActive: isOpen }
3798
+ );
3799
+ if (!isOpen) return null;
3800
+ const total = matches.length;
3801
+ const current = total > 0 ? matchIndex + 1 : 0;
3802
+ const countLabel = total > 0 ? `${current}/${total} matches` : "no matches";
3803
+ const before = query.slice(0, cursor);
3804
+ const atCursor = cursor < query.length ? query[cursor] : " ";
3805
+ const after = cursor < query.length ? query.slice(cursor + 1) : "";
3806
+ return /* @__PURE__ */ jsxs12(Box9, { flexDirection: "row", paddingX: 1, children: [
3807
+ /* @__PURE__ */ jsx16(Text12, { color: "cyan", children: "Search: " }),
3808
+ /* @__PURE__ */ jsx16(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsxs12(Text12, { children: [
3809
+ before,
3810
+ /* @__PURE__ */ jsx16(Text12, { inverse: true, children: atCursor }),
3811
+ after
3812
+ ] }) }),
3813
+ /* @__PURE__ */ jsx16(Text12, { dimColor: true, children: countLabel })
3814
+ ] });
3815
+ }
3816
+
3817
+ // src/REPL.tsx
3818
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
3027
3819
  function REPL({
3028
3820
  onSubmit,
3029
3821
  onExit,
3030
3822
  messages,
3031
3823
  isLoading = false,
3032
3824
  streamingContent,
3825
+ welcome,
3826
+ permissionRequest,
3033
3827
  commands = [],
3034
3828
  model,
3035
3829
  statusSegments,
@@ -3040,15 +3834,19 @@ function REPL({
3040
3834
  spinner
3041
3835
  }) {
3042
3836
  const { exit } = useApp();
3043
- const [inputValue, setInputValue] = useState8("");
3044
- const [internalHistory, setInternalHistory] = useState8([]);
3045
- const submittingRef = useRef7(false);
3837
+ const [inputValue, setInputValue] = useState10("");
3838
+ const [internalHistory, setInternalHistory] = useState10([]);
3839
+ const [searchOpen, setSearchOpen] = useState10(false);
3840
+ const submittingRef = useRef8(false);
3046
3841
  const history = externalHistory ?? internalHistory;
3842
+ const messageContents = messages.map(
3843
+ (m) => typeof m.content === "string" ? m.content : m.content.map((b) => "text" in b ? b.text : "").join(" ")
3844
+ );
3047
3845
  const promptCommands = commands.map((c) => ({
3048
3846
  name: c.name,
3049
3847
  description: c.description
3050
3848
  }));
3051
- const handleSubmit = useCallback6(
3849
+ const handleSubmit = useCallback8(
3052
3850
  (value) => {
3053
3851
  if (submittingRef.current) return;
3054
3852
  const trimmed = value.trim();
@@ -3080,7 +3878,7 @@ function REPL({
3080
3878
  },
3081
3879
  [commands, onSubmit, externalHistory]
3082
3880
  );
3083
- useInput5(
3881
+ useInput7(
3084
3882
  (_input, key) => {
3085
3883
  if (key.ctrl && _input === "c" && isLoading) {
3086
3884
  return;
@@ -3092,13 +3890,20 @@ function REPL({
3092
3890
  exit();
3093
3891
  }
3094
3892
  }
3893
+ if (key.ctrl && _input === "f") {
3894
+ setSearchOpen(true);
3895
+ }
3095
3896
  },
3096
- { isActive: true }
3897
+ // Deactivate when search overlay is open so only SearchOverlay handles input.
3898
+ { isActive: !searchOpen }
3097
3899
  );
3098
3900
  const resolvedSegments = statusSegments ?? buildDefaultSegments(model);
3099
- return /* @__PURE__ */ jsxs9(Box7, { flexDirection: "column", flexGrow: 1, children: [
3100
- /* @__PURE__ */ jsxs9(Box7, { flexDirection: "column", flexGrow: 1, children: [
3101
- /* @__PURE__ */ jsx14(
3901
+ const showWelcome = welcome && messages.length === 0 && !isLoading;
3902
+ const showPermission = !!permissionRequest;
3903
+ return /* @__PURE__ */ jsxs13(Box10, { flexDirection: "column", flexGrow: 1, children: [
3904
+ /* @__PURE__ */ jsxs13(Box10, { flexDirection: "column", flexGrow: 1, children: [
3905
+ showWelcome && /* @__PURE__ */ jsx17(Box10, { marginBottom: 1, children: welcome }),
3906
+ /* @__PURE__ */ jsx17(
3102
3907
  MessageList,
3103
3908
  {
3104
3909
  messages,
@@ -3106,10 +3911,29 @@ function REPL({
3106
3911
  renderMessage
3107
3912
  }
3108
3913
  ),
3109
- isLoading && !streamingContent && /* @__PURE__ */ jsx14(Box7, { marginTop: messages.length > 0 ? 1 : 0, children: spinner ?? /* @__PURE__ */ jsx14(Spinner, {}) })
3914
+ isLoading && !streamingContent && /* @__PURE__ */ jsx17(Box10, { marginTop: messages.length > 0 ? 1 : 0, children: spinner ?? /* @__PURE__ */ jsx17(Spinner, {}) })
3110
3915
  ] }),
3111
- /* @__PURE__ */ jsx14(Divider, {}),
3112
- /* @__PURE__ */ jsx14(
3916
+ searchOpen && /* @__PURE__ */ jsx17(
3917
+ SearchOverlay,
3918
+ {
3919
+ isOpen: searchOpen,
3920
+ onClose: () => setSearchOpen(false),
3921
+ onSearch: (q) => computeMatches(messageContents, q),
3922
+ onNavigate: () => {
3923
+ }
3924
+ }
3925
+ ),
3926
+ /* @__PURE__ */ jsx17(Divider, {}),
3927
+ showPermission ? /* @__PURE__ */ jsx17(
3928
+ PermissionRequest,
3929
+ {
3930
+ toolName: permissionRequest.toolName,
3931
+ description: permissionRequest.description,
3932
+ details: permissionRequest.details,
3933
+ preview: permissionRequest.preview,
3934
+ onDecision: permissionRequest.onDecision
3935
+ }
3936
+ ) : /* @__PURE__ */ jsx17(
3113
3937
  PromptInput,
3114
3938
  {
3115
3939
  value: inputValue,
@@ -3117,13 +3941,13 @@ function REPL({
3117
3941
  onSubmit: handleSubmit,
3118
3942
  prefix,
3119
3943
  placeholder,
3120
- disabled: isLoading,
3944
+ disabled: isLoading || searchOpen,
3121
3945
  commands: promptCommands,
3122
3946
  history
3123
3947
  }
3124
3948
  ),
3125
- /* @__PURE__ */ jsx14(Divider, {}),
3126
- resolvedSegments.length > 0 && /* @__PURE__ */ jsx14(StatusLine, { segments: resolvedSegments })
3949
+ /* @__PURE__ */ jsx17(Divider, {}),
3950
+ resolvedSegments.length > 0 && /* @__PURE__ */ jsx17(StatusLine, { segments: resolvedSegments })
3127
3951
  ] });
3128
3952
  }
3129
3953
  function buildDefaultSegments(model) {
@@ -3132,8 +3956,8 @@ function buildDefaultSegments(model) {
3132
3956
  }
3133
3957
 
3134
3958
  // src/design-system/ThemedBox.tsx
3135
- import { Box as Box8 } from "@claude-code-kit/ink-renderer";
3136
- import { jsx as jsx15 } from "react/jsx-runtime";
3959
+ import { Box as Box11 } from "@claude-code-kit/ink-renderer";
3960
+ import { jsx as jsx18 } from "react/jsx-runtime";
3137
3961
  function resolveColor(color2, theme) {
3138
3962
  if (!color2) return void 0;
3139
3963
  if (color2.startsWith("rgb(") || color2.startsWith("#") || color2.startsWith("ansi256(") || color2.startsWith("ansi:")) {
@@ -3160,8 +3984,8 @@ function ThemedBox({
3160
3984
  const resolvedBorderLeftColor = resolveColor(borderLeftColor, theme);
3161
3985
  const resolvedBorderRightColor = resolveColor(borderRightColor, theme);
3162
3986
  const resolvedBackgroundColor = resolveColor(backgroundColor, theme);
3163
- return /* @__PURE__ */ jsx15(
3164
- Box8,
3987
+ return /* @__PURE__ */ jsx18(
3988
+ Box11,
3165
3989
  {
3166
3990
  ref,
3167
3991
  borderColor: resolvedBorderColor,
@@ -3178,10 +4002,10 @@ function ThemedBox({
3178
4002
  var ThemedBox_default = ThemedBox;
3179
4003
 
3180
4004
  // src/design-system/ThemedText.tsx
3181
- import React13, { useContext as useContext6 } from "react";
3182
- import { Text as Text11 } from "@claude-code-kit/ink-renderer";
3183
- import { jsx as jsx16 } from "react/jsx-runtime";
3184
- var TextHoverColorContext = React13.createContext(void 0);
4005
+ import React17, { useContext as useContext7 } from "react";
4006
+ import { Text as Text13 } from "@claude-code-kit/ink-renderer";
4007
+ import { jsx as jsx19 } from "react/jsx-runtime";
4008
+ var TextHoverColorContext = React17.createContext(void 0);
3185
4009
  function resolveColor2(color2, theme) {
3186
4010
  if (!color2) return void 0;
3187
4011
  if (color2.startsWith("rgb(") || color2.startsWith("#") || color2.startsWith("ansi256(") || color2.startsWith("ansi:")) {
@@ -3203,11 +4027,11 @@ function ThemedText({
3203
4027
  }) {
3204
4028
  const [themeName] = useTheme();
3205
4029
  const theme = getTheme(themeName);
3206
- const hoverColor = useContext6(TextHoverColorContext);
4030
+ const hoverColor = useContext7(TextHoverColorContext);
3207
4031
  const resolvedColor = !color2 && hoverColor ? resolveColor2(hoverColor, theme) : dimColor ? theme.inactive : resolveColor2(color2, theme);
3208
4032
  const resolvedBackgroundColor = backgroundColor ? theme[backgroundColor] : void 0;
3209
- return /* @__PURE__ */ jsx16(
3210
- Text11,
4033
+ return /* @__PURE__ */ jsx19(
4034
+ Text13,
3211
4035
  {
3212
4036
  color: resolvedColor,
3213
4037
  backgroundColor: resolvedBackgroundColor,
@@ -3223,23 +4047,23 @@ function ThemedText({
3223
4047
  }
3224
4048
 
3225
4049
  // src/design-system/Dialog.tsx
3226
- import { useCallback as useCallback7 } from "react";
3227
- import { Box as Box10, Text as Text14, useInput as useInput6 } from "@claude-code-kit/ink-renderer";
4050
+ import { useCallback as useCallback9 } from "react";
4051
+ import { Box as Box13, Text as Text16, useInput as useInput8 } from "@claude-code-kit/ink-renderer";
3228
4052
 
3229
4053
  // src/design-system/Byline.tsx
3230
- import React14, { Children, isValidElement } from "react";
3231
- import { Text as Text12 } from "@claude-code-kit/ink-renderer";
3232
- import { Fragment, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
4054
+ import React18, { Children, isValidElement } from "react";
4055
+ import { Text as Text14 } from "@claude-code-kit/ink-renderer";
4056
+ import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
3233
4057
  function Byline({ children }) {
3234
4058
  const validChildren = Children.toArray(children);
3235
4059
  if (validChildren.length === 0) {
3236
4060
  return null;
3237
4061
  }
3238
- return /* @__PURE__ */ jsx17(Fragment, { children: validChildren.map((child, index) => /* @__PURE__ */ jsxs10(
3239
- React14.Fragment,
4062
+ return /* @__PURE__ */ jsx20(Fragment2, { children: validChildren.map((child, index) => /* @__PURE__ */ jsxs14(
4063
+ React18.Fragment,
3240
4064
  {
3241
4065
  children: [
3242
- index > 0 && /* @__PURE__ */ jsx17(Text12, { dimColor: true, children: " \xB7 " }),
4066
+ index > 0 && /* @__PURE__ */ jsx20(Text14, { dimColor: true, children: " \xB7 " }),
3243
4067
  child
3244
4068
  ]
3245
4069
  },
@@ -3248,17 +4072,17 @@ function Byline({ children }) {
3248
4072
  }
3249
4073
 
3250
4074
  // src/design-system/KeyboardShortcutHint.tsx
3251
- import { Text as Text13 } from "@claude-code-kit/ink-renderer";
3252
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
4075
+ import { Text as Text15 } from "@claude-code-kit/ink-renderer";
4076
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
3253
4077
  function KeyboardShortcutHint({
3254
4078
  shortcut,
3255
4079
  action,
3256
4080
  parens = false,
3257
4081
  bold = false
3258
4082
  }) {
3259
- const shortcutText = bold ? /* @__PURE__ */ jsx18(Text13, { bold: true, children: shortcut }) : shortcut;
4083
+ const shortcutText = bold ? /* @__PURE__ */ jsx21(Text15, { bold: true, children: shortcut }) : shortcut;
3260
4084
  if (parens) {
3261
- return /* @__PURE__ */ jsxs11(Text13, { children: [
4085
+ return /* @__PURE__ */ jsxs15(Text15, { children: [
3262
4086
  "(",
3263
4087
  shortcutText,
3264
4088
  " to ",
@@ -3266,7 +4090,7 @@ function KeyboardShortcutHint({
3266
4090
  ")"
3267
4091
  ] });
3268
4092
  }
3269
- return /* @__PURE__ */ jsxs11(Text13, { children: [
4093
+ return /* @__PURE__ */ jsxs15(Text15, { children: [
3270
4094
  shortcutText,
3271
4095
  " to ",
3272
4096
  action
@@ -3274,17 +4098,17 @@ function KeyboardShortcutHint({
3274
4098
  }
3275
4099
 
3276
4100
  // src/design-system/Pane.tsx
3277
- import { Box as Box9 } from "@claude-code-kit/ink-renderer";
3278
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
4101
+ import { Box as Box12 } from "@claude-code-kit/ink-renderer";
4102
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
3279
4103
  function Pane({ children, color: color2 }) {
3280
- return /* @__PURE__ */ jsxs12(Box9, { flexDirection: "column", paddingTop: 1, children: [
3281
- /* @__PURE__ */ jsx19(Divider, { color: color2 }),
3282
- /* @__PURE__ */ jsx19(Box9, { flexDirection: "column", paddingX: 2, children })
4104
+ return /* @__PURE__ */ jsxs16(Box12, { flexDirection: "column", paddingTop: 1, children: [
4105
+ /* @__PURE__ */ jsx22(Divider, { color: color2 }),
4106
+ /* @__PURE__ */ jsx22(Box12, { flexDirection: "column", paddingX: 2, children })
3283
4107
  ] });
3284
4108
  }
3285
4109
 
3286
4110
  // src/design-system/Dialog.tsx
3287
- import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
4111
+ import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
3288
4112
  function Dialog({
3289
4113
  title,
3290
4114
  subtitle,
@@ -3294,8 +4118,8 @@ function Dialog({
3294
4118
  hideInputGuide,
3295
4119
  hideBorder
3296
4120
  }) {
3297
- useInput6(
3298
- useCallback7(
4121
+ useInput8(
4122
+ useCallback9(
3299
4123
  (_input, key) => {
3300
4124
  if (key.escape) {
3301
4125
  onCancel();
@@ -3304,41 +4128,41 @@ function Dialog({
3304
4128
  [onCancel]
3305
4129
  )
3306
4130
  );
3307
- const defaultInputGuide = /* @__PURE__ */ jsxs13(Byline, { children: [
3308
- /* @__PURE__ */ jsx20(KeyboardShortcutHint, { shortcut: "Enter", action: "confirm" }),
3309
- /* @__PURE__ */ jsx20(KeyboardShortcutHint, { shortcut: "Esc", action: "cancel" })
4131
+ const defaultInputGuide = /* @__PURE__ */ jsxs17(Byline, { children: [
4132
+ /* @__PURE__ */ jsx23(KeyboardShortcutHint, { shortcut: "Enter", action: "confirm" }),
4133
+ /* @__PURE__ */ jsx23(KeyboardShortcutHint, { shortcut: "Esc", action: "cancel" })
3310
4134
  ] });
3311
- const content = /* @__PURE__ */ jsxs13(Fragment2, { children: [
3312
- /* @__PURE__ */ jsxs13(Box10, { flexDirection: "column", gap: 1, children: [
3313
- /* @__PURE__ */ jsxs13(Box10, { flexDirection: "column", children: [
3314
- /* @__PURE__ */ jsx20(Text14, { bold: true, color: color2, children: title }),
3315
- subtitle && /* @__PURE__ */ jsx20(Text14, { dimColor: true, children: subtitle })
4135
+ const content = /* @__PURE__ */ jsxs17(Fragment3, { children: [
4136
+ /* @__PURE__ */ jsxs17(Box13, { flexDirection: "column", gap: 1, children: [
4137
+ /* @__PURE__ */ jsxs17(Box13, { flexDirection: "column", children: [
4138
+ /* @__PURE__ */ jsx23(Text16, { bold: true, color: color2, children: title }),
4139
+ subtitle && /* @__PURE__ */ jsx23(Text16, { dimColor: true, children: subtitle })
3316
4140
  ] }),
3317
4141
  children
3318
4142
  ] }),
3319
- !hideInputGuide && /* @__PURE__ */ jsx20(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text14, { dimColor: true, italic: true, children: defaultInputGuide }) })
4143
+ !hideInputGuide && /* @__PURE__ */ jsx23(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx23(Text16, { dimColor: true, italic: true, children: defaultInputGuide }) })
3320
4144
  ] });
3321
4145
  if (hideBorder) {
3322
4146
  return content;
3323
4147
  }
3324
- return /* @__PURE__ */ jsx20(Pane, { color: color2, children: content });
4148
+ return /* @__PURE__ */ jsx23(Pane, { color: color2, children: content });
3325
4149
  }
3326
4150
 
3327
4151
  // src/design-system/FuzzyPicker.tsx
3328
- import { useCallback as useCallback8, useContext as useContext7, useEffect as useEffect7, useState as useState9 } from "react";
4152
+ import { useCallback as useCallback10, useContext as useContext8, useEffect as useEffect8, useState as useState11 } from "react";
3329
4153
  import {
3330
4154
  clamp,
3331
- Box as Box12,
3332
- Text as Text16,
3333
- useInput as useInput7,
3334
- TerminalSizeContext as TerminalSizeContext4
4155
+ Box as Box15,
4156
+ Text as Text18,
4157
+ useInput as useInput9,
4158
+ TerminalSizeContext as TerminalSizeContext5
3335
4159
  } from "@claude-code-kit/ink-renderer";
3336
4160
 
3337
4161
  // src/design-system/ListItem.tsx
3338
4162
  import figures2 from "figures";
3339
4163
  import { useDeclaredCursor } from "@claude-code-kit/ink-renderer";
3340
- import { Box as Box11, Text as Text15 } from "@claude-code-kit/ink-renderer";
3341
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
4164
+ import { Box as Box14, Text as Text17 } from "@claude-code-kit/ink-renderer";
4165
+ import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
3342
4166
  function ListItem({
3343
4167
  isFocused,
3344
4168
  isSelected = false,
@@ -3352,31 +4176,31 @@ function ListItem({
3352
4176
  }) {
3353
4177
  function renderIndicator() {
3354
4178
  if (disabled) {
3355
- return /* @__PURE__ */ jsx21(Text15, { children: " " });
4179
+ return /* @__PURE__ */ jsx24(Text17, { children: " " });
3356
4180
  }
3357
4181
  if (isFocused) {
3358
- return /* @__PURE__ */ jsx21(Text15, { color: "suggestion", children: figures2.pointer });
4182
+ return /* @__PURE__ */ jsx24(Text17, { color: "cyan", children: figures2.pointer });
3359
4183
  }
3360
4184
  if (showScrollDown) {
3361
- return /* @__PURE__ */ jsx21(Text15, { dimColor: true, children: figures2.arrowDown });
4185
+ return /* @__PURE__ */ jsx24(Text17, { dimColor: true, children: figures2.arrowDown });
3362
4186
  }
3363
4187
  if (showScrollUp) {
3364
- return /* @__PURE__ */ jsx21(Text15, { dimColor: true, children: figures2.arrowUp });
4188
+ return /* @__PURE__ */ jsx24(Text17, { dimColor: true, children: figures2.arrowUp });
3365
4189
  }
3366
- return /* @__PURE__ */ jsx21(Text15, { children: " " });
4190
+ return /* @__PURE__ */ jsx24(Text17, { children: " " });
3367
4191
  }
3368
4192
  function getTextColor() {
3369
4193
  if (disabled) {
3370
- return "inactive";
4194
+ return void 0;
3371
4195
  }
3372
4196
  if (!styled) {
3373
4197
  return void 0;
3374
4198
  }
3375
4199
  if (isSelected) {
3376
- return "success";
4200
+ return "green";
3377
4201
  }
3378
4202
  if (isFocused) {
3379
- return "suggestion";
4203
+ return "cyan";
3380
4204
  }
3381
4205
  return void 0;
3382
4206
  }
@@ -3386,18 +4210,18 @@ function ListItem({
3386
4210
  column: 0,
3387
4211
  active: isFocused && !disabled && declareCursor !== false
3388
4212
  });
3389
- return /* @__PURE__ */ jsxs14(Box11, { ref: cursorRef, flexDirection: "column", children: [
3390
- /* @__PURE__ */ jsxs14(Box11, { flexDirection: "row", gap: 1, children: [
4213
+ return /* @__PURE__ */ jsxs18(Box14, { ref: cursorRef, flexDirection: "column", children: [
4214
+ /* @__PURE__ */ jsxs18(Box14, { flexDirection: "row", gap: 1, children: [
3391
4215
  renderIndicator(),
3392
- styled ? /* @__PURE__ */ jsx21(Text15, { color: textColor, dimColor: disabled, children }) : children,
3393
- isSelected && !disabled && /* @__PURE__ */ jsx21(Text15, { color: "success", children: figures2.tick })
4216
+ styled ? /* @__PURE__ */ jsx24(Text17, { color: textColor, dimColor: disabled, children }) : children,
4217
+ isSelected && !disabled && /* @__PURE__ */ jsx24(Text17, { color: "green", children: figures2.tick })
3394
4218
  ] }),
3395
- description && /* @__PURE__ */ jsx21(Box11, { paddingLeft: 2, children: /* @__PURE__ */ jsx21(Text15, { color: "inactive", children: description }) })
4219
+ description && /* @__PURE__ */ jsx24(Box14, { paddingLeft: 2, children: /* @__PURE__ */ jsx24(Text17, { dimColor: true, children: description }) })
3396
4220
  ] });
3397
4221
  }
3398
4222
 
3399
4223
  // src/design-system/FuzzyPicker.tsx
3400
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
4224
+ import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
3401
4225
  var DEFAULT_VISIBLE = 8;
3402
4226
  var CHROME_ROWS = 10;
3403
4227
  var MIN_VISIBLE = 2;
@@ -3423,24 +4247,24 @@ function FuzzyPicker({
3423
4247
  selectAction = "select",
3424
4248
  extraHints
3425
4249
  }) {
3426
- const terminalSize = useContext7(TerminalSizeContext4);
4250
+ const terminalSize = useContext8(TerminalSizeContext5);
3427
4251
  const rows = terminalSize?.rows ?? 24;
3428
4252
  const columns = terminalSize?.columns ?? 80;
3429
- const [focusedIndex, setFocusedIndex] = useState9(0);
3430
- const [query, setQuery] = useState9(initialQuery ?? "");
4253
+ const [focusedIndex, setFocusedIndex] = useState11(0);
4254
+ const [query, setQuery] = useState11(initialQuery ?? "");
3431
4255
  const visibleCount = Math.max(
3432
4256
  MIN_VISIBLE,
3433
4257
  Math.min(requestedVisible, rows - CHROME_ROWS - (matchLabel ? 1 : 0))
3434
4258
  );
3435
4259
  const compact = columns < 120;
3436
- const step = useCallback8(
4260
+ const step = useCallback10(
3437
4261
  (delta) => {
3438
4262
  setFocusedIndex((i) => clamp(i + delta, 0, items.length - 1));
3439
4263
  },
3440
4264
  [items.length]
3441
4265
  );
3442
- useInput7(
3443
- useCallback8(
4266
+ useInput9(
4267
+ useCallback10(
3444
4268
  (input, key) => {
3445
4269
  if (key.escape) {
3446
4270
  onCancel();
@@ -3481,15 +4305,15 @@ function FuzzyPicker({
3481
4305
  [onCancel, step, direction, items, focusedIndex, onSelect, onShiftTab, onTab]
3482
4306
  )
3483
4307
  );
3484
- useEffect7(() => {
4308
+ useEffect8(() => {
3485
4309
  onQueryChange(query);
3486
4310
  setFocusedIndex(0);
3487
4311
  }, [query]);
3488
- useEffect7(() => {
4312
+ useEffect8(() => {
3489
4313
  setFocusedIndex((i) => clamp(i, 0, items.length - 1));
3490
4314
  }, [items.length]);
3491
4315
  const focused = items[focusedIndex];
3492
- useEffect7(() => {
4316
+ useEffect8(() => {
3493
4317
  onFocus?.(focused);
3494
4318
  }, [focused]);
3495
4319
  const windowStart = clamp(
@@ -3499,8 +4323,8 @@ function FuzzyPicker({
3499
4323
  );
3500
4324
  const visible = items.slice(windowStart, windowStart + visibleCount);
3501
4325
  const emptyText = typeof emptyMessage === "function" ? emptyMessage(query) : emptyMessage;
3502
- const searchInput = /* @__PURE__ */ jsx22(Box12, { borderStyle: "round", paddingX: 1, children: /* @__PURE__ */ jsx22(Text16, { dimColor: !query, children: query || placeholder }) });
3503
- const listBlock = /* @__PURE__ */ jsx22(
4326
+ const searchInput = /* @__PURE__ */ jsx25(Box15, { borderStyle: "round", paddingX: 1, children: /* @__PURE__ */ jsx25(Text18, { dimColor: !query, children: query || placeholder }) });
4327
+ const listBlock = /* @__PURE__ */ jsx25(
3504
4328
  List,
3505
4329
  {
3506
4330
  visible,
@@ -3514,50 +4338,50 @@ function FuzzyPicker({
3514
4338
  emptyText
3515
4339
  }
3516
4340
  );
3517
- const preview = renderPreview && focused ? /* @__PURE__ */ jsx22(Box12, { flexDirection: "column", flexGrow: 1, children: renderPreview(focused) }) : null;
3518
- const listGroup = renderPreview && previewPosition === "right" ? /* @__PURE__ */ jsxs15(
3519
- Box12,
4341
+ const preview = renderPreview && focused ? /* @__PURE__ */ jsx25(Box15, { flexDirection: "column", flexGrow: 1, children: renderPreview(focused) }) : null;
4342
+ const listGroup = renderPreview && previewPosition === "right" ? /* @__PURE__ */ jsxs19(
4343
+ Box15,
3520
4344
  {
3521
4345
  flexDirection: "row",
3522
4346
  gap: 2,
3523
4347
  height: visibleCount + (matchLabel ? 1 : 0),
3524
4348
  children: [
3525
- /* @__PURE__ */ jsxs15(Box12, { flexDirection: "column", flexShrink: 0, children: [
4349
+ /* @__PURE__ */ jsxs19(Box15, { flexDirection: "column", flexShrink: 0, children: [
3526
4350
  listBlock,
3527
- matchLabel && /* @__PURE__ */ jsx22(Text16, { dimColor: true, children: matchLabel })
4351
+ matchLabel && /* @__PURE__ */ jsx25(Text18, { dimColor: true, children: matchLabel })
3528
4352
  ] }),
3529
- preview ?? /* @__PURE__ */ jsx22(Box12, { flexGrow: 1 })
4353
+ preview ?? /* @__PURE__ */ jsx25(Box15, { flexGrow: 1 })
3530
4354
  ]
3531
4355
  }
3532
- ) : /* @__PURE__ */ jsxs15(Box12, { flexDirection: "column", children: [
4356
+ ) : /* @__PURE__ */ jsxs19(Box15, { flexDirection: "column", children: [
3533
4357
  listBlock,
3534
- matchLabel && /* @__PURE__ */ jsx22(Text16, { dimColor: true, children: matchLabel }),
4358
+ matchLabel && /* @__PURE__ */ jsx25(Text18, { dimColor: true, children: matchLabel }),
3535
4359
  preview
3536
4360
  ] });
3537
4361
  const inputAbove = direction !== "up";
3538
- return /* @__PURE__ */ jsx22(Pane, { color: "permission", children: /* @__PURE__ */ jsxs15(Box12, { flexDirection: "column", gap: 1, children: [
3539
- /* @__PURE__ */ jsx22(Text16, { bold: true, color: "permission", children: title }),
4362
+ return /* @__PURE__ */ jsx25(Pane, { color: "permission", children: /* @__PURE__ */ jsxs19(Box15, { flexDirection: "column", gap: 1, children: [
4363
+ /* @__PURE__ */ jsx25(Text18, { bold: true, color: "permission", children: title }),
3540
4364
  inputAbove && searchInput,
3541
4365
  listGroup,
3542
4366
  !inputAbove && searchInput,
3543
- /* @__PURE__ */ jsx22(Text16, { dimColor: true, children: /* @__PURE__ */ jsxs15(Byline, { children: [
3544
- /* @__PURE__ */ jsx22(
4367
+ /* @__PURE__ */ jsx25(Text18, { dimColor: true, children: /* @__PURE__ */ jsxs19(Byline, { children: [
4368
+ /* @__PURE__ */ jsx25(
3545
4369
  KeyboardShortcutHint,
3546
4370
  {
3547
4371
  shortcut: "up/dn",
3548
4372
  action: compact ? "nav" : "navigate"
3549
4373
  }
3550
4374
  ),
3551
- /* @__PURE__ */ jsx22(KeyboardShortcutHint, { shortcut: "Enter", action: selectAction }),
3552
- onTab && /* @__PURE__ */ jsx22(KeyboardShortcutHint, { shortcut: "Tab", action: onTab.action }),
3553
- onShiftTab && !compact && /* @__PURE__ */ jsx22(
4375
+ /* @__PURE__ */ jsx25(KeyboardShortcutHint, { shortcut: "Enter", action: selectAction }),
4376
+ onTab && /* @__PURE__ */ jsx25(KeyboardShortcutHint, { shortcut: "Tab", action: onTab.action }),
4377
+ onShiftTab && !compact && /* @__PURE__ */ jsx25(
3554
4378
  KeyboardShortcutHint,
3555
4379
  {
3556
4380
  shortcut: "shift+tab",
3557
4381
  action: onShiftTab.action
3558
4382
  }
3559
4383
  ),
3560
- /* @__PURE__ */ jsx22(KeyboardShortcutHint, { shortcut: "Esc", action: "cancel" }),
4384
+ /* @__PURE__ */ jsx25(KeyboardShortcutHint, { shortcut: "Esc", action: "cancel" }),
3561
4385
  extraHints
3562
4386
  ] }) })
3563
4387
  ] }) });
@@ -3574,14 +4398,14 @@ function List({
3574
4398
  emptyText
3575
4399
  }) {
3576
4400
  if (visible.length === 0) {
3577
- return /* @__PURE__ */ jsx22(Box12, { height: visibleCount, flexShrink: 0, children: /* @__PURE__ */ jsx22(Text16, { dimColor: true, children: emptyText }) });
4401
+ return /* @__PURE__ */ jsx25(Box15, { height: visibleCount, flexShrink: 0, children: /* @__PURE__ */ jsx25(Text18, { dimColor: true, children: emptyText }) });
3578
4402
  }
3579
4403
  const rows = visible.map((item, i) => {
3580
4404
  const actualIndex = windowStart + i;
3581
4405
  const isFocused = actualIndex === focusedIndex;
3582
4406
  const atLowEdge = i === 0 && windowStart > 0;
3583
4407
  const atHighEdge = i === visible.length - 1 && windowStart + visibleCount < total;
3584
- return /* @__PURE__ */ jsx22(
4408
+ return /* @__PURE__ */ jsx25(
3585
4409
  ListItem,
3586
4410
  {
3587
4411
  isFocused,
@@ -3593,8 +4417,8 @@ function List({
3593
4417
  getKey(item)
3594
4418
  );
3595
4419
  });
3596
- return /* @__PURE__ */ jsx22(
3597
- Box12,
4420
+ return /* @__PURE__ */ jsx25(
4421
+ Box15,
3598
4422
  {
3599
4423
  height: visibleCount,
3600
4424
  flexShrink: 0,
@@ -3605,43 +4429,43 @@ function List({
3605
4429
  }
3606
4430
 
3607
4431
  // src/design-system/LoadingState.tsx
3608
- import { Box as Box13, Text as Text17 } from "@claude-code-kit/ink-renderer";
3609
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
4432
+ import { Box as Box16, Text as Text19 } from "@claude-code-kit/ink-renderer";
4433
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
3610
4434
  function LoadingState({
3611
4435
  message,
3612
4436
  bold = false,
3613
4437
  dimColor = false,
3614
4438
  subtitle
3615
4439
  }) {
3616
- return /* @__PURE__ */ jsxs16(Box13, { flexDirection: "column", children: [
3617
- /* @__PURE__ */ jsxs16(Box13, { flexDirection: "row", children: [
3618
- /* @__PURE__ */ jsx23(Spinner, {}),
3619
- /* @__PURE__ */ jsxs16(Text17, { bold, dimColor, children: [
4440
+ return /* @__PURE__ */ jsxs20(Box16, { flexDirection: "column", children: [
4441
+ /* @__PURE__ */ jsxs20(Box16, { flexDirection: "row", children: [
4442
+ /* @__PURE__ */ jsx26(Spinner, {}),
4443
+ /* @__PURE__ */ jsxs20(Text19, { bold, dimColor, children: [
3620
4444
  " ",
3621
4445
  message
3622
4446
  ] })
3623
4447
  ] }),
3624
- subtitle && /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: subtitle })
4448
+ subtitle && /* @__PURE__ */ jsx26(Text19, { dimColor: true, children: subtitle })
3625
4449
  ] });
3626
4450
  }
3627
4451
 
3628
4452
  // src/design-system/Ratchet.tsx
3629
- import { useCallback as useCallback9, useContext as useContext8, useLayoutEffect as useLayoutEffect2, useRef as useRef8, useState as useState10 } from "react";
3630
- import { TerminalSizeContext as TerminalSizeContext5 } from "@claude-code-kit/ink-renderer";
4453
+ import { useCallback as useCallback11, useContext as useContext9, useLayoutEffect as useLayoutEffect2, useRef as useRef9, useState as useState12 } from "react";
4454
+ import { TerminalSizeContext as TerminalSizeContext6 } from "@claude-code-kit/ink-renderer";
3631
4455
  import { useTerminalViewport } from "@claude-code-kit/ink-renderer";
3632
- import { Box as Box14, measureElement } from "@claude-code-kit/ink-renderer";
3633
- import { jsx as jsx24 } from "react/jsx-runtime";
4456
+ import { Box as Box17, measureElement } from "@claude-code-kit/ink-renderer";
4457
+ import { jsx as jsx27 } from "react/jsx-runtime";
3634
4458
  function Ratchet({
3635
4459
  children,
3636
4460
  lock = "always"
3637
4461
  }) {
3638
4462
  const [viewportRef, { isVisible }] = useTerminalViewport();
3639
- const terminalSize = useContext8(TerminalSizeContext5);
4463
+ const terminalSize = useContext9(TerminalSizeContext6);
3640
4464
  const rows = terminalSize?.rows ?? 24;
3641
- const innerRef = useRef8(null);
3642
- const maxHeight = useRef8(0);
3643
- const [minHeight, setMinHeight] = useState10(0);
3644
- const outerRef = useCallback9(
4465
+ const innerRef = useRef9(null);
4466
+ const maxHeight = useRef9(0);
4467
+ const [minHeight, setMinHeight] = useState12(0);
4468
+ const outerRef = useCallback11(
3645
4469
  (el) => {
3646
4470
  viewportRef(el);
3647
4471
  },
@@ -3658,20 +4482,20 @@ function Ratchet({
3658
4482
  setMinHeight(maxHeight.current);
3659
4483
  }
3660
4484
  });
3661
- return /* @__PURE__ */ jsx24(Box14, { minHeight: engaged ? minHeight : void 0, ref: outerRef, children: /* @__PURE__ */ jsx24(Box14, { ref: innerRef, flexDirection: "column", children }) });
4485
+ return /* @__PURE__ */ jsx27(Box17, { minHeight: engaged ? minHeight : void 0, ref: outerRef, children: /* @__PURE__ */ jsx27(Box17, { ref: innerRef, flexDirection: "column", children }) });
3662
4486
  }
3663
4487
 
3664
4488
  // src/design-system/Tabs.tsx
3665
4489
  import {
3666
4490
  createContext as createContext3,
3667
- useCallback as useCallback10,
3668
- useContext as useContext9,
3669
- useState as useState11
4491
+ useCallback as useCallback12,
4492
+ useContext as useContext10,
4493
+ useState as useState13
3670
4494
  } from "react";
3671
- import { TerminalSizeContext as TerminalSizeContext6 } from "@claude-code-kit/ink-renderer";
4495
+ import { TerminalSizeContext as TerminalSizeContext7 } from "@claude-code-kit/ink-renderer";
3672
4496
  import { stringWidth as stringWidth4 } from "@claude-code-kit/ink-renderer";
3673
- import { Box as Box15, Text as Text18, useInput as useInput8 } from "@claude-code-kit/ink-renderer";
3674
- import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
4497
+ import { Box as Box18, Text as Text20, useInput as useInput10 } from "@claude-code-kit/ink-renderer";
4498
+ import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
3675
4499
  var TabsContext = createContext3({
3676
4500
  selectedTab: void 0,
3677
4501
  width: void 0
@@ -3688,7 +4512,7 @@ function Tabs({
3688
4512
  banner,
3689
4513
  disableNavigation
3690
4514
  }) {
3691
- const terminalSize = useContext9(TerminalSizeContext6);
4515
+ const terminalSize = useContext10(TerminalSizeContext7);
3692
4516
  const terminalWidth = terminalSize?.columns ?? 80;
3693
4517
  const tabs = children.map((child) => [
3694
4518
  child.props.id ?? child.props.title,
@@ -3696,12 +4520,12 @@ function Tabs({
3696
4520
  ]);
3697
4521
  const defaultTabIndex = defaultTab ? tabs.findIndex((tab) => defaultTab === tab[0]) : 0;
3698
4522
  const isControlled = controlledSelectedTab !== void 0;
3699
- const [internalSelectedTab, setInternalSelectedTab] = useState11(
4523
+ const [internalSelectedTab, setInternalSelectedTab] = useState13(
3700
4524
  defaultTabIndex !== -1 ? defaultTabIndex : 0
3701
4525
  );
3702
4526
  const controlledTabIndex = isControlled ? tabs.findIndex((tab) => tab[0] === controlledSelectedTab) : -1;
3703
4527
  const selectedTabIndex = isControlled ? controlledTabIndex !== -1 ? controlledTabIndex : 0 : internalSelectedTab;
3704
- const handleTabChange = useCallback10(
4528
+ const handleTabChange = useCallback12(
3705
4529
  (offset) => {
3706
4530
  const newIndex = (selectedTabIndex + tabs.length + offset) % tabs.length;
3707
4531
  const newTabId = tabs[newIndex]?.[0];
@@ -3713,8 +4537,8 @@ function Tabs({
3713
4537
  },
3714
4538
  [selectedTabIndex, tabs, isControlled, onTabChange]
3715
4539
  );
3716
- useInput8(
3717
- useCallback10(
4540
+ useInput10(
4541
+ useCallback12(
3718
4542
  (_input, key) => {
3719
4543
  if (hidden || disableNavigation) return;
3720
4544
  if (key.tab && !key.shift) {
@@ -3738,20 +4562,20 @@ function Tabs({
3738
4562
  const usedWidth = titleWidth + tabsWidth;
3739
4563
  const spacerWidth = useFullWidth ? Math.max(0, terminalWidth - usedWidth) : 0;
3740
4564
  const contentWidth = useFullWidth ? terminalWidth : void 0;
3741
- return /* @__PURE__ */ jsx25(
4565
+ return /* @__PURE__ */ jsx28(
3742
4566
  TabsContext.Provider,
3743
4567
  {
3744
4568
  value: {
3745
4569
  selectedTab: tabs[selectedTabIndex]?.[0],
3746
4570
  width: contentWidth
3747
4571
  },
3748
- children: /* @__PURE__ */ jsxs17(Box15, { flexDirection: "column", children: [
3749
- !hidden && /* @__PURE__ */ jsxs17(Box15, { flexDirection: "row", gap: 1, children: [
3750
- title !== void 0 && /* @__PURE__ */ jsx25(Text18, { bold: true, color: color2, children: title }),
4572
+ children: /* @__PURE__ */ jsxs21(Box18, { flexDirection: "column", children: [
4573
+ !hidden && /* @__PURE__ */ jsxs21(Box18, { flexDirection: "row", gap: 1, children: [
4574
+ title !== void 0 && /* @__PURE__ */ jsx28(Text20, { bold: true, color: color2, children: title }),
3751
4575
  tabs.map(([id, tabTitle], i) => {
3752
4576
  const isCurrent = selectedTabIndex === i;
3753
- return /* @__PURE__ */ jsxs17(
3754
- Text18,
4577
+ return /* @__PURE__ */ jsxs21(
4578
+ Text20,
3755
4579
  {
3756
4580
  inverse: isCurrent,
3757
4581
  bold: isCurrent,
@@ -3764,11 +4588,11 @@ function Tabs({
3764
4588
  id
3765
4589
  );
3766
4590
  }),
3767
- spacerWidth > 0 && /* @__PURE__ */ jsx25(Text18, { children: " ".repeat(spacerWidth) })
4591
+ spacerWidth > 0 && /* @__PURE__ */ jsx28(Text20, { children: " ".repeat(spacerWidth) })
3768
4592
  ] }),
3769
4593
  banner,
3770
- /* @__PURE__ */ jsx25(
3771
- Box15,
4594
+ /* @__PURE__ */ jsx28(
4595
+ Box18,
3772
4596
  {
3773
4597
  width: contentWidth,
3774
4598
  marginTop: hidden ? 0 : 1,
@@ -3780,22 +4604,662 @@ function Tabs({
3780
4604
  );
3781
4605
  }
3782
4606
  function Tab({ title, id, children }) {
3783
- const { selectedTab, width } = useContext9(TabsContext);
4607
+ const { selectedTab, width } = useContext10(TabsContext);
3784
4608
  if (selectedTab !== (id ?? title)) {
3785
4609
  return null;
3786
4610
  }
3787
- return /* @__PURE__ */ jsx25(Box15, { width, children });
4611
+ return /* @__PURE__ */ jsx28(Box18, { width, children });
3788
4612
  }
3789
4613
  function useTabsWidth() {
3790
- const { width } = useContext9(TabsContext);
4614
+ const { width } = useContext10(TabsContext);
3791
4615
  return width;
3792
4616
  }
4617
+
4618
+ // src/useVirtualScroll.ts
4619
+ import React22, { useState as useState14, useCallback as useCallback13, useMemo as useMemo7 } from "react";
4620
+ import { Box as Box19 } from "@claude-code-kit/ink-renderer";
4621
+ function clamp2(value, min, max) {
4622
+ return Math.max(min, Math.min(max, value));
4623
+ }
4624
+ function useVirtualScroll(options) {
4625
+ const {
4626
+ itemCount,
4627
+ estimatedItemHeight = 3,
4628
+ overscan = 20,
4629
+ viewportHeight
4630
+ } = options;
4631
+ const totalHeight = itemCount * estimatedItemHeight;
4632
+ const maxOffset = Math.max(0, totalHeight - viewportHeight);
4633
+ const [scrollOffset, setScrollOffset] = useState14(0);
4634
+ const clampedOffset = clamp2(scrollOffset, 0, maxOffset);
4635
+ const rawStart = Math.floor(clampedOffset / estimatedItemHeight);
4636
+ const rawEnd = Math.ceil((clampedOffset + viewportHeight) / estimatedItemHeight);
4637
+ const startIndex = clamp2(rawStart - overscan, 0, itemCount);
4638
+ const endIndex = clamp2(rawEnd + overscan, 0, itemCount);
4639
+ const visibleItems = endIndex - startIndex;
4640
+ const scrollTo = useCallback13(
4641
+ (index) => {
4642
+ const targetOffset = clamp2(index * estimatedItemHeight, 0, maxOffset);
4643
+ setScrollOffset(targetOffset);
4644
+ },
4645
+ [estimatedItemHeight, maxOffset]
4646
+ );
4647
+ const scrollToEnd = useCallback13(() => {
4648
+ setScrollOffset(maxOffset);
4649
+ }, [maxOffset]);
4650
+ const onScroll = useCallback13(
4651
+ (delta) => {
4652
+ setScrollOffset((prev) => clamp2(prev + delta * estimatedItemHeight, 0, maxOffset));
4653
+ },
4654
+ [estimatedItemHeight, maxOffset]
4655
+ );
4656
+ const isAtTop = clampedOffset <= 0;
4657
+ const isAtEnd = clampedOffset >= maxOffset;
4658
+ return useMemo7(
4659
+ () => ({
4660
+ startIndex,
4661
+ endIndex,
4662
+ visibleItems,
4663
+ totalHeight,
4664
+ scrollOffset: clampedOffset,
4665
+ scrollTo,
4666
+ scrollToEnd,
4667
+ onScroll,
4668
+ isAtTop,
4669
+ isAtEnd
4670
+ }),
4671
+ [
4672
+ startIndex,
4673
+ endIndex,
4674
+ visibleItems,
4675
+ totalHeight,
4676
+ clampedOffset,
4677
+ scrollTo,
4678
+ scrollToEnd,
4679
+ onScroll,
4680
+ isAtTop,
4681
+ isAtEnd
4682
+ ]
4683
+ );
4684
+ }
4685
+ function VirtualList(props) {
4686
+ const { items, renderItem, viewportHeight, estimatedItemHeight = 3, overscan = 20 } = props;
4687
+ const { startIndex, endIndex, totalHeight } = useVirtualScroll({
4688
+ itemCount: items.length,
4689
+ estimatedItemHeight,
4690
+ overscan,
4691
+ viewportHeight
4692
+ });
4693
+ const topPad = startIndex * estimatedItemHeight;
4694
+ const renderedHeight = (endIndex - startIndex) * estimatedItemHeight;
4695
+ const bottomPad = Math.max(0, totalHeight - topPad - renderedHeight);
4696
+ const visibleSlice = [];
4697
+ for (let i = startIndex; i < endIndex && i < items.length; i++) {
4698
+ visibleSlice.push(renderItem(items[i], i));
4699
+ }
4700
+ return React22.createElement(
4701
+ Box19,
4702
+ {
4703
+ flexDirection: "column",
4704
+ height: viewportHeight,
4705
+ overflow: "hidden"
4706
+ },
4707
+ topPad > 0 ? React22.createElement(Box19, { height: topPad, key: "__virtual-top" }) : null,
4708
+ ...visibleSlice,
4709
+ bottomPad > 0 ? React22.createElement(Box19, { height: bottomPad, key: "__virtual-bottom" }) : null
4710
+ );
4711
+ }
4712
+
4713
+ // src/WelcomeScreen.tsx
4714
+ import { Box as Box20, Text as Text21 } from "@claude-code-kit/ink-renderer";
4715
+ import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
4716
+ var DEFAULT_COLOR2 = "#DA7756";
4717
+ function ClawdLogo({ color: color2 = DEFAULT_COLOR2 }) {
4718
+ return /* @__PURE__ */ jsxs22(Box20, { flexDirection: "column", children: [
4719
+ /* @__PURE__ */ jsx29(Text21, { color: color2, children: " \u2590\u259B\u2588\u2588\u2588\u259C\u258C" }),
4720
+ /* @__PURE__ */ jsx29(Text21, { color: color2, children: "\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598" }),
4721
+ /* @__PURE__ */ jsx29(Text21, { color: color2, children: " \u2598\u2598 \u259D\u259D " })
4722
+ ] });
4723
+ }
4724
+ function WelcomeScreen({
4725
+ appName,
4726
+ subtitle,
4727
+ version,
4728
+ tips,
4729
+ logo,
4730
+ model,
4731
+ color: color2 = DEFAULT_COLOR2
4732
+ }) {
4733
+ const logoNode = logo ?? /* @__PURE__ */ jsx29(ClawdLogo, { color: color2 });
4734
+ return /* @__PURE__ */ jsxs22(Box20, { flexDirection: "column", gap: 1, marginTop: 1, marginLeft: 1, children: [
4735
+ /* @__PURE__ */ jsxs22(Box20, { flexDirection: "row", gap: 2, alignItems: "flex-start", children: [
4736
+ logoNode,
4737
+ /* @__PURE__ */ jsxs22(Box20, { flexDirection: "column", justifyContent: "center", children: [
4738
+ /* @__PURE__ */ jsxs22(Box20, { flexDirection: "row", gap: 1, children: [
4739
+ /* @__PURE__ */ jsx29(Text21, { bold: true, color: color2, children: appName }),
4740
+ version && /* @__PURE__ */ jsx29(Text21, { dimColor: true, children: `v${version}` })
4741
+ ] }),
4742
+ subtitle && /* @__PURE__ */ jsx29(Text21, { dimColor: true, children: subtitle }),
4743
+ model && /* @__PURE__ */ jsx29(Text21, { dimColor: true, children: model })
4744
+ ] })
4745
+ ] }),
4746
+ tips && tips.length > 0 && /* @__PURE__ */ jsxs22(Box20, { flexDirection: "column", gap: 0, children: [
4747
+ /* @__PURE__ */ jsx29(Text21, { dimColor: true, children: "Tips:" }),
4748
+ tips.map((tip, i) => /* @__PURE__ */ jsx29(Text21, { dimColor: true, children: ` - ${tip}` }, i))
4749
+ ] })
4750
+ ] });
4751
+ }
4752
+
4753
+ // src/agent/useAgent.ts
4754
+ import { useState as useState15, useCallback as useCallback14, useRef as useRef10, useEffect as useEffect9 } from "react";
4755
+ var _msgId = 0;
4756
+ function nextId() {
4757
+ return `msg-${++_msgId}-${Date.now()}`;
4758
+ }
4759
+ function toolCallToContent(tc) {
4760
+ return {
4761
+ type: "tool_use",
4762
+ toolName: tc.name,
4763
+ input: JSON.stringify(tc.input, null, 2),
4764
+ status: "running"
4765
+ };
4766
+ }
4767
+ function useAgent({ agent, onError }) {
4768
+ const [messages, setMessages] = useState15([]);
4769
+ const [isLoading, setIsLoading] = useState15(false);
4770
+ const [streamingContent, setStreamingContent] = useState15(null);
4771
+ const [permissionRequest, setPermissionRequest] = useState15(null);
4772
+ const isRunningRef = useRef10(false);
4773
+ const toolMsgMap = useRef10(/* @__PURE__ */ new Map());
4774
+ useEffect9(() => {
4775
+ agent.setPermissionHandler(async (request) => {
4776
+ return new Promise((resolve) => {
4777
+ setPermissionRequest({
4778
+ toolName: request.tool,
4779
+ description: `Tool "${request.tool}" wants to execute`,
4780
+ details: JSON.stringify(request.input, null, 2),
4781
+ resolve: (decision) => {
4782
+ setPermissionRequest(null);
4783
+ resolve({ decision });
4784
+ }
4785
+ });
4786
+ });
4787
+ });
4788
+ }, [agent]);
4789
+ const cancel = useCallback14(() => {
4790
+ agent.abort();
4791
+ isRunningRef.current = false;
4792
+ setIsLoading(false);
4793
+ setStreamingContent(null);
4794
+ setPermissionRequest(null);
4795
+ }, [agent]);
4796
+ const clearMessages = useCallback14(() => {
4797
+ agent.clearMessages();
4798
+ setMessages([]);
4799
+ setStreamingContent(null);
4800
+ setPermissionRequest(null);
4801
+ }, [agent]);
4802
+ const submit = useCallback14(
4803
+ (input) => {
4804
+ if (isRunningRef.current) return;
4805
+ const trimmed = input.trim();
4806
+ if (!trimmed) return;
4807
+ const userMsg = {
4808
+ id: nextId(),
4809
+ role: "user",
4810
+ content: trimmed,
4811
+ timestamp: Date.now()
4812
+ };
4813
+ setMessages((prev) => [...prev, userMsg]);
4814
+ isRunningRef.current = true;
4815
+ setIsLoading(true);
4816
+ setStreamingContent(null);
4817
+ (async () => {
4818
+ let accumulated = "";
4819
+ try {
4820
+ for await (const event of agent.run(trimmed)) {
4821
+ switch (event.type) {
4822
+ case "text": {
4823
+ accumulated += event.text;
4824
+ setStreamingContent(accumulated);
4825
+ break;
4826
+ }
4827
+ case "tool_call": {
4828
+ const msgId = nextId();
4829
+ toolMsgMap.current.set(event.toolCall.id, msgId);
4830
+ const toolMsg = {
4831
+ id: msgId,
4832
+ role: "assistant",
4833
+ content: [toolCallToContent(event.toolCall)],
4834
+ timestamp: Date.now()
4835
+ };
4836
+ setMessages((prev) => [...prev, toolMsg]);
4837
+ break;
4838
+ }
4839
+ case "tool_result": {
4840
+ const targetId = toolMsgMap.current.get(event.toolCallId);
4841
+ if (targetId) {
4842
+ setMessages(
4843
+ (prev) => prev.map((m) => {
4844
+ if (m.id !== targetId) return m;
4845
+ const contents = Array.isArray(m.content) ? m.content : [];
4846
+ return {
4847
+ ...m,
4848
+ content: contents.map((c) => {
4849
+ if (c.type !== "tool_use") return c;
4850
+ return {
4851
+ ...c,
4852
+ result: event.result.content,
4853
+ status: event.result.isError ? "error" : "success"
4854
+ };
4855
+ })
4856
+ };
4857
+ })
4858
+ );
4859
+ toolMsgMap.current.delete(event.toolCallId);
4860
+ }
4861
+ break;
4862
+ }
4863
+ case "error": {
4864
+ onError?.(event.error);
4865
+ break;
4866
+ }
4867
+ case "done": {
4868
+ if (accumulated.length > 0) {
4869
+ const assistantMsg = {
4870
+ id: nextId(),
4871
+ role: "assistant",
4872
+ content: accumulated,
4873
+ timestamp: Date.now()
4874
+ };
4875
+ setMessages((prev) => [...prev, assistantMsg]);
4876
+ }
4877
+ accumulated = "";
4878
+ setStreamingContent(null);
4879
+ break;
4880
+ }
4881
+ }
4882
+ }
4883
+ } catch (err) {
4884
+ const error = err instanceof Error ? err : new Error(String(err));
4885
+ onError?.(error);
4886
+ } finally {
4887
+ isRunningRef.current = false;
4888
+ setIsLoading(false);
4889
+ setStreamingContent(null);
4890
+ }
4891
+ })();
4892
+ },
4893
+ [agent, onError]
4894
+ );
4895
+ return {
4896
+ messages,
4897
+ isLoading,
4898
+ streamingContent,
4899
+ permissionRequest,
4900
+ submit,
4901
+ cancel,
4902
+ clearMessages
4903
+ };
4904
+ }
4905
+
4906
+ // src/agent/AgentProvider.tsx
4907
+ import { createContext as createContext4, useContext as useContext11, useMemo as useMemo8 } from "react";
4908
+ import { jsx as jsx30 } from "react/jsx-runtime";
4909
+ var AgentContext = createContext4(null);
4910
+ function AgentProvider({
4911
+ agent,
4912
+ model = "unknown",
4913
+ onError,
4914
+ children
4915
+ }) {
4916
+ const agentState = useAgent({ agent, onError });
4917
+ const value = useMemo8(
4918
+ () => ({
4919
+ ...agentState,
4920
+ agent,
4921
+ model
4922
+ }),
4923
+ [agentState, agent, model]
4924
+ );
4925
+ return /* @__PURE__ */ jsx30(AgentContext.Provider, { value, children });
4926
+ }
4927
+ function useAgentContext() {
4928
+ const ctx = useContext11(AgentContext);
4929
+ if (!ctx) {
4930
+ throw new Error(
4931
+ "useAgentContext must be used within an <AgentProvider>. Wrap your component tree with <AgentProvider agent={agent}>."
4932
+ );
4933
+ }
4934
+ return ctx;
4935
+ }
4936
+
4937
+ // src/agent/AgentREPL.tsx
4938
+ import { useCallback as useCallback15, useMemo as useMemo9 } from "react";
4939
+ import { jsx as jsx31 } from "react/jsx-runtime";
4940
+ function AgentREPLInner({
4941
+ commands,
4942
+ welcome,
4943
+ placeholder,
4944
+ onExit
4945
+ }) {
4946
+ const {
4947
+ messages,
4948
+ isLoading,
4949
+ streamingContent,
4950
+ permissionRequest,
4951
+ submit,
4952
+ model,
4953
+ clearMessages
4954
+ } = useAgentContext();
4955
+ const permissionState = useMemo9(() => {
4956
+ if (!permissionRequest) return void 0;
4957
+ return {
4958
+ toolName: permissionRequest.toolName,
4959
+ description: permissionRequest.description,
4960
+ details: permissionRequest.details,
4961
+ onDecision: (action) => {
4962
+ permissionRequest.resolve(action === "deny" ? "deny" : "allow");
4963
+ }
4964
+ };
4965
+ }, [permissionRequest]);
4966
+ const allCommands = useMemo9(() => {
4967
+ const builtIn = [
4968
+ {
4969
+ name: "clear",
4970
+ description: "Clear conversation history",
4971
+ onExecute: () => clearMessages()
4972
+ }
4973
+ ];
4974
+ return [...builtIn, ...commands ?? []];
4975
+ }, [commands, clearMessages]);
4976
+ const handleSubmit = useCallback15(
4977
+ async (input) => {
4978
+ submit(input);
4979
+ },
4980
+ [submit]
4981
+ );
4982
+ return /* @__PURE__ */ jsx31(
4983
+ REPL,
4984
+ {
4985
+ onSubmit: handleSubmit,
4986
+ onExit,
4987
+ messages,
4988
+ isLoading,
4989
+ streamingContent,
4990
+ permissionRequest: permissionState,
4991
+ commands: allCommands,
4992
+ model,
4993
+ welcome,
4994
+ placeholder
4995
+ }
4996
+ );
4997
+ }
4998
+ function AgentREPL({
4999
+ agent,
5000
+ model,
5001
+ commands,
5002
+ welcome,
5003
+ placeholder,
5004
+ onError,
5005
+ onExit
5006
+ }) {
5007
+ return /* @__PURE__ */ jsx31(AgentProvider, { agent, model, onError, children: /* @__PURE__ */ jsx31(
5008
+ AgentREPLInner,
5009
+ {
5010
+ commands,
5011
+ welcome,
5012
+ placeholder,
5013
+ onExit
5014
+ }
5015
+ ) });
5016
+ }
5017
+
5018
+ // src/AuthFlow.tsx
5019
+ import { useState as useState16, useCallback as useCallback16 } from "react";
5020
+ import { Box as Box21, Text as Text22, useInput as useInput11 } from "@claude-code-kit/ink-renderer";
5021
+ import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
5022
+ function CredentialInput({
5023
+ label,
5024
+ masked,
5025
+ onSubmit,
5026
+ onCancel
5027
+ }) {
5028
+ const [value, setValue] = useState16("");
5029
+ const [cursor, setCursor] = useState16(0);
5030
+ useInput11((input, key) => {
5031
+ if (key.escape) {
5032
+ onCancel?.();
5033
+ return;
5034
+ }
5035
+ if (key.return) {
5036
+ if (value.length > 0) onSubmit(value);
5037
+ return;
5038
+ }
5039
+ if (key.backspace) {
5040
+ if (cursor > 0) {
5041
+ setValue((v) => v.slice(0, cursor - 1) + v.slice(cursor));
5042
+ setCursor((c) => c - 1);
5043
+ }
5044
+ return;
5045
+ }
5046
+ if (key.leftArrow) {
5047
+ setCursor((c) => Math.max(0, c - 1));
5048
+ return;
5049
+ }
5050
+ if (key.rightArrow) {
5051
+ setCursor((c) => Math.min(value.length, c + 1));
5052
+ return;
5053
+ }
5054
+ if (key.ctrl || key.meta) return;
5055
+ if (input.length > 0) {
5056
+ setValue((v) => v.slice(0, cursor) + input + v.slice(cursor));
5057
+ setCursor((c) => c + input.length);
5058
+ }
5059
+ });
5060
+ const display = masked ? "*".repeat(value.length) : value;
5061
+ const before = display.slice(0, cursor);
5062
+ const at = cursor < display.length ? display[cursor] : " ";
5063
+ const after = cursor < display.length ? display.slice(cursor + 1) : "";
5064
+ return /* @__PURE__ */ jsxs23(Box21, { flexDirection: "column", children: [
5065
+ /* @__PURE__ */ jsx32(Text22, { bold: true, children: label }),
5066
+ /* @__PURE__ */ jsxs23(Box21, { children: [
5067
+ /* @__PURE__ */ jsx32(Text22, { color: "cyan", children: "> " }),
5068
+ /* @__PURE__ */ jsxs23(Text22, { children: [
5069
+ before,
5070
+ /* @__PURE__ */ jsx32(Text22, { inverse: true, children: at }),
5071
+ after
5072
+ ] })
5073
+ ] }),
5074
+ value.length === 0 && /* @__PURE__ */ jsx32(Text22, { dimColor: true, children: " Type your credential and press Enter" })
5075
+ ] });
5076
+ }
5077
+ function AuthFlowUI({
5078
+ auth,
5079
+ onComplete,
5080
+ onCancel,
5081
+ title = "Authentication"
5082
+ }) {
5083
+ const [phase, setPhase] = useState16({ type: "select-provider" });
5084
+ const [baseURL, setBaseURL] = useState16();
5085
+ const [error, setError] = useState16();
5086
+ const flowState = auth.interactive();
5087
+ const providerOptions = (flowState.providers ?? []).map((p) => ({
5088
+ value: p.name,
5089
+ label: `${p.displayName}`,
5090
+ description: p.description
5091
+ }));
5092
+ const handleProviderSelect = useCallback16((providerName) => {
5093
+ setError(void 0);
5094
+ try {
5095
+ const state = auth.selectProvider(providerName);
5096
+ if (state.step === "done" && state.result) {
5097
+ onComplete(state.result.provider, state.result.providerName, state.result.model);
5098
+ setPhase({ type: "done" });
5099
+ return;
5100
+ }
5101
+ if (state.step === "input-credentials" && state.currentAuthMethod) {
5102
+ const method = state.currentAuthMethod;
5103
+ const needsBaseURL = method.type === "base-url-key" && !method.defaultBaseURL;
5104
+ setPhase({
5105
+ type: "input-credentials",
5106
+ providerName,
5107
+ method,
5108
+ needsBaseURL
5109
+ });
5110
+ return;
5111
+ }
5112
+ if (state.step === "select-model" && state.models) {
5113
+ setPhase({
5114
+ type: "select-model",
5115
+ providerName,
5116
+ method: state.currentAuthMethod,
5117
+ models: state.models,
5118
+ defaultModel: state.currentModel
5119
+ });
5120
+ return;
5121
+ }
5122
+ if (state.step === "select-auth-method" && state.authMethods) {
5123
+ const method = state.authMethods[0];
5124
+ const needsBaseURL = method.type === "base-url-key" && !("defaultBaseURL" in method && method.defaultBaseURL);
5125
+ setPhase({
5126
+ type: "input-credentials",
5127
+ providerName,
5128
+ method,
5129
+ needsBaseURL: needsBaseURL && method.type === "base-url-key"
5130
+ });
5131
+ return;
5132
+ }
5133
+ } catch (err) {
5134
+ setError(err instanceof Error ? err.message : String(err));
5135
+ }
5136
+ }, [auth, onComplete]);
5137
+ const handleBaseURLSubmit = useCallback16((url) => {
5138
+ setBaseURL(url);
5139
+ }, []);
5140
+ const handleCredentialSubmit = useCallback16(async (apiKey) => {
5141
+ if (phase.type !== "input-credentials") return;
5142
+ setError(void 0);
5143
+ try {
5144
+ const credentials = {
5145
+ apiKey,
5146
+ baseURL: baseURL || (phase.method.type === "base-url-key" ? phase.method.defaultBaseURL : void 0)
5147
+ };
5148
+ const state = await auth.inputCredentials(phase.providerName, phase.method, credentials);
5149
+ if (state.step === "done" && state.result) {
5150
+ onComplete(state.result.provider, state.result.providerName, state.result.model);
5151
+ setPhase({ type: "done" });
5152
+ return;
5153
+ }
5154
+ if (state.step === "select-model" && state.models) {
5155
+ setPhase({
5156
+ type: "select-model",
5157
+ providerName: phase.providerName,
5158
+ method: phase.method,
5159
+ models: state.models,
5160
+ defaultModel: state.currentModel
5161
+ });
5162
+ return;
5163
+ }
5164
+ } catch (err) {
5165
+ setError(err instanceof Error ? err.message : String(err));
5166
+ }
5167
+ }, [auth, phase, baseURL, onComplete]);
5168
+ const handleModelSelect = useCallback16(async (model) => {
5169
+ if (phase.type !== "select-model") return;
5170
+ setError(void 0);
5171
+ try {
5172
+ const state = await auth.selectModel(phase.providerName, phase.method, model);
5173
+ if (state.step === "done" && state.result) {
5174
+ onComplete(state.result.provider, state.result.providerName, state.result.model);
5175
+ setPhase({ type: "done" });
5176
+ }
5177
+ } catch (err) {
5178
+ setError(err instanceof Error ? err.message : String(err));
5179
+ }
5180
+ }, [auth, phase, onComplete]);
5181
+ const handleCancel = useCallback16(() => {
5182
+ if (phase.type === "select-provider") {
5183
+ onCancel?.();
5184
+ } else {
5185
+ setPhase({ type: "select-provider" });
5186
+ setBaseURL(void 0);
5187
+ setError(void 0);
5188
+ }
5189
+ }, [phase, onCancel]);
5190
+ if (phase.type === "done") {
5191
+ return null;
5192
+ }
5193
+ return /* @__PURE__ */ jsxs23(Box21, { flexDirection: "column", marginTop: 1, marginLeft: 1, children: [
5194
+ /* @__PURE__ */ jsx32(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsx32(Text22, { bold: true, color: "#DA7756", children: title }) }),
5195
+ /* @__PURE__ */ jsx32(Divider, {}),
5196
+ error && /* @__PURE__ */ jsx32(Box21, { marginTop: 1, children: /* @__PURE__ */ jsxs23(Text22, { color: "red", children: [
5197
+ "Error: ",
5198
+ error
5199
+ ] }) }),
5200
+ /* @__PURE__ */ jsxs23(Box21, { marginTop: 1, children: [
5201
+ phase.type === "select-provider" && /* @__PURE__ */ jsx32(
5202
+ Select,
5203
+ {
5204
+ title: "Select a provider:",
5205
+ options: providerOptions,
5206
+ onChange: handleProviderSelect,
5207
+ onCancel: handleCancel
5208
+ }
5209
+ ),
5210
+ phase.type === "input-credentials" && phase.method.type === "base-url-key" && phase.needsBaseURL && !baseURL && /* @__PURE__ */ jsx32(
5211
+ CredentialInput,
5212
+ {
5213
+ label: "Enter Base URL:",
5214
+ masked: false,
5215
+ onSubmit: handleBaseURLSubmit,
5216
+ onCancel: handleCancel
5217
+ }
5218
+ ),
5219
+ phase.type === "input-credentials" && !(phase.method.type === "base-url-key" && phase.needsBaseURL && !baseURL) && /* @__PURE__ */ jsx32(
5220
+ CredentialInput,
5221
+ {
5222
+ label: phase.method.type === "api-key" || phase.method.type === "base-url-key" ? phase.method.inputLabel ?? "Enter API Key:" : "Enter API Key:",
5223
+ masked: true,
5224
+ onSubmit: handleCredentialSubmit,
5225
+ onCancel: handleCancel
5226
+ }
5227
+ ),
5228
+ phase.type === "select-model" && /* @__PURE__ */ jsx32(
5229
+ Select,
5230
+ {
5231
+ title: "Select a model:",
5232
+ options: phase.models.map((m) => ({
5233
+ value: m,
5234
+ label: m,
5235
+ description: m === phase.defaultModel ? "(default)" : void 0
5236
+ })),
5237
+ defaultValue: phase.defaultModel,
5238
+ onChange: handleModelSelect,
5239
+ onCancel: handleCancel
5240
+ }
5241
+ )
5242
+ ] }),
5243
+ /* @__PURE__ */ jsx32(Box21, { marginTop: 1, children: /* @__PURE__ */ jsxs23(Text22, { dimColor: true, children: [
5244
+ "Esc to ",
5245
+ phase.type === "select-provider" ? "cancel" : "go back"
5246
+ ] }) })
5247
+ ] });
5248
+ }
3793
5249
  export {
5250
+ AgentContext,
5251
+ AgentProvider,
5252
+ AgentREPL,
5253
+ AuthFlowUI,
5254
+ BashPermissionContent,
3794
5255
  Byline,
5256
+ ClawdLogo,
3795
5257
  CommandRegistry,
3796
5258
  DEFAULT_BINDINGS,
3797
5259
  Dialog,
5260
+ DiffView,
3798
5261
  Divider,
5262
+ FileEditPermissionContent,
3799
5263
  FuzzyPicker,
3800
5264
  KeybindingSetup,
3801
5265
  KeyboardShortcutHint,
@@ -3806,10 +5270,12 @@ export {
3806
5270
  MessageList,
3807
5271
  MultiSelect,
3808
5272
  Pane,
5273
+ PermissionRequest,
3809
5274
  ProgressBar,
3810
5275
  PromptInput,
3811
5276
  REPL,
3812
5277
  Ratchet,
5278
+ SearchOverlay,
3813
5279
  Select,
3814
5280
  Spinner,
3815
5281
  StatusIcon,
@@ -3822,6 +5288,8 @@ export {
3822
5288
  ThemeProvider,
3823
5289
  ThemedBox_default as ThemedBox,
3824
5290
  ThemedText,
5291
+ VirtualList,
5292
+ WelcomeScreen,
3825
5293
  clearCommand,
3826
5294
  color,
3827
5295
  createCommandRegistry,
@@ -3831,13 +5299,18 @@ export {
3831
5299
  exitCommand,
3832
5300
  getTheme,
3833
5301
  helpCommand,
5302
+ parseUnifiedDiff,
5303
+ useAgent,
5304
+ useAgentContext,
3834
5305
  useDoublePress,
3835
5306
  useKeybinding,
3836
5307
  useKeybindings,
3837
5308
  usePreviewTheme,
5309
+ useSearch,
3838
5310
  useStatusLine,
3839
5311
  useTabsWidth,
3840
5312
  useTerminalSize,
3841
5313
  useTheme,
3842
- useThemeSetting
5314
+ useThemeSetting,
5315
+ useVirtualScroll
3843
5316
  };