wave-code 0.13.4 → 0.13.5
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/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +1 -1
- package/dist/components/MessageBlockItem.d.ts.map +1 -1
- package/dist/components/MessageBlockItem.js +4 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +5 -4
- package/dist/components/ReasoningDisplay.d.ts.map +1 -1
- package/dist/components/ReasoningDisplay.js +5 -2
- package/dist/contexts/useChat.d.ts +2 -9
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +21 -39
- package/package.json +2 -2
- package/src/components/ChatInterface.tsx +1 -0
- package/src/components/MessageBlockItem.tsx +7 -0
- package/src/components/MessageList.tsx +5 -7
- package/src/components/ReasoningDisplay.tsx +8 -1
- package/src/contexts/useChat.tsx +29 -62
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,EAgIjC,CAAC"}
|
|
@@ -37,5 +37,5 @@ export const ChatInterface = () => {
|
|
|
37
37
|
]);
|
|
38
38
|
if (!sessionId)
|
|
39
39
|
return null;
|
|
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 })] }))] }));
|
|
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 }, "confirmation-details")) })) : (_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 })] }))] }));
|
|
41
41
|
};
|
|
@@ -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;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,
|
|
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,4CAuEvB,CAAC"}
|
|
@@ -8,5 +8,8 @@ import { ReasoningDisplay } from "./ReasoningDisplay.js";
|
|
|
8
8
|
import { Markdown } from "./Markdown.js";
|
|
9
9
|
import { TaskNotificationMessage } from "./TaskNotificationMessage.js";
|
|
10
10
|
export const MessageBlockItem = ({ block, message, isExpanded, paddingTop = 0, }) => {
|
|
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 })) :
|
|
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 })) : block.stage === "streaming" ? (_jsx(Text, { color: "gray", wrap: "truncate-end", children: (() => {
|
|
12
|
+
const flat = block.content.replace(/\n/g, "\\n");
|
|
13
|
+
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
14
|
+
})() })) : (_jsx(Markdown, { children: block.content }))] })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", block.content] }) })), block.type === "bang" && (_jsx(BangDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "# Image" }), block.imageUrls && block.imageUrls.length > 0 && (_jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", block.imageUrls.length, ")"] }))] })), block.type === "compress" && (_jsx(CompressDisplay, { block: block, isExpanded: isExpanded })), block.type === "reasoning" && (_jsx(ReasoningDisplay, { block: block, isExpanded: isExpanded })), block.type === "task_notification" && (_jsx(TaskNotificationMessage, { block: block }))] }));
|
|
12
15
|
};
|
|
@@ -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,6CAqIpB,CAAC"}
|
|
@@ -13,13 +13,14 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
|
|
|
13
13
|
(b.stage === "running" ||
|
|
14
14
|
b.stage === "streaming" ||
|
|
15
15
|
b.stage === "start")) ||
|
|
16
|
-
(b.type === "bang" && b.stage === "running")
|
|
16
|
+
(b.type === "bang" && b.stage === "running") ||
|
|
17
|
+
(b.type === "reasoning" && b.stage === "streaming");
|
|
17
18
|
// Flatten messages into blocks with metadata
|
|
18
|
-
// Filter out streaming text
|
|
19
|
+
// Filter out streaming text blocks to avoid frequent height changes,
|
|
20
|
+
// but allow streaming reasoning blocks (rendered as truncated gray text)
|
|
19
21
|
const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
|
|
20
22
|
return message.blocks
|
|
21
|
-
.filter((block) => !(
|
|
22
|
-
block.stage === "streaming"))
|
|
23
|
+
.filter((block) => !(block.type === "text" && block.stage === "streaming"))
|
|
23
24
|
.map((block, blockIndex) => ({
|
|
24
25
|
block,
|
|
25
26
|
message,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReasoningDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ReasoningDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,UAAU,qBAAqB;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"ReasoningDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ReasoningDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,UAAU,qBAAqB;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAmC5D,CAAC"}
|
|
@@ -2,9 +2,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { Markdown } from "./Markdown.js";
|
|
4
4
|
export const ReasoningDisplay = ({ block, isExpanded = false, }) => {
|
|
5
|
-
const { content } = block;
|
|
5
|
+
const { content, stage } = block;
|
|
6
6
|
if (!content || !content.trim()) {
|
|
7
7
|
return null;
|
|
8
8
|
}
|
|
9
|
-
return (_jsx(Box, { borderRight: false, borderTop: false, borderBottom: false, borderStyle: "classic", borderColor: "blue", paddingLeft: 1, children: _jsx(Box, { flexDirection: "column", children: isExpanded ? (_jsx(Text, { color: "white", children: content })) : (_jsx(
|
|
9
|
+
return (_jsx(Box, { borderRight: false, borderTop: false, borderBottom: false, borderStyle: "classic", borderColor: "blue", paddingLeft: 1, children: _jsx(Box, { flexDirection: "column", children: isExpanded ? (_jsx(Text, { color: "white", children: content })) : stage === "streaming" ? (_jsx(Text, { color: "gray", wrap: "truncate-end", children: ` ${(() => {
|
|
10
|
+
const flat = content.replace(/\n/g, "\\n");
|
|
11
|
+
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
12
|
+
})()}` })) : (_jsx(Markdown, { children: content })) }) }));
|
|
10
13
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { Message, McpServerStatus, BackgroundTask, Task, SlashCommand, PermissionDecision, PermissionMode } from "wave-agent-sdk";
|
|
2
|
+
import type { Message, McpServerStatus, BackgroundTask, Task, SlashCommand, PermissionDecision, PermissionMode, QueuedMessage } from "wave-agent-sdk";
|
|
3
3
|
import { BaseAppProps } from "../types.js";
|
|
4
4
|
export interface ChatContextType {
|
|
5
5
|
messages: Message[];
|
|
@@ -9,14 +9,7 @@ export interface ChatContextType {
|
|
|
9
9
|
isExpanded: boolean;
|
|
10
10
|
isTaskListVisible: boolean;
|
|
11
11
|
setIsTaskListVisible: (visible: boolean) => void;
|
|
12
|
-
queuedMessages:
|
|
13
|
-
content: string;
|
|
14
|
-
images?: Array<{
|
|
15
|
-
path: string;
|
|
16
|
-
mimeType: string;
|
|
17
|
-
}>;
|
|
18
|
-
longTextMap?: Record<string, string>;
|
|
19
|
-
}>;
|
|
12
|
+
queuedMessages: QueuedMessage[];
|
|
20
13
|
sessionId: string;
|
|
21
14
|
sendMessage: (content: string, images?: Array<{
|
|
22
15
|
path: string;
|
|
@@ -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,
|
|
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
|
@@ -22,7 +22,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
22
22
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
23
23
|
const isExpandedRef = useRef(isExpanded);
|
|
24
24
|
const [isTaskListVisible, setIsTaskListVisible] = useState(true);
|
|
25
|
-
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
26
25
|
const [messages, setMessages] = useState([]);
|
|
27
26
|
const throttledSetMessages = useMemo(() => throttle(() => {
|
|
28
27
|
if (!isExpandedRef.current && agentRef.current) {
|
|
@@ -52,6 +51,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
52
51
|
const [isCompressing, setIsCompressing] = useState(false);
|
|
53
52
|
const [currentModel, setCurrentModelState] = useState("");
|
|
54
53
|
const [configuredModels, setConfiguredModels] = useState([]);
|
|
54
|
+
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
55
55
|
// MCP State
|
|
56
56
|
const [mcpServers, setMcpServers] = useState([]);
|
|
57
57
|
// Background tasks state
|
|
@@ -150,23 +150,27 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
150
150
|
onLoadingChange: (loading) => {
|
|
151
151
|
setIsLoading(loading);
|
|
152
152
|
},
|
|
153
|
+
onCommandRunningChange: (running) => {
|
|
154
|
+
setIsCommandRunning(running);
|
|
155
|
+
},
|
|
156
|
+
onQueuedMessagesChange: (messages) => {
|
|
157
|
+
setQueuedMessages([...messages]);
|
|
158
|
+
},
|
|
153
159
|
};
|
|
154
160
|
try {
|
|
155
161
|
// Create the permission callback inside the try block to access showConfirmation
|
|
156
|
-
const permissionCallback =
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
};
|
|
162
|
+
const permissionCallback = async (context) => {
|
|
163
|
+
try {
|
|
164
|
+
return await showConfirmation(context.toolName, context.toolInput, context.suggestedPrefix, context.hidePersistentOption, context.planContent);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// If confirmation was cancelled or failed, deny the operation
|
|
168
|
+
return {
|
|
169
|
+
behavior: "deny",
|
|
170
|
+
message: OPERATION_CANCELLED_BY_USER,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
};
|
|
170
174
|
const agent = await Agent.create({
|
|
171
175
|
callbacks,
|
|
172
176
|
restoreSessionId,
|
|
@@ -249,13 +253,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
249
253
|
const hasImageAttachments = images && images.length > 0;
|
|
250
254
|
if (!hasTextContent && !hasImageAttachments)
|
|
251
255
|
return;
|
|
252
|
-
if (isLoading || isCommandRunning) {
|
|
253
|
-
setQueuedMessages((prev) => [
|
|
254
|
-
...prev,
|
|
255
|
-
{ content, images, longTextMap },
|
|
256
|
-
]);
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
256
|
try {
|
|
260
257
|
const expandedContent = longTextMap
|
|
261
258
|
? expandLongTextPlaceholders(content, longTextMap)
|
|
@@ -266,13 +263,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
266
263
|
!hasImageAttachments) {
|
|
267
264
|
const command = expandedContent.substring(1).trim();
|
|
268
265
|
if (command) {
|
|
269
|
-
|
|
270
|
-
try {
|
|
271
|
-
await agentRef.current?.bang(command);
|
|
272
|
-
}
|
|
273
|
-
finally {
|
|
274
|
-
setIsCommandRunning(false);
|
|
275
|
-
}
|
|
266
|
+
await agentRef.current?.bang(command);
|
|
276
267
|
return;
|
|
277
268
|
}
|
|
278
269
|
}
|
|
@@ -286,24 +277,15 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
286
277
|
catch (error) {
|
|
287
278
|
console.error("Failed to send message:", error);
|
|
288
279
|
}
|
|
289
|
-
}, [
|
|
280
|
+
}, []);
|
|
290
281
|
const askBtw = useCallback(async (question) => {
|
|
291
282
|
if (!agentRef.current) {
|
|
292
283
|
throw new Error("Agent not initialized");
|
|
293
284
|
}
|
|
294
285
|
return await agentRef.current.askBtw(question);
|
|
295
286
|
}, []);
|
|
296
|
-
// Process queued messages when idle
|
|
297
|
-
useEffect(() => {
|
|
298
|
-
if (!isLoading && !isCommandRunning && queuedMessages.length > 0) {
|
|
299
|
-
const nextMessage = queuedMessages[0];
|
|
300
|
-
setQueuedMessages((prev) => prev.slice(1));
|
|
301
|
-
sendMessage(nextMessage.content, nextMessage.images, nextMessage.longTextMap);
|
|
302
|
-
}
|
|
303
|
-
}, [isLoading, isCommandRunning, queuedMessages, sendMessage]);
|
|
304
287
|
// Unified interrupt method, interrupt both AI messages and command execution
|
|
305
288
|
const abortMessage = useCallback(() => {
|
|
306
|
-
setQueuedMessages([]);
|
|
307
289
|
agentRef.current?.abortMessage();
|
|
308
290
|
}, []);
|
|
309
291
|
// Permission management methods
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.5",
|
|
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.13.
|
|
45
|
+
"wave-agent-sdk": "0.13.5"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.1.8",
|
|
@@ -109,6 +109,7 @@ export const ChatInterface: React.FC = () => {
|
|
|
109
109
|
<Static items={[{ key: "confirmation-details" }]}>
|
|
110
110
|
{() => (
|
|
111
111
|
<ConfirmationDetails
|
|
112
|
+
key="confirmation-details"
|
|
112
113
|
toolName={confirmingTool!.name}
|
|
113
114
|
toolInput={confirmingTool!.input}
|
|
114
115
|
planContent={confirmingTool!.planContent}
|
|
@@ -38,6 +38,13 @@ export const MessageBlockItem = ({
|
|
|
38
38
|
>
|
|
39
39
|
{block.content}
|
|
40
40
|
</Text>
|
|
41
|
+
) : block.stage === "streaming" ? (
|
|
42
|
+
<Text color="gray" wrap="truncate-end">
|
|
43
|
+
{(() => {
|
|
44
|
+
const flat = block.content.replace(/\n/g, "\\n");
|
|
45
|
+
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
46
|
+
})()}
|
|
47
|
+
</Text>
|
|
41
48
|
) : (
|
|
42
49
|
<Markdown>{block.content}</Markdown>
|
|
43
50
|
)}
|
|
@@ -42,18 +42,16 @@ export const MessageList = React.memo(
|
|
|
42
42
|
(b.stage === "running" ||
|
|
43
43
|
b.stage === "streaming" ||
|
|
44
44
|
b.stage === "start")) ||
|
|
45
|
-
(b.type === "bang" && b.stage === "running")
|
|
45
|
+
(b.type === "bang" && b.stage === "running") ||
|
|
46
|
+
(b.type === "reasoning" && b.stage === "streaming");
|
|
46
47
|
|
|
47
48
|
// Flatten messages into blocks with metadata
|
|
48
|
-
// Filter out streaming text
|
|
49
|
+
// Filter out streaming text blocks to avoid frequent height changes,
|
|
50
|
+
// but allow streaming reasoning blocks (rendered as truncated gray text)
|
|
49
51
|
const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
|
|
50
52
|
return message.blocks
|
|
51
53
|
.filter(
|
|
52
|
-
(block) =>
|
|
53
|
-
!(
|
|
54
|
-
(block.type === "text" || block.type === "reasoning") &&
|
|
55
|
-
block.stage === "streaming"
|
|
56
|
-
),
|
|
54
|
+
(block) => !(block.type === "text" && block.stage === "streaming"),
|
|
57
55
|
)
|
|
58
56
|
.map((block, blockIndex) => ({
|
|
59
57
|
block,
|
|
@@ -12,7 +12,7 @@ export const ReasoningDisplay: React.FC<ReasoningDisplayProps> = ({
|
|
|
12
12
|
block,
|
|
13
13
|
isExpanded = false,
|
|
14
14
|
}) => {
|
|
15
|
-
const { content } = block;
|
|
15
|
+
const { content, stage } = block;
|
|
16
16
|
|
|
17
17
|
if (!content || !content.trim()) {
|
|
18
18
|
return null;
|
|
@@ -30,6 +30,13 @@ export const ReasoningDisplay: React.FC<ReasoningDisplayProps> = ({
|
|
|
30
30
|
<Box flexDirection="column">
|
|
31
31
|
{isExpanded ? (
|
|
32
32
|
<Text color="white">{content}</Text>
|
|
33
|
+
) : stage === "streaming" ? (
|
|
34
|
+
<Text color="gray" wrap="truncate-end">
|
|
35
|
+
{` ${(() => {
|
|
36
|
+
const flat = content.replace(/\n/g, "\\n");
|
|
37
|
+
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
38
|
+
})()}`}
|
|
39
|
+
</Text>
|
|
33
40
|
) : (
|
|
34
41
|
<Markdown>{content}</Markdown>
|
|
35
42
|
)}
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
SlashCommand,
|
|
18
18
|
PermissionDecision,
|
|
19
19
|
PermissionMode,
|
|
20
|
+
QueuedMessage,
|
|
20
21
|
} from "wave-agent-sdk";
|
|
21
22
|
import {
|
|
22
23
|
Agent,
|
|
@@ -41,11 +42,7 @@ export interface ChatContextType {
|
|
|
41
42
|
isExpanded: boolean;
|
|
42
43
|
isTaskListVisible: boolean;
|
|
43
44
|
setIsTaskListVisible: (visible: boolean) => void;
|
|
44
|
-
queuedMessages:
|
|
45
|
-
content: string;
|
|
46
|
-
images?: Array<{ path: string; mimeType: string }>;
|
|
47
|
-
longTextMap?: Record<string, string>;
|
|
48
|
-
}>;
|
|
45
|
+
queuedMessages: QueuedMessage[];
|
|
49
46
|
// AI functionality
|
|
50
47
|
sessionId: string;
|
|
51
48
|
sendMessage: (
|
|
@@ -158,14 +155,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
158
155
|
|
|
159
156
|
const [isTaskListVisible, setIsTaskListVisible] = useState(true);
|
|
160
157
|
|
|
161
|
-
const [queuedMessages, setQueuedMessages] = useState<
|
|
162
|
-
Array<{
|
|
163
|
-
content: string;
|
|
164
|
-
images?: Array<{ path: string; mimeType: string }>;
|
|
165
|
-
longTextMap?: Record<string, string>;
|
|
166
|
-
}>
|
|
167
|
-
>([]);
|
|
168
|
-
|
|
169
158
|
const [messages, setMessages] = useState<Message[]>([]);
|
|
170
159
|
|
|
171
160
|
const throttledSetMessages = useMemo(
|
|
@@ -216,6 +205,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
216
205
|
const [isCompressing, setIsCompressing] = useState(false);
|
|
217
206
|
const [currentModel, setCurrentModelState] = useState("");
|
|
218
207
|
const [configuredModels, setConfiguredModels] = useState<string[]>([]);
|
|
208
|
+
const [queuedMessages, setQueuedMessages] = useState<QueuedMessage[]>([]);
|
|
219
209
|
|
|
220
210
|
// MCP State
|
|
221
211
|
const [mcpServers, setMcpServers] = useState<McpServerStatus[]>([]);
|
|
@@ -378,31 +368,35 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
378
368
|
onLoadingChange: (loading) => {
|
|
379
369
|
setIsLoading(loading);
|
|
380
370
|
},
|
|
371
|
+
onCommandRunningChange: (running) => {
|
|
372
|
+
setIsCommandRunning(running);
|
|
373
|
+
},
|
|
374
|
+
onQueuedMessagesChange: (messages) => {
|
|
375
|
+
setQueuedMessages([...messages]);
|
|
376
|
+
},
|
|
381
377
|
};
|
|
382
378
|
|
|
383
379
|
try {
|
|
384
380
|
// Create the permission callback inside the try block to access showConfirmation
|
|
385
|
-
const permissionCallback =
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
behavior: "deny",
|
|
402
|
-
message: OPERATION_CANCELLED_BY_USER,
|
|
403
|
-
};
|
|
404
|
-
}
|
|
381
|
+
const permissionCallback = async (
|
|
382
|
+
context: ToolPermissionContext,
|
|
383
|
+
): Promise<PermissionDecision> => {
|
|
384
|
+
try {
|
|
385
|
+
return await showConfirmation(
|
|
386
|
+
context.toolName,
|
|
387
|
+
context.toolInput,
|
|
388
|
+
context.suggestedPrefix,
|
|
389
|
+
context.hidePersistentOption,
|
|
390
|
+
context.planContent,
|
|
391
|
+
);
|
|
392
|
+
} catch {
|
|
393
|
+
// If confirmation was cancelled or failed, deny the operation
|
|
394
|
+
return {
|
|
395
|
+
behavior: "deny",
|
|
396
|
+
message: OPERATION_CANCELLED_BY_USER,
|
|
405
397
|
};
|
|
398
|
+
}
|
|
399
|
+
};
|
|
406
400
|
|
|
407
401
|
const agent = await Agent.create({
|
|
408
402
|
callbacks,
|
|
@@ -499,14 +493,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
499
493
|
|
|
500
494
|
if (!hasTextContent && !hasImageAttachments) return;
|
|
501
495
|
|
|
502
|
-
if (isLoading || isCommandRunning) {
|
|
503
|
-
setQueuedMessages((prev) => [
|
|
504
|
-
...prev,
|
|
505
|
-
{ content, images, longTextMap },
|
|
506
|
-
]);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
496
|
try {
|
|
511
497
|
const expandedContent = longTextMap
|
|
512
498
|
? expandLongTextPlaceholders(content, longTextMap)
|
|
@@ -520,12 +506,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
520
506
|
) {
|
|
521
507
|
const command = expandedContent.substring(1).trim();
|
|
522
508
|
if (command) {
|
|
523
|
-
|
|
524
|
-
try {
|
|
525
|
-
await agentRef.current?.bang(command);
|
|
526
|
-
} finally {
|
|
527
|
-
setIsCommandRunning(false);
|
|
528
|
-
}
|
|
509
|
+
await agentRef.current?.bang(command);
|
|
529
510
|
return;
|
|
530
511
|
}
|
|
531
512
|
}
|
|
@@ -539,7 +520,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
539
520
|
console.error("Failed to send message:", error);
|
|
540
521
|
}
|
|
541
522
|
},
|
|
542
|
-
[
|
|
523
|
+
[],
|
|
543
524
|
);
|
|
544
525
|
|
|
545
526
|
const askBtw = useCallback(async (question: string) => {
|
|
@@ -549,22 +530,8 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
549
530
|
return await agentRef.current.askBtw(question);
|
|
550
531
|
}, []);
|
|
551
532
|
|
|
552
|
-
// Process queued messages when idle
|
|
553
|
-
useEffect(() => {
|
|
554
|
-
if (!isLoading && !isCommandRunning && queuedMessages.length > 0) {
|
|
555
|
-
const nextMessage = queuedMessages[0];
|
|
556
|
-
setQueuedMessages((prev) => prev.slice(1));
|
|
557
|
-
sendMessage(
|
|
558
|
-
nextMessage.content,
|
|
559
|
-
nextMessage.images,
|
|
560
|
-
nextMessage.longTextMap,
|
|
561
|
-
);
|
|
562
|
-
}
|
|
563
|
-
}, [isLoading, isCommandRunning, queuedMessages, sendMessage]);
|
|
564
|
-
|
|
565
533
|
// Unified interrupt method, interrupt both AI messages and command execution
|
|
566
534
|
const abortMessage = useCallback(() => {
|
|
567
|
-
setQueuedMessages([]);
|
|
568
535
|
agentRef.current?.abortMessage();
|
|
569
536
|
}, []);
|
|
570
537
|
|