wave-code 0.5.1 → 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 -324
  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
@@ -1 +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"}
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,CAiKtD,CAAC"}
@@ -3,6 +3,7 @@ import React, { useState, useEffect } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  import { PromptHistoryManager } from "wave-agent-sdk";
5
5
  export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
6
+ const MAX_VISIBLE_ITEMS = 5;
6
7
  const [selectedIndex, setSelectedIndex] = useState(0);
7
8
  const [entries, setEntries] = useState([]);
8
9
  const entriesRef = React.useRef([]);
@@ -16,8 +17,8 @@ export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
16
17
  useEffect(() => {
17
18
  const fetchHistory = async () => {
18
19
  const results = await PromptHistoryManager.searchHistory(searchQuery);
19
- const limitedResults = results.slice(0, 10);
20
- setEntries(limitedResults); // Limit to 10 results
20
+ const limitedResults = results.slice(0, 20);
21
+ setEntries(limitedResults); // Limit to 20 results
21
22
  setSelectedIndex(0);
22
23
  };
23
24
  fetchHistory();
@@ -44,7 +45,7 @@ export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
44
45
  }
45
46
  });
46
47
  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
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", children: ["No history found ", searchQuery && `for "${searchQuery}"`] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
48
49
  }
49
50
  const formatTimestamp = (timestamp) => {
50
51
  const date = new Date(timestamp);
@@ -63,5 +64,12 @@ export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
63
64
  return diffMinutes > 0 ? `${diffMinutes}m ago` : "just now";
64
65
  }
