wave-code 0.11.7 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +9 -51
  2. package/dist/acp/agent.js +1 -1
  3. package/dist/components/ChatInterface.d.ts.map +1 -1
  4. package/dist/components/ChatInterface.js +2 -3
  5. package/dist/components/DiffDisplay.d.ts.map +1 -1
  6. package/dist/components/DiffDisplay.js +2 -23
  7. package/dist/components/InputBox.d.ts.map +1 -1
  8. package/dist/components/InputBox.js +6 -2
  9. package/dist/components/MessageBlockItem.d.ts.map +1 -1
  10. package/dist/components/MessageBlockItem.js +2 -1
  11. package/dist/components/MessageList.d.ts +1 -2
  12. package/dist/components/MessageList.d.ts.map +1 -1
  13. package/dist/components/MessageList.js +10 -4
  14. package/dist/components/ModelSelector.d.ts +9 -0
  15. package/dist/components/ModelSelector.d.ts.map +1 -0
  16. package/dist/components/ModelSelector.js +34 -0
  17. package/dist/components/SlashDisplay.d.ts +9 -0
  18. package/dist/components/SlashDisplay.d.ts.map +1 -0
  19. package/dist/components/SlashDisplay.js +20 -0
  20. package/dist/components/StatusCommand.d.ts.map +1 -1
  21. package/dist/components/StatusCommand.js +1 -1
  22. package/dist/components/ToolDisplay.js +1 -1
  23. package/dist/constants/commands.d.ts.map +1 -1
  24. package/dist/constants/commands.js +6 -0
  25. package/dist/contexts/useChat.d.ts +4 -2
  26. package/dist/contexts/useChat.d.ts.map +1 -1
  27. package/dist/contexts/useChat.js +27 -33
  28. package/dist/hooks/useInputManager.d.ts +2 -0
  29. package/dist/hooks/useInputManager.d.ts.map +1 -1
  30. package/dist/hooks/useInputManager.js +8 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +10 -0
  33. package/dist/managers/inputHandlers.d.ts.map +1 -1
  34. package/dist/managers/inputHandlers.js +6 -0
  35. package/dist/managers/inputReducer.d.ts +5 -0
  36. package/dist/managers/inputReducer.d.ts.map +1 -1
  37. package/dist/managers/inputReducer.js +7 -0
  38. package/dist/utils/highlightUtils.d.ts.map +1 -1
  39. package/dist/utils/highlightUtils.js +0 -8
  40. package/dist/utils/logger.d.ts.map +1 -1
  41. package/dist/utils/logger.js +10 -5
  42. package/dist/utils/toolParameterTransforms.d.ts +5 -1
  43. package/dist/utils/toolParameterTransforms.d.ts.map +1 -1
  44. package/dist/utils/toolParameterTransforms.js +14 -0
  45. package/dist/utils/worktree.d.ts +0 -1
  46. package/dist/utils/worktree.d.ts.map +1 -1
  47. package/dist/utils/worktree.js +2 -2
  48. package/package.json +3 -3
  49. package/src/acp/agent.ts +1 -1
  50. package/src/components/ChatInterface.tsx +0 -4
  51. package/src/components/DiffDisplay.tsx +2 -27
  52. package/src/components/InputBox.tsx +17 -0
  53. package/src/components/MessageBlockItem.tsx +5 -5
  54. package/src/components/MessageList.tsx +15 -9
  55. package/src/components/ModelSelector.tsx +109 -0
  56. package/src/components/SlashDisplay.tsx +70 -0
  57. package/src/components/StatusCommand.tsx +7 -0
  58. package/src/components/ToolDisplay.tsx +1 -1
  59. package/src/constants/commands.ts +6 -0
  60. package/src/contexts/useChat.tsx +34 -49
  61. package/src/hooks/useInputManager.ts +10 -0
  62. package/src/index.ts +13 -0
  63. package/src/managers/inputHandlers.ts +5 -0
  64. package/src/managers/inputReducer.ts +10 -0
  65. package/src/utils/highlightUtils.ts +0 -8
  66. package/src/utils/logger.ts +9 -7
  67. package/src/utils/toolParameterTransforms.ts +23 -1
  68. package/src/utils/worktree.ts +7 -3
package/README.md CHANGED
@@ -31,38 +31,26 @@ export WAVE_API_KEY="your_token_here"
31
31
 
32
32
  # AI Gateway API URL (required)
33
33
  export WAVE_BASE_URL="https://your-api-gateway-url.com"
34
+
35
+ # AI model (required)
36
+ export WAVE_MODEL="MiniMax-M2.7"
37
+
38
+ # Fast AI model (required)
39
+ export WAVE_FAST_MODEL="MiniMax-M2.7-highspeed"
34
40
  ```
35
41
 
36
42
  ### Optional Environment Variables
37
43
 
38
44
  ```bash
