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.
Files changed (66) hide show
  1. package/README.md +9 -51
  2. package/dist/acp/agent.js +1 -1
  3. package/dist/components/App.d.ts +1 -0
  4. package/dist/components/App.d.ts.map +1 -1
  5. package/dist/components/App.js +5 -2
  6. package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
  7. package/dist/components/BackgroundTaskManager.js +2 -1
  8. package/dist/components/BangDisplay.d.ts.map +1 -1
  9. package/dist/components/BangDisplay.js +2 -14
  10. package/dist/components/ChatInterface.d.ts.map +1 -1
  11. package/dist/components/ChatInterface.js +17 -27
  12. package/dist/components/ConfirmationDetails.d.ts +0 -1
  13. package/dist/components/ConfirmationDetails.d.ts.map +1 -1
  14. package/dist/components/ConfirmationDetails.js +4 -12
  15. package/dist/components/ConfirmationSelector.d.ts +0 -1
  16. package/dist/components/ConfirmationSelector.d.ts.map +1 -1
  17. package/dist/components/ConfirmationSelector.js +4 -12
  18. package/dist/components/DiffDisplay.d.ts.map +1 -1
  19. package/dist/components/DiffDisplay.js +2 -23
  20. package/dist/components/MessageList.d.ts +1 -2
  21. package/dist/components/MessageList.d.ts.map +1 -1
  22. package/dist/components/MessageList.js +12 -17
  23. package/dist/components/RewindCommand.d.ts.map +1 -1
  24. package/dist/components/RewindCommand.js +2 -4
  25. package/dist/components/StatusCommand.d.ts.map +1 -1
  26. package/dist/components/StatusCommand.js +1 -1
  27. package/dist/components/ToolDisplay.d.ts.map +1 -1
  28. package/dist/components/ToolDisplay.js +3 -6
  29. package/dist/contexts/useChat.d.ts +0 -2
  30. package/dist/contexts/useChat.d.ts.map +1 -1
  31. package/dist/contexts/useChat.js +27 -44
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +10 -0
  34. package/dist/utils/highlightUtils.d.ts.map +1 -1
  35. package/dist/utils/highlightUtils.js +0 -8
  36. package/dist/utils/logger.d.ts.map +1 -1
  37. package/dist/utils/logger.js +13 -11
  38. package/dist/utils/throttle.d.ts +15 -0
  39. package/dist/utils/throttle.d.ts.map +1 -0
  40. package/dist/utils/throttle.js +55 -0
  41. package/dist/utils/toolParameterTransforms.d.ts +5 -1
  42. package/dist/utils/toolParameterTransforms.d.ts.map +1 -1
  43. package/dist/utils/toolParameterTransforms.js +14 -0
  44. package/dist/utils/worktree.d.ts +0 -1
  45. package/dist/utils/worktree.d.ts.map +1 -1
  46. package/dist/utils/worktree.js +2 -2
  47. package/package.json +3 -3
  48. package/src/acp/agent.ts +1 -1
  49. package/src/components/App.tsx +6 -2
  50. package/src/components/BackgroundTaskManager.tsx +3 -6
  51. package/src/components/BangDisplay.tsx +4 -22
  52. package/src/components/ChatInterface.tsx +18 -33
  53. package/src/components/ConfirmationDetails.tsx +2 -15
  54. package/src/components/ConfirmationSelector.tsx +3 -15
  55. package/src/components/DiffDisplay.tsx +2 -27
  56. package/src/components/MessageList.tsx +17 -20
  57. package/src/components/RewindCommand.tsx +3 -5
  58. package/src/components/StatusCommand.tsx +7 -0
  59. package/src/components/ToolDisplay.tsx +3 -6
  60. package/src/contexts/useChat.tsx +34 -59
  61. package/src/index.ts +13 -0
  62. package/src/utils/highlightUtils.ts +0 -8
  63. package/src/utils/logger.ts +12 -14
  64. package/src/utils/throttle.ts +75 -0
  65. package/src/utils/toolParameterTransforms.ts +23 -1
  66. package/src/utils/worktree.ts +7 -3
@@ -1 +1 @@
1
- {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
@@ -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
- if (!isExpandedRef.current && agentRef.current) {
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
- debouncedSetTasks(tasks);
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?.executeBashCommand(command);
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 = JSON.parse(JSON.stringify(lastMessage));
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,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,wBAAsB,IAAI,kBAoXzB;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"}
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":"AAqEA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAsCvE"}
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;AAUH;;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;AA+HD;;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;AAqDD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,eAAe,OAAO,CAAC,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAiBd,CAAC"}
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"}
@@ -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
- return arg.stack || arg.message || String(arg);
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
- return JSON.stringify(arg, null, 2);
117
+ result = JSON.stringify(arg);
116
118
  }
117
119
  catch {
118
120
  // If JSON.stringify fails, fallback to String()
119
- return String(arg);
121
+ result = String(arg);
120
122
  }
121
123
  }
122
- return String(arg);
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 lines = content.split("\n");
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
- const removedLines = lines.length - keepLines;
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,EAAE,KAAK,MAAM,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAmBtE;;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,CA0BV"}
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;
@@ -7,7 +7,6 @@ export interface WorktreeSession {
7
7
  hasNewCommits: boolean;
8
8
  isNew: boolean;
9
9
  }
10
- export declare const WORKTREE_DIR = ".wave/worktrees";
11
10
  /**
12
11
  * Create a new git worktree
13
12
  * @param name Worktree name
@@ -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,eAAO,MAAM,YAAY,oBAAoB,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAyEzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CA6D7D"}
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"}
@@ -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 worktreePath = path.join(repoRoot, WORKTREE_DIR, name);
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.0",
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.0"
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
@@ -670,7 +670,7 @@ export class WaveAcpAgent implements AcpAgent {
670
670
  });
671
671
  }
672
672
 
673
- if (contents.length === 0) {
673
+ if (name.startsWith("mcp__")) {
674
674
  contents.push({
675
675
  type: "content",
676
676
  content: {
@@ -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, { useState, useEffect } from "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
- {isOverflowing
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
  )}