wave-code 0.5.0 → 0.6.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 (88) hide show
  1. package/dist/components/BackgroundTaskManager.d.ts +6 -0
  2. package/dist/components/BackgroundTaskManager.d.ts.map +1 -0
  3. package/dist/components/{TaskManager.js → BackgroundTaskManager.js} +1 -1
  4. package/dist/components/ChatInterface.d.ts.map +1 -1
  5. package/dist/components/ChatInterface.js +55 -5
  6. package/dist/components/CommandSelector.d.ts.map +1 -1
  7. package/dist/components/CommandSelector.js +10 -2
  8. package/dist/components/CompressDisplay.d.ts.map +1 -1
  9. package/dist/components/CompressDisplay.js +6 -10
  10. package/dist/components/ConfirmationDetails.d.ts +9 -0
  11. package/dist/components/ConfirmationDetails.d.ts.map +1 -0
  12. package/dist/components/ConfirmationDetails.js +53 -0
  13. package/dist/components/{Confirmation.d.ts → ConfirmationSelector.d.ts} +3 -3
  14. package/dist/components/ConfirmationSelector.d.ts.map +1 -0
  15. package/dist/components/{Confirmation.js → ConfirmationSelector.js} +34 -96
  16. package/dist/components/DiffDisplay.d.ts.map +1 -1
  17. package/dist/components/DiffDisplay.js +44 -1
  18. package/dist/components/FileSelector.d.ts.map +1 -1
  19. package/dist/components/FileSelector.js +2 -2
  20. package/dist/components/HistorySearch.d.ts.map +1 -1
  21. package/dist/components/HistorySearch.js +12 -4
  22. package/dist/components/InputBox.d.ts +1 -2
  23. package/dist/components/InputBox.d.ts.map +1 -1
  24. package/dist/components/InputBox.js +5 -9
  25. package/dist/components/LoadingIndicator.d.ts +11 -0
  26. package/dist/components/LoadingIndicator.d.ts.map +1 -0
  27. package/dist/components/LoadingIndicator.js +6 -0
  28. package/dist/components/Markdown.d.ts.map +1 -1
  29. package/dist/components/Markdown.js +114 -121
  30. package/dist/components/MessageItem.d.ts.map +1 -1
  31. package/dist/components/MessageItem.js +1 -2
  32. package/dist/components/MessageList.d.ts +2 -3
  33. package/dist/components/MessageList.d.ts.map +1 -1
  34. package/dist/components/MessageList.js +7 -7
  35. package/dist/components/PlanDisplay.d.ts.map +1 -1
  36. package/dist/components/PlanDisplay.js +4 -12
  37. package/dist/components/SubagentBlock.d.ts.map +1 -1
  38. package/dist/components/SubagentBlock.js +9 -6
  39. package/dist/components/TaskList.d.ts +3 -0
  40. package/dist/components/TaskList.d.ts.map +1 -0
  41. package/dist/components/TaskList.js +49 -0
  42. package/dist/components/ToolResultDisplay.js +1 -1
  43. package/dist/contexts/useChat.d.ts +5 -2
  44. package/dist/contexts/useChat.d.ts.map +1 -1
  45. package/dist/contexts/useChat.js +25 -25
  46. package/dist/hooks/useInputManager.d.ts +2 -7
  47. package/dist/hooks/useInputManager.d.ts.map +1 -1
  48. package/dist/hooks/useInputManager.js +8 -40
  49. package/dist/hooks/useTasks.d.ts +2 -0
  50. package/dist/hooks/useTasks.d.ts.map +1 -0
  51. package/dist/hooks/useTasks.js +5 -0
  52. package/dist/managers/InputManager.d.ts +4 -19
  53. package/dist/managers/InputManager.d.ts.map +1 -1
  54. package/dist/managers/InputManager.js +22 -65
  55. package/package.json +5 -6
  56. package/src/components/{TaskManager.tsx → BackgroundTaskManager.tsx} +4 -2
  57. package/src/components/ChatInterface.tsx +100 -20
  58. package/src/components/CommandSelector.tsx +35 -17
  59. package/src/components/CompressDisplay.tsx +5 -22
  60. package/src/components/ConfirmationDetails.tsx +108 -0
  61. package/src/components/{Confirmation.tsx → ConfirmationSelector.tsx} +69 -184
  62. package/src/components/DiffDisplay.tsx +62 -1
  63. package/src/components/FileSelector.tsx +0 -2
  64. package/src/components/HistorySearch.tsx +45 -21
  65. package/src/components/InputBox.tsx +9 -24
  66. package/src/components/LoadingIndicator.tsx +56 -0
  67. package/src/components/Markdown.tsx +126 -323
  68. package/src/components/MessageItem.tsx +1 -3
  69. package/src/components/MessageList.tsx +10 -67
  70. package/src/components/PlanDisplay.tsx +4 -27
  71. package/src/components/SubagentBlock.tsx +25 -16
  72. package/src/components/TaskList.tsx +70 -0
  73. package/src/components/ToolResultDisplay.tsx +2 -2
  74. package/src/contexts/useChat.tsx +38 -33
  75. package/src/hooks/useInputManager.ts +9 -47
  76. package/src/hooks/useTasks.ts +6 -0
  77. package/src/managers/InputManager.ts +25 -83
  78. package/dist/components/Confirmation.d.ts.map +0 -1
  79. package/dist/components/MemoryDisplay.d.ts +0 -8
  80. package/dist/components/MemoryDisplay.d.ts.map +0 -1
  81. package/dist/components/MemoryDisplay.js +0 -25
  82. package/dist/components/MemoryTypeSelector.d.ts +0 -8
  83. package/dist/components/MemoryTypeSelector.d.ts.map +0 -1
  84. package/dist/components/MemoryTypeSelector.js +0 -38
  85. package/dist/components/TaskManager.d.ts +0 -6
  86. package/dist/components/TaskManager.d.ts.map +0 -1
  87. package/src/components/MemoryDisplay.tsx +0 -62
  88. package/src/components/MemoryTypeSelector.tsx +0 -98
