wave-code 0.4.0 → 0.6.1

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 (105) hide show
  1. package/dist/commands/plugin/uninstall.js +1 -1
  2. package/dist/components/App.d.ts.map +1 -1
  3. package/dist/components/App.js +38 -2
  4. package/dist/components/BackgroundTaskManager.d.ts +6 -0
  5. package/dist/components/BackgroundTaskManager.d.ts.map +1 -0
  6. package/dist/components/BackgroundTaskManager.js +114 -0
  7. package/dist/components/ChatInterface.d.ts.map +1 -1
  8. package/dist/components/ChatInterface.js +39 -5
  9. package/dist/components/CommandSelector.d.ts.map +1 -1
  10. package/dist/components/CommandSelector.js +13 -5
  11. package/dist/components/CompressDisplay.d.ts.map +1 -1
  12. package/dist/components/CompressDisplay.js +6 -10
  13. package/dist/components/ConfirmationDetails.d.ts +9 -0
  14. package/dist/components/ConfirmationDetails.d.ts.map +1 -0
  15. package/dist/components/ConfirmationDetails.js +53 -0
  16. package/dist/components/{Confirmation.d.ts → ConfirmationSelector.d.ts} +3 -3
  17. package/dist/components/ConfirmationSelector.d.ts.map +1 -0
  18. package/dist/components/{Confirmation.js → ConfirmationSelector.js} +92 -101
  19. package/dist/components/DiffDisplay.d.ts +0 -1
  20. package/dist/components/DiffDisplay.d.ts.map +1 -1
  21. package/dist/components/DiffDisplay.js +82 -60
  22. package/dist/components/FileSelector.d.ts.map +1 -1
  23. package/dist/components/FileSelector.js +2 -2
  24. package/dist/components/HistorySearch.d.ts.map +1 -1
  25. package/dist/components/HistorySearch.js +12 -4
  26. package/dist/components/InputBox.d.ts +1 -3
  27. package/dist/components/InputBox.d.ts.map +1 -1
  28. package/dist/components/InputBox.js +9 -18
  29. package/dist/components/LoadingIndicator.d.ts +11 -0
  30. package/dist/components/LoadingIndicator.d.ts.map +1 -0
  31. package/dist/components/LoadingIndicator.js +6 -0
  32. package/dist/components/Markdown.d.ts.map +1 -1
  33. package/dist/components/Markdown.js +114 -120
  34. package/dist/components/MessageItem.d.ts.map +1 -1
  35. package/dist/components/MessageItem.js +1 -2
  36. package/dist/components/MessageList.d.ts +2 -3
  37. package/dist/components/MessageList.d.ts.map +1 -1
  38. package/dist/components/MessageList.js +7 -7
  39. package/dist/components/PlanDisplay.d.ts.map +1 -1
  40. package/dist/components/PlanDisplay.js +4 -12
  41. package/dist/components/PluginDetail.js +1 -1
  42. package/dist/components/RewindCommand.d.ts +4 -0
  43. package/dist/components/RewindCommand.d.ts.map +1 -1
  44. package/dist/components/RewindCommand.js +19 -2
  45. package/dist/components/SubagentBlock.d.ts.map +1 -1
  46. package/dist/components/SubagentBlock.js +12 -5
  47. package/dist/components/TaskList.d.ts +3 -0
  48. package/dist/components/TaskList.d.ts.map +1 -0
  49. package/dist/components/TaskList.js +49 -0
  50. package/dist/components/ToolResultDisplay.d.ts.map +1 -1
  51. package/dist/components/ToolResultDisplay.js +2 -1
  52. package/dist/contexts/useChat.d.ts +15 -6
  53. package/dist/contexts/useChat.d.ts.map +1 -1
  54. package/dist/contexts/useChat.js +52 -43
  55. package/dist/hooks/useInputManager.d.ts +2 -13
  56. package/dist/hooks/useInputManager.d.ts.map +1 -1
  57. package/dist/hooks/useInputManager.js +8 -57
  58. package/dist/hooks/usePluginManager.d.ts.map +1 -1
  59. package/dist/hooks/usePluginManager.js +8 -4
  60. package/dist/hooks/useTasks.d.ts +2 -0
  61. package/dist/hooks/useTasks.d.ts.map +1 -0
  62. package/dist/hooks/useTasks.js +5 -0
  63. package/dist/managers/InputManager.d.ts +5 -28
  64. package/dist/managers/InputManager.d.ts.map +1 -1
  65. package/dist/managers/InputManager.js +26 -127
  66. package/package.json +9 -10
  67. package/src/commands/plugin/uninstall.ts +1 -1
  68. package/src/components/App.tsx +50 -3
  69. package/src/components/{BashShellManager.tsx → BackgroundTaskManager.tsx} +79 -73
  70. package/src/components/ChatInterface.tsx +79 -23
  71. package/src/components/CommandSelector.tsx +38 -20
  72. package/src/components/CompressDisplay.tsx +5 -22
  73. package/src/components/ConfirmationDetails.tsx +108 -0
  74. package/src/components/{Confirmation.tsx → ConfirmationSelector.tsx} +162 -187
  75. package/src/components/DiffDisplay.tsx +122 -107
  76. package/src/components/FileSelector.tsx +0 -2
  77. package/src/components/HistorySearch.tsx +45 -21
  78. package/src/components/InputBox.tsx +14 -34
  79. package/src/components/LoadingIndicator.tsx +56 -0
  80. package/src/components/Markdown.tsx +126 -318
  81. package/src/components/MessageItem.tsx +1 -3
  82. package/src/components/MessageList.tsx +10 -67
  83. package/src/components/PlanDisplay.tsx +5 -33
  84. package/src/components/PluginDetail.tsx +1 -1
  85. package/src/components/RewindCommand.tsx +38 -1
  86. package/src/components/SubagentBlock.tsx +28 -14
  87. package/src/components/TaskList.tsx +70 -0
  88. package/src/components/ToolResultDisplay.tsx +6 -2
  89. package/src/contexts/useChat.tsx +82 -60
  90. package/src/hooks/useInputManager.ts +9 -73
  91. package/src/hooks/usePluginManager.ts +10 -4
  92. package/src/hooks/useTasks.ts +6 -0
  93. package/src/managers/InputManager.ts +30 -157
  94. package/dist/components/BashShellManager.d.ts +0 -6
  95. package/dist/components/BashShellManager.d.ts.map +0 -1
  96. package/dist/components/BashShellManager.js +0 -116
  97. package/dist/components/Confirmation.d.ts.map +0 -1
  98. package/dist/components/MemoryDisplay.d.ts +0 -8
  99. package/dist/components/MemoryDisplay.d.ts.map +0 -1
  100. package/dist/components/MemoryDisplay.js +0 -25
  101. package/dist/components/MemoryTypeSelector.d.ts +0 -8
  102. package/dist/components/MemoryTypeSelector.d.ts.map +0 -1
  103. package/dist/components/MemoryTypeSelector.js +0 -38
  104. package/src/components/MemoryDisplay.tsx +0 -62
  105. package/src/components/MemoryTypeSelector.tsx +0 -98
