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.
- package/README.md +9 -51
- package/dist/acp/agent.js +1 -1
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +2 -3
- package/dist/components/DiffDisplay.d.ts.map +1 -1
- package/dist/components/DiffDisplay.js +2 -23
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +6 -2
- package/dist/components/MessageBlockItem.d.ts.map +1 -1
- package/dist/components/MessageBlockItem.js +2 -1
- package/dist/components/MessageList.d.ts +1 -2
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +10 -4
- package/dist/components/ModelSelector.d.ts +9 -0
- package/dist/components/ModelSelector.d.ts.map +1 -0
- package/dist/components/ModelSelector.js +34 -0
- package/dist/components/SlashDisplay.d.ts +9 -0
- package/dist/components/SlashDisplay.d.ts.map +1 -0
- package/dist/components/SlashDisplay.js +20 -0
- package/dist/components/StatusCommand.d.ts.map +1 -1
- package/dist/components/StatusCommand.js +1 -1
- package/dist/components/ToolDisplay.js +1 -1
- package/dist/constants/commands.d.ts.map +1 -1
- package/dist/constants/commands.js +6 -0
- package/dist/contexts/useChat.d.ts +4 -2
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +27 -33
- package/dist/hooks/useInputManager.d.ts +2 -0
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/managers/inputHandlers.d.ts.map +1 -1
- package/dist/managers/inputHandlers.js +6 -0
- package/dist/managers/inputReducer.d.ts +5 -0
- package/dist/managers/inputReducer.d.ts.map +1 -1
- package/dist/managers/inputReducer.js +7 -0
- package/dist/utils/highlightUtils.d.ts.map +1 -1
- package/dist/utils/highlightUtils.js +0 -8
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +10 -5
- package/dist/utils/toolParameterTransforms.d.ts +5 -1
- package/dist/utils/toolParameterTransforms.d.ts.map +1 -1
- package/dist/utils/toolParameterTransforms.js +14 -0
- package/dist/utils/worktree.d.ts +0 -1
- package/dist/utils/worktree.d.ts.map +1 -1
- package/dist/utils/worktree.js +2 -2
- package/package.json +3 -3
- package/src/acp/agent.ts +1 -1
- package/src/components/ChatInterface.tsx +0 -4
- package/src/components/DiffDisplay.tsx +2 -27
- package/src/components/InputBox.tsx +17 -0
- package/src/components/MessageBlockItem.tsx +5 -5
- package/src/components/MessageList.tsx +15 -9
- package/src/components/ModelSelector.tsx +109 -0
- package/src/components/SlashDisplay.tsx +70 -0
- package/src/components/StatusCommand.tsx +7 -0
- package/src/components/ToolDisplay.tsx +1 -1
- package/src/constants/commands.ts +6 -0
- package/src/contexts/useChat.tsx +34 -49
- package/src/hooks/useInputManager.ts +10 -0
- package/src/index.ts +13 -0
- package/src/managers/inputHandlers.ts +5 -0
- package/src/managers/inputReducer.ts +10 -0
- package/src/utils/highlightUtils.ts +0 -8
- package/src/utils/logger.ts +9 -7
- package/src/utils/toolParameterTransforms.ts +23 -1
- 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
|
|
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
|
@@ -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,
|
|
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,
|
|
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,
|
|
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;
|
|
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
|
|
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:
|
|
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;
|
|
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;
|
|
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.
|
|
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,
|
|
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,
|
|
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,
|
|
7
|
-
const welcomeMessage = (_jsxs(Box, { flexDirection: "column", paddingTop: 1, children: [_jsxs(Text, { color: "gray", children: ["WAVE", version ? ` v${version}` : ""
|
|
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
|
-
((
|
|
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,
|
|
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,
|
|
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":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IAEvB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,cAAc,EAAE,KAAK,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACnD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtC,CAAC,CAAC;IAEH,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CACX,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,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAE1B,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9D,eAAe,EAAE,cAAc,EAAE,CAAC;IAElC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,uBAAuB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAC3C,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI,CAAC;IACT,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAEhD,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAEhD,
|
|
1
|
+
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
|
package/dist/contexts/useChat.js
CHANGED
|
@@ -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
|
-
|
|
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;
|