wave-code 0.10.0 → 0.10.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.
@@ -72,7 +72,7 @@ export const ChatInterface: React.FC = () => {
72
72
 
73
73
  const terminalHeight = stdout?.rows || 24;
74
74
  const totalHeight = detailsHeight + selectorHeight + dynamicBlocksHeight;
75
- if (totalHeight > terminalHeight) {
75
+ if (totalHeight > terminalHeight - 3) {
76
76
  setIsConfirmationTooTall(true);
77
77
  }
78
78
  }, [
@@ -1,8 +1,14 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { Box, Text } from "ink";
3
- import { WRITE_TOOL_NAME, EDIT_TOOL_NAME } from "wave-agent-sdk";
3
+ import {
4
+ WRITE_TOOL_NAME,
5
+ EDIT_TOOL_NAME,
6
+ type WriteToolParameters,
7
+ } from "wave-agent-sdk";
4
8
  import { transformToolBlockToChanges } from "../utils/toolParameterTransforms.js";
5
9
  import { diffLines, diffWords } from "diff";
10
+ import path from "path";
11
+ import { Markdown } from "./Markdown.js";
6
12
 
7
13
  interface DiffDisplayProps {
8
14
  toolName?: string;
@@ -97,6 +103,23 @@ export const DiffDisplay: React.FC<DiffDisplayProps> = ({
97
103
  }
98
104
  };
99
105
 
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
+
100
123
  // Render expanded diff display
101
124
  const renderExpandedDiff = () => {
102
125
  try {
@@ -352,7 +375,9 @@ export const DiffDisplay: React.FC<DiffDisplayProps> = ({
352
375
  return (
353
376
  <Box flexDirection="column">
354
377
  <Box paddingLeft={2} borderLeft borderColor="cyan" flexDirection="column">
355
- {renderExpandedDiff()}
378
+ {toolName === WRITE_TOOL_NAME
379
+ ? renderWriteContent()
380
+ : renderExpandedDiff()}
356
381
  </Box>
357
382
  </Box>
358
383
  );
@@ -223,6 +223,20 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
223
223
  const [wasLastDetailsTooTall, setWasLastDetailsTooTall] = useState(0);
224
224
 
225
225
  const agentRef = useRef<Agent | null>(null);
226
+ const taskUpdateTimerRef = useRef<NodeJS.Timeout | null>(null);
227
+
228
+ const debouncedSetTasks = useCallback(
229
+ (newTasks: Task[]) => {
230
+ if (taskUpdateTimerRef.current) {
231
+ clearTimeout(taskUpdateTimerRef.current);
232
+ }
233
+ taskUpdateTimerRef.current = setTimeout(() => {
234
+ setTasks([...newTasks]);
235
+ taskUpdateTimerRef.current = null;
236
+ }, 100);
237
+ },
238
+ [setTasks],
239
+ );
226
240
 
227
241
  // Permission confirmation methods with queue support
228
242
  const showConfirmation = useCallback(
@@ -274,7 +288,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
274
288
  setBackgroundTasks([...tasks]);
275
289
  },
276
290
  onTasksChange: (tasks) => {
277
- setTasks([...tasks]);
291
+ debouncedSetTasks(tasks);
278
292
  },
279
293
  onSubagentMessagesChange: (subagentId: string, messages: Message[]) => {
280
294
  logger.debug("onSubagentMessagesChange", subagentId, messages.length);
@@ -295,9 +309,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
295
309
  onPermissionModeChange: (mode) => {
296
310
  setPermissionModeState(mode);
297
311
  },
298
- onSlashCommandsChange: (commands) => {
299
- setSlashCommands([...commands]);
300
- },
301
312
  };
302
313
 
303
314
  try {
@@ -374,11 +385,16 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
374
385
  workdir,
375
386
  worktreeSession,
376
387
  model,
388
+ debouncedSetTasks,
377
389
  ]);
378
390
 
379
391
  // Cleanup on unmount
380
392
  useEffect(() => {
381
393
  return () => {
394
+ if (taskUpdateTimerRef.current) {
395
+ clearTimeout(taskUpdateTimerRef.current);
396
+ }
397
+
382
398
  if (agentRef.current) {
383
399
  try {
384
400
  // Display usage summary before cleanup
@@ -49,6 +49,14 @@ 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
+ }
52
60
  return theme[className](content);
53
61
  }
54
62
  }
@@ -3,11 +3,7 @@
3
3
  * Forces type judgment based on tool name using type assertions
4
4
  */
5
5
 
6
- import {
7
- type Change,
8
- type WriteToolParameters,
9
- type EditToolParameters,
10
- } from "wave-agent-sdk";
6
+ import { type Change, type EditToolParameters } from "wave-agent-sdk";
11
7
  import { logger } from "./logger.js";
12
8
 
13
9
  /**
@@ -26,20 +22,6 @@ function parseToolParameters(parameters: string): unknown {
26
22
  }
27
23
  }
28
24
 
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
-
43
25
  /**
44
26
  * Transform Edit tool parameters to changes
45
27
  */
@@ -72,10 +54,6 @@ export function transformToolBlockToChanges(
72
54
 
73
55
  let changes: Change[] = [];
74
56
  switch (toolName) {
75
- case "Write":
76
- changes = transformWriteParameters(parsedParams as WriteToolParameters);
77
- break;
78
-
79
57
  case "Edit":
80
58
  changes = transformEditParameters(parsedParams as EditToolParameters);
81
59
  break;
@@ -1,7 +1,7 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import * as path from "node:path";
3
3
  import * as fs from "node:fs";
4
- import { getGitRepoRoot, getDefaultRemoteBranch } from "wave-agent-sdk";
4
+ import { getDefaultRemoteBranch, getGitMainRepoRoot } from "wave-agent-sdk";
5
5
 
6
6
  export interface WorktreeSession {
7
7
  name: string;
@@ -22,7 +22,7 @@ export const WORKTREE_DIR = ".wave/worktrees";
22
22
  * @returns Worktree session details
23
23
  */
24
24
  export function createWorktree(name: string, cwd: string): WorktreeSession {
25
- const repoRoot = getGitRepoRoot(cwd);
25
+ const repoRoot = getGitMainRepoRoot(cwd);
26
26
  const worktreePath = path.join(repoRoot, WORKTREE_DIR, name);
27
27
  const branchName = `worktree-${name}`;
28
28
  const baseBranch = getDefaultRemoteBranch(cwd);