@@ -3,7 +3,7 @@ export async function uninstallPluginCommand(argv) {
3
3
  const marketplaceService = new MarketplaceService();
4
4
  const workdir = process.cwd();
5
5
  try {
6
- await marketplaceService.uninstallPlugin(argv.plugin);
6
+ await marketplaceService.uninstallPlugin(argv.plugin, workdir);
7
7
  console.log(`Successfully uninstalled plugin: ${argv.plugin}`);
8
8
  const configurationService = new ConfigurationService();
9
9
  const pluginManager = new PluginManager({ workdir });
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,UAAU,QAAQ;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAaD,eAAO,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAiBlC,CAAC"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAM3D,UAAU,QAAQ;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AA2DD,eAAO,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAiBlC,CAAC"}
@@ -1,9 +1,45 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState, useEffect, useRef } from "react";
3
+ import { useStdout } from "ink";
2
4
  import { ChatInterface } from "./ChatInterface.js";
3
- import { ChatProvider } from "../contexts/useChat.js";
5
+ import { ChatProvider, useChat } from "../contexts/useChat.js";
4
6
  import { AppProvider } from "../contexts/useAppConfig.js";
5
7
  const AppWithProviders = ({ bypassPermissions, pluginDirs }) => {
6
- return (_jsx(ChatProvider, { bypassPermissions: bypassPermissions, pluginDirs: pluginDirs, children: _jsx(ChatInterface, {}) }));
8
+ return (_jsx(ChatProvider, { bypassPermissions: bypassPermissions, pluginDirs: pluginDirs, children: _jsx(ChatInterfaceWithRemount, {}) }));
9
+ };
10
+ const ChatInterfaceWithRemount = () => {
11
+ const { stdout } = useStdout();
12
+ const { isExpanded, rewindId, wasLastDetailsTooTall, sessionId } = useChat();
13
+ const [remountKey, setRemountKey] = useState(String(isExpanded) + rewindId + wasLastDetailsTooTall);
14
+ const prevSessionId = useRef(sessionId);
15
+ useEffect(() => {
16
+ let newKey = String(isExpanded) + rewindId + wasLastDetailsTooTall;
17
+ const isSessionChanged = prevSessionId.current && sessionId && prevSessionId.current !== sessionId;
18
+ if (isSessionChanged) {
19
+ newKey += sessionId;
20
+ }
21
+ if (newKey !== remountKey) {
22
+ stdout?.write("\u001b[2J\u001b[0;0H", (err) => {
23
+ if (err) {
24
+ console.error("Failed to clear terminal:", err);
25
+ }
26
+ setTimeout(() => {
27
+ setRemountKey(newKey);
28
+ }, 100);
29
+ });
30
+ }
31
+ if (sessionId) {
32
+ prevSessionId.current = sessionId;
33
+ }
34
+ }, [
35
+ isExpanded,
36
+ rewindId,
37
+ wasLastDetailsTooTall,
38
+ sessionId,
39
+ remountKey,
40
+ stdout,
41
+ ]);
42
+ return _jsx(ChatInterface, {}, remountKey);
7
43
  };