65
66
  };
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
+ // Calculate visible window
68
+ const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, entries.length - MAX_VISIBLE_ITEMS)));
69
+ const visibleEntries = entries.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
70
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "blue", borderBottom: false, borderLeft: false, borderRight: false, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "blue", bold: true, children: ["Prompt History ", searchQuery && `(filtering: "${searchQuery}")`] }) }), _jsx(Box, { flexDirection: "column", children: visibleEntries.map((entry, index) => {
71
+ const actualIndex = startIndex + index;
72
+ const isSelected = actualIndex === selectedIndex;
73
+ return (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", children: [_jsx(Box, { flexShrink: 1, children: _jsx(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "blue" : undefined, wrap: "truncate-end", children: entry.prompt.replace(/\n/g, " ") }) }), isSelected && (_jsx(Box, { marginLeft: 2, flexShrink: 0, children: _jsx(Text, { color: "gray", dimColor: true, children: formatTimestamp(entry.timestamp) }) }))] }, actualIndex));
74
+ }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select, Escape to cancel" }) })] }));
67
75
  };
@@ -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, # to add memory, Ctrl+R to search history)...";
3
+ export declare const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, Ctrl+R to search history, Ctrl+O to expand messages, Ctrl+T to toggle tasks)...";
4
4
  export declare const INPUT_PLACEHOLDER_TEXT_PREFIX: string;
5
5
  export interface InputBoxProps {
6
6
  isLoading?: boolean;
@@ -12,7 +12,6 @@ export interface InputBoxProps {
12
12
  mimeType: string;
13
13
  }>) => void;
14
14
  abortMessage?: () => void;
15
- saveMemory?: (message: string, type: "project" | "user") => Promise<void>;
16
15
  mcpServers?: McpServerStatus[];
17
16
  connectMcpServer?: (serverName: string) => Promise<boolean>;
18
17
  disconnectMcpServer?: (serverName: string) => Promise<boolean>;
@@ -1 +1 @@
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
+ {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAYzC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,iJAC6G,CAAC;AAEjJ,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;IAE1B,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,CAoN5C,CAAC"}
@@ -5,15 +5,14 @@ import { useInput } from "ink";
5
5
  import { FileSelector } from "./FileSelector.js";
6
6
  import { CommandSelector } from "./CommandSelector.js";
7
7
  import { HistorySearch } from "./HistorySearch.js";
8
- import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
9
- import { TaskManager } from "./TaskManager.js";
8
+ import { BackgroundTaskManager } from "./BackgroundTaskManager.js";
10
9
  import { McpManager } from "./McpManager.js";
11
10
  import { RewindCommand } from "./RewindCommand.js";
12
11
  import { useInputManager } from "../hooks/useInputManager.js";
13
12
  import { useChat } from "../contexts/useChat.js";
14
- export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, # to add memory, Ctrl+R to search history)...";
13
+ export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, Ctrl+R to search history, Ctrl+O to expand messages, Ctrl+T to toggle tasks)...";
15
14
  export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
16
- export const InputBox = ({ isLoading = false, isCommandRunning = false, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, saveMemory = async () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
15
+ export const InputBox = ({ isLoading = false, isCommandRunning = false, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
17
16
  const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, } = useChat();
18
17
  // Input manager with all input state and functionality (including images)
19
18
  const { inputText, cursorPosition,
@@ -23,12 +22,10 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, userInpu
23
22
  showFileSelector, filteredFiles, fileSearchQuery: searchQuery, handleFileSelect, handleCancelFileSelect,
24
23
  // Command selector
25
24
  showCommandSelector, commandSearchQuery, handleCommandSelect, handleCommandInsert, handleCancelCommandSelect, handleHistorySearchSelect, handleCancelHistorySearch,
26
- // Memory type selector
27
- showMemoryTypeSelector, memoryMessage, handleMemoryTypeSelect, handleCancelMemoryTypeSelect,
28
25
  // History search
29
26
  showHistorySearch, historySearchQuery,
30
27
  // Task/MCP Manager
31
- showTaskManager, showMcpManager, showRewindManager, setShowTaskManager, setShowMcpManager, setShowRewindManager,
28
+ showBackgroundTaskManager, showMcpManager, showRewindManager, setShowBackgroundTaskManager, setShowMcpManager, setShowRewindManager,
32
29
  // Permission mode
33
30
  permissionMode, setPermissionMode,
34
31
  // Input history
@@ -39,7 +36,6 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, userInpu
39
36
  isManagerReady, } = useInputManager({
40
37
  onSendMessage: sendMessage,
41
38
  onHasSlashCommand: hasSlashCommand,
42
- onSaveMemory: saveMemory,
43
39
  onAbortMessage: abortMessage,
44
40
  onBackgroundCurrentTask: backgroundCurrentTask,
45
41
  onPermissionModeChange: setChatPermissionMode,
@@ -84,5 +80,5 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, userInpu
84
80
  if (showRewindManager) {
85
81
  return (_jsx(RewindCommand, { messages: messages, onSelect: handleRewindSelectWithClose, onCancel: handleRewindCancel }));
86
82
  }
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)"] }) })] }))] }));
83
+ 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 })), showBackgroundTaskManager && (_jsx(BackgroundTaskManager, { onCancel: () => setShowBackgroundTaskManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showBackgroundTaskManager || 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, justifyContent: "space-between", width: "100%", children: _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan" ? "yellow" : "cyan", children: permissionMode }), " ", "(Shift+Tab to cycle)"] }) })] }))] }));
88
84
  };
@@ -0,0 +1,11 @@
1
+ export interface LoadingIndicatorProps {
2
+ isLoading?: boolean;
3
+ isCommandRunning?: boolean;
4
+ isCompressing?: boolean;
5
+ latestTotalTokens?: number;
6
+ }
7
+ export declare const LoadingIndicator: {
8
+ ({ isLoading, isCommandRunning, isCompressing, latestTotalTokens, }: LoadingIndicatorProps): import("react/jsx-runtime").JSX.Element;
9
+ displayName: string;
10
+ };
11
+ //# sourceMappingURL=LoadingIndicator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingIndicator.d.ts","sourceRoot":"","sources":["../../src/components/LoadingIndicator.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,gBAAgB;yEAK1B,qBAAqB;;CAsCvB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ export const LoadingIndicator = ({ isLoading = false, isCommandRunning = false, isCompressing = false, latestTotalTokens = 0, }) => {
4
+ return (_jsxs(Box, { flexDirection: "column", children: [isLoading && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "\uD83D\uDCAD AI is thinking... " }), latestTotalTokens > 0 && (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "blue", bold: true, children: latestTotalTokens.toLocaleString() }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "tokens", " "] })] })), _jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "red", bold: true, children: "Esc" }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "to abort"] })] })), isCommandRunning && _jsx(Text, { color: "blue", children: "\uD83D\uDE80 Command is running..." }), isCompressing && (_jsx(Text, { color: "magenta", children: "\uD83D\uDDDC\uFE0F Compressing message history..." }))] }));
5
+ };
6
+ LoadingIndicator.displayName = "LoadingIndicator";
@@ -1 +1 @@
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;AAoVD,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;AAwID,eAAO,MAAM,QAAQ,2CAA6B,aAAa,6CAc7D,CAAC"}
@@ -1,8 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useMemo } from "react";
3
- import { Box, Text, useStdout } from "ink";
4
- import { marked } from "marked";
5
- import { highlight, supportsLanguage } from "cli-highlight";
3
+ import { Box, Text } from "ink";
4
+ import { Renderer, marked } from "marked";
5
+ import chalk from "chalk";
6
6
  const unescapeHtml = (html) => {
7
7
  return html
8
8
  .replace(/&amp;/g, "&")
@@ -12,124 +12,117 @@ const unescapeHtml = (html) => {
12
12
  .replace(/&#39;/g, "'")
13
13
  .replace(/&apos;/g, "'");
14
14
  };
15
- const InlineRenderer = ({ tokens }) => {
16
- return (_jsx(_Fragment, { children: tokens.map((token, index) => {
17
- switch (token.type) {
18
- case "text": {
19
- const t = token;
20
- if (t.tokens) {
21
- return _jsx(InlineRenderer, { tokens: t.tokens }, index);
22
- }
23
- return _jsx(Text, { children: unescapeHtml(t.text) }, index);
24
- }
25
- case "strong":
26
- return (_jsx(Text, { bold: true, children: token.tokens ? (_jsx(InlineRenderer, { tokens: token.tokens })) : (unescapeHtml(token.text)) }, index));
27
- case "em":
28
- return (_jsx(Text, { italic: true, children: token.tokens ? (_jsx(InlineRenderer, { tokens: token.tokens })) : (unescapeHtml(token.text)) }, index));
29
- case "codespan":
30
- return (_jsx(Text, { color: "yellow", children: 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
- }
35
- case "br":
36
- return _jsx(Text, { children: "\n" }, index);
37
- case "del":
38
- return (_jsx(Text, { strikethrough: true, children: token.tokens ? (_jsx(InlineRenderer, { tokens: token.tokens })) : (unescapeHtml(token.text)) }, index));
39
- default:
40
- return _jsx(Text, { children: token.raw }, index);
41
- }
42
- }) }));
43
- };
44
- const TableRenderer = ({ token }) => {
45
- const { stdout } = useStdout();
46
- const terminalWidth = (stdout?.columns || 80) - 2;
47
- const columnWidths = useMemo(() => {
48
- const numCols = token.header.length;
49
- const minWidth = 5;
50
- const maxColWidth = 40;
51
- const widths = token.header.map((h) => Math.min(maxColWidth, Math.max(minWidth, h.text.length)));
52
- token.rows.forEach((row) => {
53
- row.forEach((cell, i) => {
54
- widths[i] = Math.min(maxColWidth, Math.max(widths[i] || minWidth, cell.text.length));
55
- });
56
- });
57
- const paddedWidths = widths.map((w) => w + 2);
58
- const totalWidth = paddedWidths.reduce((a, b) => a + b, 0) + numCols + 1;
59
- if (totalWidth <= terminalWidth) {
60
- return paddedWidths;
61
- }
62
- // If table is too wide, scale down columns proportionally
63
- const availableWidth = terminalWidth - numCols - 1;
64
- const scaleFactor = availableWidth / (totalWidth - numCols - 1);
65
- return paddedWidths.map((w) => Math.max(minWidth, Math.floor(w * scaleFactor)));
66
- }, [token, terminalWidth]);
67
- return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: "single", borderColor: "gray", width: columnWidths.reduce((a, b) => a + b, 0) + token.header.length + 1, children: [_jsx(Box, { flexDirection: "row", borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: "gray", children: token.header.map((cell, i) => (_jsx(Box, { width: columnWidths[i], paddingX: 1, borderStyle: "single", borderLeft: i > 0, borderRight: false, borderTop: false, borderBottom: false, borderColor: "gray", children: _jsx(Text, { bold: true, wrap: "wrap", children: _jsx(InlineRenderer, { tokens: cell.tokens }) }) }, i))) }), token.rows.map((row, rowIndex) => (_jsx(Box, { flexDirection: "row", children: row.map((cell, i) => (_jsx(Box, { width: columnWidths[i], paddingX: 1, borderStyle: "single", borderLeft: i > 0, borderRight: false, borderTop: false, borderBottom: false, borderColor: "gray", children: _jsx(Text, { wrap: "wrap", children: _jsx(InlineRenderer, { tokens: cell.tokens }) }) }, i))) }, rowIndex)))] }));
68
- };
69
- const BlockRenderer = ({ tokens }) => {
70
- return (_jsx(_Fragment, { children: tokens.map((token, index) => {
71
- switch (token.type) {
72
- case "heading": {
73
- const t = token;
74
- return (_jsx(Box, { marginBottom: 1, flexDirection: "column", children: _jsxs(Text, { bold: true, color: "cyan", children: ["#".repeat(t.depth), " ", _jsx(InlineRenderer, { tokens: t.tokens })] }) }, index));
75
- }
76
- case "paragraph": {
77
- const t = token;
78
- return (_jsx(Box, { marginBottom: 1, flexDirection: "row", children: _jsx(Text, { children: _jsx(InlineRenderer, { tokens: t.tokens }) }) }, index));
79
- }
80
- case "code": {
81
- const t = token;
82
- if (t.lang !== undefined) {
83
- const raw = token.raw.endsWith("\n")
84
- ? token.raw.slice(0, -1)
85
- : token.raw;
86
- const lines = raw.split("\n");
87
- const opening = lines[0];
88
- const closing = lines[lines.length - 1];
89
- const content = lines.slice(1, -1).join("\n");
90
- const highlighted = content
91
- ? highlight(unescapeHtml(content), {
92
- language: t.lang && supportsLanguage(t.lang) ? t.lang : undefined,
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));
97
- }
98
- return (_jsx(Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: _jsx(Text, { children: unescapeHtml(t.text) }) }, index));
99
- }
100
- case "list": {
101
- const t = token;
102
- return (_jsx(Box, { flexDirection: "column", marginBottom: 1, paddingLeft: 2, children: t.items.map((item, i) => {
103
- const start = t.start || 1;
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) => {
105
- if (itemToken.type === "text" ||
106
- itemToken.type === "paragraph") {
107
- const it = itemToken;
108
- return (_jsx(Box, { flexDirection: "row", children: _jsx(Text, { children: _jsx(InlineRenderer, { tokens: it.tokens || [itemToken] }) }) }, itemIndex));
109
- }
110
- return (_jsx(BlockRenderer, { tokens: [itemToken] }, itemIndex));
111
- }) })] }, i));
112
- }) }, index));
113
- }
114
- case "blockquote": {
115
- const t = token;
116
- return (_jsx(Box, { flexDirection: "column", paddingLeft: 2, borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, borderColor: "gray", marginBottom: 1, children: _jsx(BlockRenderer, { tokens: t.tokens }) }, index));
117
- }
118
- case "hr":
119
- return (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "gray", children: "─".repeat(20) }) }, index));
120
- case "table":
121
- return _jsx(TableRenderer, { token: token }, index);
122
- case "space":
123
- return null;
124
- default:
125
- return (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: token.raw }) }, index));
126
- }
127
- }) }));
128
- };
129
- // Markdown component using custom Ink-based renderer
15
+ class AnsiRenderer extends Renderer {
16
+ code({ text, lang }) {
17
+ const prefix = lang ? `\`\`\`${lang}` : "```";
18
+ const suffix = "```";
19
+ return `\n${chalk.gray(prefix)}\n${text}\n${chalk.gray(suffix)}\n`;
20
+ }
21
+ blockquote({ tokens }) {
22
+ const body = this.parser.parse(tokens);
23
+ return ("\n" +
24
+ body
25
+ .trim()
26
+ .split("\n")
27
+ .map((line) => chalk.gray("> ") + line)
28
+ .join("\n") +
29
+ "\n");
30
+ }
31
+ heading({ tokens, depth }) {
32
+ const text = this.parser.parseInline(tokens);
33
+ const hashes = "#".repeat(depth);
34
+ return `\n${chalk.cyan(`${hashes} ${text}`)}\n`;
35
+ }
36
+ hr() {
37
+ return `\n${chalk.gray("".repeat(20))}\n`;
38
+ }
39
+ list(token) {
40
+ const body = token.items
41
+ .map((item, i) => {
42
+ const text = this.listitem(item);
43
+ const prefix = token.ordered
44
+ ? chalk.gray(`${(token.start || 1) + i}. `)
45
+ : chalk.gray("• ");
46
+ const lines = text.split("\n");
47
+ const firstLine = prefix + lines[0];
48
+ const restLines = lines
49
+ .slice(1)
50
+ .filter((line) => line.length > 0)
51
+ .map((line) => " " + line);
52
+ return [firstLine, ...restLines].join("\n") + "\n";
53
+ })
54
+ .join("");
55
+ return `\n${body}`;
56
+ }
57
+ listitem(item) {
58
+ return `${this.parser.parse(item.tokens).trim()}\n`;
59
+ }
60
+ checkbox({ checked }) {
61
+ return checked ? chalk.green("[x] ") : chalk.gray("[ ] ");
62
+ }
63
+ paragraph({ tokens }) {
64
+ const text = this.parser.parseInline(tokens);
65
+ return `\n${text}\n`;
66
+ }
67
+ table(token) {
68
+ const header = token.header.map((cell) => this.tablecell(cell)).join("");
69
+ const body = token.rows
70
+ .map((row) => row.map((cell) => this.tablecell(cell)).join("") + "\n")
71
+ .join("");
72
+ return `\n${header}\n${body}\n`;
73
+ }
74
+ tablerow({ text }) {
75
+ return text + "\n";
76
+ }
77
+ tablecell(token) {
78
+ const text = token.header ? chalk.bold(token.text) : token.text;
79
+ return text + " | ";
80
+ }
81
+ strong({ tokens }) {
82
+ const text = this.parser.parseInline(tokens);
83
+ return chalk.bold(text);
84
+ }
85
+ em({ tokens }) {
86
+ const text = this.parser.parseInline(tokens);
87
+ return chalk.italic(text);
88
+ }
89
+ codespan({ text }) {
90
+ return chalk.yellow(text);
91
+ }
92
+ br() {
93
+ return "\n";
94
+ }
95
+ del({ tokens }) {
96
+ const text = this.parser.parseInline(tokens);
97
+ return chalk.strikethrough(text);
98
+ }
99
+ link({ href, tokens }) {
100
+ const text = this.parser.parseInline(tokens);
101
+ const linkText = chalk.blue.underline(text);
102
+ const hrefText = chalk.gray(`(${href})`);
103
+ return `${linkText} ${hrefText}`;
104
+ }
105
+ image({ href, tokens, text }) {
106
+ const alt = this.parser.parseInline(tokens) || text;
107
+ return chalk.gray(`![${alt}](${href})`);
108
+ }
109
+ text(token) {
110
+ return "tokens" in token && token.tokens
111
+ ? this.parser.parseInline(token.tokens)
112
+ : unescapeHtml(token.text);
113
+ }
114
+ }
115
+ const renderer = new AnsiRenderer();
116
+ // Markdown component using custom ANSI renderer
130
117
  export const Markdown = React.memo(({ children }) => {
131
- const tokens = useMemo(() => marked.lexer(children), [children]);
132
- return (_jsx(Box, { flexDirection: "column", children: _jsx(BlockRenderer, { tokens: tokens }) }));
118
+ const ansiContent = useMemo(() => {
119
+ return marked.parse(children, {
120
+ renderer,
121
+ gfm: true,
122
+ breaks: true,
123
+ });
124
+ }, [children]);
125
+ return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { children: ansiContent.trim() }) }));
133
126
  });