39
- # Specify AI model (optional, defaults to gemini-3-flash)
40
- export WAVE_MODEL="gemini-3-flash"
41
-
42
- # Specify fast AI model (optional, defaults to gemini-2.5-flash)
43
- export WAVE_FAST_MODEL="gemini-2.5-flash"
44
-
45
45
  # Token limit (optional, defaults to 96000)
46
46
  export WAVE_MAX_INPUT_TOKENS="96000"
47
-
48
47
  ```
49
48
 
50
49
  ## Usage
51
50
 
52
- ### Full Command
53
-
54
51
  ```bash
55
52
  # Start the CLI
56
- wave-code
57
-
58
- # Continue from last session
59
- wave-code --continue
60
-
61
- # Restore specific session
62
- wave-code --restore session_id
63
-
64
- # List available sessions
65
- wave-code --list-sessions
53
+ wave-code -h
66
54
  ```
67
55
 
68
56
  ### Short Command (wave)
@@ -70,42 +58,12 @@ wave-code --list-sessions
70
58
  For convenience, you can also use the shorter `wave` command:
71
59
 
72
60
  ```bash
73
- # Start the CLI (equivalent to wave-code)
74
- wave
75
-
76
- # Continue from last session
77
- wave --continue
78
-
79
- # Restore specific session
80
- wave --restore session_id
81
-
82
- # List available sessions
83
- wave --list-sessions
84
-
85
- # Show help
86
- wave --help
61
+ # Start the CLI
62
+ wave -h
87
63
  ```
88
64
 
89
65
  The `wave` command is an alias for `wave-code` and supports all the same options and functionality.
90
66
 
91
- ## Development
92
-
93
- This package depends on `wave-agent-sdk` for core functionality including AI services, tools, and utilities.
94
-
95
- ```bash
96
- # Install dependencies
97
- pnpm install
98
-
99
- # Start development
100
- pnpm dev
101
-
102
- # Build
103
- pnpm build
104
-
105
- # Test
106
- pnpm test
107
- ```
108
-
109
67
  ## License
110
68
 
111
69
  MIT
package/dist/acp/agent.js CHANGED
@@ -508,7 +508,7 @@ export class WaveAcpAgent {
508
508
  },
509
509
  });
510
510
  }
511
- if (contents.length === 0) {
511
+ if (name.startsWith("mcp__")) {
512
512
  contents.push({
513
513
  type: "content",
514
514
  content: {
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AActE,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAyKjC,CAAC"}
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AActE,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAqKjC,CAAC"}
@@ -16,8 +16,7 @@ export const ChatInterface = () => {
16
16
  const [selectorHeight, setSelectorHeight] = useState(0);
17
17
  const [dynamicBlocksHeight, setDynamicBlocksHeight] = useState(0);
18
18
  const [isConfirmationTooTall, setIsConfirmationTooTall] = useState(false);
19
- const { messages, isLoading, isCommandRunning, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel: originalHandleConfirmationCancel, setWasLastDetailsTooTall, version, workdir, getModelConfig, btwState, } = useChat();
20
- const model = getModelConfig().model;
19
+ const { messages, isLoading, isCommandRunning, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel: originalHandleConfirmationCancel, setWasLastDetailsTooTall, version, workdir, btwState, } = useChat();
21
20
  const displayMessages = messages;
22
21
  const handleDetailsHeightMeasured = useCallback((height) => {
23
22
  setDetailsHeight(height);
@@ -76,5 +75,5 @@ export const ChatInterface = () => {
76
75
  ]);
77
76
  if (!sessionId)
78
77
  return null;
79
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, forceStatic: isConfirmationVisible && isConfirmationTooTall, version: version, workdir: workdir, model: model, onDynamicBlocksHeightMeasured: handleDynamicBlocksHeightMeasured }), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(BtwDisplay, { btwState: btwState }), (isLoading || isCommandRunning || isCompressing) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded, onHeightMeasured: handleDetailsHeightMeasured, isStatic: isConfirmationTooTall }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage, onHeightMeasured: handleSelectorHeightMeasured })] }))] }));
78
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, forceStatic: isConfirmationVisible && isConfirmationTooTall, version: version, workdir: workdir, onDynamicBlocksHeightMeasured: handleDynamicBlocksHeightMeasured }), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(BtwDisplay, { btwState: btwState }), (isLoading || isCommandRunning || isCompressing) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded, onHeightMeasured: handleDetailsHeightMeasured, isStatic: isConfirmationTooTall }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage, onHeightMeasured: handleSelectorHeightMeasured })] }))] }));
80
79
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DiffDisplay.d.ts","sourceRoot":"","sources":["../../src/components/DiffDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAYvC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA6WlD,CAAC"}
1
+ {"version":3,"file":"DiffDisplay.d.ts","sourceRoot":"","sources":["../../src/components/DiffDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAMvC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA0VlD,CAAC"}
@@ -1,11 +1,9 @@
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
- import { WRITE_TOOL_NAME, EDIT_TOOL_NAME, } from "wave-agent-sdk";
4
+ import { WRITE_TOOL_NAME, EDIT_TOOL_NAME } from "wave-agent-sdk";
5
5
  import { transformToolBlockToChanges } from "../utils/toolParameterTransforms.js";
6
6
  import { diffLines, diffWords } from "diff";
7
- import path from "path";
8
- import { Markdown } from "./Markdown.js";
9
7
  export const DiffDisplay = ({ toolName, parameters, startLineNumber, }) => {
10
8
  const showDiff = toolName && [WRITE_TOOL_NAME, EDIT_TOOL_NAME].includes(toolName);
11
9
  // Diff detection and transformation using typed parameters
@@ -55,23 +53,6 @@ export const DiffDisplay = ({ toolName, parameters, startLineNumber, }) => {
55
53
  };
56
54
  }
57
55
  };
58
- // Render highlighted code for Write tool
59
- const renderWriteContent = () => {
60
- if (!parameters)
61
- return null;
62
- try {
63
- const parsed = JSON.parse(parameters);
64
- const content = parsed.content || "";
65
- const filePath = parsed.file_path || "";
66
- const ext = path.extname(filePath).slice(1);
67
- const markdown = `\`\`\`${ext}\n${content}\n\`\`\``;
68
- return _jsx(Markdown, { children: markdown });
69
- }
70
- catch (error) {
71
- console.warn("Error rendering write content:", error);
72
- return null;
73
- }
74
- };
75
56
  // Render expanded diff display
