@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.d.mts +265 -8
- package/dist/index.d.ts +265 -8
- package/dist/index.js +2000 -510
- package/dist/index.mjs +1866 -393
- package/package.json +18 -12
- package/LICENSE +0 -21
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__ */
|
|
144
|
+
return /* @__PURE__ */ jsxs2(Text2, { color: color2, dimColor: !color2, children: [
|
|
18
145
|
char.repeat(leftWidth),
|
|
19
146
|
" ",
|
|
20
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
30
|
-
import { jsx as
|
|
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__ */
|
|
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
|
|
51
|
-
import { jsxs as
|
|
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__ */
|
|
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
|
|
71
|
-
import { jsx as
|
|
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
|
-
|
|
206
|
+
separator = " \xB7 ",
|
|
80
207
|
borderStyle = "none",
|
|
81
208
|
borderColor
|
|
82
209
|
}) {
|
|
83
210
|
const border = borderStyle === "none" ? void 0 : borderStyle;
|
|
84
|
-
return /* @__PURE__ */
|
|
85
|
-
|
|
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__ */
|
|
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
|
|
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 =
|
|
604
|
+
const getDisplayText = useMemo2(
|
|
475
605
|
() => (action, context) => getBindingDisplayText(action, context, bindings),
|
|
476
606
|
[bindings]
|
|
477
607
|
);
|
|
478
|
-
const registerHandler =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
1769
|
-
|
|
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
|
|
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
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
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
|
-
|
|
1794
|
-
|
|
1795
|
-
}
|
|
1796
|
-
|
|
1797
|
-
)
|
|
1798
|
-
|
|
1799
|
-
(
|
|
1800
|
-
if (
|
|
1801
|
-
if (
|
|
1802
|
-
|
|
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 (
|
|
1817
|
-
|
|
1818
|
-
|
|
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.
|
|
1823
|
-
|
|
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.
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
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
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
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 (
|
|
1847
|
-
if (
|
|
1848
|
-
|
|
2050
|
+
if (input === "d") {
|
|
2051
|
+
if (!pendingD) {
|
|
2052
|
+
setPendingD(true);
|
|
1849
2053
|
return;
|
|
1850
2054
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
const
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
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.
|
|
1865
|
-
|
|
2068
|
+
if (key.upArrow || input === "k" && !key.ctrl) {
|
|
2069
|
+
if (!moveLine(-1)) historyUp();
|
|
1866
2070
|
return;
|
|
1867
2071
|
}
|
|
1868
|
-
if (key.
|
|
1869
|
-
|
|
2072
|
+
if (key.downArrow || input === "j" && !key.ctrl) {
|
|
2073
|
+
if (!moveLine(1)) historyDown();
|
|
1870
2074
|
return;
|
|
1871
2075
|
}
|
|
1872
|
-
if (key.
|
|
1873
|
-
|
|
2076
|
+
if (key.return && value.length > 0) {
|
|
2077
|
+
onSubmit(value);
|
|
1874
2078
|
return;
|
|
1875
2079
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
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 (
|
|
1881
|
-
|
|
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 (
|
|
1891
|
-
|
|
1892
|
-
|
|
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 (
|
|
1896
|
-
|
|
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
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
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 (
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
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
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
return
|
|
1920
|
-
|
|
1921
|
-
|
|
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 =
|
|
1925
|
-
const
|
|
1926
|
-
const after =
|
|
1927
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
2190
|
+
/* @__PURE__ */ jsx7(Text6, { inverse: true, children: at }),
|
|
1930
2191
|
after
|
|
1931
2192
|
] });
|
|
1932
2193
|
};
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
|
|
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
|
|
1958
|
-
import { jsx as
|
|
1959
|
-
var
|
|
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__ */
|
|
1995
|
-
/* @__PURE__ */
|
|
1996
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2281
|
+
label && /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
2002
2282
|
" ",
|
|
2003
2283
|
label
|
|
2004
2284
|
] }),
|
|
2005
|
-
showTime && /* @__PURE__ */
|
|
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
|
|
2016
|
-
import { Ansi as Ansi4, Box as
|
|
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
|
|
2020
|
-
import { jsx as
|
|
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 =
|
|
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__ */
|
|
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
|
|
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
|
|
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__ */
|
|
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__ */
|
|
3020
|
+
return /* @__PURE__ */ jsx10(Ansi3, { children: renderVerticalFormat() });
|
|
2626
3021
|
}
|
|
2627
|
-
return /* @__PURE__ */
|
|
3022
|
+
return /* @__PURE__ */ jsx10(Ansi3, { children: tableLines.join("\n") });
|
|
2628
3023
|
}
|
|
2629
3024
|
|
|
2630
3025
|
// src/Markdown.tsx
|
|
2631
|
-
import { jsx as
|
|
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__ */
|
|
3065
|
+
return /* @__PURE__ */ jsx11(MarkdownBody, { ...props, highlight: null });
|
|
2671
3066
|
}
|
|
2672
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2745
|
-
stablePrefix && /* @__PURE__ */
|
|
2746
|
-
unstableSuffix && /* @__PURE__ */
|
|
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
|
|
2752
|
-
import { Box as
|
|
2753
|
-
import { jsx as
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
2830
|
-
title && /* @__PURE__ */
|
|
2831
|
-
scrollOffset > 0 && /* @__PURE__ */
|
|
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__ */
|
|
2838
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2843
|
-
|
|
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__ */
|
|
2856
|
-
opt.description && /* @__PURE__ */
|
|
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__ */
|
|
2863
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2904
|
-
title && /* @__PURE__ */
|
|
2905
|
-
scrollOffset > 0 && /* @__PURE__ */
|
|
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__ */
|
|
2912
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2917
|
-
|
|
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__ */
|
|
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__ */
|
|
2938
|
-
/* @__PURE__ */
|
|
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 {
|
|
2944
|
-
import {
|
|
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
|
-
|
|
2960
|
-
/* @__PURE__ */
|
|
2961
|
-
/* @__PURE__ */
|
|
2962
|
-
|
|
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.
|
|
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__ */
|
|
2976
|
-
messages.map((message, i) => /* @__PURE__ */
|
|
2977
|
-
streamingContent != null && streamingContent.length > 0 && /* @__PURE__ */
|
|
2978
|
-
/* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2995
|
-
import { Text as
|
|
2996
|
-
import { jsx as
|
|
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] =
|
|
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__ */
|
|
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
|
|
3025
|
-
import { Box as
|
|
3026
|
-
|
|
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] =
|
|
3044
|
-
const [internalHistory, setInternalHistory] =
|
|
3045
|
-
const
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
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__ */
|
|
3914
|
+
isLoading && !streamingContent && /* @__PURE__ */ jsx17(Box10, { marginTop: messages.length > 0 ? 1 : 0, children: spinner ?? /* @__PURE__ */ jsx17(Spinner, {}) })
|
|
3110
3915
|
] }),
|
|
3111
|
-
/* @__PURE__ */
|
|
3112
|
-
|
|
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__ */
|
|
3126
|
-
resolvedSegments.length > 0 && /* @__PURE__ */
|
|
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
|
|
3136
|
-
import { jsx as
|
|
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__ */
|
|
3164
|
-
|
|
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
|
|
3182
|
-
import { Text as
|
|
3183
|
-
import { jsx as
|
|
3184
|
-
var TextHoverColorContext =
|
|
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 =
|
|
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__ */
|
|
3210
|
-
|
|
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
|
|
3227
|
-
import { Box as
|
|
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
|
|
3231
|
-
import { Text as
|
|
3232
|
-
import { Fragment, jsx as
|
|
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__ */
|
|
3239
|
-
|
|
4062
|
+
return /* @__PURE__ */ jsx20(Fragment2, { children: validChildren.map((child, index) => /* @__PURE__ */ jsxs14(
|
|
4063
|
+
React18.Fragment,
|
|
3240
4064
|
{
|
|
3241
4065
|
children: [
|
|
3242
|
-
index > 0 && /* @__PURE__ */
|
|
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
|
|
3252
|
-
import { jsx as
|
|
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__ */
|
|
4083
|
+
const shortcutText = bold ? /* @__PURE__ */ jsx21(Text15, { bold: true, children: shortcut }) : shortcut;
|
|
3260
4084
|
if (parens) {
|
|
3261
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3278
|
-
import { jsx as
|
|
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__ */
|
|
3281
|
-
/* @__PURE__ */
|
|
3282
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
-
|
|
3298
|
-
|
|
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__ */
|
|
3308
|
-
/* @__PURE__ */
|
|
3309
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3312
|
-
/* @__PURE__ */
|
|
3313
|
-
/* @__PURE__ */
|
|
3314
|
-
/* @__PURE__ */
|
|
3315
|
-
subtitle && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4148
|
+
return /* @__PURE__ */ jsx23(Pane, { color: color2, children: content });
|
|
3325
4149
|
}
|
|
3326
4150
|
|
|
3327
4151
|
// src/design-system/FuzzyPicker.tsx
|
|
3328
|
-
import { useCallback as
|
|
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
|
|
3332
|
-
Text as
|
|
3333
|
-
useInput as
|
|
3334
|
-
TerminalSizeContext as
|
|
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
|
|
3341
|
-
import { jsx as
|
|
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__ */
|
|
4179
|
+
return /* @__PURE__ */ jsx24(Text17, { children: " " });
|
|
3356
4180
|
}
|
|
3357
4181
|
if (isFocused) {
|
|
3358
|
-
return /* @__PURE__ */
|
|
4182
|
+
return /* @__PURE__ */ jsx24(Text17, { color: "cyan", children: figures2.pointer });
|
|
3359
4183
|
}
|
|
3360
4184
|
if (showScrollDown) {
|
|
3361
|
-
return /* @__PURE__ */
|
|
4185
|
+
return /* @__PURE__ */ jsx24(Text17, { dimColor: true, children: figures2.arrowDown });
|
|
3362
4186
|
}
|
|
3363
4187
|
if (showScrollUp) {
|
|
3364
|
-
return /* @__PURE__ */
|
|
4188
|
+
return /* @__PURE__ */ jsx24(Text17, { dimColor: true, children: figures2.arrowUp });
|
|
3365
4189
|
}
|
|
3366
|
-
return /* @__PURE__ */
|
|
4190
|
+
return /* @__PURE__ */ jsx24(Text17, { children: " " });
|
|
3367
4191
|
}
|
|
3368
4192
|
function getTextColor() {
|
|
3369
4193
|
if (disabled) {
|
|
3370
|
-
return
|
|
4194
|
+
return void 0;
|
|
3371
4195
|
}
|
|
3372
4196
|
if (!styled) {
|
|
3373
4197
|
return void 0;
|
|
3374
4198
|
}
|
|
3375
4199
|
if (isSelected) {
|
|
3376
|
-
return "
|
|
4200
|
+
return "green";
|
|
3377
4201
|
}
|
|
3378
4202
|
if (isFocused) {
|
|
3379
|
-
return "
|
|
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__ */
|
|
3390
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3393
|
-
isSelected && !disabled && /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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 =
|
|
4250
|
+
const terminalSize = useContext8(TerminalSizeContext5);
|
|
3427
4251
|
const rows = terminalSize?.rows ?? 24;
|
|
3428
4252
|
const columns = terminalSize?.columns ?? 80;
|
|
3429
|
-
const [focusedIndex, setFocusedIndex] =
|
|
3430
|
-
const [query, setQuery] =
|
|
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 =
|
|
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
|
-
|
|
3443
|
-
|
|
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
|
-
|
|
4308
|
+
useEffect8(() => {
|
|
3485
4309
|
onQueryChange(query);
|
|
3486
4310
|
setFocusedIndex(0);
|
|
3487
4311
|
}, [query]);
|
|
3488
|
-
|
|
4312
|
+
useEffect8(() => {
|
|
3489
4313
|
setFocusedIndex((i) => clamp(i, 0, items.length - 1));
|
|
3490
4314
|
}, [items.length]);
|
|
3491
4315
|
const focused = items[focusedIndex];
|
|
3492
|
-
|
|
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__ */
|
|
3503
|
-
const listBlock = /* @__PURE__ */
|
|
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__ */
|
|
3518
|
-
const listGroup = renderPreview && previewPosition === "right" ? /* @__PURE__ */
|
|
3519
|
-
|
|
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__ */
|
|
4349
|
+
/* @__PURE__ */ jsxs19(Box15, { flexDirection: "column", flexShrink: 0, children: [
|
|
3526
4350
|
listBlock,
|
|
3527
|
-
matchLabel && /* @__PURE__ */
|
|
4351
|
+
matchLabel && /* @__PURE__ */ jsx25(Text18, { dimColor: true, children: matchLabel })
|
|
3528
4352
|
] }),
|
|
3529
|
-
preview ?? /* @__PURE__ */
|
|
4353
|
+
preview ?? /* @__PURE__ */ jsx25(Box15, { flexGrow: 1 })
|
|
3530
4354
|
]
|
|
3531
4355
|
}
|
|
3532
|
-
) : /* @__PURE__ */
|
|
4356
|
+
) : /* @__PURE__ */ jsxs19(Box15, { flexDirection: "column", children: [
|
|
3533
4357
|
listBlock,
|
|
3534
|
-
matchLabel && /* @__PURE__ */
|
|
4358
|
+
matchLabel && /* @__PURE__ */ jsx25(Text18, { dimColor: true, children: matchLabel }),
|
|
3535
4359
|
preview
|
|
3536
4360
|
] });
|
|
3537
4361
|
const inputAbove = direction !== "up";
|
|
3538
|
-
return /* @__PURE__ */
|
|
3539
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3544
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3552
|
-
onTab && /* @__PURE__ */
|
|
3553
|
-
onShiftTab && !compact && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3597
|
-
|
|
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
|
|
3609
|
-
import { jsx as
|
|
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__ */
|
|
3617
|
-
/* @__PURE__ */
|
|
3618
|
-
/* @__PURE__ */
|
|
3619
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3630
|
-
import { TerminalSizeContext as
|
|
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
|
|
3633
|
-
import { jsx as
|
|
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 =
|
|
4463
|
+
const terminalSize = useContext9(TerminalSizeContext6);
|
|
3640
4464
|
const rows = terminalSize?.rows ?? 24;
|
|
3641
|
-
const innerRef =
|
|
3642
|
-
const maxHeight =
|
|
3643
|
-
const [minHeight, setMinHeight] =
|
|
3644
|
-
const outerRef =
|
|
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__ */
|
|
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
|
|
3668
|
-
useContext as
|
|
3669
|
-
useState as
|
|
4491
|
+
useCallback as useCallback12,
|
|
4492
|
+
useContext as useContext10,
|
|
4493
|
+
useState as useState13
|
|
3670
4494
|
} from "react";
|
|
3671
|
-
import { TerminalSizeContext as
|
|
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
|
|
3674
|
-
import { jsx as
|
|
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 =
|
|
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] =
|
|
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 =
|
|
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
|
-
|
|
3717
|
-
|
|
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__ */
|
|
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__ */
|
|
3749
|
-
!hidden && /* @__PURE__ */
|
|
3750
|
-
title !== void 0 && /* @__PURE__ */
|
|
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__ */
|
|
3754
|
-
|
|
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__ */
|
|
4591
|
+
spacerWidth > 0 && /* @__PURE__ */ jsx28(Text20, { children: " ".repeat(spacerWidth) })
|
|
3768
4592
|
] }),
|
|
3769
4593
|
banner,
|
|
3770
|
-
/* @__PURE__ */
|
|
3771
|
-
|
|
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 } =
|
|
4607
|
+
const { selectedTab, width } = useContext10(TabsContext);
|
|
3784
4608
|
if (selectedTab !== (id ?? title)) {
|
|
3785
4609
|
return null;
|
|
3786
4610
|
}
|
|
3787
|
-
return /* @__PURE__ */
|
|
4611
|
+
return /* @__PURE__ */ jsx28(Box18, { width, children });
|
|
3788
4612
|
}
|
|
3789
4613
|
function useTabsWidth() {
|
|
3790
|
-
const { width } =
|
|
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
|
};
|