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.
Files changed (156) hide show
  1. package/dist/commands/plugin/disable.d.ts +2 -1
  2. package/dist/commands/plugin/disable.d.ts.map +1 -1
  3. package/dist/commands/plugin/disable.js +3 -2
  4. package/dist/commands/plugin/enable.d.ts +2 -1
  5. package/dist/commands/plugin/enable.d.ts.map +1 -1
  6. package/dist/commands/plugin/enable.js +3 -2
  7. package/dist/commands/plugin/install.d.ts +2 -1
  8. package/dist/commands/plugin/install.d.ts.map +1 -1
  9. package/dist/commands/plugin/list.d.ts.map +1 -1
  10. package/dist/commands/plugin/list.js +15 -3
  11. package/dist/commands/plugin/marketplace.d.ts +3 -0
  12. package/dist/commands/plugin/marketplace.d.ts.map +1 -1
  13. package/dist/commands/plugin/marketplace.js +15 -1
  14. package/dist/commands/plugin/uninstall.d.ts +4 -0
  15. package/dist/commands/plugin/uninstall.d.ts.map +1 -0
  16. package/dist/commands/plugin/uninstall.js +29 -0
  17. package/dist/commands/plugin/update.d.ts +4 -0
  18. package/dist/commands/plugin/update.d.ts.map +1 -0
  19. package/dist/commands/plugin/update.js +15 -0
  20. package/dist/components/ChatInterface.d.ts.map +1 -1
  21. package/dist/components/ChatInterface.js +2 -2
  22. package/dist/components/CommandSelector.d.ts.map +1 -1
  23. package/dist/components/CommandSelector.js +9 -3
  24. package/dist/components/Confirmation.d.ts.map +1 -1
  25. package/dist/components/Confirmation.js +73 -20
  26. package/dist/components/DiffDisplay.d.ts +0 -1
  27. package/dist/components/DiffDisplay.d.ts.map +1 -1
  28. package/dist/components/DiffDisplay.js +38 -59
  29. package/dist/components/DiscoverView.d.ts +3 -0
  30. package/dist/components/DiscoverView.d.ts.map +1 -0
  31. package/dist/components/DiscoverView.js +25 -0
  32. package/dist/components/FileSelector.js +1 -1
  33. package/dist/components/HistorySearch.d.ts +8 -0
  34. package/dist/components/HistorySearch.d.ts.map +1 -0
  35. package/dist/components/HistorySearch.js +67 -0
  36. package/dist/components/InputBox.d.ts +1 -1
  37. package/dist/components/InputBox.d.ts.map +1 -1
  38. package/dist/components/InputBox.js +29 -19
  39. package/dist/components/InstalledView.d.ts +3 -0
  40. package/dist/components/InstalledView.d.ts.map +1 -0
  41. package/dist/components/InstalledView.js +30 -0
  42. package/dist/components/Markdown.d.ts.map +1 -1
  43. package/dist/components/Markdown.js +24 -10
  44. package/dist/components/MarketplaceAddForm.d.ts +3 -0
  45. package/dist/components/MarketplaceAddForm.d.ts.map +1 -0
  46. package/dist/components/MarketplaceAddForm.js +26 -0
  47. package/dist/components/MarketplaceDetail.d.ts +3 -0
  48. package/dist/components/MarketplaceDetail.d.ts.map +1 -0
  49. package/dist/components/MarketplaceDetail.js +38 -0
  50. package/dist/components/MarketplaceList.d.ts +9 -0
  51. package/dist/components/MarketplaceList.d.ts.map +1 -0
  52. package/dist/components/MarketplaceList.js +16 -0
  53. package/dist/components/MarketplaceView.d.ts +3 -0
  54. package/dist/components/MarketplaceView.d.ts.map +1 -0
  55. package/dist/components/MarketplaceView.js +28 -0
  56. package/dist/components/PlanDisplay.d.ts.map +1 -1
  57. package/dist/components/PlanDisplay.js +2 -2
  58. package/dist/components/PluginDetail.d.ts +3 -0
  59. package/dist/components/PluginDetail.d.ts.map +1 -0
  60. package/dist/components/PluginDetail.js +63 -0
  61. package/dist/components/PluginList.d.ts +14 -0
  62. package/dist/components/PluginList.d.ts.map +1 -0
  63. package/dist/components/PluginList.js +12 -0
  64. package/dist/components/PluginManagerShell.d.ts +5 -0
  65. package/dist/components/PluginManagerShell.d.ts.map +1 -0
  66. package/dist/components/PluginManagerShell.js +89 -0
  67. package/dist/components/PluginManagerTypes.d.ts +33 -0
  68. package/dist/components/PluginManagerTypes.d.ts.map +1 -0
  69. package/dist/components/PluginManagerTypes.js +1 -0
  70. package/dist/components/RewindCommand.d.ts +9 -0
  71. package/dist/components/RewindCommand.d.ts.map +1 -0
  72. package/dist/components/RewindCommand.js +42 -0
  73. package/dist/components/SessionSelector.d.ts +11 -0
  74. package/dist/components/SessionSelector.d.ts.map +1 -0
  75. package/dist/components/SessionSelector.js +38 -0
  76. package/dist/components/SubagentBlock.d.ts.map +1 -1
  77. package/dist/components/SubagentBlock.js +24 -1
  78. package/dist/components/TaskManager.d.ts +6 -0
  79. package/dist/components/TaskManager.d.ts.map +1 -0
  80. package/dist/components/TaskManager.js +114 -0
  81. package/dist/components/ToolResultDisplay.d.ts.map +1 -1
  82. package/dist/components/ToolResultDisplay.js +2 -1
  83. package/dist/contexts/PluginManagerContext.d.ts +4 -0
  84. package/dist/contexts/PluginManagerContext.d.ts.map +1 -0
  85. package/dist/contexts/PluginManagerContext.js +9 -0
  86. package/dist/contexts/useChat.d.ts +7 -4
  87. package/dist/contexts/useChat.d.ts.map +1 -1
  88. package/dist/contexts/useChat.js +37 -12
  89. package/dist/hooks/useInputManager.d.ts +8 -16
  90. package/dist/hooks/useInputManager.d.ts.map +1 -1
  91. package/dist/hooks/useInputManager.js +39 -55
  92. package/dist/hooks/usePluginManager.d.ts +3 -0
  93. package/dist/hooks/usePluginManager.d.ts.map +1 -0
  94. package/dist/hooks/usePluginManager.js +227 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +150 -177
  97. package/dist/managers/InputManager.d.ts +18 -26
  98. package/dist/managers/InputManager.d.ts.map +1 -1
  99. package/dist/managers/InputManager.js +93 -119
  100. package/dist/plugin-manager-cli.d.ts +6 -0
  101. package/dist/plugin-manager-cli.d.ts.map +1 -0
  102. package/dist/plugin-manager-cli.js +12 -0
  103. package/dist/session-selector-cli.d.ts +2 -0
  104. package/dist/session-selector-cli.d.ts.map +1 -0
  105. package/dist/session-selector-cli.js +25 -0
  106. package/package.json +9 -5
  107. package/src/commands/plugin/disable.ts +7 -3
  108. package/src/commands/plugin/enable.ts +7 -3
  109. package/src/commands/plugin/install.ts +2 -1
  110. package/src/commands/plugin/list.ts +21 -3
  111. package/src/commands/plugin/marketplace.ts +17 -1
  112. package/src/commands/plugin/uninstall.ts +39 -0
  113. package/src/commands/plugin/update.ts +19 -0
  114. package/src/components/ChatInterface.tsx +2 -1
  115. package/src/components/CommandSelector.tsx +10 -3
  116. package/src/components/Confirmation.tsx +115 -25
  117. package/src/components/DiffDisplay.tsx +60 -106
  118. package/src/components/DiscoverView.tsx +31 -0
  119. package/src/components/FileSelector.tsx +1 -1
  120. package/src/components/HistorySearch.tsx +148 -0
  121. package/src/components/InputBox.tsx +51 -34
  122. package/src/components/InstalledView.tsx +61 -0
  123. package/src/components/Markdown.tsx +44 -28
  124. package/src/components/MarketplaceAddForm.tsx +39 -0
  125. package/src/components/MarketplaceDetail.tsx +79 -0
  126. package/src/components/MarketplaceList.tsx +52 -0
  127. package/src/components/MarketplaceView.tsx +43 -0
  128. package/src/components/PlanDisplay.tsx +14 -19
  129. package/src/components/PluginDetail.tsx +147 -0
  130. package/src/components/PluginList.tsx +51 -0
  131. package/src/components/PluginManagerShell.tsx +189 -0
  132. package/src/components/PluginManagerTypes.ts +47 -0
  133. package/src/components/RewindCommand.tsx +114 -0
  134. package/src/components/SessionSelector.tsx +127 -0
  135. package/src/components/SubagentBlock.tsx +34 -1
  136. package/src/components/{BashShellManager.tsx → TaskManager.tsx} +79 -75
  137. package/src/components/ToolResultDisplay.tsx +6 -2
  138. package/src/contexts/PluginManagerContext.ts +15 -0
  139. package/src/contexts/useChat.tsx +51 -20
  140. package/src/hooks/useInputManager.ts +39 -71
  141. package/src/hooks/usePluginManager.ts +302 -0
  142. package/src/index.ts +241 -280
  143. package/src/managers/InputManager.ts +113 -162
  144. package/src/plugin-manager-cli.tsx +13 -0
  145. package/src/session-selector-cli.tsx +37 -0
  146. package/dist/components/BashHistorySelector.d.ts +0 -11
  147. package/dist/components/BashHistorySelector.d.ts.map +0 -1
  148. package/dist/components/BashHistorySelector.js +0 -93
  149. package/dist/components/BashShellManager.d.ts +0 -6
  150. package/dist/components/BashShellManager.d.ts.map +0 -1
  151. package/dist/components/BashShellManager.js +0 -116
  152. package/dist/hooks/usePagination.d.ts +0 -20
  153. package/dist/hooks/usePagination.d.ts.map +0 -1
  154. package/dist/hooks/usePagination.js +0 -168
  155. package/src/components/BashHistorySelector.tsx +0 -181
  156. 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, useStdout } from "ink";
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, isExpanded = false, }) => {
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 using word-level diff for all changes
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
- // Now look for pairs of removed/added lines that can be word-diffed
101
- let i = 0;
102
- while (i < diffElements.length) {
103
- const current = diffElements[i];
104
- const next = i + 1 < diffElements.length ? diffElements[i + 1] : null;
105
- // Check if we have a removed line followed by an added line
106
- const currentKey = React.isValidElement(current) ? current.key : "";
107
- const nextKey = React.isValidElement(next) ? next.key : "";
108
- const isCurrentRemoved = typeof currentKey === "string" && currentKey.includes("remove-");
109
- const isNextAdded = typeof nextKey === "string" && nextKey.includes("add-");
110
- if (isCurrentRemoved &&
111
- isNextAdded &&
112
- React.isValidElement(current) &&
113
- React.isValidElement(next)) {
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(current);
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
- const isTruncated = !isExpanded && allElements.length > maxHeight;
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,3 @@
1
+ import React from "react";
2
+ export declare const DiscoverView: React.FC;
3
+ //# sourceMappingURL=DiscoverView.d.ts.map
@@ -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, ! for bash history, # to add memory)...";
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,KAA6B,MAAM,OAAO,CAAC;AAYlD,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,CAiN5C,CAAC"}
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, useMemo } from "react";
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 { BashHistorySelector } from "./BashHistorySelector.js";
7
+ import { HistorySearch } from "./HistorySearch.js";
8
8
  import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
9
- import { BashShellManager } from "./BashShellManager.js";
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, ! for bash history, # to add memory)...";
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, workdir, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, saveMemory = async () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
16
- // Get current working directory - memoized to avoid repeated process.cwd() calls
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
- // Bash/MCP Manager
32
- showBashManager, showMcpManager, setShowBashManager, setShowMcpManager,
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
- // These methods are already memoized in useInputManager, no need to wrap again
62
- // These methods are already memoized in useInputManager and combine multiple operations
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 loading
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
- 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 })), showBashHistorySelector && (_jsx(BashHistorySelector, { searchQuery: bashHistorySearchQuery, workdir: currentWorkdir, onSelect: handleBashHistorySelect, onExecute: handleBashHistoryExecuteAndSend, onDelete: handleBashHistoryDelete, 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 || (_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
+ 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,3 @@
1
+ import React from "react";
2
+ export declare const InstalledView: React.FC;
3
+ //# sourceMappingURL=InstalledView.d.ts.map
@@ -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;AAIvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoUD,eAAO,MAAM,QAAQ,2CAA6B,aAAa,6CAQ7D,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, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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(/&amp;/g, "&")
8
9
  .replace(/&lt;/g, "<")
9
10
  .replace(/&gt;/g, ">")
10
11
  .replace(/&quot;/g, '"')
11
- .replace(/&#39;/g, "'");
12
+ .replace(/&#39;/g, "'")
13
+ .replace(/&apos;/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
- return (_jsx(Text, { color: "blue", underline: true, children: token.tokens ? (_jsx(InlineRenderer, { tokens: token.tokens })) : (unescapeHtml(token.text)) }, index));
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", flexWrap: "wrap", children: _jsx(InlineRenderer, { tokens: t.tokens }) }, index));
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 lines = token.raw.replace(/\n$/, "").split("\n");
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
- return (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [_jsx(Text, { color: "gray", children: opening }), content && _jsx(Text, { children: content }), _jsx(Text, { color: "gray", children: closing })] }, index));
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", flexWrap: "wrap", children: _jsx(InlineRenderer, { tokens: it.tokens || [itemToken] }) }, itemIndex));
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,3 @@
1
+ import React from "react";
2
+ export declare const MarketplaceAddForm: React.FC;
3
+ //# sourceMappingURL=MarketplaceAddForm.d.ts.map
@@ -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,3 @@
1
+ import React from "react";
2
+ export declare const MarketplaceDetail: React.FC;
3
+ //# sourceMappingURL=MarketplaceDetail.d.ts.map
@@ -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"}