76
57
  const renderExpandedDiff = () => {
77
58
  try {
@@ -216,7 +197,5 @@ export const DiffDisplay = ({ toolName, parameters, startLineNumber, }) => {
216
197
  if (!showDiff) {
217
198
  return null;
218
199
  }
219
- return (_jsx(Box, { flexDirection: "column", children: _jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "cyan", flexDirection: "column", children: toolName === WRITE_TOOL_NAME
220
- ? renderWriteContent()
221
- : renderExpandedDiff() }) }));
200
+ return (_jsx(Box, { flexDirection: "column", children: _jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "cyan", flexDirection: "column", children: renderExpandedDiff() }) }));
222
201
  };
@@ -1 +1 @@
1
- {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAgBzC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,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,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,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,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,CA0P5C,CAAC"}
1
+ {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAiBzC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,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,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,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,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,CA0Q5C,CAAC"}
@@ -11,13 +11,14 @@ import { RewindCommand } from "./RewindCommand.js";
11
11
  import { HelpView } from "./HelpView.js";
12
12
  import { StatusCommand } from "./StatusCommand.js";
13
13
  import { PluginManagerShell } from "./PluginManagerShell.js";
14
+ import { ModelSelector } from "./ModelSelector.js";
14
15
  import { StatusLine } from "./StatusLine.js";
15
16
  import { useInputManager } from "../hooks/useInputManager.js";
16
17
  import { useChat } from "../contexts/useChat.js";
17
18
  export const INPUT_PLACEHOLDER_TEXT = "Type your message (use /help for more info)...";
18
19
  export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
19
20
  export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
20
- const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, allowBypassInCycle: chatAllowBypassInCycle, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw, btwState: chatBtwState, setBtwState: setChatBtwState, } = useChat();
21
+ const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, allowBypassInCycle: chatAllowBypassInCycle, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw, btwState: chatBtwState, setBtwState: setChatBtwState, currentModel, configuredModels, setModel, } = useChat();
21
22
  // Input manager with all input state and functionality (including images)
