wave-code 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +9 -51
  2. package/dist/acp/agent.js +1 -1
  3. package/dist/components/DiffDisplay.d.ts.map +1 -1
  4. package/dist/components/DiffDisplay.js +2 -23
  5. package/dist/components/MessageList.d.ts.map +1 -1
  6. package/dist/components/MessageList.js +8 -3
  7. package/dist/components/StatusCommand.d.ts.map +1 -1
  8. package/dist/components/StatusCommand.js +1 -1
  9. package/dist/components/ToolDisplay.js +1 -1
  10. package/dist/contexts/useChat.d.ts +0 -2
  11. package/dist/contexts/useChat.d.ts.map +1 -1
  12. package/dist/contexts/useChat.js +1 -33
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +10 -0
  15. package/dist/utils/highlightUtils.d.ts.map +1 -1
  16. package/dist/utils/highlightUtils.js +0 -8
  17. package/dist/utils/logger.d.ts.map +1 -1
  18. package/dist/utils/logger.js +10 -5
  19. package/dist/utils/toolParameterTransforms.d.ts +5 -1
  20. package/dist/utils/toolParameterTransforms.d.ts.map +1 -1
  21. package/dist/utils/toolParameterTransforms.js +14 -0
  22. package/dist/utils/worktree.d.ts +0 -1
  23. package/dist/utils/worktree.d.ts.map +1 -1
  24. package/dist/utils/worktree.js +2 -2
  25. package/package.json +3 -3
  26. package/src/acp/agent.ts +1 -1
  27. package/src/components/DiffDisplay.tsx +2 -27
  28. package/src/components/MessageList.tsx +14 -4
  29. package/src/components/StatusCommand.tsx +7 -0
  30. package/src/components/ToolDisplay.tsx +1 -1
  31. package/src/contexts/useChat.tsx +1 -49
  32. package/src/index.ts +13 -0
  33. package/src/utils/highlightUtils.ts +0 -8
  34. package/src/utils/logger.ts +9 -7
  35. package/src/utils/toolParameterTransforms.ts +23 -1
  36. package/src/utils/worktree.ts +7 -3
package/README.md CHANGED
@@ -31,38 +31,26 @@ export WAVE_API_KEY="your_token_here"
31
31
 
32
32
  # AI Gateway API URL (required)
33
33
  export WAVE_BASE_URL="https://your-api-gateway-url.com"
34
+
35
+ # AI model (required)
36
+ export WAVE_MODEL="MiniMax-M2.7"
37
+
38
+ # Fast AI model (required)
39
+ export WAVE_FAST_MODEL="MiniMax-M2.7-highspeed"
34
40
  ```
35
41
 
36
42
  ### Optional Environment Variables
37
43
 
38
44
  ```bash
39
- # Specify AI model (optional, defaults to gemini-3-flash)
40
- export WAVE_MODEL="gemini-3-flash"
41
-
42
- # Specify fast AI model (optional, defaults to gemini-2.5-flash)
43
- export WAVE_FAST_MODEL="gemini-2.5-flash"
44
-
45
45
  # Token limit (optional, defaults to 96000)
46
46
  export WAVE_MAX_INPUT_TOKENS="96000"
47
-
48
47
  ```
49
48
 
50
49
  ## Usage
51
50
 
52
- ### Full Command
53
-
54
51
  ```bash
55
52
  # Start the CLI
56
- wave-code
57
-
58
- # Continue from last session
59
- wave-code --continue
60
-
61
- # Restore specific session
62
- wave-code --restore session_id
63
-
64
- # List available sessions
65
- wave-code --list-sessions
53
+ wave-code -h
66
54
  ```
67
55
 
68
56
  ### Short Command (wave)
@@ -70,42 +58,12 @@ wave-code --list-sessions
70
58
  For convenience, you can also use the shorter `wave` command:
71
59
 
72
60
  ```bash