134
127
  // Add display name for debugging
135
128
  Markdown.displayName = "Markdown";
@@ -1 +1 @@
1
- {"version":3,"file":"MessageItem.d.ts","sourceRoot":"","sources":["../../src/components/MessageItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAU9C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,WAAW,GAAI,4CAIzB,gBAAgB,mDAyElB,CAAC"}
1
+ {"version":3,"file":"MessageItem.d.ts","sourceRoot":"","sources":["../../src/components/MessageItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAS9C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,WAAW,GAAI,4CAIzB,gBAAgB,mDAwElB,CAAC"}
@@ -3,7 +3,6 @@ import { Box, Text } from "ink";
3
3
  import { MessageSource } from "wave-agent-sdk";
4
4
  import { CommandOutputDisplay } from "./CommandOutputDisplay.js";
5
5
  import { ToolResultDisplay } from "./ToolResultDisplay.js";
6
- import { MemoryDisplay } from "./MemoryDisplay.js";
7
6
  import { CompressDisplay } from "./CompressDisplay.js";
8
7
  import { SubagentBlock } from "./SubagentBlock.js";
9
8
  import { ReasoningDisplay } from "./ReasoningDisplay.js";
@@ -11,5 +10,5 @@ import { Markdown } from "./Markdown.js";
11
10
  export const MessageItem = ({ message, isExpanded, shouldShowHeader, }) => {
12
11
  if (message.blocks.length === 0)
13
12
  return null;
14
- return (_jsxs(Box, { flexDirection: "column", gap: 1, marginTop: 1, children: [shouldShowHeader && (_jsx(Box, { children: _jsx(Text, { color: message.role === "user" ? "cyan" : "green", bold: true, children: message.role === "user" ? "👤 You" : "🤖 Assistant" }) })), _jsx(Box, { flexDirection: "column", gap: 1, children: message.blocks.map((block, blockIndex) => (_jsxs(Box, { children: [block.type === "text" && block.content.trim() && (_jsxs(Box, { children: [block.customCommandContent && (_jsxs(Text, { color: "cyan", bold: true, children: ["\u26A1", " "] })), block.source === MessageSource.HOOK && (_jsxs(Text, { color: "magenta", bold: true, children: ["\uD83D\uDD17", " "] })), _jsx(Markdown, { children: block.content })] })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["\u274C Error: ", block.content] }) })), block.type === "command_output" && (_jsx(CommandOutputDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolResultDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "\uD83D\uDCF7 Image" }), block.imageUrls && block.imageUrls.length > 0 && (_jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", block.imageUrls.length, ")"] }))] })), block.type === "memory" && _jsx(MemoryDisplay, { block: block }), block.type === "compress" && (_jsx(CompressDisplay, { block: block, isExpanded: isExpanded })), block.type === "subagent" && _jsx(SubagentBlock, { block: block }), block.type === "reasoning" && _jsx(ReasoningDisplay, { block: block })] }, blockIndex))) })] }));
13
+ return (_jsxs(Box, { flexDirection: "column", gap: 1, marginTop: 1, children: [shouldShowHeader && (_jsx(Box, { children: _jsx(Text, { color: message.role === "user" ? "cyan" : "green", bold: true, children: message.role === "user" ? "👤 You" : "🤖 Assistant" }) })), _jsx(Box, { flexDirection: "column", gap: 1, children: message.blocks.map((block, blockIndex) => (_jsxs(Box, { children: [block.type === "text" && block.content.trim() && (_jsxs(Box, { children: [block.customCommandContent && (_jsxs(Text, { color: "cyan", bold: true, children: ["\u26A1", " "] })), block.source === MessageSource.HOOK && (_jsxs(Text, { color: "magenta", bold: true, children: ["\uD83D\uDD17", " "] })), _jsx(Markdown, { children: block.content })] })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["\u274C Error: ", block.content] }) })), block.type === "command_output" && (_jsx(CommandOutputDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolResultDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "\uD83D\uDCF7 Image" }), block.imageUrls && block.imageUrls.length > 0 && (_jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", block.imageUrls.length, ")"] }))] })), block.type === "compress" && (_jsx(CompressDisplay, { block: block, isExpanded: isExpanded })), block.type === "subagent" && _jsx(SubagentBlock, { block: block }), block.type === "reasoning" && _jsx(ReasoningDisplay, { block: block })] }, blockIndex))) })] }));
15
14
  };
@@ -4,9 +4,8 @@ export interface MessageListProps {
4
4
  messages: Message[];
5
5
  isLoading?: boolean;
6
6
  isCommandRunning?: boolean;
7
- isCompressing?: boolean;
8
- latestTotalTokens?: number;
9
7
  isExpanded?: boolean;
8
+ forceStaticLastMessage?: boolean;
10
9
  }
11
- export declare const MessageList: React.MemoExoticComponent<({ messages, isLoading, isCommandRunning, isCompressing, latestTotalTokens, isExpanded, }: MessageListProps) => import("react/jsx-runtime").JSX.Element>;
10
+ export declare const MessageList: React.MemoExoticComponent<({ messages, isLoading, isCommandRunning, isExpanded, forceStaticLastMessage, }: MessageListProps) => import("react/jsx-runtime").JSX.Element>;
12
11
  //# sourceMappingURL=MessageList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,uHAQnB,gBAAgB,6CAwIpB,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,eAAO,MAAM,WAAW,6GAOnB,gBAAgB,6CAiFpB,CAAC"}
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import { Box, Text, Static } from "ink";
4
4
  import { MessageItem } from "./MessageItem.js";
5
- export const MessageList = React.memo(({ messages, isLoading = false, isCommandRunning = false, isCompressing = false, latestTotalTokens = 0, isExpanded = false, }) => {
5
+ export const MessageList = React.memo(({ messages, isLoading = false, isCommandRunning = false, isExpanded = false, forceStaticLastMessage = false, }) => {
6
6
  // Empty message state
7
7
  if (messages.length === 0) {
8
- return (_jsx(Box, { flexDirection: "column", paddingY: 1, children: _jsx(Text, { color: "gray", children: "Welcome to WAVE Code Assistant!" }) }));
8
+ return (_jsx(Box, { flexDirection: "column", gap: 1, children: _jsx(Box, { flexDirection: "column", paddingY: 1, children: _jsx(Text, { color: "gray", children: "Welcome to WAVE Code Assistant!" }) }) }));
9
9
  }
10
10
  // Limit messages when expanded to prevent long rendering times
11
11
  const maxExpandedMessages = 20;
@@ -17,22 +17,22 @@ export const MessageList = React.memo(({ messages, isLoading = false, isCommandR
17
17
  ? messages.length - maxExpandedMessages
18
18
  : 0;
19
19
  // Compute which messages to render statically vs dynamically
20
- const shouldRenderLastDynamic = isLoading || isCommandRunning;
20
+ const shouldRenderLastDynamic = !forceStaticLastMessage && (isLoading || isCommandRunning);
21
21
  const staticMessages = shouldRenderLastDynamic
22
22
  ? displayMessages.slice(0, -1)
23
23
  : displayMessages;
24
24
  const dynamicMessages = shouldRenderLastDynamic && displayMessages.length > 0
25
25
  ? [displayMessages[displayMessages.length - 1]]
26
26
  : [];
27
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [omittedCount > 0 && (_jsx(Box, { children: _jsxs(Text, { color: "gray", dimColor: true, children: ["... ", omittedCount, " earlier message", omittedCount !== 1 ? "s" : "", " ", "omitted (showing latest ", maxExpandedMessages, ")"] }) })), _jsx(Static, { items: staticMessages, children: (message, key) => {
27
+ return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingBottom: 1, children: [omittedCount > 0 && (_jsx(Box, { children: _jsxs(Text, { color: "gray", dimColor: true, children: ["... ", omittedCount, " earlier message", omittedCount !== 1 ? "s" : "", " ", "omitted (showing latest ", maxExpandedMessages, ")"] }) })), _jsx(Static, { items: staticMessages, children: (message, key) => {
28
28
  // Get previous message
29
29
  const previousMessage = key > 0 ? staticMessages[key - 1] : undefined;
30
30
  return (_jsx(MessageItem, { message: message, shouldShowHeader: previousMessage?.role !== message.role, isExpanded: isExpanded }, key));
31
31
  } }), dynamicMessages.map((message, index) => {
32
32
  const messageIndex = staticMessages.length + index;
33
33
  const previousMessage = messageIndex > 0 ? displayMessages[messageIndex - 1] : undefined;
34
- return (_jsx(Box, { marginTop: -1, children: _jsx(MessageItem, { message: message, shouldShowHeader: previousMessage?.role !== message.role, isExpanded: isExpanded }) }, `dynamic-${index}`));
35
- }), (isLoading || isCommandRunning || isCompressing) && (_jsxs(Box, { flexDirection: "column", gap: 1, children: [isLoading && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "\uD83D\uDCAD AI is thinking... " }), _jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "red", bold: true, children: "Esc" }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "to abort"] })] })), isCommandRunning && (_jsx(Text, { color: "blue", children: "\uD83D\uDE80 Command is running..." })), isCompressing && (_jsx(Text, { color: "magenta", children: "\uD83D\uDDDC\uFE0F Compressing message history..." }))] })), messages.length > 0 && (_jsx(Box, { children: _jsxs(Box, { justifyContent: "space-between", width: "100%", children: [_jsx(Box, { children: _jsxs(Text, { color: "gray", children: ["Messages ", messages.length, latestTotalTokens > 0 && (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "gray", dimColor: true, children: [" ", "|", " "] }), _jsx(Text, { color: "blue", bold: true, children: latestTotalTokens.toLocaleString() }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "tokens"] })] }))] }) }), _jsxs(Text, { color: "gray", dimColor: true, children: [_jsx(Text, { color: "cyan", children: "Ctrl+O" }), " Toggle", " ", isExpanded ? "Collapse" : "Expand"] })] }) }))] }));
34
+ return (_jsx(Box, { children: _jsx(MessageItem, { message: message, shouldShowHeader: previousMessage?.role !== message.role, isExpanded: isExpanded }) }, `dynamic-${index}`));
35
+ })] }));
36
36
  });