22
23
  const { inputText, cursorPosition,
23
24
  // Image management
@@ -29,7 +30,7 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
29
30
  // History search
30
31
  showHistorySearch, historySearchQuery,
31
32
  // Task/MCP Manager
32
- showBackgroundTaskManager, showMcpManager, showRewindManager, showHelp, showStatusCommand, showPluginManager, setShowBackgroundTaskManager, setShowMcpManager, setShowRewindManager, setShowHelp, setShowStatusCommand, setShowPluginManager,
33
+ showBackgroundTaskManager, showMcpManager, showRewindManager, showHelp, showStatusCommand, showPluginManager, showModelSelector, setShowBackgroundTaskManager, setShowMcpManager, setShowRewindManager, setShowHelp, setShowStatusCommand, setShowPluginManager, setShowModelSelector,
33
34
  // Permission mode
34
35
  permissionMode, setPermissionMode, setAllowBypassInCycle,
35
36
  // BTW state
@@ -100,6 +101,9 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
100
101
  if (showPluginManager) {
101
102
  return _jsx(PluginManagerShell, { onCancel: () => setShowPluginManager(false) });
102
103
  }
104
+ if (showModelSelector) {
105
+ return (_jsx(ModelSelector, { onCancel: () => setShowModelSelector(false), currentModel: currentModel, configuredModels: configuredModels, onSelectModel: setModel }));
106
+ }
103
107
  return (_jsxs(Box, { flexDirection: "column", children: [showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, isLoading: isFileSearching, 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 ||
104
108
  showMcpManager ||
105
109
  showRewindManager ||
@@ -1 +1 @@
1
- {"version":3,"file":"MessageBlockItem.d.ts","sourceRoot":"","sources":["../../src/components/MessageBlockItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ5D,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,GAAI,6CAK9B,qBAAqB,4CAiEvB,CAAC"}
1
+ {"version":3,"file":"MessageBlockItem.d.ts","sourceRoot":"","sources":["../../src/components/MessageBlockItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS5D,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,GAAI,6CAK9B,qBAAqB,4CAgEvB,CAAC"}
@@ -2,10 +2,11 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Box, Text } from "ink";
3
3
  import { MessageSource } from "wave-agent-sdk";
4
4
  import { BangDisplay } from "./BangDisplay.js";
5
+ import { SlashDisplay } from "./SlashDisplay.js";
5
6
  import { ToolDisplay } from "./ToolDisplay.js";
6
7
  import { CompressDisplay } from "./CompressDisplay.js";
7
8
  import { ReasoningDisplay } from "./ReasoningDisplay.js";
8
9
  import { Markdown } from "./Markdown.js";
9
10
  export const MessageBlockItem = ({ block, message, isExpanded, paddingTop = 0, }) => {
10
- return (_jsxs(Box, { flexDirection: "column", paddingTop: paddingTop, children: [block.type === "text" && block.content.trim() && (_jsxs(Box, { children: [block.customCommandContent && (_jsxs(Text, { color: "cyan", bold: true, children: ["$", " "] })), block.source === MessageSource.HOOK && (_jsxs(Text, { color: "magenta", bold: true, children: ["~", " "] })), message.role === "user" || isExpanded ? (_jsx(Text, { backgroundColor: message.role === "user" ? "gray" : undefined, color: "white", children: block.content })) : (_jsx(Markdown, { children: block.content }))] })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", block.content] }) })), block.type === "bang" && (_jsx(BangDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "# 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 === "reasoning" && (_jsx(ReasoningDisplay, { block: block, isExpanded: isExpanded }))] }));
11
+ return (_jsxs(Box, { flexDirection: "column", paddingTop: paddingTop, children: [block.type === "text" && block.content.trim() && (_jsxs(Box, { children: [block.source === MessageSource.HOOK && (_jsxs(Text, { color: "magenta", bold: true, children: ["~", " "] })), message.role === "user" || isExpanded ? (_jsx(Text, { backgroundColor: message.role === "user" ? "gray" : undefined, color: "white", children: block.content })) : (_jsx(Markdown, { children: block.content }))] })), block.type === "slash" && (_jsx(SlashDisplay, { block: block, isExpanded: isExpanded })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", block.content] }) })), block.type === "bang" && (_jsx(BangDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "# 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 === "reasoning" && (_jsx(ReasoningDisplay, { block: block, isExpanded: isExpanded }))] }));
11
12
  };
@@ -6,8 +6,7 @@ export interface MessageListProps {
6
6
  forceStatic?: boolean;
7
7
  version?: string;
8
8
  workdir?: string;
9
- model?: string;
10
9
  onDynamicBlocksHeightMeasured?: (height: number) => void;
11
10
  }
12
- export declare const MessageList: React.MemoExoticComponent<({ messages, isExpanded, forceStatic, version, workdir, model, onDynamicBlocksHeightMeasured, }: MessageListProps) => import("react/jsx-runtime").JSX.Element>;
11
+ export declare const MessageList: React.MemoExoticComponent<({ messages, isExpanded, forceStatic, version, workdir, onDynamicBlocksHeightMeasured, }: MessageListProps) => import("react/jsx-runtime").JSX.Element>;
13
12
  //# sourceMappingURL=MessageList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAGvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,WAAW,6HASnB,gBAAgB,6CAoHpB,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAGvD,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,WAAW,sHAQnB,gBAAgB,6CA4HpB,CAAC"}
@@ -3,12 +3,19 @@ import React, { useLayoutEffect, useRef } from "react";
3
3
  import os from "os";
4
4
  import { Box, Text, Static, measureElement } from "ink";
5
5
  import { MessageBlockItem } from "./MessageBlockItem.js";
6
- export const MessageList = React.memo(({ messages, isExpanded = false, forceStatic = false, version, workdir, model, onDynamicBlocksHeightMeasured, }) => {
7
- const welcomeMessage = (_jsxs(Box, { flexDirection: "column", paddingTop: 1, children: [_jsxs(Text, { color: "gray", children: ["WAVE", version ? ` v${version}` : "", model ? ` • ${model}` : ""] }), workdir && (_jsx(Text, { color: "gray", wrap: "truncate-middle", children: workdir.replace(os.homedir(), "~") }))] }));
6
+ export const MessageList = React.memo(({ messages, isExpanded = false, forceStatic = false, version, workdir, onDynamicBlocksHeightMeasured, }) => {
7
+ const welcomeMessage = (_jsxs(Box, { flexDirection: "column", paddingTop: 1, children: [_jsxs(Text, { color: "gray", children: ["WAVE", version ? ` v${version}` : ""] }), workdir && (_jsx(Text, { color: "gray", wrap: "truncate-middle", children: workdir.replace(os.homedir(), "~") }))] }));
8
8
  // Limit messages to prevent long rendering times
9
9
  const maxMessages = 10;
10
10
  // Filter out meta messages
11
11
  const visibleMessages = messages.filter((m) => !m.isMeta);
12
+ const isRunning = (b) => (b.type === "tool" && b.stage === "running") ||
13
+ (b.type === "bang" && b.isRunning) ||
14
+ (b.type === "slash" && b.stage === "running");
15
+ const messagesWithRunningBlocks = new Set(visibleMessages
16
+ .map((m, i) => ({ m, i }))
17
+ .filter(({ m }) => m.blocks.some(isRunning))
18
+ .map(({ i }) => i));
12
19
  // Flatten messages into blocks with metadata
13
20
  const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
14
21
  return message.blocks.map((block, blockIndex) => ({
@@ -23,8 +30,7 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
23
30
  const blocksWithStatus = allBlocks.map((item) => {
24
31
  const { block } = item;
25
32
  const isDynamic = !forceStatic &&
26
- ((block.type === "tool" && block.stage === "running") ||
27
- (block.type === "bang" && block.isRunning));
33
+ (messagesWithRunningBlocks.has(item.messageIndex) || isRunning(block));
28
34
  return { ...item, isDynamic };
29
35
  });
30
36
  const staticBlocks = blocksWithStatus.filter((b) => !b.isDynamic);
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ export interface ModelSelectorProps {
3
+ onCancel: () => void;
4
+ currentModel: string;
5
+ configuredModels: string[];
6
+ onSelectModel: (model: string) => void;
7
+ }
8
+ export declare const ModelSelector: React.FC<ModelSelectorProps>;
9
+ //# sourceMappingURL=ModelSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../src/components/ModelSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkGtD,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ export const ModelSelector = ({ onCancel, currentModel, configuredModels, onSelectModel, }) => {
5
+ const [selectedIndex, setSelectedIndex] = useState(() => {
6
+ const index = configuredModels.indexOf(currentModel);
7
+ return index !== -1 ? index : 0;
8
+ });
9
+ useInput((_input, key) => {
10
+ if (key.return) {
11
+ if (configuredModels.length > 0) {
12
+ onSelectModel(configuredModels[selectedIndex]);
13
+ }
14
+ onCancel();
15
+ return;
16
+ }
17
+ if (key.escape) {
18
+ onCancel();
19
+ return;
20
+ }
21
+ if (key.upArrow) {
22
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
23
+ return;
24
+ }
25
+ if (key.downArrow) {
26
+ setSelectedIndex((prev) => Math.min(configuredModels.length - 1, prev + 1));
27
+ return;
28
+ }
29
+ });
30
+ if (configuredModels.length === 0) {
31
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Select AI Model" }), _jsx(Text, { children: "No models configured" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
32
+ }
33
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Select AI Model" }) }), _jsx(Text, { dimColor: true, children: "Select a model to use for the current session" }), configuredModels.map((model, index) => (_jsx(Box, { children: _jsxs(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "cyan" : undefined, children: [index === selectedIndex ? "▶ " : " ", model, model === currentModel ? (_jsx(Text, { color: "green", children: " (current)" })) : ("")] }) }, model))), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to select \u00B7 Enter to confirm \u00B7 Esc to cancel" }) })] }));
34
+ };
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import type { SlashBlock } from "wave-agent-sdk";
3
+ interface SlashDisplayProps {
4
+ block: SlashBlock;
5
+ isExpanded?: boolean;
6
+ }
7
+ export declare const SlashDisplay: React.FC<SlashDisplayProps>;
8
+ export {};
9
+ //# sourceMappingURL=SlashDisplay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlashDisplay.d.ts","sourceRoot":"","sources":["../../src/components/SlashDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,UAAU,iBAAiB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA4DpD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ export const SlashDisplay = ({ block, isExpanded = false, }) => {
4
+ const { command, args, stage, shortResult, error, result } = block;
5
+ const getStatusColor = () => {
6
+ switch (stage) {
7
+ case "running":
8
+ return "yellow";
9
+ case "success":
10
+ return "green";
11
+ case "error":
12
+ return "red";
13
+ case "aborted":
14
+ return "gray";
15
+ default:
16
+ return "white";
17
+ }
18
+ };
19
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: getStatusColor(), children: "/ " }), _jsx(Text, { color: "white", children: command }), args && _jsxs(Text, { color: "gray", children: [" ", args] })] }), !isExpanded && shortResult && !error && (_jsx(Box, { paddingLeft: 2, flexDirection: "column", children: shortResult.split("\n").map((line, index) => (_jsx(Text, { color: "gray", children: line }, index))) })), isExpanded && result && (_jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Result:" }), _jsx(Text, { color: "white", children: result })] })), error && (_jsx(Box, { paddingLeft: 2, children: _jsxs(Text, { color: "red", children: ["Error: ", typeof error === "string" ? error : String(error)] }) }))] }));
20
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"StatusCommand.d.ts","sourceRoot":"","sources":["../../src/components/StatusCommand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA+EtD,CAAC"}
1
+ {"version":3,"file":"StatusCommand.d.ts","sourceRoot":"","sources":["../../src/components/StatusCommand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsFtD,CAAC"}
@@ -24,5 +24,5 @@ export const StatusCommand = ({ onCancel }) => {
24
24
  catch {
25
25
  // Fallback if package.json cannot be read
26
26
  }
27
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", borderLeft: false, borderRight: false, paddingX: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "cyan", bold: true, underline: true, children: "Agent Status" }) }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Version:" }) }), _jsx(Text, { color: "white", children: version })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Session ID:" }) }), _jsx(Text, { color: "white", children: sessionId })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "cwd:" }) }), _jsx(Text, { color: "white", wrap: "wrap", children: workingDirectory })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Wave base URL:" }) }), _jsx(Text, { color: "white", children: gatewayConfig.baseURL })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Model:" }) }), _jsx(Text, { color: "white", children: modelConfig.model })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Esc to cancel" }) })] }));
27
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", borderLeft: false, borderRight: false, paddingX: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "cyan", bold: true, underline: true, children: "Agent Status" }) }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Version:" }) }), _jsx(Text, { color: "white", children: version })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Session ID:" }) }), _jsx(Text, { color: "white", children: sessionId })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "cwd:" }) }), _jsx(Text, { color: "white", wrap: "wrap", children: workingDirectory })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Wave base URL:" }) }), _jsx(Text, { color: "white", children: gatewayConfig.baseURL })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Model:" }) }), _jsx(Text, { color: "white", children: modelConfig.model })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Fast model:" }) }), _jsx(Text, { color: "white", children: modelConfig.fastModel })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Esc to cancel" }) })] }));
28
28
  };