73
- # Start the CLI (equivalent to wave-code)
74
- wave
75
-
76
- # Continue from last session
77
- wave --continue
78
-
79
- # Restore specific session
80
- wave --restore session_id
81
-
82
- # List available sessions
83
- wave --list-sessions
84
-
85
- # Show help
86
- wave --help
61
+ # Start the CLI
62
+ wave -h
87
63
  ```
88
64
 
89
65
  The `wave` command is an alias for `wave-code` and supports all the same options and functionality.
90
66
 
91
- ## Development
92
-
93
- This package depends on `wave-agent-sdk` for core functionality including AI services, tools, and utilities.
94
-
95
- ```bash
96
- # Install dependencies
97
- pnpm install
98
-
99
- # Start development
100
- pnpm dev
101
-
102
- # Build
103
- pnpm build
104
-
105
- # Test
106
- pnpm test
107
- ```
108
-
109
67
  ## License
110
68
 
111
69
  MIT
package/dist/acp/agent.js CHANGED
@@ -508,7 +508,7 @@ export class WaveAcpAgent {
508
508
  },
509
509
  });
510
510
  }
511
- if (contents.length === 0) {
511
+ if (name.startsWith("mcp__")) {
512
512
  contents.push({
513
513
  type: "content",
514
514
  content: {
@@ -1 +1 @@
1
- {"version":3,"file":"DiffDisplay.d.ts","sourceRoot":"","sources":["../../src/components/DiffDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAYvC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA6WlD,CAAC"}
1
+ {"version":3,"file":"DiffDisplay.d.ts","sourceRoot":"","sources":["../../src/components/DiffDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAMvC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA0VlD,CAAC"}
@@ -1,11 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
3
  import { Box, Text } from "ink";
4
- import { WRITE_TOOL_NAME, EDIT_TOOL_NAME, } from "wave-agent-sdk";
4
+ import { WRITE_TOOL_NAME, EDIT_TOOL_NAME } from "wave-agent-sdk";
5
5
  import { transformToolBlockToChanges } from "../utils/toolParameterTransforms.js";
6
6
  import { diffLines, diffWords } from "diff";
7
- import path from "path";
8
- import { Markdown } from "./Markdown.js";
9
7
  export const DiffDisplay = ({ toolName, parameters, startLineNumber, }) => {
10
8
  const showDiff = toolName && [WRITE_TOOL_NAME, EDIT_TOOL_NAME].includes(toolName);
11
9
  // Diff detection and transformation using typed parameters
@@ -55,23 +53,6 @@ export const DiffDisplay = ({ toolName, parameters, startLineNumber, }) => {
55
53
  };
56
54
  }
57
55
  };
58
- // Render highlighted code for Write tool
59
- const renderWriteContent = () => {
60
- if (!parameters)
61
- return null;
62
- try {
63
- const parsed = JSON.parse(parameters);
64
- const content = parsed.content || "";
65
- const filePath = parsed.file_path || "";
66
- const ext = path.extname(filePath).slice(1);
67
- const markdown = `\`\`\`${ext}\n${content}\n\`\`\``;
68
- return _jsx(Markdown, { children: markdown });
69
- }
70
- catch (error) {
71
- console.warn("Error rendering write content:", error);
72
- return null;
73
- }
74
- };
75
56
  // Render expanded diff display
76
57
  const renderExpandedDiff = () => {
77
58
  try {
@@ -216,7 +197,5 @@ export const DiffDisplay = ({ toolName, parameters, startLineNumber, }) => {
216
197
  if (!showDiff) {
217
198
  return null;
218
199
  }
219
- return (_jsx(Box, { flexDirection: "column", children: _jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "cyan", flexDirection: "column", children: toolName === WRITE_TOOL_NAME
220
- ? renderWriteContent()
221
- : renderExpandedDiff() }) }));
200
+ return (_jsx(Box, { flexDirection: "column", children: _jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "cyan", flexDirection: "column", children: renderExpandedDiff() }) }));
222
201
  };
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAGvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,WAAW,sHAQnB,gBAAgB,6CAkHpB,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAGvD,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,WAAW,sHAQnB,gBAAgB,6CA4HpB,CAAC"}
@@ -9,6 +9,13 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
9
9
  const maxMessages = 10;