@@ -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"}
@@ -2,7 +2,7 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  import { useChat } from "../contexts/useChat.js";
5
- export const TaskManager = ({ onCancel }) => {
5
+ export const BackgroundTaskManager = ({ onCancel, }) => {
6
6
  const { backgroundTasks, getBackgroundTaskOutput, stopBackgroundTask } = useChat();
7
7
  const [tasks, setTasks] = useState([]);
8
8
  const [selectedIndex, setSelectedIndex] = useState(0);
@@ -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,KAA2C,MAAM,OAAO,CAAC;AAYhE,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAgJjC,CAAC"}
@@ -1,12 +1,62 @@
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, useEffect } 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 [wasLastDetailsTooTall, setWasLastDetailsTooTall] = useState(0);
15
+ const { messages, isLoading, isCommandRunning, userInputHistory, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel: originalHandleConfirmationCancel, rewindId, } = useChat();
16
+ const [remountKey, setRemountKey] = useState(String(isExpanded) + sessionId + rewindId + wasLastDetailsTooTall);
17
+ useEffect(() => {
18
+ const newKey = String(isExpanded) + sessionId + rewindId + wasLastDetailsTooTall;
19
+ if (newKey !== remountKey) {
20
+ stdout?.write("\u001b[2J\u001b[0;0H", (err) => {
21
+ if (err) {
22
+ console.error("Failed to clear terminal:", err);
23
+ }
24
+ setRemountKey(newKey);
25
+ });
26
+ }
27
+ }, [
28
+ isExpanded,
29
+ sessionId,
30
+ rewindId,
31
+ wasLastDetailsTooTall,
32
+ remountKey,
33
+ stdout,
34
+ ]);
35
+ const handleHeightMeasured = useCallback((height) => {
36
+ const terminalHeight = stdout?.rows || 24;
37
+ if (height > terminalHeight - 10) {
38
+ setIsDetailsTooTall(true);
39
+ }
40
+ else {
41
+ setIsDetailsTooTall(false);
42
+ }
43
+ }, [stdout?.rows]);
44
+ const handleConfirmationCancel = useCallback(() => {
45
+ if (isDetailsTooTall) {
46
+ setWasLastDetailsTooTall((prev) => prev + 1);
47
+ setIsDetailsTooTall(false);
48
+ }
49
+ originalHandleConfirmationCancel();
50
+ }, [isDetailsTooTall, originalHandleConfirmationCancel]);
51
+ const wrappedHandleConfirmationDecision = useCallback((decision) => {
52
+ if (isDetailsTooTall) {
53
+ setWasLastDetailsTooTall((prev) => prev + 1);
54
+ setIsDetailsTooTall(false);
55
+ }
56
+ handleConfirmationDecision(decision);
57
+ }, [isDetailsTooTall, handleConfirmationDecision]);
9
58
  if (!sessionId)
10
59
  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 }))] }));