@@ -40,5 +40,5 @@ export const ToolDisplay = ({ block, isExpanded = false, }) => {
40
40
  return null;
41
41
  };
42
42
  const shortResult = getShortResult();
43
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Box, { flexShrink: 0, children: [_jsx(Text, { color: getStatusColor(), children: "\u25CF " }), _jsx(Text, { color: "white", children: toolName })] }), !isExpanded && compactParams && (_jsxs(Text, { color: "gray", children: [" ", compactParams] })), hasImages() && _jsxs(Text, { color: "blue", children: [" ", getImageIndicator()] })] }), !isExpanded && shortResult && !error && (_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: shortResult.split("\n").map((line, index) => (_jsx(Text, { color: "gray", children: line }, index))) })), isExpanded && parameters && (_jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Parameters:" }), _jsx(Text, { color: "gray", children: parameters })] })), isExpanded && result && (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "green", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Result:" }), _jsx(Text, { color: "white", children: result })] }) })), error && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", typeof error === "string" ? error : String(error)] }) })), !isExpanded && stage === "end" && success && (_jsx(DiffDisplay, { toolName: name, parameters: parameters, startLineNumber: block.startLineNumber }))] }));
43
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Box, { flexShrink: 0, children: [_jsx(Text, { color: getStatusColor(), children: "\u25CF " }), _jsx(Text, { color: "white", children: toolName })] }), !isExpanded && compactParams && (_jsxs(Text, { color: "gray", children: [" ", compactParams] })), hasImages() && _jsxs(Text, { color: "blue", children: [" ", getImageIndicator()] })] }), !isExpanded && shortResult && !error && (_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: shortResult.split("\n").map((line, index) => (_jsx(Text, { color: "gray", wrap: "truncate-end", children: line }, index))) })), isExpanded && parameters && (_jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Parameters:" }), _jsx(Text, { color: "gray", children: parameters })] })), isExpanded && result && (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "green", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Result:" }), _jsx(Text, { color: "white", children: result })] }) })), error && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", typeof error === "string" ? error : String(error)] }) })), !isExpanded && stage === "end" && success && (_jsx(DiffDisplay, { toolName: name, parameters: parameters, startLineNumber: block.startLineNumber }))] }));
44
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/constants/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,eAAO,MAAM,kBAAkB,EAAE,YAAY,EA4C5C,CAAC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/constants/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,eAAO,MAAM,kBAAkB,EAAE,YAAY,EAkD5C,CAAC"}
@@ -41,4 +41,10 @@ export const AVAILABLE_COMMANDS = [
41
41
  description: "Ask a side question without tool use",
42
42
  handler: () => { }, // Handler here won't be used, actual processing is in the hook
43
43
  },