10
10
  // Filter out meta messages
11
11
  const visibleMessages = messages.filter((m) => !m.isMeta);
12
+ const isRunning = (b) => (b.type === "tool" && b.stage === "running") ||
13
+ (b.type === "bang" && b.isRunning) ||
14
+ (b.type === "slash" && b.stage === "running");
15
+ const messagesWithRunningBlocks = new Set(visibleMessages
16
+ .map((m, i) => ({ m, i }))
17
+ .filter(({ m }) => m.blocks.some(isRunning))
18
+ .map(({ i }) => i));
12
19
  // Flatten messages into blocks with metadata
13
20
  const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
14
21
  return message.blocks.map((block, blockIndex) => ({
@@ -23,9 +30,7 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
23
30
  const blocksWithStatus = allBlocks.map((item) => {
24
31
  const { block } = item;
25
32
  const isDynamic = !forceStatic &&
26
- ((block.type === "tool" && block.stage === "running") ||
27
- (block.type === "bang" && block.isRunning) ||
28
- (block.type === "slash" && block.stage === "running"));
33
+ (messagesWithRunningBlocks.has(item.messageIndex) || isRunning(block));
29
34
  return { ...item, isDynamic };
30
35
  });
31
36
  const staticBlocks = blocksWithStatus.filter((b) => !b.isDynamic);
@@ -1 +1 @@
1
- {"version":3,"file":"StatusCommand.d.ts","sourceRoot":"","sources":["../../src/components/StatusCommand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA+EtD,CAAC"}
1
+ {"version":3,"file":"StatusCommand.d.ts","sourceRoot":"","sources":["../../src/components/StatusCommand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsFtD,CAAC"}
@@ -24,5 +24,5 @@ export const StatusCommand = ({ onCancel }) => {
24
24
  catch {
25
25
  // Fallback if package.json cannot be read
26
26
  }
27
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", borderLeft: false, borderRight: false, paddingX: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "cyan", bold: true, underline: true, children: "Agent Status" }) }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Version:" }) }), _jsx(Text, { color: "white", children: version })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Session ID:" }) }), _jsx(Text, { color: "white", children: sessionId })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "cwd:" }) }), _jsx(Text, { color: "white", wrap: "wrap", children: workingDirectory })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Wave base URL:" }) }), _jsx(Text, { color: "white", children: gatewayConfig.baseURL })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Model:" }) }), _jsx(Text, { color: "white", children: modelConfig.model })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Esc to cancel" }) })] }));
27
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", borderLeft: false, borderRight: false, paddingX: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "cyan", bold: true, underline: true, children: "Agent Status" }) }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Version:" }) }), _jsx(Text, { color: "white", children: version })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Session ID:" }) }), _jsx(Text, { color: "white", children: sessionId })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "cwd:" }) }), _jsx(Text, { color: "white", wrap: "wrap", children: workingDirectory })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Wave base URL:" }) }), _jsx(Text, { color: "white", children: gatewayConfig.baseURL })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Model:" }) }), _jsx(Text, { color: "white", children: modelConfig.model })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "Fast model:" }) }), _jsx(Text, { color: "white", children: modelConfig.fastModel })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Esc to cancel" }) })] }));
28
28
  };
@@ -40,5 +40,5 @@ export const ToolDisplay = ({ block, isExpanded = false, }) => {
40
40
  return null;
41
41
  };
42
42
  const shortResult = getShortResult();
