wave-code 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/bin/wave-code.js +16 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/components/App.d.ts +8 -0
- package/dist/components/App.d.ts.map +1 -0
- package/dist/components/App.js +10 -0
- package/dist/components/BashHistorySelector.d.ts +10 -0
- package/dist/components/BashHistorySelector.d.ts.map +1 -0
- package/dist/components/BashHistorySelector.js +83 -0
- package/dist/components/BashShellManager.d.ts +6 -0
- package/dist/components/BashShellManager.d.ts.map +1 -0
- package/dist/components/BashShellManager.js +116 -0
- package/dist/components/ChatInterface.d.ts +3 -0
- package/dist/components/ChatInterface.d.ts.map +1 -0
- package/dist/components/ChatInterface.js +31 -0
- package/dist/components/CommandOutputDisplay.d.ts +9 -0
- package/dist/components/CommandOutputDisplay.d.ts.map +1 -0
- package/dist/components/CommandOutputDisplay.js +40 -0
- package/dist/components/CommandSelector.d.ts +11 -0
- package/dist/components/CommandSelector.d.ts.map +1 -0
- package/dist/components/CommandSelector.js +60 -0
- package/dist/components/CompressDisplay.d.ts +9 -0
- package/dist/components/CompressDisplay.d.ts.map +1 -0
- package/dist/components/CompressDisplay.js +17 -0
- package/dist/components/DiffViewer.d.ts +9 -0
- package/dist/components/DiffViewer.d.ts.map +1 -0
- package/dist/components/DiffViewer.js +221 -0
- package/dist/components/FileSelector.d.ts +13 -0
- package/dist/components/FileSelector.d.ts.map +1 -0
- package/dist/components/FileSelector.js +48 -0
- package/dist/components/InputBox.d.ts +23 -0
- package/dist/components/InputBox.d.ts.map +1 -0
- package/dist/components/InputBox.js +124 -0
- package/dist/components/McpManager.d.ts +10 -0
- package/dist/components/McpManager.d.ts.map +1 -0
- package/dist/components/McpManager.js +123 -0
- package/dist/components/MemoryDisplay.d.ts +8 -0
- package/dist/components/MemoryDisplay.d.ts.map +1 -0
- package/dist/components/MemoryDisplay.js +25 -0
- package/dist/components/MemoryTypeSelector.d.ts +8 -0
- package/dist/components/MemoryTypeSelector.d.ts.map +1 -0
- package/dist/components/MemoryTypeSelector.js +38 -0
- package/dist/components/MessageList.d.ts +12 -0
- package/dist/components/MessageList.d.ts.map +1 -0
- package/dist/components/MessageList.js +36 -0
- package/dist/components/ToolResultDisplay.d.ts +9 -0
- package/dist/components/ToolResultDisplay.d.ts.map +1 -0
- package/dist/components/ToolResultDisplay.js +52 -0
- package/dist/contexts/useAppConfig.d.ts +11 -0
- package/dist/contexts/useAppConfig.d.ts.map +1 -0
- package/dist/contexts/useAppConfig.js +13 -0
- package/dist/contexts/useChat.d.ts +36 -0
- package/dist/contexts/useChat.d.ts.map +1 -0
- package/dist/contexts/useChat.js +208 -0
- package/dist/hooks/useBashHistorySelector.d.ts +15 -0
- package/dist/hooks/useBashHistorySelector.d.ts.map +1 -0
- package/dist/hooks/useBashHistorySelector.js +61 -0
- package/dist/hooks/useCommandSelector.d.ts +24 -0
- package/dist/hooks/useCommandSelector.d.ts.map +1 -0
- package/dist/hooks/useCommandSelector.js +98 -0
- package/dist/hooks/useFileSelector.d.ts +16 -0
- package/dist/hooks/useFileSelector.d.ts.map +1 -0
- package/dist/hooks/useFileSelector.js +174 -0
- package/dist/hooks/useImageManager.d.ts +13 -0
- package/dist/hooks/useImageManager.d.ts.map +1 -0
- package/dist/hooks/useImageManager.js +46 -0
- package/dist/hooks/useInputHistory.d.ts +11 -0
- package/dist/hooks/useInputHistory.d.ts.map +1 -0
- package/dist/hooks/useInputHistory.js +64 -0
- package/dist/hooks/useInputKeyboardHandler.d.ts +83 -0
- package/dist/hooks/useInputKeyboardHandler.d.ts.map +1 -0
- package/dist/hooks/useInputKeyboardHandler.js +507 -0
- package/dist/hooks/useInputState.d.ts +14 -0
- package/dist/hooks/useInputState.d.ts.map +1 -0
- package/dist/hooks/useInputState.js +57 -0
- package/dist/hooks/useMemoryTypeSelector.d.ts +9 -0
- package/dist/hooks/useMemoryTypeSelector.d.ts.map +1 -0
- package/dist/hooks/useMemoryTypeSelector.js +27 -0
- package/dist/hooks/usePagination.d.ts +20 -0
- package/dist/hooks/usePagination.d.ts.map +1 -0
- package/dist/hooks/usePagination.js +168 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/plain-cli.d.ts +7 -0
- package/dist/plain-cli.d.ts.map +1 -0
- package/dist/plain-cli.js +49 -0
- package/dist/utils/clipboard.d.ts +22 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +347 -0
- package/dist/utils/constants.d.ts +17 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +18 -0
- package/dist/utils/logger.d.ts +72 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +245 -0
- package/package.json +60 -0
- package/src/cli.tsx +82 -0
- package/src/components/App.tsx +31 -0
- package/src/components/BashHistorySelector.tsx +163 -0
- package/src/components/BashShellManager.tsx +306 -0
- package/src/components/ChatInterface.tsx +88 -0
- package/src/components/CommandOutputDisplay.tsx +81 -0
- package/src/components/CommandSelector.tsx +144 -0
- package/src/components/CompressDisplay.tsx +58 -0
- package/src/components/DiffViewer.tsx +321 -0
- package/src/components/FileSelector.tsx +137 -0
- package/src/components/InputBox.tsx +310 -0
- package/src/components/McpManager.tsx +328 -0
- package/src/components/MemoryDisplay.tsx +62 -0
- package/src/components/MemoryTypeSelector.tsx +96 -0
- package/src/components/MessageList.tsx +215 -0
- package/src/components/ToolResultDisplay.tsx +138 -0
- package/src/contexts/useAppConfig.tsx +32 -0
- package/src/contexts/useChat.tsx +300 -0
- package/src/hooks/useBashHistorySelector.ts +77 -0
- package/src/hooks/useCommandSelector.ts +131 -0
- package/src/hooks/useFileSelector.ts +227 -0
- package/src/hooks/useImageManager.ts +64 -0
- package/src/hooks/useInputHistory.ts +74 -0
- package/src/hooks/useInputKeyboardHandler.ts +778 -0
- package/src/hooks/useInputState.ts +66 -0
- package/src/hooks/useMemoryTypeSelector.ts +40 -0
- package/src/hooks/usePagination.ts +203 -0
- package/src/index.ts +108 -0
- package/src/plain-cli.ts +66 -0
- package/src/utils/clipboard.ts +384 -0
- package/src/utils/constants.ts +22 -0
- package/src/utils/logger.ts +301 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompressDisplay.d.ts","sourceRoot":"","sources":["../../src/components/CompressDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgD1D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
|
+
export const CompressDisplay = ({ block, isExpanded = false, }) => {
|
|
5
|
+
const { content } = block;
|
|
6
|
+
const MAX_LINES = 3; // Set maximum display lines for compressed content
|
|
7
|
+
const { displayContent, isOverflowing } = useMemo(() => {
|
|
8
|
+
if (!content) {
|
|
9
|
+
return { displayContent: "", isOverflowing: false };
|
|
10
|
+
}
|
|
11
|
+
const lines = content.split("\n");
|
|
12
|
+
const overflow = !isExpanded && lines.length > MAX_LINES;
|
|
13
|
+
const display = overflow ? lines.slice(0, MAX_LINES).join("\n") : content;
|
|
14
|
+
return { displayContent: display, isOverflowing: overflow };
|
|
15
|
+
}, [content, isExpanded]);
|
|
16
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsx(Text, { children: "\uD83D\uDCE6 Compressed Messages" }) }), content && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: _jsx(Text, { color: "white", children: displayContent }) }), isOverflowing && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsxs(Text, { color: "yellow", dimColor: true, children: ["Content truncated (", content.split("\n").length, " lines total, showing first ", MAX_LINES, " lines. Press Ctrl+O to expand."] }) }))] }))] }));
|
|
17
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { DiffBlock } from "wave-agent-sdk";
|
|
3
|
+
interface DiffViewerProps {
|
|
4
|
+
block: DiffBlock;
|
|
5
|
+
isExpanded?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const DiffViewer: React.FC<DiffViewerProps>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=DiffViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiffViewer.d.ts","sourceRoot":"","sources":["../../src/components/DiffViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,UAAU,eAAe;IACvB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAwCD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgRhD,CAAC"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { Text, Box } from "ink";
|
|
4
|
+
import { diffWords } from "diff";
|
|
5
|
+
// Render word-level diff
|
|
6
|
+
const renderWordLevelDiff = (removedLine, addedLine) => {
|
|
7
|
+
const changes = diffWords(removedLine, addedLine);
|
|
8
|
+
const removedParts = [];
|
|
9
|
+
const addedParts = [];
|
|
10
|
+
changes.forEach((part, index) => {
|
|
11
|
+
if (part.removed) {
|
|
12
|
+
removedParts.push(_jsx(Text, { color: "black", backgroundColor: "red", children: part.value }, `removed-${index}`));
|
|
13
|
+
}
|
|
14
|
+
else if (part.added) {
|
|
15
|
+
addedParts.push(_jsx(Text, { color: "black", backgroundColor: "green", children: part.value }, `added-${index}`));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
// Unchanged parts, need to display on both sides
|
|
19
|
+
removedParts.push(_jsx(Text, { color: "red", children: part.value }, `removed-unchanged-${index}`));
|
|
20
|
+
addedParts.push(_jsx(Text, { color: "green", children: part.value }, `added-unchanged-${index}`));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return { removedParts, addedParts };
|
|
24
|
+
};
|
|
25
|
+
export const DiffViewer = ({ block, isExpanded = false, }) => {
|
|
26
|
+
const { diffResult } = block;
|
|
27
|
+
const diffLines = useMemo(() => {
|
|
28
|
+
if (!diffResult)
|
|
29
|
+
return [];
|
|
30
|
+
const lines = [];
|
|
31
|
+
let originalLineNum = 1;
|
|
32
|
+
let modifiedLineNum = 1;
|
|
33
|
+
const maxContext = 3; // Show at most 3 lines of context
|
|
34
|
+
// Buffer for storing context
|
|
35
|
+
let contextBuffer = [];
|
|
36
|
+
let hasAnyChanges = false;
|
|
37
|
+
let afterChangeContext = 0;
|
|
38
|
+
// Temporarily store adjacent deleted and added lines for word-level comparison
|
|
39
|
+
let pendingRemovedLines = [];
|
|
40
|
+
const flushPendingLines = () => {
|
|
41
|
+
pendingRemovedLines.forEach((line) => {
|
|
42
|
+
lines.push({
|
|
43
|
+
content: line.content,
|
|
44
|
+
type: "removed",
|
|
45
|
+
lineNumber: line.lineNumber,
|
|
46
|
+
rawContent: line.rawContent,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
pendingRemovedLines = [];
|
|
50
|
+
};
|
|
51
|
+
diffResult.forEach((part) => {
|
|
52
|
+
const partLines = part.value.split("\n");
|
|
53
|
+
// Remove the last empty line (produced by split)
|
|
54
|
+
if (partLines[partLines.length - 1] === "") {
|
|
55
|
+
partLines.pop();
|
|
56
|
+
}
|
|
57
|
+
if (part.removed) {
|
|
58
|
+
// If this is the first change encountered, add preceding context
|
|
59
|
+
if (!hasAnyChanges) {
|
|
60
|
+
// Take the last few lines from the buffer as preceding context
|
|
61
|
+
const preContext = contextBuffer.slice(-maxContext);
|
|
62
|
+
if (contextBuffer.length > maxContext) {
|
|
63
|
+
lines.push({
|
|
64
|
+
content: "...",
|
|
65
|
+
type: "separator",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
lines.push(...preContext);
|
|
69
|
+
}
|
|
70
|
+
else if (afterChangeContext > maxContext) {
|
|
71
|
+
// If there's too much context after the previous change, add a separator
|
|
72
|
+
lines.push({
|
|
73
|
+
content: "...",
|
|
74
|
+
type: "separator",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// Temporarily store deleted lines, waiting for possible added lines for word-level comparison
|
|
78
|
+
partLines.forEach((line) => {
|
|
79
|
+
pendingRemovedLines.push({
|
|
80
|
+
content: `- ${line}`,
|
|
81
|
+
rawContent: line,
|
|
82
|
+
lineNumber: originalLineNum++,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
hasAnyChanges = true;
|
|
86
|
+
afterChangeContext = 0;
|
|
87
|
+
contextBuffer = []; // Clear buffer
|
|
88
|
+
}
|
|
89
|
+
else if (part.added) {
|
|
90
|
+
// If this is the first change encountered, add preceding context
|
|
91
|
+
if (!hasAnyChanges) {
|
|
92
|
+
const preContext = contextBuffer.slice(-maxContext);
|
|
93
|
+
if (contextBuffer.length > maxContext) {
|
|
94
|
+
lines.push({
|
|
95
|
+
content: "...",
|
|
96
|
+
type: "separator",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
lines.push(...preContext);
|
|
100
|
+
}
|
|
101
|
+
else if (afterChangeContext > maxContext) {
|
|
102
|
+
lines.push({
|
|
103
|
+
content: "...",
|
|
104
|
+
type: "separator",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// Process added lines, try to do word-level comparison with pending deleted lines
|
|
108
|
+
partLines.forEach((line, index) => {
|
|
109
|
+
if (index < pendingRemovedLines.length) {
|
|
110
|
+
// Has corresponding deleted line, perform word-level comparison
|
|
111
|
+
const removedLine = pendingRemovedLines[index];
|
|
112
|
+
const wordDiff = renderWordLevelDiff(removedLine.rawContent, line);
|
|
113
|
+
// Add deleted line (with word-level highlighting)
|
|
114
|
+
lines.push({
|
|
115
|
+
content: `- ${removedLine.rawContent}`,
|
|
116
|
+
type: "removed",
|
|
117
|
+
lineNumber: removedLine.lineNumber,
|
|
118
|
+
rawContent: removedLine.rawContent,
|
|
119
|
+
wordDiff: {
|
|
120
|
+
removedParts: wordDiff.removedParts,
|
|
121
|
+
addedParts: [],
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
// Add added line (with word-level highlighting)
|
|
125
|
+
lines.push({
|
|
126
|
+
content: `+ ${line}`,
|
|
127
|
+
type: "added",
|
|
128
|
+
lineNumber: modifiedLineNum++,
|
|
129
|
+
rawContent: line,
|
|
130
|
+
wordDiff: { removedParts: [], addedParts: wordDiff.addedParts },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// No corresponding deleted line, directly add the added line
|
|
135
|
+
lines.push({
|
|
136
|
+
content: `+ ${line}`,
|
|
137
|
+
type: "added",
|
|
138
|
+
lineNumber: modifiedLineNum++,
|
|
139
|
+
rawContent: line,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
// If there are more deleted lines than added lines, add remaining deleted lines
|
|
144
|
+
for (let i = partLines.length; i < pendingRemovedLines.length; i++) {
|
|
145
|
+
const removedLine = pendingRemovedLines[i];
|
|
146
|
+
lines.push({
|
|
147
|
+
content: removedLine.content,
|
|
148
|
+
type: "removed",
|
|
149
|
+
lineNumber: removedLine.lineNumber,
|
|
150
|
+
rawContent: removedLine.rawContent,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
pendingRemovedLines = []; // Clear pending deleted lines
|
|
154
|
+
hasAnyChanges = true;
|
|
155
|
+
afterChangeContext = 0;
|
|
156
|
+
contextBuffer = [];
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// Before processing unchanged lines, first clear pending deleted lines
|
|
160
|
+
flushPendingLines();
|
|
161
|
+
// Process unchanged lines
|
|
162
|
+
partLines.forEach((line) => {
|
|
163
|
+
const contextLine = {
|
|
164
|
+
content: ` ${line}`,
|
|
165
|
+
type: "unchanged",
|
|
166
|
+
lineNumber: originalLineNum,
|
|
167
|
+
};
|
|
168
|
+
if (hasAnyChanges) {
|
|
169
|
+
// If there are already changes, these are post-change context
|
|
170
|
+
if (afterChangeContext < maxContext) {
|
|
171
|
+
lines.push(contextLine);
|
|
172
|
+
afterChangeContext++;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// If no changes yet, add to buffer
|
|
177
|
+
contextBuffer.push(contextLine);
|
|
178
|
+
}
|
|
179
|
+
originalLineNum++;
|
|
180
|
+
modifiedLineNum++;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
// Handle remaining deleted lines at the end
|
|
185
|
+
flushPendingLines();
|
|
186
|
+
// Only limit displayed lines in collapsed state
|
|
187
|
+
if (!isExpanded) {
|
|
188
|
+
const MAX_DISPLAY_LINES = 50;
|
|
189
|
+
if (lines.length > MAX_DISPLAY_LINES) {
|
|
190
|
+
const truncatedLines = lines.slice(0, MAX_DISPLAY_LINES);
|
|
191
|
+
truncatedLines.push({
|
|
192
|
+
content: `... (${lines.length - MAX_DISPLAY_LINES} more lines truncated, press Ctrl+O to expand)`,
|
|
193
|
+
type: "separator",
|
|
194
|
+
});
|
|
195
|
+
return truncatedLines;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return lines;
|
|
199
|
+
}, [diffResult, isExpanded]);
|
|
200
|
+
if (!diffResult || diffResult.length === 0) {
|
|
201
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { color: "gray", children: "No changes detected" }) }));
|
|
202
|
+
}
|
|
203
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(Box, { flexDirection: "column", children: _jsx(Box, { flexDirection: "column", children: diffLines.map((line, index) => {
|
|
204
|
+
// If has word-level diff, render special effects
|
|
205
|
+
if (line.wordDiff) {
|
|
206
|
+
const prefix = line.type === "removed" ? "- " : "+ ";
|
|
207
|
+
const parts = line.type === "removed"
|
|
208
|
+
? line.wordDiff.removedParts
|
|
209
|
+
: line.wordDiff.addedParts;
|
|
210
|
+
return (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: line.type === "removed" ? "red" : "green", children: prefix }), _jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: parts })] }, index));
|
|
211
|
+
}
|
|
212
|
+
// Normal rendering
|
|
213
|
+
return (_jsx(Text, { color: line.type === "added"
|
|
214
|
+
? "green"
|
|
215
|
+
: line.type === "removed"
|
|
216
|
+
? "red"
|
|
217
|
+
: line.type === "separator"
|
|
218
|
+
? "gray"
|
|
219
|
+
: "white", dimColor: line.type === "separator", children: line.content }, index));
|
|
220
|
+
}) }) }) }));
|
|
221
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface FileItem {
|
|
3
|
+
path: string;
|
|
4
|
+
type: "file" | "directory";
|
|
5
|
+
}
|
|
6
|
+
export interface FileSelectorProps {
|
|
7
|
+
files: FileItem[];
|
|
8
|
+
searchQuery: string;
|
|
9
|
+
onSelect: (filePath: string) => void;
|
|
10
|
+
onCancel: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const FileSelector: React.FC<FileSelectorProps>;
|
|
13
|
+
//# sourceMappingURL=FileSelector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSelector.d.ts","sourceRoot":"","sources":["../../src/components/FileSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAyHpD,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
|
|
5
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6
|
+
useInput((input, key) => {
|
|
7
|
+
if (key.return) {
|
|
8
|
+
if (files.length > 0 && selectedIndex < files.length) {
|
|
9
|
+
onSelect(files[selectedIndex].path);
|
|
10
|
+
}
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (key.escape) {
|
|
14
|
+
onCancel();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (key.upArrow) {
|
|
18
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (key.downArrow) {
|
|
22
|
+
setSelectedIndex(Math.min(files.length - 1, selectedIndex + 1));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
if (files.length === 0) {
|
|
27
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", padding: 1, marginBottom: 1, children: [_jsxs(Text, { color: "yellow", children: ["\uD83D\uDCC1 No files found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
|
|
28
|
+
}
|
|
29
|
+
const maxDisplay = 10;
|
|
30
|
+
// Calculate display window start and end positions
|
|
31
|
+
const getDisplayWindow = () => {
|
|
32
|
+
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(maxDisplay / 2), files.length - maxDisplay));
|
|
33
|
+
const endIndex = Math.min(files.length, startIndex + maxDisplay);
|
|
34
|
+
const adjustedStartIndex = Math.max(0, endIndex - maxDisplay);
|
|
35
|
+
return {
|
|
36
|
+
startIndex: adjustedStartIndex,
|
|
37
|
+
endIndex: endIndex,
|
|
38
|
+
displayFiles: files.slice(adjustedStartIndex, endIndex),
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const { startIndex, endIndex, displayFiles } = getDisplayWindow();
|
|
42
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", padding: 1, marginBottom: 1, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["\uD83D\uDCC1 Select File/Directory", " ", searchQuery && `(filtering: "${searchQuery}")`] }), startIndex > 0 && (_jsxs(Text, { dimColor: true, children: ["... ", startIndex, " more files above"] })), displayFiles.map((fileItem, displayIndex) => {
|
|
43
|
+
const actualIndex = startIndex + displayIndex;
|
|
44
|
+
const isSelected = actualIndex === selectedIndex;
|
|
45
|
+
const icon = fileItem.type === "directory" ? "📁" : "📄";
|
|
46
|
+
return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "cyan" : undefined, children: [isSelected ? "▶ " : " ", icon, " ", fileItem.path] }) }, fileItem.path));
|
|
47
|
+
}), endIndex < files.length && (_jsxs(Text, { dimColor: true, children: ["... ", files.length - endIndex, " more files below"] })), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select, Escape to cancel" }), _jsxs(Text, { dimColor: true, children: ["File ", selectedIndex + 1, " of ", files.length] })] })] }));
|
|
48
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { McpServerStatus, SlashCommand } from "wave-agent-sdk";
|
|
3
|
+
export declare const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, ! for bash history, # to add memory)...";
|
|
4
|
+
export declare const INPUT_PLACEHOLDER_TEXT_PREFIX: string;
|
|
5
|
+
export interface InputBoxProps {
|
|
6
|
+
isLoading?: boolean;
|
|
7
|
+
isCommandRunning?: boolean;
|
|
8
|
+
workdir?: string;
|
|
9
|
+
userInputHistory?: string[];
|
|
10
|
+
sendMessage?: (message: string, images?: Array<{
|
|
11
|
+
path: string;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
}>) => void;
|
|
14
|
+
abortMessage?: () => void;
|
|
15
|
+
saveMemory?: (message: string, type: "project" | "user") => Promise<void>;
|
|
16
|
+
mcpServers?: McpServerStatus[];
|
|
17
|
+
connectMcpServer?: (serverName: string) => Promise<boolean>;
|
|
18
|
+
disconnectMcpServer?: (serverName: string) => Promise<boolean>;
|
|
19
|
+
slashCommands?: SlashCommand[];
|
|
20
|
+
hasSlashCommand?: (commandId: string) => boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const InputBox: React.FC<InputBoxProps>;
|
|
23
|
+
//# sourceMappingURL=InputBox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAgBrD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,yGACqE,CAAC;AAEzG,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,KAC/C,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAClD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAuQ5C,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback } from "react";
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
|
+
import { FileSelector } from "./FileSelector.js";
|
|
5
|
+
import { CommandSelector } from "./CommandSelector.js";
|
|
6
|
+
import { BashHistorySelector } from "./BashHistorySelector.js";
|
|
7
|
+
import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
|
|
8
|
+
import { BashShellManager } from "./BashShellManager.js";
|
|
9
|
+
import { McpManager } from "./McpManager.js";
|
|
10
|
+
import { useInputState } from "../hooks/useInputState.js";
|
|
11
|
+
import { useFileSelector } from "../hooks/useFileSelector.js";
|
|
12
|
+
import { useCommandSelector } from "../hooks/useCommandSelector.js";
|
|
13
|
+
import { useBashHistorySelector } from "../hooks/useBashHistorySelector.js";
|
|
14
|
+
import { useMemoryTypeSelector } from "../hooks/useMemoryTypeSelector.js";
|
|
15
|
+
import { useInputHistory } from "../hooks/useInputHistory.js";
|
|
16
|
+
import { useInputKeyboardHandler } from "../hooks/useInputKeyboardHandler.js";
|
|
17
|
+
import { useImageManager } from "../hooks/useImageManager.js";
|
|
18
|
+
export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, ! for bash history, # to add memory)...";
|
|
19
|
+
export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
|
|
20
|
+
export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, saveMemory = async () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
|
|
21
|
+
// Get current working directory
|
|
22
|
+
const currentWorkdir = workdir || process.cwd();
|
|
23
|
+
// Bash shell manager state
|
|
24
|
+
const [showBashManager, setShowBashManager] = useState(false);
|
|
25
|
+
// MCP manager state
|
|
26
|
+
const [showMcpManager, setShowMcpManager] = useState(false);
|
|
27
|
+
// Basic input state
|
|
28
|
+
const { inputText, setInputText, cursorPosition, setCursorPosition, insertTextAtCursor, deleteCharAtCursor, clearInput, moveCursorLeft, moveCursorRight, moveCursorToStart, moveCursorToEnd, } = useInputState();
|
|
29
|
+
// File selector functionality
|
|
30
|
+
const { showFileSelector, filteredFiles, searchQuery, activateFileSelector, handleFileSelect: handleFileSelectorSelect, handleCancelFileSelect, updateSearchQuery, checkForAtDeletion, atPosition, } = useFileSelector();
|
|
31
|
+
// Command selector functionality
|
|
32
|
+
const { showCommandSelector, commandSearchQuery, activateCommandSelector, handleCommandSelect: handleCommandSelectorSelect, handleCommandInsert: handleCommandSelectorInsert, handleCancelCommandSelect, updateCommandSearchQuery, checkForSlashDeletion, slashPosition, } = useCommandSelector({
|
|
33
|
+
onShowBashManager: () => setShowBashManager(true),
|
|
34
|
+
onShowMcpManager: () => setShowMcpManager(true),
|
|
35
|
+
sendMessage: async (content) => {
|
|
36
|
+
await sendMessage(content);
|
|
37
|
+
},
|
|
38
|
+
hasSlashCommand,
|
|
39
|
+
});
|
|
40
|
+
// Bash history selector functionality
|
|
41
|
+
const { showBashHistorySelector, bashHistorySearchQuery, activateBashHistorySelector, handleBashHistorySelect: handleBashHistorySelectorSelect, handleBashHistoryExecute, handleCancelBashHistorySelect, updateBashHistorySearchQuery, checkForExclamationDeletion, exclamationPosition, } = useBashHistorySelector();
|
|
42
|
+
// Memory type selector functionality
|
|
43
|
+
const { showMemoryTypeSelector, memoryMessage, activateMemoryTypeSelector, handleMemoryTypeSelect: handleMemoryTypeSelectorSelect, handleCancelMemoryTypeSelect, } = useMemoryTypeSelector();
|
|
44
|
+
// Input history functionality
|
|
45
|
+
const { resetHistoryNavigation, navigateHistory } = useInputHistory({
|
|
46
|
+
userInputHistory,
|
|
47
|
+
});
|
|
48
|
+
// Image management functionality (includes clipboard paste)
|
|
49
|
+
const { attachedImages, clearImages, handlePasteImage } = useImageManager(insertTextAtCursor);
|
|
50
|
+
// Keyboard handling
|
|
51
|
+
const { handleFileSelect, handleCommandSelect, handleBashHistorySelect, handleBashHistoryExecute: keyboardHandleBashHistoryExecute, handleMemoryTypeSelect, } = useInputKeyboardHandler({
|
|
52
|
+
inputText,
|
|
53
|
+
setInputText,
|
|
54
|
+
cursorPosition,
|
|
55
|
+
setCursorPosition,
|
|
56
|
+
moveCursorLeft,
|
|
57
|
+
moveCursorRight,
|
|
58
|
+
moveCursorToStart,
|
|
59
|
+
moveCursorToEnd,
|
|
60
|
+
deleteCharAtCursor,
|
|
61
|
+
insertTextAtCursor,
|
|
62
|
+
clearInput,
|
|
63
|
+
resetHistoryNavigation,
|
|
64
|
+
navigateHistory,
|
|
65
|
+
handlePasteImage,
|
|
66
|
+
attachedImages,
|
|
67
|
+
clearImages,
|
|
68
|
+
showFileSelector,
|
|
69
|
+
activateFileSelector,
|
|
70
|
+
handleFileSelect: handleFileSelectorSelect,
|
|
71
|
+
handleCancelFileSelect,
|
|
72
|
+
updateSearchQuery,
|
|
73
|
+
checkForAtDeletion,
|
|
74
|
+
atPosition,
|
|
75
|
+
showCommandSelector,
|
|
76
|
+
activateCommandSelector,
|
|
77
|
+
handleCommandSelect: handleCommandSelectorSelect,
|
|
78
|
+
handleCommandInsert: handleCommandSelectorInsert,
|
|
79
|
+
handleCancelCommandSelect,
|
|
80
|
+
updateCommandSearchQuery,
|
|
81
|
+
checkForSlashDeletion,
|
|
82
|
+
slashPosition,
|
|
83
|
+
showBashHistorySelector,
|
|
84
|
+
activateBashHistorySelector,
|
|
85
|
+
handleBashHistorySelect: handleBashHistorySelectorSelect,
|
|
86
|
+
handleBashHistoryExecute,
|
|
87
|
+
handleCancelBashHistorySelect,
|
|
88
|
+
updateBashHistorySearchQuery,
|
|
89
|
+
checkForExclamationDeletion,
|
|
90
|
+
exclamationPosition,
|
|
91
|
+
showMemoryTypeSelector,
|
|
92
|
+
activateMemoryTypeSelector,
|
|
93
|
+
handleMemoryTypeSelect: handleMemoryTypeSelectorSelect,
|
|
94
|
+
showBashManager,
|
|
95
|
+
showMcpManager,
|
|
96
|
+
isCommandRunning,
|
|
97
|
+
isLoading,
|
|
98
|
+
sendMessage,
|
|
99
|
+
abortMessage,
|
|
100
|
+
saveMemory,
|
|
101
|
+
});
|
|
102
|
+
const isPlaceholder = !inputText;
|
|
103
|
+
const placeholderText = INPUT_PLACEHOLDER_TEXT;
|
|
104
|
+
// Create adapter function for CommandSelector
|
|
105
|
+
const handleCommandInsert = useCallback((command) => {
|
|
106
|
+
const result = handleCommandSelectorInsert(command, inputText, cursorPosition);
|
|
107
|
+
setInputText(result.newInput);
|
|
108
|
+
setCursorPosition(result.newCursorPosition);
|
|
109
|
+
}, [
|
|
110
|
+
handleCommandSelectorInsert,
|
|
111
|
+
inputText,
|
|
112
|
+
cursorPosition,
|
|
113
|
+
setInputText,
|
|
114
|
+
setCursorPosition,
|
|
115
|
+
]);
|
|
116
|
+
// Split text into three parts: before cursor, cursor position, after cursor
|
|
117
|
+
const displayText = isPlaceholder ? placeholderText : inputText;
|
|
118
|
+
const beforeCursor = displayText.substring(0, cursorPosition);
|
|
119
|
+
const atCursor = cursorPosition < displayText.length ? displayText[cursorPosition] : " ";
|
|
120
|
+
const afterCursor = displayText.substring(cursorPosition + 1);
|
|
121
|
+
// Always show cursor, allow user to continue input during loading
|
|
122
|
+
const shouldShowCursor = true;
|
|
123
|
+
return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showBashHistorySelector && (_jsx(BashHistorySelector, { searchQuery: bashHistorySearchQuery, workdir: currentWorkdir, onSelect: handleBashHistorySelect, onExecute: keyboardHandleBashHistoryExecute, onCancel: handleCancelBashHistorySelect })), showMemoryTypeSelector && (_jsx(MemoryTypeSelector, { message: memoryMessage, onSelect: handleMemoryTypeSelect, onCancel: handleCancelMemoryTypeSelect })), showBashManager && (_jsx(BashShellManager, { onCancel: () => setShowBashManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showBashManager || showMcpManager || (_jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: _jsx(Box, { width: "100%", flexDirection: "row", justifyContent: "space-between", children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }) }))] }));
|
|
124
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { McpServerStatus } from "wave-agent-sdk";
|
|
3
|
+
export interface McpManagerProps {
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
servers: McpServerStatus[];
|
|
6
|
+
onConnectServer: (serverName: string) => Promise<boolean>;
|
|
7
|
+
onDisconnectServer: (serverName: string) => Promise<boolean>;
|
|
8
|
+
}
|
|
9
|
+
export declare const McpManager: React.FC<McpManagerProps>;
|
|
10
|
+
//# sourceMappingURL=McpManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpManager.d.ts","sourceRoot":"","sources":["../../src/components/McpManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA4ThD,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
export const McpManager = ({ onCancel, servers, onConnectServer, onDisconnectServer, }) => {
|
|
5
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6
|
+
const [viewMode, setViewMode] = useState("list");
|
|
7
|
+
// Dynamically calculate selectedServer based on selectedIndex and servers
|
|
8
|
+
const selectedServer = viewMode === "detail" &&
|
|
9
|
+
servers.length > 0 &&
|
|
10
|
+
selectedIndex < servers.length
|
|
11
|
+
? servers[selectedIndex]
|
|
12
|
+
: null;
|
|
13
|
+
const formatTime = (timestamp) => {
|
|
14
|
+
return new Date(timestamp).toLocaleTimeString();
|
|
15
|
+
};
|
|
16
|
+
const getStatusColor = (status) => {
|
|
17
|
+
switch (status) {
|
|
18
|
+
case "connected":
|
|
19
|
+
return "green";
|
|
20
|
+
case "connecting":
|
|
21
|
+
return "yellow";
|
|
22
|
+
case "error":
|
|
23
|
+
return "red";
|
|
24
|
+
default:
|
|
25
|
+
return "gray";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const getStatusIcon = (status) => {
|
|
29
|
+
switch (status) {
|
|
30
|
+
case "connected":
|
|
31
|
+
return "✓";
|
|
32
|
+
case "connecting":
|
|
33
|
+
return "⟳";
|
|
34
|
+
case "error":
|
|
35
|
+
return "✗";
|
|
36
|
+
default:
|
|
37
|
+
return "○";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const handleConnect = async (serverName) => {
|
|
41
|
+
await onConnectServer(serverName);
|
|
42
|
+
};
|
|
43
|
+
const handleDisconnect = async (serverName) => {
|
|
44
|
+
await onDisconnectServer(serverName);
|
|
45
|
+
};
|
|
46
|
+
useInput((input, key) => {
|
|
47
|
+
if (viewMode === "list") {
|
|
48
|
+
// List mode navigation
|
|
49
|
+
if (key.return) {
|
|
50
|
+
if (servers.length > 0 && selectedIndex < servers.length) {
|
|
51
|
+
setViewMode("detail");
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (key.escape) {
|
|
56
|
+
onCancel();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (key.upArrow) {
|
|
60
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (key.downArrow) {
|
|
64
|
+
setSelectedIndex(Math.min(servers.length - 1, selectedIndex + 1));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Hotkeys for server actions
|
|
68
|
+
if (input === "c" &&
|
|
69
|
+
servers.length > 0 &&
|
|
70
|
+
selectedIndex < servers.length) {
|
|
71
|
+
const server = servers[selectedIndex];
|
|
72
|
+
if (server.status === "disconnected" || server.status === "error") {
|
|
73
|
+
handleConnect(server.name);
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (input === "d" &&
|
|
78
|
+
servers.length > 0 &&
|
|
79
|
+
selectedIndex < servers.length) {
|
|
80
|
+
const server = servers[selectedIndex];
|
|
81
|
+
if (server.status === "connected") {
|
|
82
|
+
handleDisconnect(server.name);
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (viewMode === "detail") {
|
|
88
|
+
// Detail mode navigation
|
|
89
|
+
if (key.escape) {
|
|
90
|
+
setViewMode("list");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (selectedServer) {
|
|
94
|
+
if (input === "c" &&
|
|
95
|
+
(selectedServer.status === "disconnected" ||
|
|
96
|
+
selectedServer.status === "error")) {
|
|
97
|
+
handleConnect(selectedServer.name);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (input === "d" && selectedServer.status === "connected") {
|
|
101
|
+
handleDisconnect(selectedServer.name);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
if (viewMode === "detail" && selectedServer) {
|
|
108
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", padding: 1, gap: 1, marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["MCP Server Details: ", selectedServer.name] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", _jsxs(Text, { color: getStatusColor(selectedServer.status), children: [getStatusIcon(selectedServer.status), " ", selectedServer.status] })] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Command:" }), " ", selectedServer.config.command] }) }), selectedServer.config.args && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Args:" }), " ", selectedServer.config.args.join(" ")] }) })), selectedServer.toolCount !== undefined && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Tools:" }), " ", selectedServer.toolCount, " ", "tools"] }) })), selectedServer.capabilities && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Capabilities:" }), " ", selectedServer.capabilities.join(", ")] }) })), selectedServer.lastConnected && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Last Connected:" }), " ", formatTime(selectedServer.lastConnected)] }) })), selectedServer.error && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "red", children: "Error:" }), " ", selectedServer.error] }) }))] }), selectedServer.config.env &&
|
|
109
|
+
Object.keys(selectedServer.config.env).length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "blue", bold: true, children: "Environment Variables:" }), _jsx(Box, { borderStyle: "single", borderColor: "blue", padding: 1, children: Object.entries(selectedServer.config.env).map(([key, value]) => (_jsxs(Text, { children: [key, "=", value] }, key))) })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [selectedServer.status === "disconnected" ||
|
|
110
|
+
selectedServer.status === "error"
|
|
111
|
+
? "c to connect · "
|
|
112
|
+
: "", selectedServer.status === "connected" ? "d to disconnect · " : "", "Esc to go back"] }) })] }));
|
|
113
|
+
}
|
|
114
|
+
if (servers.length === 0) {
|
|
115
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", padding: 1, marginBottom: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Manage MCP servers" }), _jsx(Text, { children: "No MCP servers configured" }), _jsx(Text, { dimColor: true, children: "Create a .mcp.json file in your project root to add servers" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
|
|
116
|
+
}
|
|
117
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", padding: 1, gap: 1, marginBottom: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Manage MCP servers" }) }), _jsx(Text, { dimColor: true, children: "Select a server to view details" }), servers.map((server, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "cyan" : undefined, children: [index === selectedIndex ? "▶ " : " ", index + 1, ".", " ", _jsx(Text, { color: getStatusColor(server.status), children: getStatusIcon(server.status) }), " ", server.name, server.status === "connected" && server.toolCount && (_jsxs(Text, { color: "green", children: [" \u00B7 ", server.toolCount, " tools"] }))] }), index === selectedIndex && (_jsxs(Box, { marginLeft: 4, flexDirection: "column", children: [_jsxs(Text, { color: "gray", dimColor: true, children: [server.config.command, server.config.args ? ` ${server.config.args.join(" ")}` : ""] }), server.lastConnected && (_jsxs(Text, { color: "gray", dimColor: true, children: ["Last connected: ", formatTime(server.lastConnected)] }))] }))] }, server.name))), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["\u2191/\u2193 to select \u00B7 Enter to view \u00B7", " ", servers[selectedIndex]?.status === "disconnected" ||
|
|
118
|
+
servers[selectedIndex]?.status === "error"
|
|
119
|
+
? "c to connect · "
|
|
120
|
+
: "", servers[selectedIndex]?.status === "connected"
|
|
121
|
+
? "d to disconnect · "
|
|
122
|
+
: "", "Esc to close"] }) })] }));
|
|
123
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryDisplay.d.ts","sourceRoot":"","sources":["../../src/components/MemoryDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,UAAU,kBAAkB;IAC1B,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqDtD,CAAC"}
|