60
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(MessageList, { messages: messages, isLoading: isLoading, isCommandRunning: isCommandRunning, isExpanded: isExpanded, forceStaticLastMessage: isDetailsTooTall }, remountKey), (isLoading || isCommandRunning || isCompressing) &&
61
+ !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, userInputHistory: userInputHistory, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand }))] }));
12
62
  };
@@ -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"}
@@ -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"}
@@ -1,33 +1,7 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { Box, Text, useInput } 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
- };
4
+ import { BASH_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
31
5
  const getHeaderColor = (header) => {
32
6
  const colors = ["red", "green", "blue", "magenta", "cyan"];
33
7
  let hash = 0;
@@ -36,14 +10,13 @@ const getHeaderColor = (header) => {
36
10
  }
37
11
  return colors[Math.abs(hash) % colors.length];
38
12
  };
39
- export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersistentOption, isExpanded = false, onDecision, onCancel, onAbort, }) => {
13
+ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hidePersistentOption, isExpanded = false, onDecision, onCancel, onAbort, }) => {
40
14
  const [state, setState] = useState({
41
15
  selectedOption: "allow",
42
16
  alternativeText: "",
43
17
  alternativeCursorPosition: 0,
44
18
  hasUserInput: false,
45
19
  });
46
- // Specialized state for AskUserQuestion
47
20
  const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
48
21
  const [selectedOptionIndex, setSelectedOptionIndex] = useState(0);
49
22
  const [selectedOptionIndices, setSelectedOptionIndices] = useState(new Set());
@@ -65,7 +38,6 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
65
38
  return "Yes, and auto-accept edits";
66
39
  };