43
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Box, { flexShrink: 0, children: [_jsx(Text, { color: getStatusColor(), children: "\u25CF " }), _jsx(Text, { color: "white", children: toolName })] }), !isExpanded && compactParams && (_jsxs(Text, { color: "gray", children: [" ", compactParams] })), hasImages() && _jsxs(Text, { color: "blue", children: [" ", getImageIndicator()] })] }), !isExpanded && shortResult && !error && (_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: shortResult.split("\n").map((line, index) => (_jsx(Text, { color: "gray", children: line }, index))) })), isExpanded && parameters && (_jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Parameters:" }), _jsx(Text, { color: "gray", children: parameters })] })), isExpanded && result && (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "green", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Result:" }), _jsx(Text, { color: "white", children: result })] }) })), error && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", typeof error === "string" ? error : String(error)] }) })), !isExpanded && stage === "end" && success && (_jsx(DiffDisplay, { toolName: name, parameters: parameters, startLineNumber: block.startLineNumber }))] }));
43
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Box, { flexShrink: 0, children: [_jsx(Text, { color: getStatusColor(), children: "\u25CF " }), _jsx(Text, { color: "white", children: toolName })] }), !isExpanded && compactParams && (_jsxs(Text, { color: "gray", children: [" ", compactParams] })), hasImages() && _jsxs(Text, { color: "blue", children: [" ", getImageIndicator()] })] }), !isExpanded && shortResult && !error && (_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: shortResult.split("\n").map((line, index) => (_jsx(Text, { color: "gray", wrap: "truncate-end", children: line }, index))) })), isExpanded && parameters && (_jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Parameters:" }), _jsx(Text, { color: "gray", children: parameters })] })), isExpanded && result && (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { paddingLeft: 2, borderLeft: true, borderColor: "green", flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Result:" }), _jsx(Text, { color: "white", children: result })] }) })), error && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", typeof error === "string" ? error : String(error)] }) })), !isExpanded && stage === "end" && success && (_jsx(DiffDisplay, { toolName: name, parameters: parameters, startLineNumber: block.startLineNumber }))] }));
44
44
  };
@@ -43,8 +43,6 @@ export interface ChatContextType {
43
43
  stopBackgroundTask: (taskId: string) => boolean;
44
44
  slashCommands: SlashCommand[];
45
45
  hasSlashCommand: (commandId: string) => boolean;
46
- subagentMessages: Record<string, Message[]>;
47
- subagentLatestTokens: Record<string, number>;
48
46
  permissionMode: PermissionMode;
49
47
  setPermissionMode: (mode: PermissionMode) => void;
50
48
  allowBypassInCycle: boolean;
@@ -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":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IAEvB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,cAAc,EAAE,KAAK,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACnD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtC,CAAC,CAAC;IAEH,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CACX,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAE1B,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,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,QAAQ,EAAE,MAAM,CAAC;IACjB,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;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,wBAAwB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvE,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;IACjB,QAAQ,EAAE,OAAO,6BAA6B,EAAE,QAAQ,CAAC;IACzD,WAAW,EAAE,CACX,OAAO,EAAE,OAAO,CAAC,OAAO,6BAA6B,EAAE,QAAQ,CAAC,KAC7D,IAAI,CAAC;CACX;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,CAwmBpD,CAAC"}
@@ -41,9 +41,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
41
41
  const [tasks, setTasks] = useState([]);
42
42
  // Command state
43
43
  const [slashCommands, setSlashCommands] = useState([]);
44
- // Subagent messages state
45
- const [subagentMessages, setSubagentMessages] = useState({});
46
- const [subagentLatestTokens, setSubagentLatestTokens] = useState({});
47
44
  // Permission state
48
45
  const [permissionMode, setPermissionModeState] = useState(initialPermissionMode ||
49
46
  (bypassPermissions ? "bypassPermissions" : "default"));
@@ -75,16 +72,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
75
72
  const [wasLastDetailsTooTall, setWasLastDetailsTooTall] = useState(0);
76
73
  const allowBypassInCycle = !!bypassPermissions || initialPermissionMode === "bypassPermissions";
77
74
  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
75
  // Permission confirmation methods with queue support
89
76
  const showConfirmation = useCallback(async (toolName, toolInput, suggestedPrefix, hidePersistentOption, planContent) => {
90
77
  return new Promise((resolve, reject) => {
@@ -126,20 +113,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
126
113
  setBackgroundTasks([...tasks]);
127
114
  },
128
115
  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
- }));
116
+ setTasks([...tasks]);
143
117
  },