44
+ {
45
+ id: "model",
46
+ name: "model",
47
+ description: "Switch between configured AI models",
48
+ handler: () => { }, // Handler here won't be used, actual processing is in the hook
49
+ },
44
50
  ];
@@ -25,6 +25,10 @@ export interface ChatContextType {
25
25
  askBtw: (question: string) => Promise<string>;
26
26
  abortMessage: () => void;
27
27
  latestTotalTokens: number;
28
+ currentModel: string;
29
+ configuredModels: string[];
30
+ getConfiguredModels: () => string[];
31
+ setModel: (model: string) => void;
28
32
  mcpServers: McpServerStatus[];
29
33
  connectMcpServer: (serverName: string) => Promise<boolean>;
30
34
  disconnectMcpServer: (serverName: string) => Promise<boolean>;
@@ -39,8 +43,6 @@ export interface ChatContextType {
39
43
  stopBackgroundTask: (taskId: string) => boolean;
40
44
  slashCommands: SlashCommand[];
41
45
  hasSlashCommand: (commandId: string) => boolean;
42
- subagentMessages: Record<string, Message[]>;
43
- subagentLatestTokens: Record<string, number>;
44
46
  permissionMode: PermissionMode;
45
47
  setPermissionMode: (mode: PermissionMode) => void;
46
48
  allowBypassInCycle: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
@@ -31,6 +31,8 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
31
31
  const [sessionId, setSessionId] = useState("");
32
32
  const [isCommandRunning, setIsCommandRunning] = useState(false);
33
33
  const [isCompressing, setIsCompressing] = useState(false);
34
+ const [currentModel, setCurrentModelState] = useState("");
35
+ const [configuredModels, setConfiguredModels] = useState([]);
34
36
  // MCP State
35
37
  const [mcpServers, setMcpServers] = useState([]);
36
38
  // Background tasks state
@@ -39,9 +41,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
39
41
  const [tasks, setTasks] = useState([]);
40
42
  // Command state
41
43
  const [slashCommands, setSlashCommands] = useState([]);
42
- // Subagent messages state
43
- const [subagentMessages, setSubagentMessages] = useState({});
44
- const [subagentLatestTokens, setSubagentLatestTokens] = useState({});
45
44
  // Permission state
46
45
  const [permissionMode, setPermissionModeState] = useState(initialPermissionMode ||
47
46
  (bypassPermissions ? "bypassPermissions" : "default"));
@@ -73,16 +72,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
73
72
  const [wasLastDetailsTooTall, setWasLastDetailsTooTall] = useState(0);
74
73
  const allowBypassInCycle = !!bypassPermissions || initialPermissionMode === "bypassPermissions";
75
74
  const agentRef = useRef(null);
76
- const taskUpdateTimerRef = useRef(null);
77
- const debouncedSetTasks = useCallback((newTasks) => {
78
- if (taskUpdateTimerRef.current) {
79
- clearTimeout(taskUpdateTimerRef.current);
80
- }
81
- taskUpdateTimerRef.current = setTimeout(() => {
82
- setTasks([...newTasks]);
83
- taskUpdateTimerRef.current = null;
84
- }, 100);
85
- }, [setTasks]);
86
75
  // Permission confirmation methods with queue support
87
76
  const showConfirmation = useCallback(async (toolName, toolInput, suggestedPrefix, hidePersistentOption, planContent) => {
88
77
  return new Promise((resolve, reject) => {
@@ -124,24 +113,17 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
124
113
  setBackgroundTasks([...tasks]);
125
114
  },
126
115
  onTasksChange: (tasks) => {
127
- debouncedSetTasks(tasks);
128
- },
129
- onSubagentMessagesChange: (subagentId, messages) => {
130
- logger.debug("onSubagentMessagesChange", subagentId, messages.length);
131
- setSubagentMessages((prev) => ({
132
- ...prev,
133
- [subagentId]: [...messages],
134
- }));
135
- },
136
- onSubagentLatestTotalTokensChange: (subagentId, tokens) => {
137
- setSubagentLatestTokens((prev) => ({
138
- ...prev,
139
- [subagentId]: tokens,
140
- }));
116
+ setTasks([...tasks]);
141
117
  },
142
118
  onPermissionModeChange: (mode) => {
143
119
  setPermissionModeState(mode);
144
120
  },
121
+ onModelChange: (model) => {
122
+ setCurrentModelState(model);
123
+ },
124
+ onConfiguredModelsChange: (models) => {
125
+ setConfiguredModels(models);
126
+ },
145
127
  };
146
128
  try {
147
129
  // Create the permission callback inside the try block to access showConfirmation
@@ -187,6 +169,8 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
187
169
  setIsCompressing(agent.isCompressing);
188
170
  setPermissionModeState(agent.getPermissionMode());
189
171
  setWorkingDirectory(agent.workingDirectory);
172
+ setCurrentModelState(agent.getModelConfig().model);
173
+ setConfiguredModels(agent.getConfiguredModels());
190
174
  // Get initial MCP servers state
191
175
  const mcpServers = agent.getMcpServers?.() || [];
192
176
  setMcpServers(mcpServers);
@@ -211,15 +195,11 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
211
195
  workdir,
212
196
  worktreeSession,
213
197
  model,
214
- debouncedSetTasks,
215
198
  initialPermissionMode,
216
199
  ]);
217
200
  // Cleanup on unmount
218
201
  useEffect(() => {
219
202
  return () => {
220
- if (taskUpdateTimerRef.current) {
221
- clearTimeout(taskUpdateTimerRef.current);
222
- }
223
203
  if (agentRef.current) {
224
204
  try {
225
205
  // Display usage summary before cleanup
@@ -406,6 +386,18 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
406
386
  }
407
387
  return agentRef.current.getModelConfig();
408
388
  }, []);
389
+ const getConfiguredModels = useCallback(() => {
390
+ if (!agentRef.current) {
391
+ return [];
392
+ }
393
+ return agentRef.current.getConfiguredModels();
394
+ }, []);
395
+ const setModel = useCallback((model) => {
396
+ if (agentRef.current) {
397
+ agentRef.current.setModel(model);
398
+ setCurrentModelState(model);
399
+ }
400
+ }, []);
409
401
  // Listen for Ctrl+O hotkey to toggle collapse/expand state and ESC to cancel confirmation
410
402
  useInput((input, key) => {
411
403
  if (key.ctrl && input === "o") {
@@ -463,6 +455,10 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
463
455
  askBtw,
464
456
  abortMessage,
465
457
  latestTotalTokens,
458
+ currentModel,
459
+ configuredModels,
460
+ getConfiguredModels,
461
+ setModel,
466
462
  isCompressing,
467
463
  mcpServers,
468
464
  connectMcpServer,
@@ -473,8 +469,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
473
469
  stopBackgroundTask,
474
470
  slashCommands,
475
471
  hasSlashCommand,
476
- subagentMessages,
477
- subagentLatestTokens,
478
472
  permissionMode,
479
473
  setPermissionMode,
480
474
  allowBypassInCycle,
@@ -20,6 +20,7 @@ export declare const useInputManager: (callbacks?: Partial<InputManagerCallbacks
20
20
  showHelp: boolean;
21
21
  showStatusCommand: boolean;
22
22
  showPluginManager: boolean;
23
+ showModelSelector: boolean;
23
24
  permissionMode: PermissionMode;
24
25
  attachedImages: import("../managers/inputReducer.js").AttachedImage[];
25
26
  btwState: import("../managers/inputReducer.js").BtwState;
@@ -58,6 +59,7 @@ export declare const useInputManager: (callbacks?: Partial<InputManagerCallbacks
58
59
  setShowHelp: (show: boolean) => void;
59
60
  setShowStatusCommand: (show: boolean) => void;
60
61
  setShowPluginManager: (show: boolean) => void;
62
+ setShowModelSelector: (show: boolean) => void;
61
63
  setPermissionMode: (mode: PermissionMode) => void;
62
64
  setAllowBypassInCycle: (allow: boolean) => void;
63
65
  setBtwState: (payload: Partial<import("../managers/inputReducer.js").BtwState>) => void;