67
40
  useInput((input, key) => {
68
- // Handle ESC to cancel and abort
69
41
  if (key.escape) {
70
42
  onCancel();
71
43
  onAbort();
@@ -75,7 +47,7 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
75
47
  if (!currentQuestion)
76
48
  return;
77
49
  const options = [...currentQuestion.options, { label: "Other" }];
78
- const isMultiSelect = !!currentQuestion.multiSelect;
50
+ const isMultiSelect = currentQuestion.multiSelect;
79
51
  const isOtherFocused = selectedOptionIndex === options.length - 1;
80
52
  if (key.return) {
81
53
  let answer = "";
@@ -112,7 +84,6 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
112
84
  setOtherCursorPosition(0);
113
85
  }
114
86
  else {
115
- // All questions answered
116
87
  onDecision({
117
88
  behavior: "allow",
118
89
  message: JSON.stringify(newAnswers),
@@ -125,31 +96,25 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
125
96
  (!isOtherFocused || !selectedOptionIndices.has(selectedOptionIndex))) {
126
97
  setSelectedOptionIndices((prev) => {
127
98
  const next = new Set(prev);
128
- if (next.has(selectedOptionIndex)) {
99
+ if (next.has(selectedOptionIndex))
129
100
  next.delete(selectedOptionIndex);
130
- }
131
- else {
101
+ else
132
102
  next.add(selectedOptionIndex);
133
- }
134
103
  return next;
135
104
  });
136
105
  return;
137
106
  }
138
- if (!isOtherFocused) {
107
+ if (!isOtherFocused)
139
108
  return;
140
- }
141
- // If isOtherFocused is true, fall through to handle space as text input
142
109
  }
143
110
  if (key.upArrow) {
144
- if (selectedOptionIndex > 0) {
111
+ if (selectedOptionIndex > 0)
145
112
  setSelectedOptionIndex(selectedOptionIndex - 1);
146
- }
147
113
  return;
148
114
  }
149
115
  if (key.downArrow) {
150
- if (selectedOptionIndex < options.length - 1) {
116
+ if (selectedOptionIndex < options.length - 1)
151
117
  setSelectedOptionIndex(selectedOptionIndex + 1);
152
- }
153
118
  return;
154
119
  }
155
120
  if (isOtherFocused) {
@@ -163,30 +128,22 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
163
128
  }
164
129
  if (key.backspace || key.delete) {
165
130
  if (otherCursorPosition > 0) {
166
- setOtherText((prev) => {
167
- const next = prev.slice(0, otherCursorPosition - 1) +
168
- prev.slice(otherCursorPosition);
169
- return next;
170
- });
131
+ setOtherText((prev) => prev.slice(0, otherCursorPosition - 1) +
132
+ prev.slice(otherCursorPosition));
171
133
  setOtherCursorPosition((prev) => prev - 1);
172
134
  }
173
135
  return;
174
136
  }
175
137
  if (input && !key.ctrl && !key.meta) {
176
- setOtherText((prev) => {
177
- const next = prev.slice(0, otherCursorPosition) +
178
- input +
179
- prev.slice(otherCursorPosition);
180
- return next;
181
- });
138
+ setOtherText((prev) => prev.slice(0, otherCursorPosition) +
139
+ input +
140
+ prev.slice(otherCursorPosition));
182
141
  setOtherCursorPosition((prev) => prev + input.length);
183
142
  return;
184
143
  }
185
- return;
186
144
  }
187
145
  return;
188
146
  }
189
- // Handle Enter to confirm selection
190
147
  if (key.return) {
191
148
  if (state.selectedOption === "allow") {
192
149
  if (toolName === EXIT_PLAN_MODE_TOOL_NAME) {
@@ -201,26 +158,14 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
201
158
  const rule = suggestedPrefix
202
159
  ? `Bash(${suggestedPrefix}*)`
203
160
  : `Bash(${toolInput?.command})`;
204
- onDecision({
205
- behavior: "allow",
206
- newPermissionRule: rule,
207
- });
161
+ onDecision({ behavior: "allow", newPermissionRule: rule });
208
162
  }
209
163
  else {
210
- onDecision({
211
- behavior: "allow",
212
- newPermissionMode: "acceptEdits",
213
- });
164
+ onDecision({ behavior: "allow", newPermissionMode: "acceptEdits" });
214
165
  }
215
166
  }
216
- else {
217
- // For alternative option, require text input
218
- if (state.alternativeText.trim()) {
219
- onDecision({
220
- behavior: "deny",
221
- message: state.alternativeText.trim(),
222
- });
223
- }
167
+ else if (state.alternativeText.trim()) {
168
+ onDecision({ behavior: "deny", message: state.alternativeText.trim() });
224
169
  }
225
170
  return;
226
171
  }
@@ -240,15 +185,13 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
240
185
  return;
241
186
  }
242
187
  }
243
- // Handle arrow keys for navigation
244
188
  if (key.upArrow) {
245
189
  setState((prev) => {
246
- if (prev.selectedOption === "alternative") {
190
+ if (prev.selectedOption === "alternative")
247
191
  return {
248
192
  ...prev,
249
193
  selectedOption: hidePersistentOption ? "allow" : "auto",
250
194
  };
251
- }
252
195
  if (prev.selectedOption === "auto")
253
196
  return { ...prev, selectedOption: "allow" };
254
197
  return prev;
@@ -257,21 +200,18 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
257
200
  }
258
201
  if (key.downArrow) {
259
202
  setState((prev) => {
260
- if (prev.selectedOption === "allow") {
203
+ if (prev.selectedOption === "allow")
261
204
  return {
262
205
  ...prev,
263
206
  selectedOption: hidePersistentOption ? "alternative" : "auto",
264
207
  };
265
- }
266
208
  if (prev.selectedOption === "auto")
267
209
  return { ...prev, selectedOption: "alternative" };
268
210
  return prev;
269
211
  });
270
212
  return;
271
213
  }
272
- // Handle text input for alternative option
273
214
  if (input && !key.ctrl && !key.meta && !("alt" in key && key.alt)) {
274
- // Focus on alternative option when user starts typing
275
215
  setState((prev) => {
276
216
  const nextText = prev.alternativeText.slice(0, prev.alternativeCursorPosition) +
277
217
  input +
@@ -286,7 +226,6 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
286
226
  });
287
227
  return;
288
228
  }
289
- // Handle backspace and delete
290
229
  if (key.backspace || key.delete) {
291
230
  setState((prev) => {
292
231
  if (prev.alternativeCursorPosition > 0) {
@@ -307,22 +246,21 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
307
246
  });
308
247
  const placeholderText = "Type here to tell Wave what to do differently";
309
248
  const showPlaceholder = state.selectedOption === "alternative" && !state.hasUserInput;
310
- return (_jsxs(Box, { 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 &&
249
+ return (_jsxs(Box, { flexDirection: "column", children: [toolName === ASK_USER_QUESTION_TOOL_NAME &&
311
250
  currentQuestion &&
312
- !isExpanded && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Box, { backgroundColor: getHeaderColor(currentQuestion.header), paddingX: 1, marginRight: 1, children: _jsx(Text, { color: "black", bold: true, children: currentQuestion.header.slice(0, 12).toUpperCase() }) }), _jsx(Text, { bold: true, children: currentQuestion.question })] }), _jsx(Box, { flexDirection: "column", children: (() => {
313
- const isMultiSelect = !!currentQuestion.multiSelect;
314
- return [...currentQuestion.options, { label: "Other" }].map((option, index) => {
315
- const isSelected = selectedOptionIndex === index;
316
- const isChecked = isMultiSelect
317
- ? selectedOptionIndices.has(index)
318
- : isSelected;
319
- const isOther = index === currentQuestion.options.length;
320
- const isRecommended = !isOther && option.isRecommended;
321
- return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "yellow" : undefined, children: [isSelected ? "> " : " ", isMultiSelect ? (isChecked ? "[x] " : "[ ] ") : "", option.label, isRecommended && (_jsxs(Text, { color: "green", bold: true, children: [" ", "(Recommended)"] })), option.description ? ` - ${option.description}` : "", isOther && isSelected && (_jsxs(Text, { children: [":", " ", otherText ? (_jsxs(_Fragment, { children: [otherText.slice(0, otherCursorPosition), _jsx(Text, { backgroundColor: "white", color: "black", children: otherText[otherCursorPosition] || " " }), otherText.slice(otherCursorPosition + 1)] })) : (_jsx(Text, { color: "gray", dimColor: true, children: "[Type your answer...]" }))] }))] }) }, index));
322
- });
323
- })() }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Question ", currentQuestionIndex + 1, " of ", questions.length, " \u2022", currentQuestion.multiSelect ? " Space to toggle •" : "", " Use \u2191\u2193 to navigate \u2022 Enter to confirm"] }) })] })), toolName !== ASK_USER_QUESTION_TOOL_NAME &&
324
- toolName === EXIT_PLAN_MODE_TOOL_NAME &&
325
- !!toolInput?.plan_content && (_jsx(PlanDisplay, { plan: toolInput.plan_content, isExpanded: isExpanded })), toolName !== ASK_USER_QUESTION_TOOL_NAME && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Do you want to proceed?" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "allow" ? "black" : "white", backgroundColor: state.selectedOption === "allow" ? "yellow" : undefined, bold: state.selectedOption === "allow", children: [state.selectedOption === "allow" ? "> " : " ", toolName === EXIT_PLAN_MODE_TOOL_NAME
251
+ !isExpanded && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Box, { backgroundColor: getHeaderColor(currentQuestion.header), paddingX: 1, marginRight: 1, children: _jsx(Text, { color: "black", bold: true, children: currentQuestion.header.slice(0, 12).toUpperCase() }) }), _jsx(Text, { bold: true, children: currentQuestion.question })] }), _jsx(Box, { flexDirection: "column", children: [...currentQuestion.options, { label: "Other" }].map((option, index) => {
252
+ const isSelected = selectedOptionIndex === index;
253
+ const isChecked = currentQuestion.multiSelect
254
+ ? selectedOptionIndices.has(index)
255
+ : isSelected;
256
+ const isOther = index === currentQuestion.options.length;
257
+ return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "yellow" : undefined, children: [isSelected ? "> " : " ", currentQuestion.multiSelect
258
+ ? isChecked
259
+ ? "[x] "
260
+ : "[ ] "
261
+ : "", option.label, option.description ? ` - ${option.description}` : "", isOther && isSelected && (_jsxs(Text, { children: [":", " ", otherText ? (_jsxs(_Fragment, { children: [otherText.slice(0, otherCursorPosition), _jsx(Text, { backgroundColor: "white", color: "black", children: otherText[otherCursorPosition] || " " }), otherText.slice(otherCursorPosition + 1)] })) : (_jsx(Text, { color: "gray", dimColor: true, children: "[Type your answer...]" }))] }))] }) }, index));
262
+ }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Question ", currentQuestionIndex + 1, " of ", questions.length, " \u2022", currentQuestion.multiSelect ? " Space to toggle •" : "", " Use \u2191\u2193 to navigate \u2022 Enter to confirm"] }) })] })), toolName !== ASK_USER_QUESTION_TOOL_NAME && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Do you want to proceed?" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "allow" ? "black" : "white", backgroundColor: state.selectedOption === "allow" ? "yellow" : undefined, bold: state.selectedOption === "allow", children: [state.selectedOption === "allow" ? "> " : " ", toolName === EXIT_PLAN_MODE_TOOL_NAME
326
263
  ? "Yes, proceed with default mode"
327
264
  : "Yes"] }) }, "allow-option"), !hidePersistentOption && (_jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "auto" ? "black" : "white", backgroundColor: state.selectedOption === "auto" ? "yellow" : undefined, bold: state.selectedOption === "auto", children: [state.selectedOption === "auto" ? "> " : " ", getAutoOptionText()] }) }, "auto-option")), _jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "alternative" ? "black" : "white", backgroundColor: state.selectedOption === "alternative" ? "yellow" : undefined, bold: state.selectedOption === "alternative", children: [state.selectedOption === "alternative" ? "> " : " ", showPlaceholder ? (_jsx(Text, { color: "gray", dimColor: true, children: placeholderText })) : (_jsx(Text, { children: state.alternativeText ? (_jsxs(_Fragment, { children: [state.alternativeText.slice(0, state.alternativeCursorPosition), _jsx(Text, { backgroundColor: "white", color: "black", children: state.alternativeText[state.alternativeCursorPosition] || " " }), state.alternativeText.slice(state.alternativeCursorPosition + 1)] })) : ("Type here to tell Wave what to do differently") }))] }) }, "alternative-option")] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate \u2022 ESC to cancel" }) })] }))] }));
