wave-code 0.2.1 → 0.5.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/commands/plugin/disable.d.ts +2 -1
- package/dist/commands/plugin/disable.d.ts.map +1 -1
- package/dist/commands/plugin/disable.js +3 -2
- package/dist/commands/plugin/enable.d.ts +2 -1
- package/dist/commands/plugin/enable.d.ts.map +1 -1
- package/dist/commands/plugin/enable.js +3 -2
- package/dist/commands/plugin/install.d.ts +2 -1
- package/dist/commands/plugin/install.d.ts.map +1 -1
- package/dist/commands/plugin/list.d.ts.map +1 -1
- package/dist/commands/plugin/list.js +15 -3
- package/dist/commands/plugin/marketplace.d.ts +3 -0
- package/dist/commands/plugin/marketplace.d.ts.map +1 -1
- package/dist/commands/plugin/marketplace.js +15 -1
- package/dist/commands/plugin/uninstall.d.ts +4 -0
- package/dist/commands/plugin/uninstall.d.ts.map +1 -0
- package/dist/commands/plugin/uninstall.js +29 -0
- package/dist/commands/plugin/update.d.ts +4 -0
- package/dist/commands/plugin/update.d.ts.map +1 -0
- package/dist/commands/plugin/update.js +15 -0
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +2 -2
- package/dist/components/CommandSelector.d.ts.map +1 -1
- package/dist/components/CommandSelector.js +9 -3
- package/dist/components/Confirmation.d.ts.map +1 -1
- package/dist/components/Confirmation.js +73 -20
- package/dist/components/DiffDisplay.d.ts +0 -1
- package/dist/components/DiffDisplay.d.ts.map +1 -1
- package/dist/components/DiffDisplay.js +38 -59
- package/dist/components/DiscoverView.d.ts +3 -0
- package/dist/components/DiscoverView.d.ts.map +1 -0
- package/dist/components/DiscoverView.js +25 -0
- package/dist/components/FileSelector.js +1 -1
- package/dist/components/HistorySearch.d.ts +8 -0
- package/dist/components/HistorySearch.d.ts.map +1 -0
- package/dist/components/HistorySearch.js +67 -0
- package/dist/components/InputBox.d.ts +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +29 -19
- package/dist/components/InstalledView.d.ts +3 -0
- package/dist/components/InstalledView.d.ts.map +1 -0
- package/dist/components/InstalledView.js +30 -0
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown.js +24 -10
- package/dist/components/MarketplaceAddForm.d.ts +3 -0
- package/dist/components/MarketplaceAddForm.d.ts.map +1 -0
- package/dist/components/MarketplaceAddForm.js +26 -0
- package/dist/components/MarketplaceDetail.d.ts +3 -0
- package/dist/components/MarketplaceDetail.d.ts.map +1 -0
- package/dist/components/MarketplaceDetail.js +38 -0
- package/dist/components/MarketplaceList.d.ts +9 -0
- package/dist/components/MarketplaceList.d.ts.map +1 -0
- package/dist/components/MarketplaceList.js +16 -0
- package/dist/components/MarketplaceView.d.ts +3 -0
- package/dist/components/MarketplaceView.d.ts.map +1 -0
- package/dist/components/MarketplaceView.js +28 -0
- package/dist/components/PlanDisplay.d.ts.map +1 -1
- package/dist/components/PlanDisplay.js +2 -2
- package/dist/components/PluginDetail.d.ts +3 -0
- package/dist/components/PluginDetail.d.ts.map +1 -0
- package/dist/components/PluginDetail.js +63 -0
- package/dist/components/PluginList.d.ts +14 -0
- package/dist/components/PluginList.d.ts.map +1 -0
- package/dist/components/PluginList.js +12 -0
- package/dist/components/PluginManagerShell.d.ts +5 -0
- package/dist/components/PluginManagerShell.d.ts.map +1 -0
- package/dist/components/PluginManagerShell.js +89 -0
- package/dist/components/PluginManagerTypes.d.ts +33 -0
- package/dist/components/PluginManagerTypes.d.ts.map +1 -0
- package/dist/components/PluginManagerTypes.js +1 -0
- package/dist/components/RewindCommand.d.ts +9 -0
- package/dist/components/RewindCommand.d.ts.map +1 -0
- package/dist/components/RewindCommand.js +42 -0
- package/dist/components/SessionSelector.d.ts +11 -0
- package/dist/components/SessionSelector.d.ts.map +1 -0
- package/dist/components/SessionSelector.js +38 -0
- package/dist/components/SubagentBlock.d.ts.map +1 -1
- package/dist/components/SubagentBlock.js +24 -1
- package/dist/components/TaskManager.d.ts +6 -0
- package/dist/components/TaskManager.d.ts.map +1 -0
- package/dist/components/TaskManager.js +114 -0
- package/dist/components/ToolResultDisplay.d.ts.map +1 -1
- package/dist/components/ToolResultDisplay.js +2 -1
- package/dist/contexts/PluginManagerContext.d.ts +4 -0
- package/dist/contexts/PluginManagerContext.d.ts.map +1 -0
- package/dist/contexts/PluginManagerContext.js +9 -0
- package/dist/contexts/useChat.d.ts +7 -4
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +37 -12
- package/dist/hooks/useInputManager.d.ts +8 -16
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +39 -55
- package/dist/hooks/usePluginManager.d.ts +3 -0
- package/dist/hooks/usePluginManager.d.ts.map +1 -0
- package/dist/hooks/usePluginManager.js +227 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +150 -177
- package/dist/managers/InputManager.d.ts +18 -26
- package/dist/managers/InputManager.d.ts.map +1 -1
- package/dist/managers/InputManager.js +93 -119
- package/dist/plugin-manager-cli.d.ts +6 -0
- package/dist/plugin-manager-cli.d.ts.map +1 -0
- package/dist/plugin-manager-cli.js +12 -0
- package/dist/session-selector-cli.d.ts +2 -0
- package/dist/session-selector-cli.d.ts.map +1 -0
- package/dist/session-selector-cli.js +25 -0
- package/package.json +9 -5
- package/src/commands/plugin/disable.ts +7 -3
- package/src/commands/plugin/enable.ts +7 -3
- package/src/commands/plugin/install.ts +2 -1
- package/src/commands/plugin/list.ts +21 -3
- package/src/commands/plugin/marketplace.ts +17 -1
- package/src/commands/plugin/uninstall.ts +39 -0
- package/src/commands/plugin/update.ts +19 -0
- package/src/components/ChatInterface.tsx +2 -1
- package/src/components/CommandSelector.tsx +10 -3
- package/src/components/Confirmation.tsx +115 -25
- package/src/components/DiffDisplay.tsx +60 -106
- package/src/components/DiscoverView.tsx +31 -0
- package/src/components/FileSelector.tsx +1 -1
- package/src/components/HistorySearch.tsx +148 -0
- package/src/components/InputBox.tsx +51 -34
- package/src/components/InstalledView.tsx +61 -0
- package/src/components/Markdown.tsx +44 -28
- package/src/components/MarketplaceAddForm.tsx +39 -0
- package/src/components/MarketplaceDetail.tsx +79 -0
- package/src/components/MarketplaceList.tsx +52 -0
- package/src/components/MarketplaceView.tsx +43 -0
- package/src/components/PlanDisplay.tsx +14 -19
- package/src/components/PluginDetail.tsx +147 -0
- package/src/components/PluginList.tsx +51 -0
- package/src/components/PluginManagerShell.tsx +189 -0
- package/src/components/PluginManagerTypes.ts +47 -0
- package/src/components/RewindCommand.tsx +114 -0
- package/src/components/SessionSelector.tsx +127 -0
- package/src/components/SubagentBlock.tsx +34 -1
- package/src/components/{BashShellManager.tsx → TaskManager.tsx} +79 -75
- package/src/components/ToolResultDisplay.tsx +6 -2
- package/src/contexts/PluginManagerContext.ts +15 -0
- package/src/contexts/useChat.tsx +51 -20
- package/src/hooks/useInputManager.ts +39 -71
- package/src/hooks/usePluginManager.ts +302 -0
- package/src/index.ts +241 -280
- package/src/managers/InputManager.ts +113 -162
- package/src/plugin-manager-cli.tsx +13 -0
- package/src/session-selector-cli.tsx +37 -0
- package/dist/components/BashHistorySelector.d.ts +0 -11
- package/dist/components/BashHistorySelector.d.ts.map +0 -1
- package/dist/components/BashHistorySelector.js +0 -93
- package/dist/components/BashShellManager.d.ts +0 -6
- package/dist/components/BashShellManager.d.ts.map +0 -1
- package/dist/components/BashShellManager.js +0 -116
- package/dist/hooks/usePagination.d.ts +0 -20
- package/dist/hooks/usePagination.d.ts.map +0 -1
- package/dist/hooks/usePagination.js +0 -168
- package/src/components/BashHistorySelector.tsx +0 -181
- package/src/hooks/usePagination.ts +0 -203
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useMemo } from "react";
|
|
3
|
-
import { Box, Text
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
4
|
import { WRITE_TOOL_NAME, EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME, } from "wave-agent-sdk";
|
|
5
5
|
import { transformToolBlockToChanges } from "../utils/toolParameterTransforms.js";
|
|
6
6
|
import { diffLines, diffWords } from "diff";
|
|
7
|
-
export const DiffDisplay = ({ toolName, parameters,
|
|
8
|
-
const { stdout } = useStdout();
|
|
9
|
-
const maxHeight = useMemo(() => {
|
|
10
|
-
return Math.max(5, (stdout?.rows || 24) - 20);
|
|
11
|
-
}, [stdout?.rows]);
|
|
7
|
+
export const DiffDisplay = ({ toolName, parameters, }) => {
|
|
12
8
|
const showDiff = toolName &&
|
|
13
9
|
[WRITE_TOOL_NAME, EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME].includes(toolName);
|
|
14
10
|
// Diff detection and transformation using typed parameters
|
|
@@ -58,7 +54,7 @@ export const DiffDisplay = ({ toolName, parameters, isExpanded = false, }) => {
|
|
|
58
54
|
};
|
|
59
55
|
}
|
|
60
56
|
};
|
|
61
|
-
// Render expanded diff display
|
|
57
|
+
// Render expanded diff display
|
|
62
58
|
const renderExpandedDiff = () => {
|
|
63
59
|
try {
|
|
64
60
|
if (changes.length === 0)
|
|
@@ -68,8 +64,8 @@ export const DiffDisplay = ({ toolName, parameters, isExpanded = false, }) => {
|
|
|
68
64
|
try {
|
|
69
65
|
// Get line-level diff to understand the structure
|
|
70
66
|
const lineDiffs = diffLines(change.oldContent || "", change.newContent || "");
|
|
67
|
+
// Process line diffs
|
|
71
68
|
const diffElements = [];
|
|
72
|
-
// Process line diffs and apply word-level diff to changed lines
|
|
73
69
|
lineDiffs.forEach((part, partIndex) => {
|
|
74
70
|
if (part.added) {
|
|
75
71
|
const lines = part.value
|
|
@@ -97,41 +93,28 @@ export const DiffDisplay = ({ toolName, parameters, isExpanded = false, }) => {
|
|
|
97
93
|
});
|
|
98
94
|
}
|
|
99
95
|
});
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// Extract the text content from the removed and added lines
|
|
115
|
-
const removedText = extractTextFromElement(current);
|
|
116
|
-
const addedText = extractTextFromElement(next);
|
|
117
|
-
if (removedText && addedText) {
|
|
118
|
-
// Apply word-level diff
|
|
119
|
-
const { removedParts, addedParts } = renderWordLevelDiff(removedText, addedText, `word-${changeIndex}-${i}`);
|
|
120
|
-
allElements.push(_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "red", children: "-" }), removedParts] }, `word-diff-removed-${changeIndex}-${i}`));
|
|
121
|
-
allElements.push(_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "green", children: "+" }), addedParts] }, `word-diff-added-${changeIndex}-${i}`));
|
|
122
|
-
i += 2; // Skip the next element since we processed it
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// Fallback to original elements
|
|
126
|
-
allElements.push(current);
|
|
127
|
-
i += 1;
|
|
128
|
-
}
|
|
96
|
+
// If it's a single line change (one removed, one added), use word-level diff
|
|
97
|
+
if (diffElements.length === 2 &&
|
|
98
|
+
React.isValidElement(diffElements[0]) &&
|
|
99
|
+
React.isValidElement(diffElements[1]) &&
|
|
100
|
+
typeof diffElements[0].key === "string" &&
|
|
101
|
+
diffElements[0].key.includes("remove-") &&
|
|
102
|
+
typeof diffElements[1].key === "string" &&
|
|
103
|
+
diffElements[1].key.includes("add-")) {
|
|
104
|
+
const removedText = extractTextFromElement(diffElements[0]);
|
|
105
|
+
const addedText = extractTextFromElement(diffElements[1]);
|
|
106
|
+
if (removedText && addedText) {
|
|
107
|
+
const { removedParts, addedParts } = renderWordLevelDiff(removedText, addedText, `word-${changeIndex}`);
|
|
108
|
+
allElements.push(_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "red", children: "-" }), removedParts] }, `word-diff-removed-${changeIndex}`));
|
|
109
|
+
allElements.push(_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "green", children: "+" }), addedParts] }, `word-diff-added-${changeIndex}`));
|
|
129
110
|
}
|
|
130
111
|
else {
|
|
131
|
-
allElements.push(
|
|
132
|
-
i += 1;
|
|
112
|
+
allElements.push(...diffElements);
|
|
133
113
|
}
|
|
134
114
|
}
|
|
115
|
+
else {
|
|
116
|
+
allElements.push(...diffElements);
|
|
117
|
+
}
|
|
135
118
|
}
|
|
136
119
|
catch (error) {
|
|
137
120
|
console.warn(`Error rendering diff for change ${changeIndex}:`, error);
|
|
@@ -139,35 +122,31 @@ export const DiffDisplay = ({ toolName, parameters, isExpanded = false, }) => {
|
|
|
139
122
|
allElements.push(_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "red", children: ["-", change.oldContent || ""] }), _jsxs(Text, { color: "green", children: ["+", change.newContent || ""] })] }, `fallback-${changeIndex}`));
|
|
140
123
|
}
|
|
141
124
|
});
|
|
142
|
-
|
|
143
|
-
const displayElements = isTruncated
|
|
144
|
-
? allElements.slice(0, maxHeight - 1)
|
|
145
|
-
: allElements;
|
|
146
|
-
return (_jsxs(Box, { flexDirection: "column", children: [displayElements, isTruncated && (_jsxs(Text, { color: "yellow", dimColor: true, children: ["... (truncated ", allElements.length - (maxHeight - 1), " more lines)"] }))] }));
|
|
125
|
+
return _jsx(Box, { flexDirection: "column", children: allElements });
|
|
147
126
|
}
|
|
148
127
|
catch (error) {
|
|
149
128
|
console.warn("Error rendering expanded diff:", error);
|
|
150
129
|
return (_jsx(Box, { children: _jsx(Text, { color: "gray", children: "Error rendering diff display" }) }));
|
|
151
130
|
}
|
|
152
131
|
};
|
|
153
|
-
// Helper function to extract text content from a React element
|
|
154
|
-
const extractTextFromElement = (element) => {
|
|
155
|
-
if (!React.isValidElement(element))
|
|
156
|
-
return null;
|
|
157
|
-
// Navigate through Box -> Text structure
|
|
158
|
-
const children = element.props.children;
|
|
159
|
-
if (Array.isArray(children) && children.length >= 2) {
|
|
160
|
-
const textElement = children[1]; // Second child should be the Text with content
|
|
161
|
-
if (React.isValidElement(textElement) &&
|
|
162
|
-
textElement.props.children) {
|
|
163
|
-
return textElement.props.children;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return null;
|
|
167
|
-
};
|
|
168
132
|
// Don't render anything if no diff should be shown
|
|
169
133
|
if (!showDiff) {
|
|
170
134
|
return null;
|
|
171
135
|
}
|
|
172
136
|
return (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "cyan", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Diff:" }), renderExpandedDiff()] }) }));
|
|
173
137
|
};
|
|
138
|
+
// Helper function to extract text content from a React element
|
|
139
|
+
const extractTextFromElement = (element) => {
|
|
140
|
+
if (!React.isValidElement(element))
|
|
141
|
+
return null;
|
|
142
|
+
// Navigate through Box -> Text structure
|
|
143
|
+
const children = element.props.children;
|
|
144
|
+
if (Array.isArray(children) && children.length >= 2) {
|
|
145
|
+
const textElement = children[1]; // Second child should be the Text with content
|
|
146
|
+
if (React.isValidElement(textElement) &&
|
|
147
|
+
textElement.props.children) {
|
|
148
|
+
return textElement.props.children;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoverView.d.ts","sourceRoot":"","sources":["../../src/components/DiscoverView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAyBhC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, useInput } from "ink";
|
|
4
|
+
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
5
|
+
import { PluginList } from "./PluginList.js";
|
|
6
|
+
export const DiscoverView = () => {
|
|
7
|
+
const { discoverablePlugins, actions } = usePluginManagerContext();
|
|
8
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
9
|
+
useInput((input, key) => {
|
|
10
|
+
if (key.upArrow) {
|
|
11
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
12
|
+
}
|
|
13
|
+
else if (key.downArrow) {
|
|
14
|
+
setSelectedIndex(Math.min(discoverablePlugins.length - 1, selectedIndex + 1));
|
|
15
|
+
}
|
|
16
|
+
else if (key.return) {
|
|
17
|
+
const plugin = discoverablePlugins[selectedIndex];
|
|
18
|
+
if (plugin) {
|
|
19
|
+
actions.setSelectedId(`${plugin.name}@${plugin.marketplace}`);
|
|
20
|
+
actions.setView("PLUGIN_DETAIL");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(PluginList, { plugins: discoverablePlugins, selectedIndex: selectedIndex }) }));
|
|
25
|
+
};
|
|
@@ -44,5 +44,5 @@ export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
|
|
|
44
44
|
const isSelected = actualIndex === selectedIndex;
|
|
45
45
|
const icon = fileItem.type === "directory" ? "📁" : "📄";
|
|
46
46
|
return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "cyan" : undefined, children: [" ", 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/Tab to select, Escape to cancel" }), _jsxs(Text, { dimColor: true, children: ["File ", selectedIndex + 1, " of ", files.length] })] })] }));
|
|
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/Tab to select, Escape to cancel" }), _jsxs(Text, { dimColor: true, children: [", File ", selectedIndex + 1, " of ", files.length] })] })] }));
|
|
48
48
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface HistorySearchProps {
|
|
3
|
+
searchQuery: string;
|
|
4
|
+
onSelect: (prompt: string) => void;
|
|
5
|
+
onCancel: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const HistorySearch: React.FC<HistorySearchProps>;
|
|
8
|
+
//# sourceMappingURL=HistorySearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HistorySearch.d.ts","sourceRoot":"","sources":["../../src/components/HistorySearch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAyItD,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState, useEffect } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
import { PromptHistoryManager } from "wave-agent-sdk";
|
|
5
|
+
export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
|
|
6
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
7
|
+
const [entries, setEntries] = useState([]);
|
|
8
|
+
const entriesRef = React.useRef([]);
|
|
9
|
+
const selectedIndexRef = React.useRef(0);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
entriesRef.current = entries;
|
|
12
|
+
}, [entries]);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
selectedIndexRef.current = selectedIndex;
|
|
15
|
+
}, [selectedIndex]);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const fetchHistory = async () => {
|
|
18
|
+
const results = await PromptHistoryManager.searchHistory(searchQuery);
|
|
19
|
+
const limitedResults = results.slice(0, 10);
|
|
20
|
+
setEntries(limitedResults); // Limit to 10 results
|
|
21
|
+
setSelectedIndex(0);
|
|
22
|
+
};
|
|
23
|
+
fetchHistory();
|
|
24
|
+
}, [searchQuery]);
|
|
25
|
+
useInput((input, key) => {
|
|
26
|
+
if (key.return) {
|
|
27
|
+
if (entriesRef.current.length > 0 &&
|
|
28
|
+
selectedIndexRef.current < entriesRef.current.length) {
|
|
29
|
+
onSelect(entriesRef.current[selectedIndexRef.current].prompt);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (key.escape) {
|
|
34
|
+
onCancel();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (key.upArrow) {
|
|
38
|
+
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (key.downArrow) {
|
|
42
|
+
setSelectedIndex((prev) => Math.min(entriesRef.current.length - 1, prev + 1));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (entries.length === 0) {
|
|
47
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "yellow", children: ["No history found ", searchQuery && `for "${searchQuery}"`] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
|
|
48
|
+
}
|
|
49
|
+
const formatTimestamp = (timestamp) => {
|
|
50
|
+
const date = new Date(timestamp);
|
|
51
|
+
const now = new Date();
|
|
52
|
+
const diffMs = now.getTime() - date.getTime();
|
|
53
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
54
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
55
|
+
if (diffDays > 0) {
|
|
56
|
+
return `${diffDays}d ago`;
|
|
57
|
+
}
|
|
58
|
+
else if (diffHours > 0) {
|
|
59
|
+
return `${diffHours}h ago`;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
63
|
+
return diffMinutes > 0 ? `${diffMinutes}m ago` : "just now";
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "blue", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "blue", bold: true, children: ["Prompt History ", searchQuery && `(filtering: "${searchQuery}")`] }) }), entries.map((entry, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "blue" : undefined, wrap: "truncate-end", children: entry.prompt.replace(/\n/g, " ") }), index === selectedIndex && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { color: "gray", dimColor: true, children: formatTimestamp(entry.timestamp) }) }))] }, index))), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select, Escape to cancel" }) })] }));
|
|
67
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
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,
|
|
3
|
+
export declare const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, # to add memory, Ctrl+R to search history)...";
|
|
4
4
|
export declare const INPUT_PLACEHOLDER_TEXT_PREFIX: string;
|
|
5
5
|
export interface InputBoxProps {
|
|
6
6
|
isLoading?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAazC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,+GAC2E,CAAC;AAE/G,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,CAiO5C,CAAC"}
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect
|
|
2
|
+
import { useEffect } from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
4
|
import { useInput } from "ink";
|
|
5
5
|
import { FileSelector } from "./FileSelector.js";
|
|
6
6
|
import { CommandSelector } from "./CommandSelector.js";
|
|
7
|
-
import {
|
|
7
|
+
import { HistorySearch } from "./HistorySearch.js";
|
|
8
8
|
import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
|
|
9
|
-
import {
|
|
9
|
+
import { TaskManager } from "./TaskManager.js";
|
|
10
10
|
import { McpManager } from "./McpManager.js";
|
|
11
|
+
import { RewindCommand } from "./RewindCommand.js";
|
|
11
12
|
import { useInputManager } from "../hooks/useInputManager.js";
|
|
12
13
|
import { useChat } from "../contexts/useChat.js";
|
|
13
|
-
export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands,
|
|
14
|
+
export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, # to add memory, Ctrl+R to search history)...";
|
|
14
15
|
export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
|
|
15
|
-
export const InputBox = ({ isLoading = false, isCommandRunning = false,
|
|
16
|
-
|
|
17
|
-
const currentWorkdir = useMemo(() => workdir || process.cwd(), [workdir]);
|
|
18
|
-
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, } = useChat();
|
|
16
|
+
export const InputBox = ({ isLoading = false, isCommandRunning = false, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, saveMemory = async () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
|
|
17
|
+
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, } = useChat();
|
|
19
18
|
// Input manager with all input state and functionality (including images)
|
|
20
19
|
const { inputText, cursorPosition,
|
|
21
20
|
// Image management
|
|
@@ -23,19 +22,17 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
|
|
|
23
22
|
// File selector
|
|
24
23
|
showFileSelector, filteredFiles, fileSearchQuery: searchQuery, handleFileSelect, handleCancelFileSelect,
|
|
25
24
|
// Command selector
|
|
26
|
-
showCommandSelector, commandSearchQuery, handleCommandSelect, handleCommandInsert, handleCancelCommandSelect,
|
|
27
|
-
// Bash history selector
|
|
28
|
-
showBashHistorySelector, bashHistorySearchQuery, handleBashHistorySelect, handleCancelBashHistorySelect,
|
|
25
|
+
showCommandSelector, commandSearchQuery, handleCommandSelect, handleCommandInsert, handleCancelCommandSelect, handleHistorySearchSelect, handleCancelHistorySearch,
|
|
29
26
|
// Memory type selector
|
|
30
27
|
showMemoryTypeSelector, memoryMessage, handleMemoryTypeSelect, handleCancelMemoryTypeSelect,
|
|
31
|
-
//
|
|
32
|
-
|
|
28
|
+
// History search
|
|
29
|
+
showHistorySearch, historySearchQuery,
|
|
30
|
+
// Task/MCP Manager
|
|
31
|
+
showTaskManager, showMcpManager, showRewindManager, setShowTaskManager, setShowMcpManager, setShowRewindManager,
|
|
33
32
|
// Permission mode
|
|
34
33
|
permissionMode, setPermissionMode,
|
|
35
34
|
// Input history
|
|
36
35
|
setUserInputHistory,
|
|
37
|
-
// Complex handlers combining multiple operations
|
|
38
|
-
handleBashHistoryExecuteAndSend, handleBashHistoryDelete,
|
|
39
36
|
// Main handler
|
|
40
37
|
handleInput,
|
|
41
38
|
// Manager ready state
|
|
@@ -44,6 +41,7 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
|
|
|
44
41
|
onHasSlashCommand: hasSlashCommand,
|
|
45
42
|
onSaveMemory: saveMemory,
|
|
46
43
|
onAbortMessage: abortMessage,
|
|
44
|
+
onBackgroundCurrentTask: backgroundCurrentTask,
|
|
47
45
|
onPermissionModeChange: setChatPermissionMode,
|
|
48
46
|
});
|
|
49
47
|
// Sync permission mode from useChat to InputManager
|
|
@@ -58,8 +56,11 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
|
|
|
58
56
|
useInput(async (input, key) => {
|
|
59
57
|
await handleInput(input, key, attachedImages, isLoading, isCommandRunning, clearImages);
|
|
60
58
|
});
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const handleRewindCancel = () => {
|
|
60
|
+
if (setShowRewindManager) {
|
|
61
|
+
setShowRewindManager(false);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
63
64
|
const isPlaceholder = !inputText;
|
|
64
65
|
const placeholderText = INPUT_PLACEHOLDER_TEXT;
|
|
65
66
|
// handleCommandSelectorInsert is already memoized in useInputManager, no need to wrap again
|
|
@@ -68,11 +69,20 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
|
|
|
68
69
|
const beforeCursor = displayText.substring(0, cursorPosition);
|
|
69
70
|
const atCursor = cursorPosition < displayText.length ? displayText[cursorPosition] : " ";
|
|
70
71
|
const afterCursor = displayText.substring(cursorPosition + 1);
|
|
71
|
-
// Always show cursor, allow user to continue input during
|
|
72
|
+
// Always show cursor, allow user to continue input during memory mode
|
|
72
73
|
const shouldShowCursor = true;
|
|
73
74
|
// Only show the Box after InputManager is created on first mount
|
|
74
75
|
if (!isManagerReady) {
|
|
75
76
|
return null;
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
const handleRewindSelectWithClose = async (index) => {
|
|
79
|
+
if (setShowRewindManager) {
|
|
80
|
+
setShowRewindManager(false);
|
|
81
|
+
}
|
|
82
|
+
await handleRewindSelect(index);
|
|
83
|
+
};
|
|
84
|
+
if (showRewindManager) {
|
|
85
|
+
return (_jsx(RewindCommand, { messages: messages, onSelect: handleRewindSelectWithClose, onCancel: handleRewindCancel }));
|
|
86
|
+
}
|
|
87
|
+
return (_jsxs(Box, { flexDirection: "column", 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 })), showHistorySearch && (_jsx(HistorySearch, { searchQuery: historySearchQuery, onSelect: handleHistorySearchSelect, onCancel: handleCancelHistorySearch })), showMemoryTypeSelector && (_jsx(MemoryTypeSelector, { message: memoryMessage, onSelect: handleMemoryTypeSelect, onCancel: handleCancelMemoryTypeSelect })), showTaskManager && (_jsx(TaskManager, { onCancel: () => setShowTaskManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showTaskManager || showMcpManager || showRewindManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(Box, { paddingRight: 1, children: _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan" ? "yellow" : "cyan", children: permissionMode }), " ", "(Shift+Tab to cycle)"] }) })] }))] }));
|
|
78
88
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstalledView.d.ts","sourceRoot":"","sources":["../../src/components/InstalledView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAwDjC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
5
|
+
export const InstalledView = () => {
|
|
6
|
+
const { installedPlugins, actions } = usePluginManagerContext();
|
|
7
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
8
|
+
useInput((input, key) => {
|
|
9
|
+
if (key.upArrow) {
|
|
10
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
11
|
+
}
|
|
12
|
+
else if (key.downArrow) {
|
|
13
|
+
setSelectedIndex(Math.min(installedPlugins.length - 1, selectedIndex + 1));
|
|
14
|
+
}
|
|
15
|
+
else if (key.return) {
|
|
16
|
+
const plugin = installedPlugins[selectedIndex];
|
|
17
|
+
if (plugin) {
|
|
18
|
+
actions.setSelectedId(`${plugin.name}@${plugin.marketplace}`);
|
|
19
|
+
actions.setView("PLUGIN_DETAIL");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
if (installedPlugins.length === 0) {
|
|
24
|
+
return (_jsx(Box, { padding: 1, children: _jsx(Text, { dimColor: true, children: "No plugins installed." }) }));
|
|
25
|
+
}
|
|
26
|
+
return (_jsx(Box, { flexDirection: "column", children: installedPlugins.map((plugin, index) => {
|
|
27
|
+
const isSelected = index === selectedIndex;
|
|
28
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "cyan" : undefined, children: [isSelected ? "> " : " ", _jsx(Text, { bold: true, children: plugin.name }), _jsxs(Text, { dimColor: true, children: [" @", plugin.marketplace] }), plugin.scope && _jsxs(Text, { color: "gray", children: [" (", plugin.scope, ")"] })] }) }), isSelected && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { dimColor: true, children: "Press Enter for actions" }) }))] }, `${plugin.name}@${plugin.marketplace}`));
|
|
29
|
+
}) }));
|
|
30
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/components/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/components/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAKvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAmVD,eAAO,MAAM,QAAQ,2CAA6B,aAAa,6CAQ7D,CAAC"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, { useMemo } from "react";
|
|
3
3
|
import { Box, Text, useStdout } from "ink";
|
|
4
4
|
import { marked } from "marked";
|
|
5
|
+
import { highlight } from "cli-highlight";
|
|
5
6
|
const unescapeHtml = (html) => {
|
|
6
7
|
return html
|
|
7
8
|
.replace(/&/g, "&")
|
|
8
9
|
.replace(/</g, "<")
|
|
9
10
|
.replace(/>/g, ">")
|
|
10
11
|
.replace(/"/g, '"')
|
|
11
|
-
.replace(/'/g, "'")
|
|
12
|
+
.replace(/'/g, "'")
|
|
13
|
+
.replace(/'/g, "'");
|
|
12
14
|
};
|
|
13
15
|
const InlineRenderer = ({ tokens }) => {
|
|
14
16
|
return (_jsx(_Fragment, { children: tokens.map((token, index) => {
|
|
@@ -26,8 +28,10 @@ const InlineRenderer = ({ tokens }) => {
|
|
|
26
28
|
return (_jsx(Text, { italic: true, children: token.tokens ? (_jsx(InlineRenderer, { tokens: token.tokens })) : (unescapeHtml(token.text)) }, index));
|
|
27
29
|
case "codespan":
|
|
28
30
|
return (_jsx(Text, { color: "yellow", children: unescapeHtml(token.text) }, index));
|
|
29
|
-
case "link":
|
|
30
|
-
|
|
31
|
+
case "link": {
|
|
32
|
+
const t = token;
|
|
33
|
+
return (_jsxs(Text, { children: [_jsx(Text, { color: "blue", underline: true, children: t.tokens ? (_jsx(InlineRenderer, { tokens: t.tokens })) : (unescapeHtml(t.text)) }), _jsxs(Text, { color: "gray", children: [" (", t.href, ")"] })] }, index));
|
|
34
|
+
}
|
|
31
35
|
case "br":
|
|
32
36
|
return _jsx(Text, { children: "\n" }, index);
|
|
33
37
|
case "del":
|
|
@@ -71,27 +75,37 @@ const BlockRenderer = ({ tokens }) => {
|
|
|
71
75
|
}
|
|
72
76
|
case "paragraph": {
|
|
73
77
|
const t = token;
|
|
74
|
-
return (_jsx(Box, { marginBottom: 1, flexDirection: "row",
|
|
78
|
+
return (_jsx(Box, { marginBottom: 1, flexDirection: "row", children: _jsx(Text, { children: _jsx(InlineRenderer, { tokens: t.tokens }) }) }, index));
|
|
75
79
|
}
|
|
76
80
|
case "code": {
|
|
77
81
|
const t = token;
|
|
78
82
|
if (t.lang !== undefined) {
|
|
79
|
-
const
|
|
83
|
+
const raw = token.raw.endsWith("\n")
|
|
84
|
+
? token.raw.slice(0, -1)
|
|
85
|
+
: token.raw;
|
|
86
|
+
const lines = raw.split("\n");
|
|
80
87
|
const opening = lines[0];
|
|
81
88
|
const closing = lines[lines.length - 1];
|
|
82
89
|
const content = lines.slice(1, -1).join("\n");
|
|
83
|
-
|
|
90
|
+
const highlighted = content
|
|
91
|
+
? highlight(unescapeHtml(content), {
|
|
92
|
+
language: t.lang,
|
|
93
|
+
ignoreIllegals: true,
|
|
94
|
+
})
|
|
95
|
+
: "";
|
|
96
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [_jsx(Text, { color: "gray", children: opening }), highlighted && _jsx(Text, { children: highlighted }), _jsx(Text, { color: "gray", children: closing })] }, index));
|
|
84
97
|
}
|
|
85
|
-
return (_jsx(Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: _jsx(Text, { children: t.text }) }, index));
|
|
98
|
+
return (_jsx(Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: _jsx(Text, { children: unescapeHtml(t.text) }) }, index));
|
|
86
99
|
}
|
|
87
100
|
case "list": {
|
|
88
101
|
const t = token;
|
|
89
102
|
return (_jsx(Box, { flexDirection: "column", marginBottom: 1, paddingLeft: 2, children: t.items.map((item, i) => {
|
|
90
103
|
const start = t.start || 1;
|
|
91
104
|
return (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "gray", children: t.ordered ? `${start + i}. ` : "• " }), _jsx(Box, { flexDirection: "column", flexGrow: 1, children: item.tokens.map((itemToken, itemIndex) => {
|
|
92
|
-
if (itemToken.type === "text"
|
|
105
|
+
if (itemToken.type === "text" ||
|
|
106
|
+
itemToken.type === "paragraph") {
|
|
93
107
|
const it = itemToken;
|
|
94
|
-
return (_jsx(Box, { flexDirection: "row",
|
|
108
|
+
return (_jsx(Box, { flexDirection: "row", children: _jsx(Text, { children: _jsx(InlineRenderer, { tokens: it.tokens || [itemToken] }) }) }, itemIndex));
|
|
95
109
|
}
|
|
96
110
|
return (_jsx(BlockRenderer, { tokens: [itemToken] }, itemIndex));
|
|
97
111
|
}) })] }, i));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketplaceAddForm.d.ts","sourceRoot":"","sources":["../../src/components/MarketplaceAddForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAkCtC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
5
|
+
export const MarketplaceAddForm = () => {
|
|
6
|
+
const { actions } = usePluginManagerContext();
|
|
7
|
+
const [source, setSource] = useState("");
|
|
8
|
+
useInput((input, key) => {
|
|
9
|
+
if (key.escape) {
|
|
10
|
+
actions.setView("MARKETPLACES");
|
|
11
|
+
}
|
|
12
|
+
else if (key.return) {
|
|
13
|
+
if (source.trim()) {
|
|
14
|
+
actions.addMarketplace(source.trim());
|
|
15
|
+
actions.setView("MARKETPLACES");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else if (key.backspace || key.delete) {
|
|
19
|
+
setSource((prev) => prev.slice(0, -1));
|
|
20
|
+
}
|
|
21
|
+
else if (input.length === 1) {
|
|
22
|
+
setSource((prev) => prev + input);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "Add Marketplace" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { children: "Source (URL or Path): " }), _jsx(Text, { color: "yellow", children: source }), _jsx(Text, { color: "yellow", children: "_" })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter to add, Esc to cancel" }) })] }));
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketplaceDetail.d.ts","sourceRoot":"","sources":["../../src/components/MarketplaceDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EA0ErC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
5
|
+
export const MarketplaceDetail = () => {
|
|
6
|
+
const { state, marketplaces, actions } = usePluginManagerContext();
|
|
7
|
+
const [selectedActionIndex, setSelectedActionIndex] = useState(0);
|
|
8
|
+
const marketplace = marketplaces.find((m) => m.name === state.selectedId);
|
|
9
|
+
const ACTIONS = [
|
|
10
|
+
{ id: "update", label: "Update marketplace" },
|
|
11
|
+
{ id: "remove", label: "Remove marketplace" },
|
|
12
|
+
];
|
|
13
|
+
useInput((input, key) => {
|
|
14
|
+
if (key.escape) {
|
|
15
|
+
actions.setView("MARKETPLACES");
|
|
16
|
+
}
|
|
17
|
+
else if (key.upArrow) {
|
|
18
|
+
setSelectedActionIndex((prev) => prev > 0 ? prev - 1 : ACTIONS.length - 1);
|
|
19
|
+
}
|
|
20
|
+
else if (key.downArrow) {
|
|
21
|
+
setSelectedActionIndex((prev) => prev < ACTIONS.length - 1 ? prev + 1 : 0);
|
|
22
|
+
}
|
|
23
|
+
else if (key.return && marketplace) {
|
|
24
|
+
const action = ACTIONS[selectedActionIndex].id;
|
|
25
|
+
if (action === "update") {
|
|
26
|
+
actions.updateMarketplace(marketplace.name);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
actions.removeMarketplace(marketplace.name);
|
|
30
|
+
}
|
|
31
|
+
actions.setView("MARKETPLACES");
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
if (!marketplace) {
|
|
35
|
+
return (_jsx(Box, { children: _jsx(Text, { color: "red", children: "Marketplace not found." }) }));
|
|
36
|
+
}
|
|
37
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: marketplace.name }), marketplace.isBuiltin && _jsx(Text, { dimColor: true, children: " (Built-in)" })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Source: ", JSON.stringify(marketplace.source)] }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Marketplace Actions:" }), ACTIONS.map((action, index) => (_jsxs(Text, { color: index === selectedActionIndex ? "yellow" : undefined, children: [index === selectedActionIndex ? "> " : " ", action.label] }, action.id))), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Use \u2191/\u2193 to select, Enter to confirm" }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Esc to go back" }) })] })] }));
|
|
38
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { KnownMarketplace } from "wave-agent-sdk";
|
|
3
|
+
interface MarketplaceListProps {
|
|
4
|
+
marketplaces: KnownMarketplace[];
|
|
5
|
+
selectedIndex: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const MarketplaceList: React.FC<MarketplaceListProps>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=MarketplaceList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketplaceList.d.ts","sourceRoot":"","sources":["../../src/components/MarketplaceList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,UAAU,oBAAoB;IAC5B,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0C1D,CAAC"}
|