144
118
  onPermissionModeChange: (mode) => {
145
119
  setPermissionModeState(mode);
@@ -221,15 +195,11 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
221
195
  workdir,
222
196
  worktreeSession,
223
197
  model,
224
- debouncedSetTasks,
225
198
  initialPermissionMode,
226
199
  ]);
227
200
  // Cleanup on unmount
228
201
  useEffect(() => {
229
202
  return () => {
230
- if (taskUpdateTimerRef.current) {
231
- clearTimeout(taskUpdateTimerRef.current);
232
- }
233
203
  if (agentRef.current) {
234
204
  try {
235
205
  // Display usage summary before cleanup
@@ -499,8 +469,6 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
499
469
  stopBackgroundTask,
500
470
  slashCommands,
501
471
  hasSlashCommand,
502
- subagentMessages,
503
- subagentLatestTokens,
504
472
  permissionMode,
505
473
  setPermissionMode,
506
474
  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;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;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;AAqDD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,eAAe,OAAO,CAAC,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAiBd,CAAC"}
@@ -106,20 +106,25 @@ const formatArg = (arg) => {
106
106
  return "null";
107
107
  if (arg === undefined)
108
108
  return "undefined";
109
+ let result;
109
110
  if (arg instanceof Error) {
110
111
  // Special handling for Error objects, display stack or message
111
- return arg.stack || arg.message || String(arg);
112
+ result = arg.stack || arg.message || String(arg);
112
113
  }
113
- if (typeof arg === "object") {
114
+ else if (typeof arg === "object") {
114
115
  try {
115
- return JSON.stringify(arg, null, 2);
116
+ result = JSON.stringify(arg);
116
117
  }
117
118
  catch {
118
119
  // If JSON.stringify fails, fallback to String()
119
- return String(arg);
120
+ result = String(arg);
120
121
  }
121
122
  }
122
- return String(arg);
123
+ else {
124
+ result = String(arg);
125
+ }
126
+ // Ensure no newlines in the result to keep log entries single-line
127
+ return result.replace(/[\n\r]+/g, " ");
123
128
  };
124
129
  /**
125
130
  * Generic log output function
@@ -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.1",
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.1"
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: {
@@ -1,14 +1,8 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { Box, Text } from "ink";
3
- import {
4
- WRITE_TOOL_NAME,
5
- EDIT_TOOL_NAME,
6
- type WriteToolParameters,
7
- } from "wave-agent-sdk";
3
+ import { WRITE_TOOL_NAME, EDIT_TOOL_NAME } from "wave-agent-sdk";
8
4
  import { transformToolBlockToChanges } from "../utils/toolParameterTransforms.js";
9
5
  import { diffLines, diffWords } from "diff";
10
- import path from "path";
11
- import { Markdown } from "./Markdown.js";
12
6
 
13
7
  interface DiffDisplayProps {
14
8
  toolName?: string;
@@ -103,23 +97,6 @@ export const DiffDisplay: React.FC<DiffDisplayProps> = ({
103
97
  }
104
98
  };
105
99
 
106
- // Render highlighted code for Write tool
107
- const renderWriteContent = () => {
108
- if (!parameters) return null;
109
- try {
110
- const parsed = JSON.parse(parameters) as WriteToolParameters;
111
- const content = parsed.content || "";
112
- const filePath = parsed.file_path || "";
113
- const ext = path.extname(filePath).slice(1);
114
-
115
- const markdown = `\`\`\`${ext}\n${content}\n\`\`\``;
116
- return <Markdown>{markdown}</Markdown>;
117
- } catch (error) {
118
- console.warn("Error rendering write content:", error);
119
- return null;
120
- }
121
- };
122
-
123
100
  // Render expanded diff display
124
101
  const renderExpandedDiff = () => {
125
102
  try {
@@ -375,9 +352,7 @@ export const DiffDisplay: React.FC<DiffDisplayProps> = ({
375
352
  return (
376
353
  <Box flexDirection="column">
377
354
  <Box paddingLeft={2} borderLeft borderColor="cyan" flexDirection="column">
378
- {toolName === WRITE_TOOL_NAME
379
- ? renderWriteContent()
380
- : renderExpandedDiff()}
355
+ {renderExpandedDiff()}
381
356
  </Box>
382
357
  </Box>
383
358
  );
@@ -1,7 +1,7 @@
1
1
  import React, { useLayoutEffect, useRef } from "react";
2
2
  import os from "os";
3
3
  import { Box, Text, Static, measureElement } from "ink";
4
- import type { Message } from "wave-agent-sdk";
4
+ import type { Message, MessageBlock } from "wave-agent-sdk";
5
5
  import { MessageBlockItem } from "./MessageBlockItem.js";
6
6
 
7
7
  export interface MessageListProps {
@@ -39,6 +39,18 @@ export const MessageList = React.memo(
39
39
  // Filter out meta messages
40
40
  const visibleMessages = messages.filter((m) => !m.isMeta);
41
41
 
42
+ const isRunning = (b: MessageBlock) =>
43
+ (b.type === "tool" && b.stage === "running") ||
44
+ (b.type === "bang" && b.isRunning) ||
45
+ (b.type === "slash" && b.stage === "running");
46
+
47
+ const messagesWithRunningBlocks = new Set(
48
+ visibleMessages
49
+ .map((m, i) => ({ m, i }))
50
+ .filter(({ m }) => m.blocks.some(isRunning))
51
+ .map(({ i }) => i),
52
+ );
53
+
42
54
  // Flatten messages into blocks with metadata
43
55
  const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
44
56
  return message.blocks.map((block, blockIndex) => ({
@@ -55,9 +67,7 @@ export const MessageList = React.memo(
55
67
  const { block } = item;
56
68
  const isDynamic =
57
69
  !forceStatic &&
58
- ((block.type === "tool" && block.stage === "running") ||
59
- (block.type === "bang" && block.isRunning) ||
60
- (block.type === "slash" && block.stage === "running"));
70
+ (messagesWithRunningBlocks.has(item.messageIndex) || isRunning(block));
61
71
  return { ...item, isDynamic };
62
72
  });
63
73
 
@@ -86,6 +86,13 @@ export const StatusCommand: React.FC<StatusCommandProps> = ({ onCancel }) => {
86
86
  <Text color="white">{modelConfig.model}</Text>
87
87
  </Box>
88
88
 
89
+ <Box>
90
+ <Box width={20}>
91
+ <Text color="yellow">Fast model:</Text>
92
+ </Box>
93
+ <Text color="white">{modelConfig.fastModel}</Text>
94
+ </Box>
95
+
89
96
  <Box marginTop={1}>
90
97
  <Text dimColor>Esc to cancel</Text>
91
98
  </Box>
@@ -81,7 +81,7 @@ export const ToolDisplay: React.FC<ToolDisplayProps> = ({
81
81
  flexDirection="column"
82
82
  >
83
83
  {shortResult.split("\n").map((line, index) => (
84
- <Text key={index} color="gray">
84
+ <Text key={index} color="gray" wrap="truncate-end">
85
85
  {line}
86
86
  </Text>
87
87
  ))}
@@ -77,9 +77,6 @@ export interface ChatContextType {
77
77
  // Slash Command functionality
78
78
  slashCommands: SlashCommand[];
79
79
  hasSlashCommand: (commandId: string) => boolean;
80
- // Subagent messages
81
- subagentMessages: Record<string, Message[]>;
82
- subagentLatestTokens: Record<string, number>;
83
80
  // Permission functionality
84
81
  permissionMode: PermissionMode;
85
82
  setPermissionMode: (mode: PermissionMode) => void;
@@ -195,14 +192,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
195
192
  // Command state
196
193
  const [slashCommands, setSlashCommands] = useState<SlashCommand[]>([]);
197
194
 
198
- // Subagent messages state
199
- const [subagentMessages, setSubagentMessages] = useState<
200
- Record<string, Message[]>
201
- >({});
202
- const [subagentLatestTokens, setSubagentLatestTokens] = useState<
203
- Record<string, number>
204
- >({});
205
-
206
195
  // Permission state
207
196
  const [permissionMode, setPermissionModeState] = useState<PermissionMode>(
208
197
  initialPermissionMode ||
@@ -276,20 +265,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
276
265
  !!bypassPermissions || initialPermissionMode === "bypassPermissions";
277
266
 
278
267
  const agentRef = useRef<Agent | null>(null);
279
- const taskUpdateTimerRef = useRef<NodeJS.Timeout | null>(null);
280
-
281
- const debouncedSetTasks = useCallback(
282
- (newTasks: Task[]) => {
283
- if (taskUpdateTimerRef.current) {
284
- clearTimeout(taskUpdateTimerRef.current);
285
- }
286
- taskUpdateTimerRef.current = setTimeout(() => {
287
- setTasks([...newTasks]);
288
- taskUpdateTimerRef.current = null;
289
- }, 100);
290
- },
291
- [setTasks],
292
- );
293
268
 
294
269
  // Permission confirmation methods with queue support
295
270
  const showConfirmation = useCallback(
@@ -343,23 +318,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
343
318
  setBackgroundTasks([...tasks]);
344
319
  },
345
320
  onTasksChange: (tasks) => {
346
- debouncedSetTasks(tasks);
347
- },
348
- onSubagentMessagesChange: (subagentId: string, messages: Message[]) => {
349
- logger.debug("onSubagentMessagesChange", subagentId, messages.length);
350
- setSubagentMessages((prev) => ({
351
- ...prev,
352
- [subagentId]: [...messages],
353
- }));
354
- },
355
- onSubagentLatestTotalTokensChange: (
356
- subagentId: string,
357
- tokens: number,
358
- ) => {
359
- setSubagentLatestTokens((prev) => ({
360
- ...prev,
361
- [subagentId]: tokens,
362
- }));
321
+ setTasks([...tasks]);
363
322
  },
364
323
  onPermissionModeChange: (mode) => {
365
324
  setPermissionModeState(mode);
@@ -455,17 +414,12 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
455
414
  workdir,
456
415
  worktreeSession,
457
416
  model,
458
- debouncedSetTasks,
459
417
  initialPermissionMode,
460
418
  ]);
461
419
 
462
420
  // Cleanup on unmount
463
421
  useEffect(() => {
464
422
  return () => {
465
- if (taskUpdateTimerRef.current) {
466
- clearTimeout(taskUpdateTimerRef.current);
467
- }
468
-
469
423
  if (agentRef.current) {
470
424
  try {
471
425
  // Display usage summary before cleanup
@@ -772,8 +726,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
772
726
  stopBackgroundTask,
773
727
  slashCommands,
774
728
  hasSlashCommand,
775
- subagentMessages,
776
- subagentLatestTokens,
777
729
  permissionMode,
778
730
  setPermissionMode,
779
731
  allowBypassInCycle,
package/src/index.ts 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 { Scope, generateRandomName, type PermissionMode } from "wave-agent-sdk";
5
6
  import { createWorktree, type WorktreeSession } from "./utils/worktree.js";
6
7
  import path from "path";
@@ -14,6 +15,18 @@ const version = packageJson.version;
14
15
 
15
16
  // Export main function for external use
16
17
  export async function main() {
18
+ // Start memory monitoring in debug mode
19
+ if (process.env.LOG_LEVEL === "DEBUG") {
20
+ setInterval(() => {
21
+ const usage = process.memoryUsage();
22
+ logger.debug(
23
+ `[Memory] RSS: ${Math.round(usage.rss / 1024 / 1024)}MB, ` +
24
+ `Heap: ${Math.round(usage.heapUsed / 1024 / 1024)}/${Math.round(usage.heapTotal / 1024 / 1024)}MB, ` +
25
+ `External: ${Math.round(usage.external / 1024 / 1024)}MB`,
26
+ );
27
+ }, 10000).unref();
28
+ }
29
+
17
30
  try {
18
31
  const originalCwd = process.cwd();
19
32
  const argv = await yargs(hideBin(process.argv))
@@ -49,14 +49,6 @@ function nodeToAnsi(node: Node): string {
49
49
 
50
50
  for (const className of classes) {
51
51
  if (theme[className]) {
52
- // If content has newlines, split it and apply style to each line
53
- // to ensure ANSI codes are correctly applied when splitting the final string by lines.
54
- if (content.includes("\n")) {
55
- return content
56
- .split("\n")
57
- .map((line) => theme[className](line))
58
- .join("\n");
59
- }
60
52
  return theme[className](content);
61
53
  }
62
54
  }
@@ -124,21 +124,23 @@ const formatArg = (arg: unknown): string => {
124
124
  if (arg === null) return "null";
125
125
  if (arg === undefined) return "undefined";
126
126
 
127
+ let result: string;
127
128
  if (arg instanceof Error) {
128
129
  // Special handling for Error objects, display stack or message
129
- return arg.stack || arg.message || String(arg);
130
- }
131
-
132
- if (typeof arg === "object") {
130
+ result = arg.stack || arg.message || String(arg);
131
+ } else if (typeof arg === "object") {
133
132
  try {
134
- return JSON.stringify(arg, null, 2);
133
+ result = JSON.stringify(arg);
135
134
  } catch {
136
135
  // If JSON.stringify fails, fallback to String()
137
- return String(arg);
136
+ result = String(arg);
138
137
  }
138
+ } else {
139
+ result = String(arg);
139
140
  }
140
141
 
141
- return String(arg);
142
+ // Ensure no newlines in the result to keep log entries single-line
143
+ return result.replace(/[\n\r]+/g, " ");
142
144
  };
143
145
 
144
146
  /**
@@ -3,7 +3,11 @@
3
3
  * Forces type judgment based on tool name using type assertions
4
4
  */
5
5
 
6
- import { type Change, type EditToolParameters } from "wave-agent-sdk";
6
+ import {
7
+ type Change,
8
+ type WriteToolParameters,
9
+ type EditToolParameters,
10
+ } from "wave-agent-sdk";
7
11
  import { logger } from "./logger.js";
8
12
 
9
13
  /**
@@ -22,6 +26,20 @@ function parseToolParameters(parameters: string): unknown {
22
26
  }
23
27
  }
24
28
 
29
+ /**
30
+ * Transform Write tool parameters to changes
31
+ */
32
+ export function transformWriteParameters(
33
+ parameters: WriteToolParameters,
34
+ ): Change[] {
35
+ return [
36
+ {
37
+ oldContent: "", // No previous content for write operations
38
+ newContent: parameters.content,
39
+ },
40
+ ];
41
+ }
42
+
25
43
  /**
26
44
  * Transform Edit tool parameters to changes
27
45
  */
@@ -54,6 +72,10 @@ export function transformToolBlockToChanges(
54
72
 
55
73
  let changes: Change[] = [];
56
74
  switch (toolName) {
75
+ case "Write":
76
+ changes = transformWriteParameters(parsedParams as WriteToolParameters);
77
+ break;
78
+
57
79
  case "Edit":
58
80
  changes = transformEditParameters(parsedParams as EditToolParameters);
59
81
  break;
@@ -13,8 +13,6 @@ export interface WorktreeSession {
13
13
  isNew: boolean;
14
14
  }
15
15
 
16
- export const WORKTREE_DIR = ".wave/worktrees";
17
-
18
16
  /**
19
17
  * Create a new git worktree
20
18
  * @param name Worktree name
@@ -23,7 +21,13 @@ export const WORKTREE_DIR = ".wave/worktrees";
23
21
  */
24
22
  export function createWorktree(name: string, cwd: string): WorktreeSession {
25
23
  const repoRoot = getGitMainRepoRoot(cwd);
26
- const worktreePath = path.join(repoRoot, WORKTREE_DIR, name);
24
+ const projectName = path.basename(repoRoot);
25
+ const worktreePath = path.join(
26
+ repoRoot,
27
+ "..",
28
+ `${projectName}.worktrees`,
29
+ name,
30
+ );
27
31
  const branchName = `worktree-${name}`;
28
32
  const baseBranch = getDefaultRemoteBranch(cwd);
29
33