328
265
  };
266
+ ConfirmationSelector.displayName = "ConfirmationSelector";
@@ -1 +1 @@
1
- {"version":3,"file":"DiffDisplay.d.ts","sourceRoot":"","sources":["../../src/components/DiffDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAUvC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA4OlD,CAAC"}
1
+ {"version":3,"file":"DiffDisplay.d.ts","sourceRoot":"","sources":["../../src/components/DiffDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAUvC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAySlD,CAAC"}
@@ -88,9 +88,52 @@ export const DiffDisplay = ({ toolName, parameters, }) => {
88
88
  const lines = part.value
89
89
  .split("\n")
90
90
  .filter((line) => line !== "");
91
- lines.forEach((line, lineIndex) => {
91
+ const isFirstBlock = partIndex === 0;
92
+ const isLastBlock = partIndex === lineDiffs.length - 1;
93
+ let linesToDisplay = lines;
94
+ let showEllipsisTop = false;
95
+ let showEllipsisBottom = false;
96
+ if (isFirstBlock && !isLastBlock) {
97
+ // First block: keep last 3
98
+ if (lines.length > 3) {
99
+ linesToDisplay = lines.slice(-3);
100
+ showEllipsisTop = true;
101
+ }
102
+ }
103
+ else if (isLastBlock && !isFirstBlock) {
104
+ // Last block: keep first 3
105
+ if (lines.length > 3) {
106
+ linesToDisplay = lines.slice(0, 3);
107
+ showEllipsisBottom = true;
108
+ }
109
+ }
110
+ else if (!isFirstBlock && !isLastBlock) {
111
+ // Middle block: keep first 3 and last 3
112
+ if (lines.length > 6) {
113
+ linesToDisplay = [...lines.slice(0, 3), ...lines.slice(-3)];
114
+ showEllipsisTop = false; // We'll put ellipsis in the middle
115
+ }
116
+ }
117
+ else if (isFirstBlock && isLastBlock) {
118
+ // Only one block (no changes?) - keep all or apply a general limit
119
+ // For now, let's keep all if it's the only block
120
+ }
121
+ if (showEllipsisTop) {
122
+ diffElements.push(_jsx(Box, { children: _jsx(Text, { color: "gray", children: " ..." }) }, `ellipsis-top-${changeIndex}-${partIndex}`));
123
+ }
124
+ linesToDisplay.forEach((line, lineIndex) => {
125
+ // If it's a middle block and we are at the split point
126
+ if (!isFirstBlock &&
127
+ !isLastBlock &&
128
+ lines.length > 6 &&
129
+ lineIndex === 3) {
130
+ diffElements.push(_jsx(Box, { children: _jsx(Text, { color: "gray", children: " ..." }) }, `ellipsis-mid-${changeIndex}-${partIndex}`));
131
+ }
92
132
  diffElements.push(_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "white", children: " " }), _jsx(Text, { color: "white", children: line })] }, `context-${changeIndex}-${partIndex}-${lineIndex}`));
93
133
  });