37
37
  // Add display name for debugging
38
38
  MessageList.displayName = "MessageList";
@@ -1 +1 @@
1
- {"version":3,"file":"PlanDisplay.d.ts","sourceRoot":"","sources":["../../src/components/PlanDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAIvC,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+BlD,CAAC"}
1
+ {"version":3,"file":"PlanDisplay.d.ts","sourceRoot":"","sources":["../../src/components/PlanDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAQlD,CAAC"}
@@ -1,14 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from "react";
3
- import { Box, Text, useStdout } from "ink";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from "ink";
4
3
  import { Markdown } from "./Markdown.js";
5
- export const PlanDisplay = ({ plan, isExpanded = false, }) => {
6
- const { stdout } = useStdout();
7
- const maxHeight = useMemo(() => {
8
- // Similar to DiffDisplay.tsx maxHeight calculation
9
- return Math.max(5, (stdout?.rows || 24) - 25);
10
- }, [stdout?.rows]);
11
- const lines = useMemo(() => plan.split("\n"), [plan]);
12
- const isOverflowing = !isExpanded && lines.length > maxHeight;
13
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { flexDirection: "column", height: isOverflowing ? maxHeight : undefined, overflow: "hidden", children: _jsx(Markdown, { children: plan }) }), isOverflowing && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "yellow", dimColor: true, children: ["... (plan truncated, ", lines.length, " lines total)"] }) }))] }));
4
+ export const PlanDisplay = ({ plan }) => {
5
+ return (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Box, { flexDirection: "column", children: _jsx(Markdown, { children: plan }) }) }));
14
6
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SubagentBlock.d.ts","sourceRoot":"","sources":["../../src/components/SubagentBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIzE,UAAU,kBAAkB;IAC1B,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAoItD,CAAC"}
1
+ {"version":3,"file":"SubagentBlock.d.ts","sourceRoot":"","sources":["../../src/components/SubagentBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIzE,UAAU,kBAAkB;IAC1B,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6ItD,CAAC"}
@@ -1,15 +1,18 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
2
3
  import { Box, Text } from "ink";
3
4
  import { useChat } from "../contexts/useChat.js";
4
5
  import { Markdown } from "./Markdown.js";
5
6
  export const SubagentBlock = ({ block }) => {
6
- const { subagentMessages } = useChat();
7
+ const { subagentMessages, subagentLatestTokens } = useChat();
8
+ // Get messages for this subagent from context
9
+ const messages = useMemo(() => subagentMessages[block.subagentId] || [], [subagentMessages, block.subagentId]);
10
+ // Get latest turn tokens for this subagent
11
+ const latestTurnTokens = subagentLatestTokens[block.subagentId] || 0;
7
12
  // If the subagent is running in the background, don't show the block
8
13
  if (block.runInBackground) {
9
14
  return null;
10
15
  }
11
- // Get messages for this subagent from context
12
- const messages = subagentMessages[block.subagentId] || [];
13
16
  // Status indicator mapping
14
17
  const getStatusIndicator = (status) => {
15
18
  switch (status) {
@@ -47,7 +50,7 @@ export const SubagentBlock = ({ block }) => {
47
50
  }
48
51
  return { tools: tools.reverse(), totalToolCount }; // Reverse to show oldest first, newest last
49
52
  };
50
- const { tools: lastTwoTools, totalToolCount } = getLastTwoTools();
53
+ const { tools: lastTwoTools } = getLastTwoTools();
51
54
  // Get the last text message content if completed
52
55
  const getLastTextMessage = () => {
53
56
  if (block.status !== "completed")
@@ -66,5 +69,5 @@ export const SubagentBlock = ({ block }) => {
66
69
  return null;
67
70
  };
68
71
  const lastTextMessage = getLastTextMessage();
69
- return (_jsxs(Box, { borderRight: false, borderTop: false, borderBottom: false, borderStyle: "classic", borderColor: "magenta", paddingX: 1, paddingY: 0, flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { flexDirection: "row", gap: 1, children: _jsxs(Box, { flexDirection: "row", alignItems: "center", children: [_jsxs(Text, { color: "cyan", children: ["\uD83E\uDD16 ", block.subagentName] }), _jsxs(Text, { color: statusInfo.color, dimColor: false, children: [" ", statusInfo.icon] }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", messages.length, " messages)"] })] }) }), lastTextMessage && (_jsx(Box, { marginTop: 1, children: _jsx(Markdown, { children: lastTextMessage }) })), block.status !== "completed" && lastTwoTools.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, gap: 1, children: [totalToolCount > 2 && (_jsx(Text, { color: "gray", dimColor: true, children: "..." })), lastTwoTools.map((tool, index) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "magenta", children: "\uD83D\uDD27 " }), _jsx(Text, { color: "white", children: tool.name }), tool.compactParams && (_jsxs(Text, { color: "gray", children: [" ", tool.compactParams] }))] }, index)))] }))] }));
72
+ return (_jsxs(Box, { borderRight: false, borderTop: false, borderBottom: false, borderStyle: "classic", borderColor: "magenta", paddingX: 1, flexDirection: "column", children: [_jsx(Box, { flexDirection: "row", gap: 1, children: _jsxs(Box, { flexDirection: "row", alignItems: "center", children: [_jsxs(Text, { color: "cyan", children: ["\uD83E\uDD16 ", block.subagentName] }), _jsxs(Text, { color: statusInfo.color, dimColor: false, children: [" ", statusInfo.icon] }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", messages.length, " messages", latestTurnTokens > 0 && (_jsxs(_Fragment, { children: [" | ", _jsx(Text, { color: "blue", bold: true, children: latestTurnTokens.toLocaleString() }), " tokens"] })), ")"] })] }) }), lastTextMessage && (_jsx(Box, { children: _jsx(Markdown, { children: lastTextMessage }) })), block.status !== "completed" && lastTwoTools.length > 0 && (_jsx(Box, { flexDirection: "column", children: lastTwoTools.map((tool, index) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "magenta", children: "\uD83D\uDD27 " }), _jsx(Text, { color: "white", children: tool.name }), tool.compactParams && (_jsxs(Text, { color: "gray", children: [" ", tool.compactParams] }))] }, index))) }))] }));
70
73
  };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export declare const TaskList: React.FC;
3
+ //# sourceMappingURL=TaskList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskList.d.ts","sourceRoot":"","sources":["../../src/components/TaskList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAgE5B,CAAC"}