wave-code 0.12.0 → 0.12.2
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/App.d.ts +1 -0
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +5 -2
- package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
- package/dist/components/BackgroundTaskManager.js +2 -1
- package/dist/components/BangDisplay.d.ts.map +1 -1
- package/dist/components/BangDisplay.js +2 -14
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +17 -27
- package/dist/components/ConfirmationDetails.d.ts +0 -1
- package/dist/components/ConfirmationDetails.d.ts.map +1 -1
- package/dist/components/ConfirmationDetails.js +4 -12
- package/dist/components/ConfirmationSelector.d.ts +0 -1
- package/dist/components/ConfirmationSelector.d.ts.map +1 -1
- package/dist/components/ConfirmationSelector.js +4 -12
- package/dist/components/DiffDisplay.d.ts.map +1 -1
- package/dist/components/DiffDisplay.js +2 -23
- package/dist/components/MessageList.d.ts +1 -2
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +12 -17
- package/dist/components/RewindCommand.d.ts.map +1 -1
- package/dist/components/RewindCommand.js +2 -4
- package/dist/components/StatusCommand.d.ts.map +1 -1
- package/dist/components/StatusCommand.js +1 -1
- package/dist/components/ToolDisplay.d.ts.map +1 -1
- package/dist/components/ToolDisplay.js +3 -6
- package/dist/contexts/useChat.d.ts +0 -2
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +27 -44
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -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 +13 -11
- package/dist/utils/throttle.d.ts +15 -0
- package/dist/utils/throttle.d.ts.map +1 -0
- package/dist/utils/throttle.js +55 -0
- 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/App.tsx +6 -2
- package/src/components/BackgroundTaskManager.tsx +3 -6
- package/src/components/BangDisplay.tsx +4 -22
- package/src/components/ChatInterface.tsx +18 -33
- package/src/components/ConfirmationDetails.tsx +2 -15
- package/src/components/ConfirmationSelector.tsx +3 -15
- package/src/components/DiffDisplay.tsx +2 -27
- package/src/components/MessageList.tsx +17 -20
- package/src/components/RewindCommand.tsx +3 -5
- package/src/components/StatusCommand.tsx +7 -0
- package/src/components/ToolDisplay.tsx +3 -6
- package/src/contexts/useChat.tsx +34 -59
- package/src/index.ts +13 -0
- package/src/utils/highlightUtils.ts +0 -8
- package/src/utils/logger.ts +12 -14
- package/src/utils/throttle.ts +75 -0
- package/src/utils/toolParameterTransforms.ts +23 -1
- package/src/utils/worktree.ts +7 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
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
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext, useCallback, useRef, useEffect, useState, } from "react";
|
|
2
|
+
import { createContext, useContext, useCallback, useRef, useEffect, useState, useMemo, } from "react";
|
|
3
3
|
import { useInput } from "ink";
|
|
4
4
|
import { useAppConfig } from "./useAppConfig.js";
|
|
5
|
-
import { Agent, OPERATION_CANCELLED_BY_USER, } from "wave-agent-sdk";
|
|
5
|
+
import { Agent, OPERATION_CANCELLED_BY_USER, cloneMessage, } from "wave-agent-sdk";
|
|
6
6
|
import { logger } from "../utils/logger.js";
|
|
7
|
+
import { throttle } from "../utils/throttle.js";
|
|
7
8
|
import { displayUsageSummary } from "../utils/usageSummary.js";
|
|
8
9
|
import { expandLongTextPlaceholders } from "../managers/inputHandlers.js";
|
|
9
10
|
const ChatContext = createContext(null);
|
|
@@ -19,13 +20,25 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
19
20
|
// Message Display State
|
|
20
21
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
21
22
|
const isExpandedRef = useRef(isExpanded);
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
isExpandedRef.current = isExpanded;
|
|
24
|
-
}, [isExpanded]);
|
|
25
23
|
const [isTaskListVisible, setIsTaskListVisible] = useState(true);
|
|
26
24
|
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
27
|
-
// AI State
|
|
28
25
|
const [messages, setMessages] = useState([]);
|
|
26
|
+
const throttledSetMessages = useMemo(() => throttle(() => {
|
|
27
|
+
if (!isExpandedRef.current && agentRef.current) {
|
|
28
|
+
setMessages([...agentRef.current.messages]);
|
|
29
|
+
}
|
|
30
|
+
}, 300), []);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
isExpandedRef.current = isExpanded;
|
|
33
|
+
if (isExpanded) {
|
|
34
|
+
throttledSetMessages.cancel();
|
|
35
|
+
}
|
|
36
|
+
}, [isExpanded, throttledSetMessages]);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
return () => {
|
|
39
|
+
throttledSetMessages.cancel();
|
|
40
|
+
};
|
|
41
|
+
}, [throttledSetMessages]);
|
|
29
42
|
const [isLoading, setIsLoading] = useState(false);
|
|
30
43
|
const [latestTotalTokens, setlatestTotalTokens] = useState(0);
|
|
31
44
|
const [sessionId, setSessionId] = useState("");
|
|
@@ -41,9 +54,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
41
54
|
const [tasks, setTasks] = useState([]);
|
|
42
55
|
// Command state
|
|
43
56
|
const [slashCommands, setSlashCommands] = useState([]);
|
|
44
|
-
// Subagent messages state
|
|
45
|
-
const [subagentMessages, setSubagentMessages] = useState({});
|
|
46
|
-
const [subagentLatestTokens, setSubagentLatestTokens] = useState({});
|
|
47
57
|
// Permission state
|
|
48
58
|
const [permissionMode, setPermissionModeState] = useState(initialPermissionMode ||
|
|
49
59
|
(bypassPermissions ? "bypassPermissions" : "default"));
|
|
@@ -75,16 +85,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
75
85
|
const [wasLastDetailsTooTall, setWasLastDetailsTooTall] = useState(0);
|
|
76
86
|
const allowBypassInCycle = !!bypassPermissions || initialPermissionMode === "bypassPermissions";
|
|
77
87
|
const agentRef = useRef(null);
|
|
78
|
-
const taskUpdateTimerRef = useRef(null);
|
|
79
|
-
const debouncedSetTasks = useCallback((newTasks) => {
|
|
80
|
-
if (taskUpdateTimerRef.current) {
|
|
81
|
-
clearTimeout(taskUpdateTimerRef.current);
|
|
82
|
-
}
|
|
83
|
-
taskUpdateTimerRef.current = setTimeout(() => {
|
|
84
|
-
setTasks([...newTasks]);
|
|
85
|
-
taskUpdateTimerRef.current = null;
|
|
86
|
-
}, 100);
|
|
87
|
-
}, [setTasks]);
|
|
88
88
|
// Permission confirmation methods with queue support
|
|
89
89
|
const showConfirmation = useCallback(async (toolName, toolInput, suggestedPrefix, hidePersistentOption, planContent) => {
|
|
90
90
|
return new Promise((resolve, reject) => {
|
|
@@ -106,9 +106,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
106
106
|
const initializeAgent = async () => {
|
|
107
107
|
const callbacks = {
|
|
108
108
|
onMessagesChange: () => {
|
|
109
|
-
|
|
110
|
-
setMessages([...agentRef.current.messages]);
|
|
111
|
-
}
|
|
109
|
+
throttledSetMessages();
|
|
112
110
|
},
|
|
113
111
|
onServersChange: (servers) => {
|
|
114
112
|
setMcpServers([...servers]);
|
|
@@ -126,20 +124,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
126
124
|
setBackgroundTasks([...tasks]);
|
|
127
125
|
},
|
|
128
126
|
onTasksChange: (tasks) => {
|
|
129
|
-
|
|
130
|
-
},
|
|
131
|
-
onSubagentMessagesChange: (subagentId, messages) => {
|
|
132
|
-
logger.debug("onSubagentMessagesChange", subagentId, messages.length);
|
|
133
|
-
setSubagentMessages((prev) => ({
|
|
134
|
-
...prev,
|
|
135
|
-
[subagentId]: [...messages],
|
|
136
|
-
}));
|
|
137
|
-
},
|
|
138
|
-
onSubagentLatestTotalTokensChange: (subagentId, tokens) => {
|
|
139
|
-
setSubagentLatestTokens((prev) => ({
|
|
140
|
-
...prev,
|
|
141
|
-
[subagentId]: tokens,
|
|
142
|
-
}));
|
|
127
|
+
setTasks([...tasks]);
|
|
143
128
|
},
|
|
144
129
|
onPermissionModeChange: (mode) => {
|
|
145
130
|
setPermissionModeState(mode);
|
|
@@ -221,15 +206,12 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
221
206
|
workdir,
|
|
222
207
|
worktreeSession,
|
|
223
208
|
model,
|
|
224
|
-
debouncedSetTasks,
|
|
225
209
|
initialPermissionMode,
|
|
210
|
+
throttledSetMessages,
|
|
226
211
|
]);
|
|
227
212
|
// Cleanup on unmount
|
|
228
213
|
useEffect(() => {
|
|
229
214
|
return () => {
|
|
230
|
-
if (taskUpdateTimerRef.current) {
|
|
231
|
-
clearTimeout(taskUpdateTimerRef.current);
|
|
232
|
-
}
|
|
233
215
|
if (agentRef.current) {
|
|
234
216
|
try {
|
|
235
217
|
// Display usage summary before cleanup
|
|
@@ -270,7 +252,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
270
252
|
if (command) {
|
|
271
253
|
setIsCommandRunning(true);
|
|
272
254
|
try {
|
|
273
|
-
await agentRef.current?.
|
|
255
|
+
await agentRef.current?.bang(command);
|
|
274
256
|
}
|
|
275
257
|
finally {
|
|
276
258
|
setIsCommandRunning(false);
|
|
@@ -434,14 +416,17 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
434
416
|
// Clear terminal screen when expanded state changes
|
|
435
417
|
setIsExpanded((prev) => {
|
|
436
418
|
const newExpanded = !prev;
|
|
419
|
+
isExpandedRef.current = newExpanded;
|
|
437
420
|
if (newExpanded) {
|
|
438
421
|
// Transitioning to EXPANDED: Freeze the current view
|
|
422
|
+
// Cancel any pending throttled updates to avoid overwriting the frozen state
|
|
423
|
+
throttledSetMessages.cancel();
|
|
439
424
|
// Deep copy the last message to ensure it doesn't update if the agent is still writing to it
|
|
440
425
|
setMessages((currentMessages) => {
|
|
441
426
|
if (currentMessages.length === 0)
|
|
442
427
|
return currentMessages;
|
|
443
428
|
const lastMessage = currentMessages[currentMessages.length - 1];
|
|
444
|
-
const frozenLastMessage =
|
|
429
|
+
const frozenLastMessage = cloneMessage(lastMessage);
|
|
445
430
|
return [...currentMessages.slice(0, -1), frozenLastMessage];
|
|
446
431
|
});
|
|
447
432
|
}
|
|
@@ -499,8 +484,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
499
484
|
stopBackgroundTask,
|
|
500
485
|
slashCommands,
|
|
501
486
|
hasSlashCommand,
|
|
502
|
-
subagentMessages,
|
|
503
|
-
subagentLatestTokens,
|
|
504
487
|
permissionMode,
|
|
505
488
|
setPermissionMode,
|
|
506
489
|
allowBypassInCycle,
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,wBAAsB,IAAI,kBAgYzB;AAGD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import yargs from "yargs";
|
|
2
2
|
import { hideBin } from "yargs/helpers";
|
|
3
3
|
import { startCli } from "./cli.js";
|
|
4
|
+
import { logger } from "./utils/logger.js";
|
|
4
5
|
import { generateRandomName } from "wave-agent-sdk";
|
|
5
6
|
import { createWorktree } from "./utils/worktree.js";
|
|
6
7
|
import path from "path";
|
|
@@ -12,6 +13,15 @@ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
|
12
13
|
const version = packageJson.version;
|
|
13
14
|
// Export main function for external use
|
|
14
15
|
export async function main() {
|
|
16
|
+
// Start memory monitoring in debug mode
|
|
17
|
+
if (process.env.LOG_LEVEL === "DEBUG") {
|
|
18
|
+
setInterval(() => {
|
|
19
|
+
const usage = process.memoryUsage();
|
|
20
|
+
logger.debug(`[Memory] RSS: ${Math.round(usage.rss / 1024 / 1024)}MB, ` +
|
|
21
|
+
`Heap: ${Math.round(usage.heapUsed / 1024 / 1024)}/${Math.round(usage.heapTotal / 1024 / 1024)}MB, ` +
|
|
22
|
+
`External: ${Math.round(usage.external / 1024 / 1024)}MB`);
|
|
23
|
+
}, 10000).unref();
|
|
24
|
+
}
|
|
15
25
|
try {
|
|
16
26
|
const originalCwd = process.cwd();
|
|
17
27
|
const argv = await yargs(hideBin(process.argv))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"highlightUtils.d.ts","sourceRoot":"","sources":["../../src/utils/highlightUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"highlightUtils.d.ts","sourceRoot":"","sources":["../../src/utils/highlightUtils.ts"],"names":[],"mappings":"AA6DA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAsCvE"}
|
|
@@ -45,14 +45,6 @@ function nodeToAnsi(node) {
|
|
|
45
45
|
const classes = node.getAttribute("class")?.split(/\s+/) || [];
|
|
46
46
|
for (const className of classes) {
|
|
47
47
|
if (theme[className]) {
|
|
48
|
-
// If content has newlines, split it and apply style to each line
|
|
49
|
-
// to ensure ANSI codes are correctly applied when splitting the final string by lines.
|
|
50
|
-
if (content.includes("\n")) {
|
|
51
|
-
return content
|
|
52
|
-
.split("\n")
|
|
53
|
-
.map((line) => theme[className](line))
|
|
54
|
-
.join("\n");
|
|
55
|
-
}
|
|
56
48
|
return theme[className](content);
|
|
57
49
|
}
|
|
58
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAsBD;;GAEG;AACH,UAAU,SAAS;IACjB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAC7B;AAiID;;GAEG;AACH,eAAO,MAAM,MAAM;IACjB;;OAEG;qBACc,OAAO,EAAE,KAAG,IAAI;IAIjC;;OAEG;oBACa,OAAO,EAAE,KAAG,IAAI;IAIhC;;OAEG;oBACa,OAAO,EAAE,KAAG,IAAI;IAIhC;;OAEG;qBACc,OAAO,EAAE,KAAG,IAAI;CAGlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,QAAO,SAE/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,QAAO,MAE7B,CAAC;AAEF;;GAEG;AACH,UAAU,gBAAgB;IACxB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAgDD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,eAAe,OAAO,CAAC,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAiBd,CAAC"}
|
package/dist/utils/logger.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import { Chalk } from "chalk";
|
|
12
|
+
import { getLastLines } from "wave-agent-sdk";
|
|
12
13
|
import { LOG_FILE, DATA_DIRECTORY } from "./constants.js";
|
|
13
14
|
const chalk = new Chalk({ level: 3 });
|
|
14
15
|
const logFile = process.env.LOG_FILE || LOG_FILE;
|
|
@@ -106,20 +107,25 @@ const formatArg = (arg) => {
|
|
|
106
107
|
return "null";
|
|
107
108
|
if (arg === undefined)
|
|
108
109
|
return "undefined";
|
|
110
|
+
let result;
|
|
109
111
|
if (arg instanceof Error) {
|
|
110
112
|
// Special handling for Error objects, display stack or message
|
|
111
|
-
|
|
113
|
+
result = arg.stack || arg.message || String(arg);
|
|
112
114
|
}
|
|
113
|
-
if (typeof arg === "object") {
|
|
115
|
+
else if (typeof arg === "object") {
|
|
114
116
|
try {
|
|
115
|
-
|
|
117
|
+
result = JSON.stringify(arg);
|
|
116
118
|
}
|
|
117
119
|
catch {
|
|
118
120
|
// If JSON.stringify fails, fallback to String()
|
|
119
|
-
|
|
121
|
+
result = String(arg);
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
|
-
|
|
124
|
+
else {
|
|
125
|
+
result = String(arg);
|
|
126
|
+
}
|
|
127
|
+
// Ensure no newlines in the result to keep log entries single-line
|
|
128
|
+
return result.replace(/[\n\r]+/g, " ");
|
|
123
129
|
};
|
|
124
130
|
/**
|
|
125
131
|
* Generic log output function
|
|
@@ -220,15 +226,11 @@ const truncateLogFileIfNeeded = (config) => {
|
|
|
220
226
|
// If file size exceeds limit, truncate file
|
|
221
227
|
if (stats.size > config.maxFileSize) {
|
|
222
228
|
const content = fs.readFileSync(logFile, "utf8");
|
|
223
|
-
const
|
|
224
|
-
// Keep the last specified number of lines
|
|
225
|
-
const keepLines = Math.min(config.keepLines, lines.length);
|
|
226
|
-
const truncatedContent = lines.slice(-keepLines).join("\n");
|
|
229
|
+
const truncatedContent = getLastLines(content, config.keepLines);
|
|
227
230
|
// Write truncated content
|
|
228
231
|
fs.writeFileSync(logFile, truncatedContent);
|
|
229
232
|
// Record truncation operation
|
|
230
|
-
|
|
231
|
-
logger.debug(`Log file truncated: removed ${removedLines} lines, kept last ${keepLines} lines`);
|
|
233
|
+
logger.debug(`Log file truncated: file size ${stats.size} exceeded limit ${config.maxFileSize}, kept last ${config.keepLines} lines`);
|
|
232
234
|
}
|
|
233
235
|
}
|
|
234
236
|
catch (error) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ThrottleOptions {
|
|
2
|
+
leading?: boolean;
|
|
3
|
+
trailing?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export interface ThrottledFunction<T extends (...args: unknown[]) => void> {
|
|
6
|
+
(...args: Parameters<T>): void;
|
|
7
|
+
cancel: () => void;
|
|
8
|
+
flush: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates a throttled function that only invokes `func` at most once per
|
|
12
|
+
* every `wait` milliseconds.
|
|
13
|
+
*/
|
|
14
|
+
export declare function throttle<T extends (...args: unknown[]) => void>(func: T, wait: number, options?: ThrottleOptions): ThrottledFunction<T>;
|
|
15
|
+
//# sourceMappingURL=throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/utils/throttle.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;IACvE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAC7D,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,eAAmD,GAC3D,iBAAiB,CAAC,CAAC,CAAC,CAuDtB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a throttled function that only invokes `func` at most once per
|
|
3
|
+
* every `wait` milliseconds.
|
|
4
|
+
*/
|
|
5
|
+
export function throttle(func, wait, options = { leading: true, trailing: true }) {
|
|
6
|
+
let timeoutId = null;
|
|
7
|
+
let lastArgs = null;
|
|
8
|
+
let lastCallTime = 0;
|
|
9
|
+
const invokeFunc = () => {
|
|
10
|
+
if (lastArgs) {
|
|
11
|
+
func(...lastArgs);
|
|
12
|
+
lastCallTime = Date.now();
|
|
13
|
+
lastArgs = null;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const throttled = (...args) => {
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
const remaining = wait - (now - lastCallTime);
|
|
19
|
+
lastArgs = args;
|
|
20
|
+
if (remaining <= 0 || remaining > wait) {
|
|
21
|
+
if (timeoutId) {
|
|
22
|
+
clearTimeout(timeoutId);
|
|
23
|
+
timeoutId = null;
|
|
24
|
+
}
|
|
25
|
+
if (options.leading !== false || lastCallTime !== 0) {
|
|
26
|
+
invokeFunc();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
lastCallTime = now;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (!timeoutId && options.trailing !== false) {
|
|
33
|
+
timeoutId = setTimeout(() => {
|
|
34
|
+
timeoutId = null;
|
|
35
|
+
invokeFunc();
|
|
36
|
+
}, remaining);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
throttled.cancel = () => {
|
|
40
|
+
if (timeoutId) {
|
|
41
|
+
clearTimeout(timeoutId);
|
|
42
|
+
timeoutId = null;
|
|
43
|
+
}
|
|
44
|
+
lastArgs = null;
|
|
45
|
+
lastCallTime = 0;
|
|
46
|
+
};
|
|
47
|
+
throttled.flush = () => {
|
|
48
|
+
if (timeoutId) {
|
|
49
|
+
clearTimeout(timeoutId);
|
|
50
|
+
timeoutId = null;
|
|
51
|
+
}
|
|
52
|
+
invokeFunc();
|
|
53
|
+
};
|
|
54
|
+
return throttled;
|
|
55
|
+
}
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
* Tool parameter transformation utilities for UI rendering
|
|
3
3
|
* Forces type judgment based on tool name using type assertions
|
|
4
4
|
*/
|
|
5
|
-
import { type Change, type EditToolParameters } from "wave-agent-sdk";
|
|
5
|
+
import { type Change, type WriteToolParameters, type EditToolParameters } from "wave-agent-sdk";
|
|
6
|
+
/**
|
|
7
|
+
* Transform Write tool parameters to changes
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformWriteParameters(parameters: WriteToolParameters): Change[];
|
|
6
10
|
/**
|
|
7
11
|
* Transform Edit tool parameters to changes
|
|
8
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolParameterTransforms.d.ts","sourceRoot":"","sources":["../../src/utils/toolParameterTransforms.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"toolParameterTransforms.d.ts","sourceRoot":"","sources":["../../src/utils/toolParameterTransforms.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,KAAK,MAAM,EACX,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAmBxB;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,mBAAmB,GAC9B,MAAM,EAAE,CAOV;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,kBAAkB,GAC7B,MAAM,EAAE,CAOV;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,EAAE,CA8BV"}
|
|
@@ -18,6 +18,17 @@ function parseToolParameters(parameters) {
|
|
|
18
18
|
return {};
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Transform Write tool parameters to changes
|
|
23
|
+
*/
|
|
24
|
+
export function transformWriteParameters(parameters) {
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
oldContent: "", // No previous content for write operations
|
|
28
|
+
newContent: parameters.content,
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
}
|
|
21
32
|
/**
|
|
22
33
|
* Transform Edit tool parameters to changes
|
|
23
34
|
*/
|
|
@@ -41,6 +52,9 @@ export function transformToolBlockToChanges(toolName, parameters, startLineNumbe
|
|
|
41
52
|
const parsedParams = parseToolParameters(parameters);
|
|
42
53
|
let changes = [];
|
|
43
54
|
switch (toolName) {
|
|
55
|
+
case "Write":
|
|
56
|
+
changes = transformWriteParameters(parsedParams);
|
|
57
|
+
break;
|
|
44
58
|
case "Edit":
|
|
45
59
|
changes = transformEditParameters(parsedParams);
|
|
46
60
|
break;
|
package/dist/utils/worktree.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/utils/worktree.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/utils/worktree.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CA+EzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CA6D7D"}
|
package/dist/utils/worktree.js
CHANGED
|
@@ -2,7 +2,6 @@ import { execSync } from "node:child_process";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import { getDefaultRemoteBranch, getGitMainRepoRoot } from "wave-agent-sdk";
|
|
5
|
-
export const WORKTREE_DIR = ".wave/worktrees";
|
|
6
5
|
/**
|
|
7
6
|
* Create a new git worktree
|
|
8
7
|
* @param name Worktree name
|
|
@@ -11,7 +10,8 @@ export const WORKTREE_DIR = ".wave/worktrees";
|
|
|
11
10
|
*/
|
|
12
11
|
export function createWorktree(name, cwd) {
|
|
13
12
|
const repoRoot = getGitMainRepoRoot(cwd);
|
|
14
|
-
const
|
|
13
|
+
const projectName = path.basename(repoRoot);
|
|
14
|
+
const worktreePath = path.join(repoRoot, "..", `${projectName}.worktrees`, name);
|
|
15
15
|
const branchName = `worktree-${name}`;
|
|
16
16
|
const baseBranch = getDefaultRemoteBranch(cwd);
|
|
17
17
|
// Ensure parent directory exists
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
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.2"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.1.8",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
},
|
|
66
66
|
"license": "MIT",
|
|
67
67
|
"scripts": {
|
|
68
|
-
"wave": "tsx --tsconfig tsconfig.dev.json src/index.ts",
|
|
68
|
+
"wave": "NODE_OPTIONS='--heapsnapshot-near-heap-limit=1' tsx --tsconfig tsconfig.dev.json src/index.ts",
|
|
69
69
|
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
70
70
|
"type-check": "tsc --noEmit --incremental",
|
|
71
71
|
"watch": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
package/src/acp/agent.ts
CHANGED
package/src/components/App.tsx
CHANGED
|
@@ -112,7 +112,7 @@ const AppWithProviders: React.FC<AppWithProvidersProps> = ({
|
|
|
112
112
|
);
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
const ChatInterfaceWithRemount: React.FC = () => {
|
|
115
|
+
export const ChatInterfaceWithRemount: React.FC = () => {
|
|
116
116
|
const { stdout } = useStdout();
|
|
117
117
|
const { isExpanded, rewindId, wasLastDetailsTooTall, sessionId } = useChat();
|
|
118
118
|
|
|
@@ -121,6 +121,7 @@ const ChatInterfaceWithRemount: React.FC = () => {
|
|
|
121
121
|
);
|
|
122
122
|
|
|
123
123
|
const prevSessionId = useRef(sessionId);
|
|
124
|
+
const isRemountScheduled = useRef(false);
|
|
124
125
|
|
|
125
126
|
useEffect(() => {
|
|
126
127
|
const newKey =
|
|
@@ -131,13 +132,16 @@ const ChatInterfaceWithRemount: React.FC = () => {
|
|
|
131
132
|
? sessionId
|
|
132
133
|
: "");
|
|
133
134
|
|
|
134
|
-
if (newKey !== remountKey) {
|
|
135
|
+
if (newKey !== remountKey && !isRemountScheduled.current) {
|
|
136
|
+
isRemountScheduled.current = true;
|
|
137
|
+
|
|
135
138
|
const timeout = setTimeout(() => {
|
|
136
139
|
stdout?.write("\u001b[2J\u001b[3J\u001b[0;0H", (err?: Error | null) => {
|
|
137
140
|
if (err) {
|
|
138
141
|
console.error("Failed to clear terminal:", err);
|
|
139
142
|
}
|
|
140
143
|
setRemountKey(newKey);
|
|
144
|
+
isRemountScheduled.current = false;
|
|
141
145
|
});
|
|
142
146
|
}, 100);
|
|
143
147
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
3
|
import { useChat } from "../contexts/useChat.js";
|
|
4
|
+
import { getLastLines } from "wave-agent-sdk";
|
|
4
5
|
|
|
5
6
|
interface Task {
|
|
6
7
|
id: string;
|
|
@@ -207,9 +208,7 @@ export const BackgroundTaskManager: React.FC<BackgroundTaskManagerProps> = ({
|
|
|
207
208
|
OUTPUT (last 10 lines):
|
|
208
209
|
</Text>
|
|
209
210
|
<Box borderStyle="single" borderColor="green" padding={1}>
|
|
210
|
-
<Text>
|
|
211
|
-
{detailOutput.stdout.split("\n").slice(-10).join("\n")}
|
|
212
|
-
</Text>
|
|
211
|
+
<Text>{getLastLines(detailOutput.stdout, 10)}</Text>
|
|
213
212
|
</Box>
|
|
214
213
|
</Box>
|
|
215
214
|
)}
|
|
@@ -220,9 +219,7 @@ export const BackgroundTaskManager: React.FC<BackgroundTaskManagerProps> = ({
|
|
|
220
219
|
ERRORS:
|
|
221
220
|
</Text>
|
|
222
221
|
<Box borderStyle="single" borderColor="red" padding={1}>
|
|
223
|
-
<Text color="red">
|
|
224
|
-
{detailOutput.stderr.split("\n").slice(-10).join("\n")}
|
|
225
|
-
</Text>
|
|
222
|
+
<Text color="red">{getLastLines(detailOutput.stderr, 10)}</Text>
|
|
226
223
|
</Box>
|
|
227
224
|
</Box>
|
|
228
225
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import type { BangBlock } from "wave-agent-sdk";
|
|
4
|
+
import { getLastLines } from "wave-agent-sdk";
|
|
4
5
|
|
|
5
6
|
interface BangDisplayProps {
|
|
6
7
|
block: BangBlock;
|
|
@@ -12,17 +13,8 @@ export const BangDisplay: React.FC<BangDisplayProps> = ({
|
|
|
12
13
|
isExpanded = false,
|
|
13
14
|
}) => {
|
|
14
15
|
const { command, output, isRunning, exitCode } = block;
|
|
15
|
-
const [isOverflowing, setIsOverflowing] = useState(false);
|
|
16
16
|
const MAX_LINES = 3; // Set maximum display lines
|
|
17
17
|
|
|
18
|
-
// Detect if content is overflowing
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (output) {
|
|
21
|
-
const lines = output.split("\n");
|
|
22
|
-
setIsOverflowing(!isExpanded && lines.length > MAX_LINES);
|
|
23
|
-
}
|
|
24
|
-
}, [output, isExpanded]);
|
|
25
|
-
|
|
26
18
|
const getStatusColor = () => {
|
|
27
19
|
if (isRunning) return "yellow";
|
|
28
20
|
if (exitCode === 0) return "green";
|
|
@@ -38,19 +30,9 @@ export const BangDisplay: React.FC<BangDisplayProps> = ({
|
|
|
38
30
|
</Box>
|
|
39
31
|
|
|
40
32
|
{output && (
|
|
41
|
-
<Box
|
|
42
|
-
paddingLeft={2}
|
|
43
|
-
height={
|
|
44
|
-
isExpanded
|
|
45
|
-
? undefined
|
|
46
|
-
: Math.min(output.split("\n").length, MAX_LINES)
|
|
47
|
-
}
|
|
48
|
-
overflow="hidden"
|
|
49
|
-
>
|
|
33
|
+
<Box paddingLeft={2} overflow="hidden">
|
|
50
34
|
<Text color="gray">
|
|
51
|
-
{
|
|
52
|
-
? output.split("\n").slice(-MAX_LINES).join("\n")
|
|
53
|
-
: output}
|
|
35
|
+
{isExpanded ? output : getLastLines(output, MAX_LINES)}
|
|
54
36
|
</Text>
|
|
55
37
|
</Box>
|
|
56
38
|
)}
|