134
+ if (showEllipsisBottom) {
135
+ diffElements.push(_jsx(Box, { children: _jsx(Text, { color: "gray", children: " ..." }) }, `ellipsis-bottom-${changeIndex}-${partIndex}`));
136
+ }
94
137
  }
95
138
  });
96
139
  // If it's a single line change (one removed, one added), use word-level diff
@@ -1 +1 @@
1
- {"version":3,"file":"FileSelector.d.ts","sourceRoot":"","sources":["../../src/components/FileSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA6HpD,CAAC"}
1
+ {"version":3,"file":"FileSelector.d.ts","sourceRoot":"","sources":["../../src/components/FileSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA2HpD,CAAC"}
@@ -24,7 +24,7 @@ export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
24
24
  }
25
25
  });
26
26
  if (files.length === 0) {
27
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "yellow", children: ["\uD83D\uDCC1 No files found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
27
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", children: ["\uD83D\uDCC1 No files found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
28
28
  }
29
29
  const maxDisplay = 10;
30
30
  // Calculate display window start and end positions
@@ -39,7 +39,7 @@ export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
39
39
  };
40
40
  };
41
41
  const { startIndex, endIndex, displayFiles } = getDisplayWindow();
42
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["\uD83D\uDCC1 Select File/Directory", " ", searchQuery && `(filtering: "${searchQuery}")`] }), startIndex > 0 && (_jsxs(Text, { dimColor: true, children: ["... ", startIndex, " more files above"] })), displayFiles.map((fileItem, displayIndex) => {
42
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["\uD83D\uDCC1 Select File/Directory", " ", searchQuery && `(filtering: "${searchQuery}")`] }), startIndex > 0 && (_jsxs(Text, { dimColor: true, children: ["... ", startIndex, " more files above"] })), displayFiles.map((fileItem, displayIndex) => {
43
43
  const actualIndex = startIndex + displayIndex;
44
44
  const isSelected = actualIndex === selectedIndex;
45
45
  const icon = fileItem.type === "directory" ? "📁" : "📄";