wave-code 0.12.6 → 0.12.8
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/dist/components/BtwDisplay.js +1 -1
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +2 -3
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +3 -4
- package/dist/components/MarketplaceAddForm.d.ts.map +1 -1
- package/dist/components/MarketplaceAddForm.js +9 -7
- package/dist/components/McpManager.d.ts.map +1 -1
- package/dist/components/McpManager.js +27 -35
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +1 -0
- package/dist/components/PluginDetail.d.ts.map +1 -1
- package/dist/components/PluginDetail.js +18 -15
- package/dist/contexts/useChat.d.ts +0 -2
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +24 -53
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +1 -11
- package/dist/managers/inputReducer.d.ts +0 -2
- package/dist/managers/inputReducer.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/BtwDisplay.tsx +3 -3
- package/src/components/ChatInterface.tsx +0 -3
- package/src/components/InputBox.tsx +2 -4
- package/src/components/MarketplaceAddForm.tsx +10 -7
- package/src/components/McpManager.tsx +31 -37
- package/src/components/MessageList.tsx +1 -0
- package/src/components/PluginDetail.tsx +24 -18
- package/src/contexts/useChat.tsx +36 -65
- package/src/hooks/useInputManager.ts +1 -11
- package/src/managers/inputReducer.ts +0 -2
|
@@ -5,5 +5,5 @@ export const BtwDisplay = ({ btwState }) => {
|
|
|
5
5
|
if (!btwState.isActive) {
|
|
6
6
|
return null;
|
|
7
7
|
}
|
|
8
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 0, marginBottom:
|
|
8
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 0, marginBottom: 0, children: [btwState.question && (_jsxs(Box, { children: [_jsx(Text, { color: btwState.isLoading ? "yellow" : "green", children: "/ " }), _jsxs(Text, { italic: true, color: "gray", children: ["btw ", btwState.question] })] })), btwState.answer && (_jsx(Box, { flexDirection: "column", children: _jsx(Markdown, { children: btwState.answer }) }))] }));
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EA+HjC,CAAC"}
|
|
@@ -2,7 +2,6 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useState, useRef, useEffect } from "react";
|
|
3
3
|
import { Box, useStdout, measureElement, Static } from "ink";
|
|
4
4
|
import { MessageList } from "./MessageList.js";
|
|
5
|
-
import { BtwDisplay } from "./BtwDisplay.js";
|
|
6
5
|
import { InputBox } from "./InputBox.js";
|
|
7
6
|
import { LoadingIndicator } from "./LoadingIndicator.js";
|
|
8
7
|
import { TaskList } from "./TaskList.js";
|
|
@@ -11,7 +10,7 @@ import { ConfirmationDetails } from "./ConfirmationDetails.js";
|
|
|
11
10
|
import { ConfirmationSelector } from "./ConfirmationSelector.js";
|
|
12
11
|
import { useChat } from "../contexts/useChat.js";
|
|
13
12
|
export const ChatInterface = () => {
|
|
14
|
-
const { messages, isLoading, isCommandRunning, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir,
|
|
13
|
+
const { messages, isLoading, isCommandRunning, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, requestRemount, } = useChat();
|
|
15
14
|
const displayMessages = messages;
|
|
16
15
|
const [forceStatic, setForceStatic] = useState(false);
|
|
17
16
|
const { stdout } = useStdout();
|
|
@@ -38,5 +37,5 @@ export const ChatInterface = () => {
|
|
|
38
37
|
]);
|
|
39
38
|
if (!sessionId)
|
|
40
39
|
return null;
|
|
41
|
-
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [
|
|
40
|
+
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(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: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })] }))] }));
|
|
42
41
|
};
|
|
@@ -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;AAkBzC,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,CAuQ5C,CAAC"}
|
|
@@ -13,12 +13,13 @@ import { StatusCommand } from "./StatusCommand.js";
|
|
|
13
13
|
import { PluginManagerShell } from "./PluginManagerShell.js";
|
|
14
14
|
import { ModelSelector } from "./ModelSelector.js";
|
|
15
15
|
import { StatusLine } from "./StatusLine.js";
|
|
16
|
+
import { BtwDisplay } from "./BtwDisplay.js";
|
|
16
17
|
import { useInputManager } from "../hooks/useInputManager.js";
|
|
17
18
|
import { useChat } from "../contexts/useChat.js";
|
|
18
19
|
export const INPUT_PLACEHOLDER_TEXT = "Type your message (use /help for more info)...";
|
|
19
20
|
export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
|
|
20
21
|
export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
|
|
21
|
-
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, allowBypassInCycle: chatAllowBypassInCycle, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw,
|
|
22
|
+
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, allowBypassInCycle: chatAllowBypassInCycle, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw, currentModel, configuredModels, setModel, } = useChat();
|
|
22
23
|
// Input manager with all input state and functionality (including images)
|
|
23
24
|
const { inputText, cursorPosition,
|
|
24
25
|
// Image management
|
|
@@ -41,8 +42,6 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
41
42
|
isManagerReady, } = useInputManager({
|
|
42
43
|
onSendMessage: sendMessage,
|
|
43
44
|
onAskBtw: askBtw,
|
|
44
|
-
btwState: chatBtwState,
|
|
45
|
-
onBtwStateChange: setChatBtwState,
|
|
46
45
|
onHasSlashCommand: hasSlashCommand,
|
|
47
46
|
onAbortMessage: abortMessage,
|
|
48
47
|
onBackgroundCurrentTask: backgroundCurrentTask,
|
|
@@ -104,7 +103,7 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
104
103
|
if (showModelSelector) {
|
|
105
104
|
return (_jsx(ModelSelector, { onCancel: () => setShowModelSelector(false), currentModel: currentModel, configuredModels: configuredModels, onSelectModel: setModel }));
|
|
106
105
|
}
|
|
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 ||
|
|
106
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BtwDisplay, { btwState: btwState }), 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 ||
|
|
108
107
|
showMcpManager ||
|
|
109
108
|
showRewindManager ||
|
|
110
109
|
showHelp ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarketplaceAddForm.d.ts","sourceRoot":"","sources":["../../src/components/MarketplaceAddForm.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"MarketplaceAddForm.d.ts","sourceRoot":"","sources":["../../src/components/MarketplaceAddForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAI3D,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAkDtC,CAAC"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useState, useRef, useEffect } from "react";
|
|
3
3
|
import { Box, Text, useInput } from "ink";
|
|
4
4
|
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
5
5
|
export const MarketplaceAddForm = () => {
|
|
6
6
|
const { state, actions } = usePluginManagerContext();
|
|
7
7
|
const [source, setSource] = useState("");
|
|
8
|
+
const sourceRef = useRef(source);
|
|
9
|
+
// Keep ref in sync with state
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
sourceRef.current = source;
|
|
12
|
+
}, [source]);
|
|
8
13
|
useInput((input, key) => {
|
|
9
14
|
if (key.escape) {
|
|
10
15
|
actions.setView("MARKETPLACES");
|
|
@@ -13,12 +18,9 @@ export const MarketplaceAddForm = () => {
|
|
|
13
18
|
return;
|
|
14
19
|
}
|
|
15
20
|
else if (key.return) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
return prev;
|
|
21
|
-
});
|
|
21
|
+
if (sourceRef.current.trim()) {
|
|
22
|
+
actions.addMarketplace(sourceRef.current.trim());
|
|
23
|
+
}
|
|
22
24
|
}
|
|
23
25
|
else if (key.backspace || key.delete) {
|
|
24
26
|
setSource((prev) => prev.slice(0, -1));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManager.d.ts","sourceRoot":"","sources":["../../src/components/McpManager.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"McpManager.d.ts","sourceRoot":"","sources":["../../src/components/McpManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAoThD,CAAC"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useState, useRef, useEffect } from "react";
|
|
3
3
|
import { Box, Text, useInput } from "ink";
|
|
4
4
|
export const McpManager = ({ onCancel, servers, onConnectServer, onDisconnectServer, }) => {
|
|
5
5
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6
6
|
const [viewMode, setViewMode] = useState("list");
|
|
7
|
+
// Keep ref in sync with state to avoid stale closures in useInput
|
|
8
|
+
const selectedIndexRef = useRef(selectedIndex);
|
|
9
|
+
const viewModeRef = useRef(viewMode);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
selectedIndexRef.current = selectedIndex;
|
|
12
|
+
}, [selectedIndex]);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
viewModeRef.current = viewMode;
|
|
15
|
+
}, [viewMode]);
|
|
7
16
|
// Dynamically calculate selectedServer based on selectedIndex and servers
|
|
8
17
|
const selectedServer = viewMode === "detail" &&
|
|
9
18
|
servers.length > 0 &&
|
|
@@ -45,29 +54,18 @@ export const McpManager = ({ onCancel, servers, onConnectServer, onDisconnectSer
|
|
|
45
54
|
};
|
|
46
55
|
useInput((input, key) => {
|
|
47
56
|
if (key.return) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (servers.length > 0 && prevIndex < servers.length) {
|
|
52
|
-
// We can't call setViewMode here because we're already in a setViewMode call
|
|
53
|
-
// But we can return the new mode from the outer setViewMode
|
|
54
|
-
}
|
|
55
|
-
return prevIndex;
|
|
56
|
-
});
|
|
57
|
-
return "detail";
|
|
58
|
-
}
|
|
59
|
-
return prevMode;
|
|
60
|
-
});
|
|
57
|
+
if (viewModeRef.current === "list") {
|
|
58
|
+
setViewMode("detail");
|
|
59
|
+
}
|
|
61
60
|
return;
|
|
62
61
|
}
|
|
63
62
|
if (key.escape) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
if (viewModeRef.current === "detail") {
|
|
64
|
+
setViewMode("list");
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
68
67
|
onCancel();
|
|
69
|
-
|
|
70
|
-
});
|
|
68
|
+
}
|
|
71
69
|
return;
|
|
72
70
|
}
|
|
73
71
|
if (key.upArrow) {
|
|
@@ -80,24 +78,18 @@ export const McpManager = ({ onCancel, servers, onConnectServer, onDisconnectSer
|
|
|
80
78
|
}
|
|
81
79
|
// Hotkeys for server actions
|
|
82
80
|
if (input === "c") {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
return prev;
|
|
90
|
-
});
|
|
81
|
+
const server = servers[selectedIndexRef.current];
|
|
82
|
+
if (server &&
|
|
83
|
+
(server.status === "disconnected" || server.status === "error")) {
|
|
84
|
+
handleConnect(server.name);
|
|
85
|
+
}
|
|
91
86
|
return;
|
|
92
87
|
}
|
|
93
88
|
if (input === "d") {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
return prev;
|
|
100
|
-
});
|
|
89
|
+
const server = servers[selectedIndexRef.current];
|
|
90
|
+
if (server && server.status === "connected") {
|
|
91
|
+
handleDisconnect(server.name);
|
|
92
|
+
}
|
|
101
93
|
return;
|
|
102
94
|
}
|
|
103
95
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,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;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,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;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,6CAkHpB,CAAC"}
|
|
@@ -30,6 +30,7 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
|
|
|
30
30
|
const blocksWithStatus = allBlocks.map((item) => {
|
|
31
31
|
const { block } = item;
|
|
32
32
|
const isDynamic = !forceStatic &&
|
|
33
|
+
!isExpanded &&
|
|
33
34
|
(messagesWithRunningBlocks.has(item.messageIndex) || isRunning(block));
|
|
34
35
|
return { ...item, isDynamic };
|
|
35
36
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginDetail.d.ts","sourceRoot":"","sources":["../../src/components/PluginDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"PluginDetail.d.ts","sourceRoot":"","sources":["../../src/components/PluginDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAU3D,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAqKhC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useState, useRef, useEffect } from "react";
|
|
3
3
|
import { Box, Text, useInput } from "ink";
|
|
4
4
|
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
5
5
|
const SCOPES = [
|
|
@@ -11,6 +11,15 @@ export const PluginDetail = () => {
|
|
|
11
11
|
const { state, discoverablePlugins, installedPlugins, actions } = usePluginManagerContext();
|
|
12
12
|
const [selectedScopeIndex, setSelectedScopeIndex] = useState(0);
|
|
13
13
|
const [selectedActionIndex, setSelectedActionIndex] = useState(0);
|
|
14
|
+
// Keep refs in sync with state to avoid stale closures in useInput
|
|
15
|
+
const selectedScopeIndexRef = useRef(selectedScopeIndex);
|
|
16
|
+
const selectedActionIndexRef = useRef(selectedActionIndex);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
selectedScopeIndexRef.current = selectedScopeIndex;
|
|
19
|
+
}, [selectedScopeIndex]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
selectedActionIndexRef.current = selectedActionIndex;
|
|
22
|
+
}, [selectedActionIndex]);
|
|
14
23
|
const plugin = discoverablePlugins.find((p) => `${p.name}@${p.marketplace}` === state.selectedId) ||
|
|
15
24
|
installedPlugins.find((p) => `${p.name}@${p.marketplace}` === state.selectedId);
|
|
16
25
|
const INSTALLED_ACTIONS = [
|
|
@@ -33,22 +42,16 @@ export const PluginDetail = () => {
|
|
|
33
42
|
}
|
|
34
43
|
else if (key.return && plugin && !state.isLoading) {
|
|
35
44
|
if (isInstalledAndEnabled) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
return prev;
|
|
45
|
-
});
|
|
45
|
+
const action = INSTALLED_ACTIONS[selectedActionIndexRef.current].id;
|
|
46
|
+
if (action === "uninstall") {
|
|
47
|
+
actions.uninstallPlugin(plugin.name, plugin.marketplace);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
actions.updatePlugin(plugin.name, plugin.marketplace);
|
|
51
|
+
}
|
|
46
52
|
}
|
|
47
53
|
else {
|
|
48
|
-
|
|
49
|
-
actions.installPlugin(plugin.name, plugin.marketplace, SCOPES[prev].id);
|
|
50
|
-
return prev;
|
|
51
|
-
});
|
|
54
|
+
actions.installPlugin(plugin.name, plugin.marketplace, SCOPES[selectedScopeIndexRef.current].id);
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
});
|
|
@@ -72,8 +72,6 @@ export interface ChatContextType {
|
|
|
72
72
|
workingDirectory: string;
|
|
73
73
|
version?: string;
|
|
74
74
|
workdir?: string;
|
|
75
|
-
btwState: import("../managers/inputReducer.js").BtwState;
|
|
76
|
-
setBtwState: (payload: Partial<import("../managers/inputReducer.js").BtwState>) => void;
|
|
77
75
|
}
|
|
78
76
|
export declare const useChat: () => ChatContextType;
|
|
79
77
|
export interface ChatProviderProps extends BaseAppProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACf,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAYxB,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,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,MAAM,EAAE,CAAC;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,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,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,kBAAkB,EAAE,OAAO,CAAC;IAE5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uBAAuB,EAAE,OAAO,CAAC;IACjC,cAAc,CAAC,EAAE;QACf,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,eAAe,CAAC,EAAE,MAAM,EACxB,oBAAoB,CAAC,EAAE,OAAO,EAC9B,WAAW,CAAC,EAAE,MAAM,KACjB,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,0BAA0B,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnE,wBAAwB,EAAE,MAAM,IAAI,CAAC;IAErC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAElC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,IAAI,CAAC;IAE3B,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,oBAAoB,EAAE,MAAM,OAAO,CAAC;QAClC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC,CAAC;IAEH,gBAAgB,EAAE,MAAM,OAAO,gBAAgB,EAAE,aAAa,CAAC;IAC/D,cAAc,EAAE,MAAM,OAAO,gBAAgB,EAAE,WAAW,CAAC;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,eAAO,MAAM,OAAO,uBAMnB,CAAC;AAEF,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA6nBpD,CAAC"}
|
package/dist/contexts/useChat.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { createContext, useContext, useCallback, useRef, useEffect, useState, useMemo, } from "react";
|
|
3
3
|
import { useInput, useStdout } from "ink";
|
|
4
4
|
import { useAppConfig } from "./useAppConfig.js";
|
|
5
|
-
import { Agent, OPERATION_CANCELLED_BY_USER,
|
|
5
|
+
import { Agent, OPERATION_CANCELLED_BY_USER, } from "wave-agent-sdk";
|
|
6
6
|
import { logger } from "../utils/logger.js";
|
|
7
7
|
import { throttle } from "../utils/throttle.js";
|
|
8
8
|
import { displayUsageSummary } from "../utils/usageSummary.js";
|
|
@@ -66,12 +66,17 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
66
66
|
// Remount state
|
|
67
67
|
const [remountKey, setRemountKey] = useState(0);
|
|
68
68
|
const prevSessionId = useRef(null);
|
|
69
|
-
const requestRemount =
|
|
69
|
+
const requestRemount = useMemo(() => throttle(() => {
|
|
70
70
|
logger.info("requesting remount");
|
|
71
71
|
stdout?.write("\u001b[2J\u001b[3J\u001b[0;0H", () => {
|
|
72
72
|
setRemountKey((prev) => prev + 1);
|
|
73
73
|
});
|
|
74
|
-
}, [stdout]);
|
|
74
|
+
}, 1000, { leading: true, trailing: false }), [stdout]);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
return () => {
|
|
77
|
+
requestRemount.cancel();
|
|
78
|
+
};
|
|
79
|
+
}, [requestRemount]);
|
|
75
80
|
// Track sessionId changes to trigger remount
|
|
76
81
|
useEffect(() => {
|
|
77
82
|
if (prevSessionId.current &&
|
|
@@ -85,21 +90,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
85
90
|
}, [sessionId, requestRemount]);
|
|
86
91
|
// Status metadata state
|
|
87
92
|
const [workingDirectory, setWorkingDirectory] = useState("");
|
|
88
|
-
// /btw state
|
|
89
|
-
const [btwState, setBtwStateInternal] = useState({
|
|
90
|
-
isActive: false,
|
|
91
|
-
question: "",
|
|
92
|
-
isLoading: false,
|
|
93
|
-
});
|
|
94
|
-
const setBtwState = useCallback((payload) => {
|
|
95
|
-
setBtwStateInternal((prev) => {
|
|
96
|
-
const newState = { ...prev, ...payload };
|
|
97
|
-
if (process.env.NODE_ENV === "test") {
|
|
98
|
-
// console.log("setBtwState", newState);
|
|
99
|
-
}
|
|
100
|
-
return newState;
|
|
101
|
-
});
|
|
102
|
-
}, []);
|
|
103
93
|
const allowBypassInCycle = !!bypassPermissions || initialPermissionMode === "bypassPermissions";
|
|
104
94
|
const agentRef = useRef(null);
|
|
105
95
|
// Permission confirmation methods with queue support
|
|
@@ -430,49 +420,32 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
430
420
|
useInput((input, key) => {
|
|
431
421
|
if (key.ctrl && input === "o") {
|
|
432
422
|
// Clear terminal screen when expanded state changes
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
return [...currentMessages.slice(0, -1), frozenLastMessage];
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
// Transitioning to COLLAPSED: Restore from agent's actual state
|
|
451
|
-
if (agentRef.current) {
|
|
452
|
-
setMessages([...agentRef.current.messages]);
|
|
453
|
-
}
|
|
423
|
+
// Use ref to get the current value to avoid stale closure
|
|
424
|
+
const nextExpanded = !isExpandedRef.current;
|
|
425
|
+
setIsExpanded(nextExpanded);
|
|
426
|
+
isExpandedRef.current = nextExpanded;
|
|
427
|
+
if (nextExpanded) {
|
|
428
|
+
// Transitioning to EXPANDED: Freeze the current view
|
|
429
|
+
// Cancel any pending throttled updates to avoid overwriting the frozen state
|
|
430
|
+
throttledSetMessages.cancel();
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
// Transitioning to COLLAPSED: Restore from agent's actual state
|
|
434
|
+
if (agentRef.current) {
|
|
435
|
+
setMessages([...agentRef.current.messages]);
|
|
454
436
|
}
|
|
455
|
-
|
|
456
|
-
});
|
|
437
|
+
}
|
|
457
438
|
// Force remount to re-render Static items with new isExpanded state
|
|
458
439
|
requestRemount();
|
|
459
440
|
}
|
|
460
441
|
if (key.ctrl && input === "t") {
|
|
461
442
|
setIsTaskListVisible((prev) => !prev);
|
|
462
443
|
}
|
|
463
|
-
// Handle ESC key to cancel confirmation
|
|
444
|
+
// Handle ESC key to cancel confirmation
|
|
464
445
|
if (key.escape) {
|
|
465
446
|
if (isConfirmationVisible) {
|
|
466
447
|
handleConfirmationCancel();
|
|
467
448
|
}
|
|
468
|
-
else if (btwState.isActive) {
|
|
469
|
-
setBtwState({
|
|
470
|
-
isActive: false,
|
|
471
|
-
question: "",
|
|
472
|
-
answer: undefined,
|
|
473
|
-
isLoading: false,
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
449
|
}
|
|
477
450
|
});
|
|
478
451
|
const contextValue = {
|
|
@@ -514,7 +487,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
514
487
|
handleConfirmationCancel,
|
|
515
488
|
backgroundCurrentTask,
|
|
516
489
|
remountKey,
|
|
517
|
-
requestRemount,
|
|
490
|
+
requestRemount: requestRemount,
|
|
518
491
|
handleRewindSelect,
|
|
519
492
|
getFullMessageThread,
|
|
520
493
|
getGatewayConfig,
|
|
@@ -522,8 +495,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
522
495
|
workingDirectory,
|
|
523
496
|
version,
|
|
524
497
|
workdir,
|
|
525
|
-
btwState,
|
|
526
|
-
setBtwState,
|
|
527
498
|
};
|
|
528
499
|
return (_jsx(ChatContext.Provider, { value: contextValue, children: children }));
|
|
529
500
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInputManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useInputManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAGL,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,cAAc,EACd,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAGxB,eAAO,MAAM,eAAe,GAC1B,YAAW,OAAO,CAAC,qBAAqB,CAAM;;;;;;;;;;;;;;;;;;;;;;;;+
|
|
1
|
+
{"version":3,"file":"useInputManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useInputManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAGL,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,cAAc,EACd,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAGxB,eAAO,MAAM,eAAe,GAC1B,YAAW,OAAO,CAAC,qBAAqB,CAAM;;;;;;;;;;;;;;;;;;;;;;;;+BAoLA,MAAM;;;;;qCAoBA,MAAM;iCAIV,MAAM;;;;;mCAaJ,MAAM;oCAIL,MAAM;wCAIF,MAAM;mCAIX,MAAM;;;;mCASN,MAAM;;;;;sCAkCH,MAAM;uCAIL,MAAM;uCAQN,WAAW;;iCAQjB,MAAM;yCAYE,OAAO;8BAIlB,OAAO;iCAIJ,OAAO;wBAIhB,OAAO;iCAIE,OAAO;iCAIP,OAAO;iCAIP,OAAO;8BAIV,cAAc;mCAKT,OAAO;2BAK7C,OAAO,CAAC,OAAO,6BAA6B,EAAE,QAAQ,CAAC;0BAM1B,MAAM,YAAY,MAAM;2BAIvB,MAAM;;;8BAYH,MAAM;mCAW/B,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;uCAYnB,MAAM;;yBAajD,MAAM,OACR,GAAG,kBACQ,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,gBACvD,MAAM,IAAI;yBA3GY,MAAM;kCAIG,MAAM;;CA8MxD,CAAC"}
|
|
@@ -106,11 +106,6 @@ export const useInputManager = (callbacks = {}) => {
|
|
|
106
106
|
useEffect(() => {
|
|
107
107
|
callbacksRef.current.onImagesStateChange?.(state.attachedImages);
|
|
108
108
|
}, [state.attachedImages]);
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
if (callbacksRef.current.onBtwStateChange) {
|
|
111
|
-
callbacksRef.current.onBtwStateChange(state.btwState);
|
|
112
|
-
}
|
|
113
|
-
}, [state.btwState]);
|
|
114
109
|
// Handle /btw side question
|
|
115
110
|
useEffect(() => {
|
|
116
111
|
if (state.btwState.isActive &&
|
|
@@ -252,12 +247,7 @@ export const useInputManager = (callbacks = {}) => {
|
|
|
252
247
|
dispatch({ type: "SET_ALLOW_BYPASS_IN_CYCLE", payload: allow });
|
|
253
248
|
}, []);
|
|
254
249
|
const setBtwState = useCallback((payload) => {
|
|
255
|
-
|
|
256
|
-
callbacksRef.current.onBtwStateChange(payload);
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
dispatch({ type: "SET_BTW_STATE", payload });
|
|
260
|
-
}
|
|
250
|
+
dispatch({ type: "SET_BTW_STATE", payload });
|
|
261
251
|
}, []);
|
|
262
252
|
const addImage = useCallback((imagePath, mimeType) => {
|
|
263
253
|
dispatch({ type: "ADD_IMAGE", payload: { path: imagePath, mimeType } });
|
|
@@ -33,8 +33,6 @@ export interface InputManagerCallbacks {
|
|
|
33
33
|
onBackgroundCurrentTask?: () => void;
|
|
34
34
|
onPermissionModeChange?: (mode: PermissionMode) => void;
|
|
35
35
|
onAskBtw?: (question: string) => Promise<string>;
|
|
36
|
-
btwState?: BtwState;
|
|
37
|
-
onBtwStateChange?: (payload: Partial<BtwState>) => void;
|
|
38
36
|
sessionId?: string;
|
|
39
37
|
workdir?: string;
|
|
40
38
|
getFullMessageThread?: () => Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputReducer.d.ts","sourceRoot":"","sources":["../../src/managers/inputReducer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,cAAc,EACd,MAAM,EACN,WAAW,EACX,OAAO,EACR,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,yBAAyB,CAAC,EAAE,CAC1B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;IACV,4BAA4B,CAAC,EAAE,CAC7B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;IACV,0BAA0B,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,kCAAkC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,0BAA0B,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,0BAA0B,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,0BAA0B,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,0BAA0B,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IACxD,aAAa,CAAC,EAAE,CACd,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,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,
|
|
1
|
+
{"version":3,"file":"inputReducer.d.ts","sourceRoot":"","sources":["../../src/managers/inputReducer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.8",
|
|
4
4
|
"description": "CLI-based code assistant powered by AI, built with React and Ink",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"semver": "^7.7.4",
|
|
43
43
|
"yargs": "^17.7.2",
|
|
44
44
|
"zod": "^3.23.8",
|
|
45
|
-
"wave-agent-sdk": "0.12.
|
|
45
|
+
"wave-agent-sdk": "0.12.8"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.1.8",
|
|
@@ -13,12 +13,12 @@ export const BtwDisplay: React.FC<BtwDisplayProps> = ({ btwState }) => {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
|
-
<Box flexDirection="column" marginTop={0} marginBottom={
|
|
16
|
+
<Box flexDirection="column" marginTop={0} marginBottom={0}>
|
|
17
17
|
{btwState.question && (
|
|
18
18
|
<Box>
|
|
19
|
-
<Text color={btwState.isLoading ? "yellow" : "green"}
|
|
19
|
+
<Text color={btwState.isLoading ? "yellow" : "green"}>/ </Text>
|
|
20
20
|
<Text italic color="gray">
|
|
21
|
-
|
|
21
|
+
btw {btwState.question}
|
|
22
22
|
</Text>
|
|
23
23
|
</Box>
|
|
24
24
|
)}
|
|
@@ -2,7 +2,6 @@ import React, { useState, useRef, useEffect } from "react";
|
|
|
2
2
|
import { Box, useStdout, measureElement, Static } from "ink";
|
|
3
3
|
import type { DOMElement } from "ink";
|
|
4
4
|
import { MessageList } from "./MessageList.js";
|
|
5
|
-
import { BtwDisplay } from "./BtwDisplay.js";
|
|
6
5
|
import { InputBox } from "./InputBox.js";
|
|
7
6
|
import { LoadingIndicator } from "./LoadingIndicator.js";
|
|
8
7
|
import { TaskList } from "./TaskList.js";
|
|
@@ -35,7 +34,6 @@ export const ChatInterface: React.FC = () => {
|
|
|
35
34
|
handleConfirmationCancel,
|
|
36
35
|
version,
|
|
37
36
|
workdir,
|
|
38
|
-
btwState,
|
|
39
37
|
remountKey,
|
|
40
38
|
requestRemount,
|
|
41
39
|
} = useChat();
|
|
@@ -81,7 +79,6 @@ export const ChatInterface: React.FC = () => {
|
|
|
81
79
|
|
|
82
80
|
{!isConfirmationVisible && !isExpanded && (
|
|
83
81
|
<>
|
|
84
|
-
<BtwDisplay btwState={btwState} />
|
|
85
82
|
{(isLoading || isCommandRunning || isCompressing) && (
|
|
86
83
|
<LoadingIndicator
|
|
87
84
|
isLoading={isLoading}
|
|
@@ -12,6 +12,7 @@ import { StatusCommand } from "./StatusCommand.js";
|
|
|
12
12
|
import { PluginManagerShell } from "./PluginManagerShell.js";
|
|
13
13
|
import { ModelSelector } from "./ModelSelector.js";
|
|
14
14
|
import { StatusLine } from "./StatusLine.js";
|
|
15
|
+
import { BtwDisplay } from "./BtwDisplay.js";
|
|
15
16
|
import { useInputManager } from "../hooks/useInputManager.js";
|
|
16
17
|
import { useChat } from "../contexts/useChat.js";
|
|
17
18
|
|
|
@@ -64,8 +65,6 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
64
65
|
sessionId,
|
|
65
66
|
workingDirectory,
|
|
66
67
|
askBtw,
|
|
67
|
-
btwState: chatBtwState,
|
|
68
|
-
setBtwState: setChatBtwState,
|
|
69
68
|
currentModel,
|
|
70
69
|
configuredModels,
|
|
71
70
|
setModel,
|
|
@@ -124,8 +123,6 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
124
123
|
} = useInputManager({
|
|
125
124
|
onSendMessage: sendMessage,
|
|
126
125
|
onAskBtw: askBtw,
|
|
127
|
-
btwState: chatBtwState,
|
|
128
|
-
onBtwStateChange: setChatBtwState,
|
|
129
126
|
onHasSlashCommand: hasSlashCommand,
|
|
130
127
|
onAbortMessage: abortMessage,
|
|
131
128
|
onBackgroundCurrentTask: backgroundCurrentTask,
|
|
@@ -224,6 +221,7 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
224
221
|
|
|
225
222
|
return (
|
|
226
223
|
<Box flexDirection="column">
|
|
224
|
+
<BtwDisplay btwState={btwState} />
|
|
227
225
|
{showFileSelector && (
|
|
228
226
|
<FileSelector
|
|
229
227
|
files={filteredFiles}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
3
|
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
4
4
|
|
|
5
5
|
export const MarketplaceAddForm: React.FC = () => {
|
|
6
6
|
const { state, actions } = usePluginManagerContext();
|
|
7
7
|
const [source, setSource] = useState("");
|
|
8
|
+
const sourceRef = useRef(source);
|
|
9
|
+
|
|
10
|
+
// Keep ref in sync with state
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
sourceRef.current = source;
|
|
13
|
+
}, [source]);
|
|
8
14
|
|
|
9
15
|
useInput((input, key) => {
|
|
10
16
|
if (key.escape) {
|
|
@@ -12,12 +18,9 @@ export const MarketplaceAddForm: React.FC = () => {
|
|
|
12
18
|
} else if (state.isLoading) {
|
|
13
19
|
return;
|
|
14
20
|
} else if (key.return) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
return prev;
|
|
20
|
-
});
|
|
21
|
+
if (sourceRef.current.trim()) {
|
|
22
|
+
actions.addMarketplace(sourceRef.current.trim());
|
|
23
|
+
}
|
|
21
24
|
} else if (key.backspace || key.delete) {
|
|
22
25
|
setSource((prev) => prev.slice(0, -1));
|
|
23
26
|
} else if (input.length === 1) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
3
|
import { McpServerStatus } from "wave-agent-sdk";
|
|
4
4
|
|
|
@@ -18,6 +18,18 @@ export const McpManager: React.FC<McpManagerProps> = ({
|
|
|
18
18
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
19
19
|
const [viewMode, setViewMode] = useState<"list" | "detail">("list");
|
|
20
20
|
|
|
21
|
+
// Keep ref in sync with state to avoid stale closures in useInput
|
|
22
|
+
const selectedIndexRef = useRef(selectedIndex);
|
|
23
|
+
const viewModeRef = useRef(viewMode);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
selectedIndexRef.current = selectedIndex;
|
|
27
|
+
}, [selectedIndex]);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
viewModeRef.current = viewMode;
|
|
31
|
+
}, [viewMode]);
|
|
32
|
+
|
|
21
33
|
// Dynamically calculate selectedServer based on selectedIndex and servers
|
|
22
34
|
const selectedServer =
|
|
23
35
|
viewMode === "detail" &&
|
|
@@ -66,30 +78,18 @@ export const McpManager: React.FC<McpManagerProps> = ({
|
|
|
66
78
|
|
|
67
79
|
useInput((input, key) => {
|
|
68
80
|
if (key.return) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (servers.length > 0 && prevIndex < servers.length) {
|
|
73
|
-
// We can't call setViewMode here because we're already in a setViewMode call
|
|
74
|
-
// But we can return the new mode from the outer setViewMode
|
|
75
|
-
}
|
|
76
|
-
return prevIndex;
|
|
77
|
-
});
|
|
78
|
-
return "detail";
|
|
79
|
-
}
|
|
80
|
-
return prevMode;
|
|
81
|
-
});
|
|
81
|
+
if (viewModeRef.current === "list") {
|
|
82
|
+
setViewMode("detail");
|
|
83
|
+
}
|
|
82
84
|
return;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
if (key.escape) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
88
|
+
if (viewModeRef.current === "detail") {
|
|
89
|
+
setViewMode("list");
|
|
90
|
+
} else {
|
|
90
91
|
onCancel();
|
|
91
|
-
|
|
92
|
-
});
|
|
92
|
+
}
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -105,27 +105,21 @@ export const McpManager: React.FC<McpManagerProps> = ({
|
|
|
105
105
|
|
|
106
106
|
// Hotkeys for server actions
|
|
107
107
|
if (input === "c") {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
return prev;
|
|
117
|
-
});
|
|
108
|
+
const server = servers[selectedIndexRef.current];
|
|
109
|
+
if (
|
|
110
|
+
server &&
|
|
111
|
+
(server.status === "disconnected" || server.status === "error")
|
|
112
|
+
) {
|
|
113
|
+
handleConnect(server.name);
|
|
114
|
+
}
|
|
118
115
|
return;
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
if (input === "d") {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
return prev;
|
|
128
|
-
});
|
|
119
|
+
const server = servers[selectedIndexRef.current];
|
|
120
|
+
if (server && server.status === "connected") {
|
|
121
|
+
handleDisconnect(server.name);
|
|
122
|
+
}
|
|
129
123
|
return;
|
|
130
124
|
}
|
|
131
125
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
3
|
import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
|
|
4
4
|
|
|
@@ -14,6 +14,18 @@ export const PluginDetail: React.FC = () => {
|
|
|
14
14
|
const [selectedScopeIndex, setSelectedScopeIndex] = useState(0);
|
|
15
15
|
const [selectedActionIndex, setSelectedActionIndex] = useState(0);
|
|
16
16
|
|
|
17
|
+
// Keep refs in sync with state to avoid stale closures in useInput
|
|
18
|
+
const selectedScopeIndexRef = useRef(selectedScopeIndex);
|
|
19
|
+
const selectedActionIndexRef = useRef(selectedActionIndex);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
selectedScopeIndexRef.current = selectedScopeIndex;
|
|
23
|
+
}, [selectedScopeIndex]);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
selectedActionIndexRef.current = selectedActionIndex;
|
|
27
|
+
}, [selectedActionIndex]);
|
|
28
|
+
|
|
17
29
|
const plugin =
|
|
18
30
|
discoverablePlugins.find(
|
|
19
31
|
(p) => `${p.name}@${p.marketplace}` === state.selectedId,
|
|
@@ -51,24 +63,18 @@ export const PluginDetail: React.FC = () => {
|
|
|
51
63
|
);
|
|
52
64
|
} else if (key.return && plugin && !state.isLoading) {
|
|
53
65
|
if (isInstalledAndEnabled) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
return prev;
|
|
62
|
-
});
|
|
66
|
+
const action = INSTALLED_ACTIONS[selectedActionIndexRef.current].id;
|
|
67
|
+
if (action === "uninstall") {
|
|
68
|
+
actions.uninstallPlugin(plugin.name, plugin.marketplace);
|
|
69
|
+
} else {
|
|
70
|
+
actions.updatePlugin(plugin.name, plugin.marketplace);
|
|
71
|
+
}
|
|
63
72
|
} else {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
);
|
|
70
|
-
return prev;
|
|
71
|
-
});
|
|
73
|
+
actions.installPlugin(
|
|
74
|
+
plugin.name,
|
|
75
|
+
plugin.marketplace,
|
|
76
|
+
SCOPES[selectedScopeIndexRef.current].id,
|
|
77
|
+
);
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
});
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
AgentCallbacks,
|
|
24
24
|
type ToolPermissionContext,
|
|
25
25
|
OPERATION_CANCELLED_BY_USER,
|
|
26
|
-
cloneMessage,
|
|
27
26
|
} from "wave-agent-sdk";
|
|
28
27
|
import { logger } from "../utils/logger.js";
|
|
29
28
|
import { throttle } from "../utils/throttle.js";
|
|
@@ -121,10 +120,6 @@ export interface ChatContextType {
|
|
|
121
120
|
workingDirectory: string;
|
|
122
121
|
version?: string;
|
|
123
122
|
workdir?: string;
|
|
124
|
-
btwState: import("../managers/inputReducer.js").BtwState;
|
|
125
|
-
setBtwState: (
|
|
126
|
-
payload: Partial<import("../managers/inputReducer.js").BtwState>,
|
|
127
|
-
) => void;
|
|
128
123
|
}
|
|
129
124
|
|
|
130
125
|
const ChatContext = createContext<ChatContextType | null>(null);
|
|
@@ -258,12 +253,26 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
258
253
|
const [remountKey, setRemountKey] = useState(0);
|
|
259
254
|
const prevSessionId = useRef<string | null>(null);
|
|
260
255
|
|
|
261
|
-
const requestRemount =
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
256
|
+
const requestRemount = useMemo(
|
|
257
|
+
() =>
|
|
258
|
+
throttle(
|
|
259
|
+
() => {
|
|
260
|
+
logger.info("requesting remount");
|
|
261
|
+
stdout?.write("\u001b[2J\u001b[3J\u001b[0;0H", () => {
|
|
262
|
+
setRemountKey((prev) => prev + 1);
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
1000,
|
|
266
|
+
{ leading: true, trailing: false },
|
|
267
|
+
),
|
|
268
|
+
[stdout],
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
return () => {
|
|
273
|
+
requestRemount.cancel();
|
|
274
|
+
};
|
|
275
|
+
}, [requestRemount]);
|
|
267
276
|
|
|
268
277
|
// Track sessionId changes to trigger remount
|
|
269
278
|
useEffect(() => {
|
|
@@ -282,28 +291,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
282
291
|
// Status metadata state
|
|
283
292
|
const [workingDirectory, setWorkingDirectory] = useState("");
|
|
284
293
|
|
|
285
|
-
// /btw state
|
|
286
|
-
const [btwState, setBtwStateInternal] = useState<
|
|
287
|
-
import("../managers/inputReducer.js").BtwState
|
|
288
|
-
>({
|
|
289
|
-
isActive: false,
|
|
290
|
-
question: "",
|
|
291
|
-
isLoading: false,
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
const setBtwState = useCallback(
|
|
295
|
-
(payload: Partial<import("../managers/inputReducer.js").BtwState>) => {
|
|
296
|
-
setBtwStateInternal((prev) => {
|
|
297
|
-
const newState = { ...prev, ...payload };
|
|
298
|
-
if (process.env.NODE_ENV === "test") {
|
|
299
|
-
// console.log("setBtwState", newState);
|
|
300
|
-
}
|
|
301
|
-
return newState;
|
|
302
|
-
});
|
|
303
|
-
},
|
|
304
|
-
[],
|
|
305
|
-
);
|
|
306
|
-
|
|
307
294
|
const allowBypassInCycle =
|
|
308
295
|
!!bypassPermissions || initialPermissionMode === "bypassPermissions";
|
|
309
296
|
|
|
@@ -702,28 +689,21 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
702
689
|
useInput((input, key) => {
|
|
703
690
|
if (key.ctrl && input === "o") {
|
|
704
691
|
// Clear terminal screen when expanded state changes
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
});
|
|
719
|
-
} else {
|
|
720
|
-
// Transitioning to COLLAPSED: Restore from agent's actual state
|
|
721
|
-
if (agentRef.current) {
|
|
722
|
-
setMessages([...agentRef.current.messages]);
|
|
723
|
-
}
|
|
692
|
+
// Use ref to get the current value to avoid stale closure
|
|
693
|
+
const nextExpanded = !isExpandedRef.current;
|
|
694
|
+
setIsExpanded(nextExpanded);
|
|
695
|
+
isExpandedRef.current = nextExpanded;
|
|
696
|
+
|
|
697
|
+
if (nextExpanded) {
|
|
698
|
+
// Transitioning to EXPANDED: Freeze the current view
|
|
699
|
+
// Cancel any pending throttled updates to avoid overwriting the frozen state
|
|
700
|
+
throttledSetMessages.cancel();
|
|
701
|
+
} else {
|
|
702
|
+
// Transitioning to COLLAPSED: Restore from agent's actual state
|
|
703
|
+
if (agentRef.current) {
|
|
704
|
+
setMessages([...agentRef.current.messages]);
|
|
724
705
|
}
|
|
725
|
-
|
|
726
|
-
});
|
|
706
|
+
}
|
|
727
707
|
// Force remount to re-render Static items with new isExpanded state
|
|
728
708
|
requestRemount();
|
|
729
709
|
}
|
|
@@ -732,17 +712,10 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
732
712
|
setIsTaskListVisible((prev) => !prev);
|
|
733
713
|
}
|
|
734
714
|
|
|
735
|
-
// Handle ESC key to cancel confirmation
|
|
715
|
+
// Handle ESC key to cancel confirmation
|
|
736
716
|
if (key.escape) {
|
|
737
717
|
if (isConfirmationVisible) {
|
|
738
718
|
handleConfirmationCancel();
|
|
739
|
-
} else if (btwState.isActive) {
|
|
740
|
-
setBtwState({
|
|
741
|
-
isActive: false,
|
|
742
|
-
question: "",
|
|
743
|
-
answer: undefined,
|
|
744
|
-
isLoading: false,
|
|
745
|
-
});
|
|
746
719
|
}
|
|
747
720
|
}
|
|
748
721
|
});
|
|
@@ -786,7 +759,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
786
759
|
handleConfirmationCancel,
|
|
787
760
|
backgroundCurrentTask,
|
|
788
761
|
remountKey,
|
|
789
|
-
requestRemount,
|
|
762
|
+
requestRemount: requestRemount as () => void,
|
|
790
763
|
handleRewindSelect,
|
|
791
764
|
getFullMessageThread,
|
|
792
765
|
|
|
@@ -795,8 +768,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
795
768
|
workingDirectory,
|
|
796
769
|
version,
|
|
797
770
|
workdir,
|
|
798
|
-
btwState,
|
|
799
|
-
setBtwState,
|
|
800
771
|
};
|
|
801
772
|
|
|
802
773
|
return (
|
|
@@ -157,12 +157,6 @@ export const useInputManager = (
|
|
|
157
157
|
callbacksRef.current.onImagesStateChange?.(state.attachedImages);
|
|
158
158
|
}, [state.attachedImages]);
|
|
159
159
|
|
|
160
|
-
useEffect(() => {
|
|
161
|
-
if (callbacksRef.current.onBtwStateChange) {
|
|
162
|
-
callbacksRef.current.onBtwStateChange(state.btwState);
|
|
163
|
-
}
|
|
164
|
-
}, [state.btwState]);
|
|
165
|
-
|
|
166
160
|
// Handle /btw side question
|
|
167
161
|
useEffect(() => {
|
|
168
162
|
if (
|
|
@@ -362,11 +356,7 @@ export const useInputManager = (
|
|
|
362
356
|
|
|
363
357
|
const setBtwState = useCallback(
|
|
364
358
|
(payload: Partial<import("../managers/inputReducer.js").BtwState>) => {
|
|
365
|
-
|
|
366
|
-
callbacksRef.current.onBtwStateChange(payload);
|
|
367
|
-
} else {
|
|
368
|
-
dispatch({ type: "SET_BTW_STATE", payload });
|
|
369
|
-
}
|
|
359
|
+
dispatch({ type: "SET_BTW_STATE", payload });
|
|
370
360
|
},
|
|
371
361
|
[],
|
|
372
362
|
);
|
|
@@ -52,8 +52,6 @@ export interface InputManagerCallbacks {
|
|
|
52
52
|
onBackgroundCurrentTask?: () => void;
|
|
53
53
|
onPermissionModeChange?: (mode: PermissionMode) => void;
|
|
54
54
|
onAskBtw?: (question: string) => Promise<string>;
|
|
55
|
-
btwState?: BtwState;
|
|
56
|
-
onBtwStateChange?: (payload: Partial<BtwState>) => void;
|
|
57
55
|
sessionId?: string;
|
|
58
56
|
workdir?: string;
|
|
59
57
|
getFullMessageThread?: () => Promise<{
|