8
44
  export const App = ({ restoreSessionId, continueLastSession, bypassPermissions, pluginDirs, }) => {
9
45
  return (_jsx(AppProvider, { restoreSessionId: restoreSessionId, continueLastSession: continueLastSession, children: _jsx(AppWithProviders, { bypassPermissions: bypassPermissions, pluginDirs: pluginDirs }) }));
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ export interface BackgroundTaskManagerProps {
3
+ onCancel: () => void;
4
+ }
5
+ export declare const BackgroundTaskManager: React.FC<BackgroundTaskManagerProps>;
6
+ //# sourceMappingURL=BackgroundTaskManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackgroundTaskManager.d.ts","sourceRoot":"","sources":["../../src/components/BackgroundTaskManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAcnD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CA6StE,CAAC"}
@@ -0,0 +1,114 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import { useChat } from "../contexts/useChat.js";
5
+ export const BackgroundTaskManager = ({ onCancel, }) => {
6
+ const { backgroundTasks, getBackgroundTaskOutput, stopBackgroundTask } = useChat();
7
+ const [tasks, setTasks] = useState([]);
8
+ const [selectedIndex, setSelectedIndex] = useState(0);
9
+ const [viewMode, setViewMode] = useState("list");
10
+ const [detailTaskId, setDetailTaskId] = useState(null);
11
+ const [detailOutput, setDetailOutput] = useState(null);
12
+ // Convert backgroundTasks to local Task format
13
+ useEffect(() => {
14
+ setTasks(backgroundTasks.map((task) => ({
15
+ id: task.id,
16
+ type: task.type,
17
+ description: task.description,
18
+ status: task.status,
19
+ startTime: task.startTime,
20
+ exitCode: task.exitCode,
21
+ runtime: task.runtime,
22
+ })));
23
+ }, [backgroundTasks]);
24
+ // Load detail output for selected task
25
+ useEffect(() => {
26
+ if (viewMode === "detail" && detailTaskId) {
27
+ const output = getBackgroundTaskOutput(detailTaskId);
28
+ setDetailOutput(output);
29
+ }
30
+ }, [viewMode, detailTaskId, getBackgroundTaskOutput]);
31
+ const formatDuration = (ms) => {
32
+ if (ms < 1000)
33
+ return `${ms}ms`;
34
+ if (ms < 60000)
35
+ return `${Math.round(ms / 1000)}s`;
36
+ const minutes = Math.floor(ms / 60000);
37
+ const seconds = Math.round((ms % 60000) / 1000);
38
+ return `${minutes}m ${seconds}s`;
39
+ };
40
+ const formatTime = (timestamp) => {
41
+ return new Date(timestamp).toLocaleTimeString();
42
+ };
43
+ const stopTask = (taskId) => {
44
+ stopBackgroundTask(taskId);
45
+ };
46
+ useInput((input, key) => {
47
+ if (viewMode === "list") {
48
+ // List mode navigation
49
+ if (key.return) {
50
+ if (tasks.length > 0 && selectedIndex < tasks.length) {
51
+ const selectedTask = tasks[selectedIndex];
52
+ setDetailTaskId(selectedTask.id);
53
+ setViewMode("detail");
54
+ }
55
+ return;
56
+ }
57
+ if (key.escape) {
58
+ onCancel();
59
+ return;
60
+ }
61
+ if (key.upArrow) {
62
+ setSelectedIndex(Math.max(0, selectedIndex - 1));
63
+ return;
64
+ }
65
+ if (key.downArrow) {
66
+ setSelectedIndex(Math.min(tasks.length - 1, selectedIndex + 1));
67
+ return;
68
+ }
69
+ if (input === "k" && tasks.length > 0 && selectedIndex < tasks.length) {
70
+ const selectedTask = tasks[selectedIndex];
71
+ if (selectedTask.status === "running") {
72
+ stopTask(selectedTask.id);
73
+ }
74
+ return;
75
+ }
76
+ }
77
+ else if (viewMode === "detail") {
78
+ // Detail mode navigation
79
+ if (key.escape) {
80
+ setViewMode("list");
81
+ setDetailTaskId(null);
82
+ setDetailOutput(null);
83
+ return;
84
+ }
85
+ if (input === "k" && detailTaskId) {
86
+ const task = tasks.find((t) => t.id === detailTaskId);
87
+ if (task && task.status === "running") {
88
+ stopTask(detailTaskId);
89
+ }
90
+ return;
91
+ }
92
+ }
93
+ });
94
+ if (viewMode === "detail" && detailTaskId && detailOutput) {
95
+ const task = tasks.find((t) => t.id === detailTaskId);
96
+ if (!task) {
97
+ setViewMode("list");
98
+ return null;
99
+ }
100
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["Background Task Details: ", task.id] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Type:" }), " ", task.type] }) }), task.description && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Description:" }), " ", task.description] }) })), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", task.status, task.exitCode !== undefined && ` (exit code: ${task.exitCode})`] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Started:" }), " ", formatTime(task.startTime), task.runtime !== undefined && (_jsxs(Text, { children: [" ", "| ", _jsx(Text, { color: "blue", children: "Runtime:" }), " ", formatDuration(task.runtime)] }))] }) })] }), detailOutput.stdout && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "green", bold: true, children: "OUTPUT (last 10 lines):" }), _jsx(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: _jsx(Text, { children: detailOutput.stdout.split("\n").slice(-10).join("\n") }) })] })), detailOutput.stderr && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "red", bold: true, children: "ERRORS:" }), _jsx(Box, { borderStyle: "single", borderColor: "red", padding: 1, children: _jsx(Text, { color: "red", children: detailOutput.stderr.split("\n").slice(-10).join("\n") }) })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [task.status === "running" ? "k to stop · " : "", "Esc to go back"] }) })] }));
101
+ }
102
+ if (!backgroundTasks) {
103
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Background Tasks" }), _jsx(Text, { children: "Background tasks not available" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
104
+ }
105
+ if (tasks.length === 0) {
106
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Background Tasks" }), _jsx(Text, { children: "No background tasks found" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
107
+ }
108
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Background Tasks" }) }), _jsx(Text, { dimColor: true, children: "Select a task to view details" }), tasks.map((task, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "cyan" : undefined, children: [index === selectedIndex ? "▶ " : " ", index + 1, ". [", task.id, "] ", task.type, task.description ? `: ${task.description}` : "", _jsxs(Text, { color: task.status === "running"
109
+ ? "green"
110
+ : task.status === "completed"
111
+ ? "blue"
112
+ : "red", children: [" ", "(", task.status, ")"] })] }), index === selectedIndex && (_jsx(Box, { marginLeft: 4, flexDirection: "column", children: _jsxs(Text, { color: "gray", dimColor: true, children: ["Started: ", formatTime(task.startTime), task.runtime !== undefined &&
113
+ ` | Runtime: ${formatDuration(task.runtime)}`, task.exitCode !== undefined && ` | Exit: ${task.exitCode}`] }) }))] }, task.id))), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["\u2191/\u2193 to select \u00B7 Enter to view \u00B7", " ", tasks[selectedIndex]?.status === "running" ? "k to stop · " : "", "Esc to close"] }) })] }));
114
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAqEjC,CAAC"}
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAYrD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAwHjC,CAAC"}
@@ -1,12 +1,46 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box } from "ink";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useCallback } from "react";
3
+ import { Box, useStdout } from "ink";
3
4
  import { MessageList } from "./MessageList.js";
4
5
  import { InputBox } from "./InputBox.js";
5
- import { Confirmation } from "./Confirmation.js";
6
+ import { LoadingIndicator } from "./LoadingIndicator.js";
7
+ import { TaskList } from "./TaskList.js";
8
+ import { ConfirmationDetails } from "./ConfirmationDetails.js";
9
+ import { ConfirmationSelector } from "./ConfirmationSelector.js";
6
10
  import { useChat } from "../contexts/useChat.js";
7
11
  export const ChatInterface = () => {
8
- const { messages, isLoading, isCommandRunning, userInputHistory, isCompressing, sendMessage, abortMessage, saveMemory, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, rewindId, } = useChat();
12
+ const { stdout } = useStdout();
13
+ const [isDetailsTooTall, setIsDetailsTooTall] = useState(false);
14
+ const { messages, isLoading, isCommandRunning, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel: originalHandleConfirmationCancel, setWasLastDetailsTooTall, } = useChat();
15
+ const handleHeightMeasured = useCallback((height) => {
16
+ const terminalHeight = stdout?.rows || 24;
17
+ if (height > terminalHeight - 10) {
18
+ setIsDetailsTooTall(true);
19
+ }
20
+ else {
21
+ setIsDetailsTooTall(false);
22
+ }
23
+ }, [stdout?.rows]);
24
+ const handleConfirmationCancel = useCallback(() => {
25
+ if (isDetailsTooTall) {
26
+ setWasLastDetailsTooTall((prev) => prev + 1);
27
+ setIsDetailsTooTall(false);
28
+ }
29
+ originalHandleConfirmationCancel();
30
+ }, [
31
+ isDetailsTooTall,
32
+ originalHandleConfirmationCancel,
33
+ setWasLastDetailsTooTall,
34
+ ]);
35
+ const wrappedHandleConfirmationDecision = useCallback((decision) => {
36
+ if (isDetailsTooTall) {
37
+ setWasLastDetailsTooTall((prev) => prev + 1);
38
+ setIsDetailsTooTall(false);
39
+ }
40
+ handleConfirmationDecision(decision);
41
+ }, [isDetailsTooTall, handleConfirmationDecision, setWasLastDetailsTooTall]);
9
42
  if (!sessionId)
10
43
  return null;
11
- return (_jsxs(Box, { flexDirection: "column", height: "100%", paddingY: 1, paddingRight: 1, children: [_jsx(MessageList, { messages: messages, isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens, isExpanded: isExpanded }, String(isExpanded) + sessionId + rewindId), isConfirmationVisible && (_jsx(Confirmation, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })), !isConfirmationVisible && !isExpanded && (_jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, userInputHistory: userInputHistory, sendMessage: sendMessage, abortMessage: abortMessage, saveMemory: saveMemory, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand }))] }));
44
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(MessageList, { messages: messages, isLoading: isLoading, isCommandRunning: isCommandRunning, isExpanded: isExpanded, forceStaticLastMessage: isDetailsTooTall }), (isLoading || isCommandRunning || isCompressing) &&
45
+ !isConfirmationVisible && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), !isConfirmationVisible && _jsx(TaskList, {}), isConfirmationVisible && (_jsxs(_Fragment, { children: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, isExpanded: isExpanded, onHeightMeasured: handleHeightMeasured }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })] })), !isConfirmationVisible && !isExpanded && (_jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand }))] }));
12
46
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CommandSelector.d.ts","sourceRoot":"","sources":["../../src/components/CommandSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAwBnD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAwH1D,CAAC"}
1
+ {"version":3,"file":"CommandSelector.d.ts","sourceRoot":"","sources":["../../src/components/CommandSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAwBnD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0I1D,CAAC"}
@@ -3,9 +3,9 @@ import { useState } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  const AVAILABLE_COMMANDS = [
5
5
  {
6
- id: "bashes",
7
- name: "bashes",
8
- description: "View and manage background bash shells",
6
+ id: "tasks",
7
+ name: "tasks",
8
+ description: "View and manage background tasks (shells and subagents)",
9
9
  handler: () => { }, // Handler here won't be used, actual processing is in the hook
10
10
  },
11
11
  {
@@ -23,12 +23,16 @@ const AVAILABLE_COMMANDS = [
23
23
  ];
24
24
  export const CommandSelector = ({ searchQuery, onSelect, onInsert, onCancel, commands = [], // Default to empty array
25
25
  }) => {
26
+ const MAX_VISIBLE_ITEMS = 3;
26
27
  const [selectedIndex, setSelectedIndex] = useState(0);
27
28
  // Merge agent commands and local commands
28
29
  const allCommands = [...commands, ...AVAILABLE_COMMANDS];
29
30
  // Filter command list
30
31
  const filteredCommands = allCommands.filter((command) => !searchQuery ||
31
32
  command.id.toLowerCase().includes(searchQuery.toLowerCase()));
33
+ // Calculate visible window
34
+ const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, filteredCommands.length - MAX_VISIBLE_ITEMS)));
35
+ const visibleCommands = filteredCommands.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
32
36
  useInput((input, key) => {
33
37
  if (key.return) {
34
38
  if (filteredCommands.length > 0 &&
@@ -60,7 +64,11 @@ export const CommandSelector = ({ searchQuery, onSelect, onInsert, onCancel, com
60
64
  }
61
65
  });
62
66
  if (filteredCommands.length === 0) {
63
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "yellow", children: ["No commands found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
67
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", children: ["No commands found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
64
68
  }
65
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "magenta", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "magenta", bold: true, children: ["Command Selector ", searchQuery && `(filtering: "${searchQuery}")`] }) }), filteredCommands.map((command, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "magenta" : undefined, children: [index === selectedIndex ? "▶ " : " ", "/", command.id] }), index === selectedIndex && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { color: "gray", dimColor: true, children: command.description }) }))] }, command.id))), _jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["\u2191\u2193 navigate \u2022 Enter execute \u2022 ", onInsert ? "Tab insert • " : "", "Esc cancel"] }) })] }));
69
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "magenta", borderBottom: false, borderLeft: false, borderRight: false, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "magenta", bold: true, children: ["Command Selector ", searchQuery && `(filtering: "${searchQuery}")`] }) }), _jsx(Box, { flexDirection: "column", children: visibleCommands.map((command, index) => {
70
+ const actualIndex = startIndex + index;
71
+ const isSelected = actualIndex === selectedIndex;
72
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "magenta" : undefined, children: [isSelected ? "▶ " : " ", "/", command.id] }), isSelected && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { color: "gray", dimColor: true, children: command.description }) }))] }, command.id));
73
+ }) }), _jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["\u2191\u2193 navigate \u2022 Enter execute \u2022 ", onInsert ? "Tab insert • " : "", "Esc cancel"] }) })] }));
66
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CompressDisplay.d.ts","sourceRoot":"","sources":["../../src/components/CompressDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgD1D,CAAC"}
1
+ {"version":3,"file":"CompressDisplay.d.ts","sourceRoot":"","sources":["../../src/components/CompressDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+B1D,CAAC"}
@@ -1,17 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
3
  import { Box, Text } from "ink";
4
- export const CompressDisplay = ({ block, isExpanded = false, }) => {
4
+ export const CompressDisplay = ({ block }) => {
5
5
  const { content } = block;
6
- const MAX_LINES = 3; // Set maximum display lines for compressed content
7
- const { displayContent, isOverflowing } = useMemo(() => {
6
+ const { displayContent } = useMemo(() => {
8
7
  if (!content) {
9
- return { displayContent: "", isOverflowing: false };
8
+ return { displayContent: "" };
10
9
  }
11
- const lines = content.split("\n");
12
- const overflow = !isExpanded && lines.length > MAX_LINES;
13
- const display = overflow ? lines.slice(0, MAX_LINES).join("\n") : content;
14
- return { displayContent: display, isOverflowing: overflow };
15
- }, [content, isExpanded]);
16
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsx(Text, { children: "\uD83D\uDCE6 Compressed Messages" }) }), content && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: _jsx(Text, { color: "white", children: displayContent }) }), isOverflowing && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsxs(Text, { color: "yellow", dimColor: true, children: ["Content truncated (", content.split("\n").length, " lines total, showing first ", MAX_LINES, " lines. Press Ctrl+O to expand."] }) }))] }))] }));
10
+ return { displayContent: content };
11
+ }, [content]);
12
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsx(Text, { children: "\uD83D\uDCE6 Compressed Messages" }) }), content && (_jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: _jsx(Text, { color: "white", children: displayContent }) }) }))] }));
17
13
  };
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ export interface ConfirmationDetailsProps {
3
+ toolName: string;
4
+ toolInput?: Record<string, unknown>;
5
+ isExpanded?: boolean;
6
+ onHeightMeasured?: (height: number) => void;
7
+ }
8
+ export declare const ConfirmationDetails: React.FC<ConfirmationDetailsProps>;
9
+ //# sourceMappingURL=ConfirmationDetails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AA2CjE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAuDlE,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useLayoutEffect, useRef, useState } from "react";
3
+ import { Box, Text, useStdout, measureElement, Static } from "ink";
4
+ import { BASH_TOOL_NAME, EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME, DELETE_FILE_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
5
+ import { DiffDisplay } from "./DiffDisplay.js";
6
+ import { PlanDisplay } from "./PlanDisplay.js";
7
+ // Helper function to generate descriptive action text
8
+ const getActionDescription = (toolName, toolInput) => {
9
+ if (!toolInput) {
10
+ return "Execute operation";
11
+ }
12
+ switch (toolName) {
13
+ case BASH_TOOL_NAME:
14
+ return `Execute command: ${toolInput.command || "unknown command"}`;
15
+ case EDIT_TOOL_NAME:
16
+ return `Edit file: ${toolInput.file_path || "unknown file"}`;
17
+ case MULTI_EDIT_TOOL_NAME:
18
+ return `Edit multiple sections in: ${toolInput.file_path || "unknown file"}`;
19
+ case DELETE_FILE_TOOL_NAME:
20
+ return `Delete file: ${toolInput.target_file || "unknown file"}`;
21
+ case WRITE_TOOL_NAME:
22
+ return `Write to file: ${toolInput.file_path || "unknown file"}`;
23
+ case EXIT_PLAN_MODE_TOOL_NAME:
24
+ return "Review and approve the plan";
25
+ case ASK_USER_QUESTION_TOOL_NAME:
26
+ return "Answer questions to clarify intent";
27
+ default:
28
+ return "Execute operation";
29
+ }
30
+ };
31
+ export const ConfirmationDetails = ({ toolName, toolInput, isExpanded = false, onHeightMeasured, }) => {
32
+ const { stdout } = useStdout();
33
+ const [isStatic, setIsStatic] = useState(false);
34
+ const boxRef = useRef(null);
35
+ useLayoutEffect(() => {
36
+ if (boxRef.current) {
37
+ const { height } = measureElement(boxRef.current);
38
+ const terminalHeight = stdout?.rows || 24;
39
+ if (height > terminalHeight - 10) {
40
+ setIsStatic(true);
41
+ }
42
+ onHeightMeasured?.(height);
43
+ }
44
+ }, [stdout?.rows, onHeightMeasured]);
45
+ const content = (_jsxs(Box, { ref: boxRef, flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Tool: ", toolName] }), _jsx(Text, { color: "yellow", children: getActionDescription(toolName, toolInput) }), _jsx(DiffDisplay, { toolName: toolName, parameters: JSON.stringify(toolInput) }), toolName !== ASK_USER_QUESTION_TOOL_NAME &&
46
+ toolName === EXIT_PLAN_MODE_TOOL_NAME &&
47
+ !!toolInput?.plan_content && (_jsx(PlanDisplay, { plan: toolInput.plan_content, isExpanded: isExpanded }))] }));
48
+ if (isStatic) {
49
+ return _jsx(Static, { items: [1], children: () => content });
50
+ }
51
+ return content;
52
+ };
53
+ ConfirmationDetails.displayName = "ConfirmationDetails";
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type { PermissionDecision } from "wave-agent-sdk";
3
- export interface ConfirmationProps {
3
+ export interface ConfirmationSelectorProps {
4
4
  toolName: string;
5
5
  toolInput?: Record<string, unknown>;
6
6
  suggestedPrefix?: string;
@@ -10,5 +10,5 @@ export interface ConfirmationProps {
10
10
  onCancel: () => void;
11
11
  onAbort: () => void;
12
12
  }
13
- export declare const Confirmation: React.FC<ConfirmationProps>;
14
- //# sourceMappingURL=Confirmation.d.ts.map
13
+ export declare const ConfirmationSelector: React.FC<ConfirmationSelectorProps>;
14
+ //# sourceMappingURL=ConfirmationSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;AAgB/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AASD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA4apE,CAAC"}