wave-code 0.11.3 → 0.11.4

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.
@@ -20,7 +20,6 @@ export declare class WaveAcpAgent implements AcpAgent {
20
20
  cancel(params: CancelNotification): Promise<void>;
21
21
  private getAllowAlwaysName;
22
22
  private handlePermissionRequest;
23
- private getToolContentAsync;
24
23
  private getToolContent;
25
24
  private getToolLocations;
26
25
  private getToolKind;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,KAAK,IAAI,QAAQ,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAUzB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EAMpC,MAAM,0BAA0B,CAAC;AAElC,qBAAa,YAAa,YAAW,QAAQ;IAC3C,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,mBAAmB;IAI3C,OAAO,CAAC,mBAAmB;IAkC3B,OAAO,CAAC,uBAAuB;YAmBjB,gBAAgB;IASxB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAwBzC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAI5C,WAAW;IAiEnB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAalE,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAWrE,YAAY,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,oBAAoB,CAAC;IAuB1B,qBAAqB,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAc7B,SAAS,CACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAO7B,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5D,sBAAsB,CAC1B,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,8BAA8B,CAAC;IAqBpC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAyDtD,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IASvD,OAAO,CAAC,kBAAkB;YA2BZ,uBAAuB;YAqKvB,mBAAmB;IA6EjC,OAAO,CAAC,cAAc;IA0BtB,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,eAAe;CA+LxB"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,KAAK,KAAK,IAAI,QAAQ,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAUzB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EAMpC,MAAM,0BAA0B,CAAC;AAElC,qBAAa,YAAa,YAAW,QAAQ;IAC3C,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,mBAAmB;IAI3C,OAAO,CAAC,mBAAmB;IAkC3B,OAAO,CAAC,uBAAuB;YAmBjB,gBAAgB;IASxB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAwBzC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAI5C,WAAW;IAiEnB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAalE,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAWrE,YAAY,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,oBAAoB,CAAC;IAuB1B,qBAAqB,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAc7B,SAAS,CACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAO7B,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5D,sBAAsB,CAC1B,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,8BAA8B,CAAC;IAqBpC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAyDtD,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IASvD,OAAO,CAAC,kBAAkB;YA2BZ,uBAAuB;IAqKrC,OAAO,CAAC,cAAc;IAwFtB,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,eAAe;CAmMxB"}
package/dist/acp/agent.js CHANGED
@@ -1,6 +1,4 @@
1
- import { Agent as WaveAgent, listSessions as listWaveSessions, listAllSessions as listAllWaveSessions, deleteSession as deleteWaveSession, truncateContent, BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, } from "wave-agent-sdk";
2
- import * as fs from "node:fs/promises";
3
- import * as path from "node:path";
1
+ import { Agent as WaveAgent, listSessions as listWaveSessions, listAllSessions as listAllWaveSessions, deleteSession as deleteWaveSession, truncateContent, BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
4
2
  import { logger } from "../utils/logger.js";
5
3
  import { AGENT_METHODS, } from "@agentclientprotocol/sdk";
6
4
  export class WaveAcpAgent {
@@ -304,7 +302,6 @@ export class WaveAcpAgent {
304
302
  async handlePermissionRequest(sessionId, context) {
305
303
  logger.info(`Handling permission request for ${context.toolName} in session ${sessionId}`);
306
304
  const agent = this.agents.get(sessionId);
307
- const workdir = agent?.workingDirectory || process.cwd();
308
305
  const toolCallId = context.toolCallId ||
309
306
  "perm-" + Math.random().toString(36).substring(2, 9);
310
307
  let effectiveName = context.toolName;
@@ -370,7 +367,7 @@ export class WaveAcpAgent {
370
367
  ];
371
368
  }
372
369
  const content = context.toolName
373
- ? await this.getToolContentAsync(context.toolName, context.toolInput, workdir)
370
+ ? this.getToolContent(context.toolName, context.toolInput, undefined, context.planContent)
374
371
  : undefined;
375
372
  const locations = context.toolName
376
373
  ? this.getToolLocations(context.toolName, context.toolInput)
@@ -438,96 +435,78 @@ export class WaveAcpAgent {
438
435
  };
439
436
  }
440
437
  }
441
- async getToolContentAsync(name, parameters, workdir) {
442
- if (!parameters)
443
- return undefined;
444
- if (name === "Write") {
445
- let oldText = null;
446
- try {
447
- const filePath = (parameters.file_path ||
448
- parameters.filePath);
449
- const fullPath = path.isAbsolute(filePath)
450
- ? filePath
451
- : path.join(workdir, filePath);
452
- oldText = await fs.readFile(fullPath, "utf-8");
453
- }
454
- catch {
455
- // File might not exist, which is fine for Write
456
- }
457
- return [
458
- {
459
- type: "diff",
460
- path: (parameters.file_path || parameters.filePath),
461
- oldText,
462
- newText: parameters.content,
463
- },
464
- ];
465
- }
466
- if (name === "Edit") {
467
- let oldText = null;
468
- let newText = null;
469
- try {
470
- const filePath = (parameters.file_path ||
471
- parameters.filePath);
472
- const fullPath = path.isAbsolute(filePath)
473
- ? filePath
474
- : path.join(workdir, filePath);
475
- oldText = await fs.readFile(fullPath, "utf-8");
476
- if (oldText) {
477
- if (parameters.replace_all) {
478
- newText = oldText
479
- .split(parameters.old_string)
480
- .join(parameters.new_string);
481
- }
482
- else {
483
- newText = oldText.replace(parameters.old_string, parameters.new_string);
484
- }
485
- }
486
- }
487
- catch {
488
- logger.error("Failed to read file for Edit diff");
489
- }
490
- if (oldText && newText) {
491
- return [
492
- {
493
- type: "diff",
494
- path: (parameters.file_path || parameters.filePath),
495
- oldText,
496
- newText,
497
- },
498
- ];
499
- }
500
- // Fallback to snippets if file reading fails
501
- return [
502
- {
503
- type: "diff",
504
- path: (parameters.file_path || parameters.filePath),
505
- oldText: parameters.old_string,
506
- newText: parameters.new_string,
507
- },
508
- ];
509
- }
510
- return this.getToolContent(name, parameters);
511
- }
512
- getToolContent(name, parameters) {
438
+ getToolContent(name, parameters, shortResult, planContent) {
513
439
  const contents = [];
514
440
  if (parameters) {
515
- if (name === "Write") {
441
+ if (name === "Write" &&
442
+ typeof parameters.file_path === "string" &&
443
+ typeof parameters.content === "string") {
516
444
  contents.push({
517
445
  type: "diff",
518
- path: (parameters.file_path || parameters.filePath),
446
+ path: parameters.file_path,
519
447
  oldText: null,
520
448
  newText: parameters.content,
521
449
  });
522
450
  }
523
- else if (name === "Edit") {
451
+ else if (name === "Edit" &&
452
+ typeof parameters.file_path === "string" &&
453
+ typeof parameters.old_string === "string" &&
454
+ typeof parameters.new_string === "string") {
524
455
  contents.push({
525
456
  type: "diff",
526
- path: (parameters.file_path || parameters.filePath),
457
+ path: parameters.file_path,
527
458
  oldText: parameters.old_string,
528
459
  newText: parameters.new_string,
529
460
  });
530
461
  }
462
+ else if (name === "Bash" && typeof parameters.command === "string") {
463
+ contents.push({
464
+ type: "content",
465
+ content: {
466
+ type: "text",
467
+ text: parameters.command,
468
+ },
469
+ });
470
+ }
471
+ else if (name === EXIT_PLAN_MODE_TOOL_NAME && planContent) {
472
+ contents.push({
473
+ type: "content",
474
+ content: {
475
+ type: "text",
476
+ text: planContent,
477
+ },
478
+ });
479
+ }
480
+ else if (name === ASK_USER_QUESTION_TOOL_NAME &&
481
+ Array.isArray(parameters.questions)) {
482
+ const markdown = parameters.questions
483
+ .map((q, i) => {
484
+ let text = `### Question ${i + 1}\n${q.question}\n`;
485
+ if (Array.isArray(q.options)) {
486
+ text += q.options
487
+ .map((opt) => `- ${opt.label}${opt.description ? `: ${opt.description}` : ""}`)
488
+ .join("\n");
489
+ }
490
+ return text;
491
+ })
492
+ .join("\n\n");
493
+ contents.push({
494
+ type: "content",
495
+ content: {
496
+ type: "text",
497
+ text: markdown,
498
+ },
499
+ });
500
+ }
501
+ }
502
+ if (shortResult) {
503
+ contents.push({
504
+ type: "content",
505
+ content: {
506
+ type: "text",
507
+ text: shortResult,
508
+ },
509
+ });
531
510
  }
532
511
  return contents.length > 0 ? contents : undefined;
533
512
  }
@@ -640,7 +619,7 @@ export class WaveAcpAgent {
640
619
  }
641
620
  }
642
621
  const content = effectiveName && (parsedParameters || effectiveShortResult)
643
- ? this.getToolContent(effectiveName, parsedParameters)
622
+ ? this.getToolContent(effectiveName, parsedParameters, effectiveShortResult)
644
623
  : undefined;
645
624
  const locations = effectiveName && parsedParameters
646
625
  ? this.getToolLocations(effectiveName, parsedParameters, effectiveStartLineNumber)
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAatE,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAyKjC,CAAC"}
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAatE,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EA0KjC,CAAC"}
@@ -77,5 +77,5 @@ export const ChatInterface = () => {
77
77
  return null;
78
78
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, forceStatic: isConfirmationVisible && isConfirmationTooTall, version: version, workdir: workdir, model: model, onDynamicBlocksHeightMeasured: handleDynamicBlocksHeightMeasured }), (isLoading || isCommandRunning || isCompressing) &&
79
79
  !isConfirmationVisible &&
80
- !isExpanded && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), !isConfirmationVisible && !isExpanded && _jsx(TaskList, {}), isConfirmationVisible && (_jsxs(_Fragment, { children: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, isExpanded: isExpanded, onHeightMeasured: handleDetailsHeightMeasured, isStatic: isConfirmationTooTall }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage, onHeightMeasured: handleSelectorHeightMeasured })] })), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] }))] }));
80
+ !isExpanded && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), !isConfirmationVisible && !isExpanded && _jsx(TaskList, {}), isConfirmationVisible && (_jsxs(_Fragment, { children: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded, onHeightMeasured: handleDetailsHeightMeasured, isStatic: isConfirmationTooTall }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage, onHeightMeasured: handleSelectorHeightMeasured })] })), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] }))] }));
81
81
  };
@@ -2,6 +2,7 @@ import React from "react";
2
2
  export interface ConfirmationDetailsProps {
3
3
  toolName: string;
4
4
  toolInput?: Record<string, unknown>;
5
+ planContent?: string;
5
6
  isExpanded?: boolean;
6
7
  onHeightMeasured?: (height: number) => void;
7
8
  isStatic?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAqCvD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA8DlE,CAAC"}
1
+ {"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAqCvD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA4DlE,CAAC"}
@@ -24,7 +24,7 @@ const getActionDescription = (toolName, toolInput) => {
24
24
  return "Execute operation";
25
25
  }
26
26
  };
27
- export const ConfirmationDetails = ({ toolName, toolInput, isExpanded = false, onHeightMeasured, isStatic = false, }) => {
27
+ export const ConfirmationDetails = ({ toolName, toolInput, planContent, isExpanded = false, onHeightMeasured, isStatic = false, }) => {
28
28
  const { stdout } = useStdout();
29
29
  const boxRef = useRef(null);
30
30
  const startLineNumber = toolInput?.startLineNumber ??
@@ -37,7 +37,7 @@ export const ConfirmationDetails = ({ toolName, toolInput, isExpanded = false, o
37
37
  }, [stdout?.rows, onHeightMeasured, toolInput, isExpanded]);
38
38
  const content = (_jsxs(Box, { ref: boxRef, flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Tool: ", toolName] }), _jsx(Text, { color: "yellow", children: getActionDescription(toolName, toolInput) }), _jsx(DiffDisplay, { toolName: toolName, parameters: JSON.stringify(toolInput), startLineNumber: startLineNumber }), toolName !== ASK_USER_QUESTION_TOOL_NAME &&
39
39
  toolName === EXIT_PLAN_MODE_TOOL_NAME &&
40
- !!toolInput?.plan_content && (_jsx(PlanDisplay, { plan: toolInput.plan_content, isExpanded: isExpanded }))] }));
40
+ !!planContent && (_jsx(PlanDisplay, { plan: planContent, isExpanded: isExpanded }))] }));
41
41
  if (isStatic) {
42
42
  return (_jsx(Static, { items: [1], children: (item) => _jsx(React.Fragment, { children: content }, item) }));
43
43
  }
@@ -48,8 +48,9 @@ export interface ChatContextType {
48
48
  input?: Record<string, unknown>;
49
49
  suggestedPrefix?: string;
50
50
  hidePersistentOption?: boolean;
51
+ planContent?: string;
51
52
  };
52
- showConfirmation: (toolName: string, toolInput?: Record<string, unknown>, suggestedPrefix?: string, hidePersistentOption?: boolean) => Promise<PermissionDecision>;
53
+ showConfirmation: (toolName: string, toolInput?: Record<string, unknown>, suggestedPrefix?: string, hidePersistentOption?: boolean, planContent?: string) => Promise<PermissionDecision>;
53
54
  hideConfirmation: () => void;
54
55
  handleConfirmationDecision: (decision: PermissionDecision) => void;
55
56
  handleConfirmationCancel: () => void;
@@ -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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"}
@@ -68,13 +68,14 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
68
68
  }, 100);
69
69
  }, [setTasks]);
70
70
  // Permission confirmation methods with queue support
71
- const showConfirmation = useCallback(async (toolName, toolInput, suggestedPrefix, hidePersistentOption) => {
71
+ const showConfirmation = useCallback(async (toolName, toolInput, suggestedPrefix, hidePersistentOption, planContent) => {
72
72
  return new Promise((resolve, reject) => {
73
73
  const queueItem = {
74
74
  toolName,
75
75
  toolInput,
76
76
  suggestedPrefix,
77
77
  hidePersistentOption,
78
+ planContent,
78
79
  resolver: resolve,
79
80
  reject,
80
81
  };
@@ -132,7 +133,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
132
133
  ? undefined
133
134
  : async (context) => {
134
135
  try {
135
- return await showConfirmation(context.toolName, context.toolInput, context.suggestedPrefix, context.hidePersistentOption);
136
+ return await showConfirmation(context.toolName, context.toolInput, context.suggestedPrefix, context.hidePersistentOption, context.planContent);
136
137
  }
137
138
  catch {
138
139
  // If confirmation was cancelled or failed, deny the operation
@@ -323,6 +324,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
323
324
  input: next.toolInput,
324
325
  suggestedPrefix: next.suggestedPrefix,
325
326
  hidePersistentOption: next.hidePersistentOption,
327
+ planContent: next.planContent,
326
328
  });
327
329
  setIsConfirmationVisible(true);
328
330
  setConfirmationQueue((prev) => prev.slice(1));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-code",
3
- "version": "0.11.3",
3
+ "version": "0.11.4",
4
4
  "description": "CLI-based code assistant powered by AI, built with React and Ink",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  "README.md"
30
30
  ],
31
31
  "dependencies": {
32
- "@agentclientprotocol/sdk": "0.17.0",
32
+ "@agentclientprotocol/sdk": "0.17.1",
33
33
  "chalk": "^5.6.2",
34
34
  "diff": "^8.0.2",
35
35
  "glob": "^13.0.0",
@@ -41,7 +41,7 @@
41
41
  "react-dom": "19.2.4",
42
42
  "yargs": "^17.7.2",
43
43
  "zod": "^3.23.8",
44
- "wave-agent-sdk": "0.11.3"
44
+ "wave-agent-sdk": "0.11.4"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/react": "^19.1.8",
package/src/acp/agent.ts CHANGED
@@ -13,9 +13,10 @@ import {
13
13
  EDIT_TOOL_NAME,
14
14
  WRITE_TOOL_NAME,
15
15
  EXIT_PLAN_MODE_TOOL_NAME,
16
+ ASK_USER_QUESTION_TOOL_NAME,
17
+ AskUserQuestion,
18
+ AskUserQuestionOption,
16
19
  } from "wave-agent-sdk";
17
- import * as fs from "node:fs/promises";
18
- import * as path from "node:path";
19
20
  import { logger } from "../utils/logger.js";
20
21
  import {
21
22
  type Agent as AcpAgent,
@@ -427,7 +428,6 @@ export class WaveAcpAgent implements AcpAgent {
427
428
  );
428
429
 
429
430
  const agent = this.agents.get(sessionId);
430
- const workdir = agent?.workingDirectory || process.cwd();
431
431
 
432
432
  const toolCallId =
433
433
  context.toolCallId ||
@@ -505,10 +505,11 @@ export class WaveAcpAgent implements AcpAgent {
505
505
  }
506
506
 
507
507
  const content = context.toolName
508
- ? await this.getToolContentAsync(
508
+ ? this.getToolContent(
509
509
  context.toolName,
510
510
  context.toolInput,
511
- workdir,
511
+ undefined,
512
+ context.planContent,
512
513
  )
513
514
  : undefined;
514
515
  const locations = context.toolName
@@ -583,106 +584,91 @@ export class WaveAcpAgent implements AcpAgent {
583
584
  }
584
585
  }
585
586
 
586
- private async getToolContentAsync(
587
- name: string,
588
- parameters: Record<string, unknown> | undefined,
589
- workdir: string,
590
- ): Promise<ToolCallContent[] | undefined> {
591
- if (!parameters) return undefined;
592
- if (name === "Write") {
593
- let oldText: string | null = null;
594
- try {
595
- const filePath = (parameters.file_path ||
596
- parameters.filePath) as string;
597
- const fullPath = path.isAbsolute(filePath)
598
- ? filePath
599
- : path.join(workdir, filePath);
600
- oldText = await fs.readFile(fullPath, "utf-8");
601
- } catch {
602
- // File might not exist, which is fine for Write
603
- }
604
- return [
605
- {
606
- type: "diff",
607
- path: (parameters.file_path || parameters.filePath) as string,
608
- oldText,
609
- newText: parameters.content as string,
610
- },
611
- ];
612
- }
613
- if (name === "Edit") {
614
- let oldText: string | null = null;
615
- let newText: string | null = null;
616
- try {
617
- const filePath = (parameters.file_path ||
618
- parameters.filePath) as string;
619
- const fullPath = path.isAbsolute(filePath)
620
- ? filePath
621
- : path.join(workdir, filePath);
622
- oldText = await fs.readFile(fullPath, "utf-8");
623
- if (oldText) {
624
- if (parameters.replace_all) {
625
- newText = oldText
626
- .split(parameters.old_string as string)
627
- .join(parameters.new_string as string);
628
- } else {
629
- newText = oldText.replace(
630
- parameters.old_string as string,
631
- parameters.new_string as string,
632
- );
633
- }
634
- }
635
- } catch {
636
- logger.error("Failed to read file for Edit diff");
637
- }
638
-
639
- if (oldText && newText) {
640
- return [
641
- {
642
- type: "diff",
643
- path: (parameters.file_path || parameters.filePath) as string,
644
- oldText,
645
- newText,
646
- },
647
- ];
648
- }
649
-
650
- // Fallback to snippets if file reading fails
651
- return [
652
- {
653
- type: "diff",
654
- path: (parameters.file_path || parameters.filePath) as string,
655
- oldText: parameters.old_string as string,
656
- newText: parameters.new_string as string,
657
- },
658
- ];
659
- }
660
- return this.getToolContent(name, parameters);
661
- }
662
-
663
587
  private getToolContent(
664
588
  name: string,
665
589
  parameters: Record<string, unknown> | undefined,
590
+ shortResult: string | undefined,
591
+ planContent?: string,
666
592
  ): ToolCallContent[] | undefined {
667
593
  const contents: ToolCallContent[] = [];
668
594
  if (parameters) {
669
- if (name === "Write") {
595
+ if (
596
+ name === "Write" &&
597
+ typeof parameters.file_path === "string" &&
598
+ typeof parameters.content === "string"
599
+ ) {
670
600
  contents.push({
671
601
  type: "diff",
672
- path: (parameters.file_path || parameters.filePath) as string,
602
+ path: parameters.file_path,
673
603
  oldText: null,
674
- newText: parameters.content as string,
604
+ newText: parameters.content,
675
605
  });
676
- } else if (name === "Edit") {
606
+ } else if (
607
+ name === "Edit" &&
608
+ typeof parameters.file_path === "string" &&
609
+ typeof parameters.old_string === "string" &&
610
+ typeof parameters.new_string === "string"
611
+ ) {
677
612
  contents.push({
678
613
  type: "diff",
679
- path: (parameters.file_path || parameters.filePath) as string,
680
- oldText: parameters.old_string as string,
681
- newText: parameters.new_string as string,
614
+ path: parameters.file_path,
615
+ oldText: parameters.old_string,
616
+ newText: parameters.new_string,
617
+ });
618
+ } else if (name === "Bash" && typeof parameters.command === "string") {
619
+ contents.push({
620
+ type: "content",
621
+ content: {
622
+ type: "text",
623
+ text: parameters.command,
624
+ },
625
+ });
626
+ } else if (name === EXIT_PLAN_MODE_TOOL_NAME && planContent) {
627
+ contents.push({
628
+ type: "content",
629
+ content: {
630
+ type: "text",
631
+ text: planContent,
632
+ },
633
+ });
634
+ } else if (
635
+ name === ASK_USER_QUESTION_TOOL_NAME &&
636
+ Array.isArray(parameters.questions)
637
+ ) {
638
+ const markdown = (parameters.questions as AskUserQuestion[])
639
+ .map((q, i) => {
640
+ let text = `### Question ${i + 1}\n${q.question}\n`;
641
+ if (Array.isArray(q.options)) {
642
+ text += q.options
643
+ .map(
644
+ (opt: AskUserQuestionOption) =>
645
+ `- ${opt.label}${opt.description ? `: ${opt.description}` : ""}`,
646
+ )
647
+ .join("\n");
648
+ }
649
+ return text;
650
+ })
651
+ .join("\n\n");
652
+ contents.push({
653
+ type: "content",
654
+ content: {
655
+ type: "text",
656
+ text: markdown,
657
+ },
682
658
  });
683
659
  }
684
660
  }
685
661
 
662
+ if (shortResult) {
663
+ contents.push({
664
+ type: "content",
665
+ content: {
666
+ type: "text",
667
+ text: shortResult,
668
+ },
669
+ });
670
+ }
671
+
686
672
  return contents.length > 0 ? contents : undefined;
687
673
  }
688
674
 
@@ -828,7 +814,11 @@ export class WaveAcpAgent implements AcpAgent {
828
814
 
829
815
  const content =
830
816
  effectiveName && (parsedParameters || effectiveShortResult)
831
- ? this.getToolContent(effectiveName, parsedParameters)
817
+ ? this.getToolContent(
818
+ effectiveName,
819
+ parsedParameters,
820
+ effectiveShortResult,
821
+ )
832
822
  : undefined;
833
823
  const locations =
834
824
  effectiveName && parsedParameters
@@ -144,6 +144,7 @@ export const ChatInterface: React.FC = () => {
144
144
  <ConfirmationDetails
145
145
  toolName={confirmingTool!.name}
146
146
  toolInput={confirmingTool!.input}
147
+ planContent={confirmingTool!.planContent}
147
148
  isExpanded={isExpanded}
148
149
  onHeightMeasured={handleDetailsHeightMeasured}
149
150
  isStatic={isConfirmationTooTall}
@@ -38,6 +38,7 @@ const getActionDescription = (
38
38
  export interface ConfirmationDetailsProps {
39
39
  toolName: string;
40
40
  toolInput?: Record<string, unknown>;
41
+ planContent?: string;
41
42
  isExpanded?: boolean;
42
43
  onHeightMeasured?: (height: number) => void;
43
44
  isStatic?: boolean;
@@ -46,6 +47,7 @@ export interface ConfirmationDetailsProps {
46
47
  export const ConfirmationDetails: React.FC<ConfirmationDetailsProps> = ({
47
48
  toolName,
48
49
  toolInput,
50
+ planContent,
49
51
  isExpanded = false,
50
52
  onHeightMeasured,
51
53
  isStatic = false,
@@ -87,11 +89,8 @@ export const ConfirmationDetails: React.FC<ConfirmationDetailsProps> = ({
87
89
 
88
90
  {toolName !== ASK_USER_QUESTION_TOOL_NAME &&
89
91
  toolName === EXIT_PLAN_MODE_TOOL_NAME &&
90
- !!toolInput?.plan_content && (
91
- <PlanDisplay
92
- plan={toolInput.plan_content as string}
93
- isExpanded={isExpanded}
94
- />
92
+ !!planContent && (
93
+ <PlanDisplay plan={planContent} isExpanded={isExpanded} />
95
94
  )}
96
95
  </Box>
97
96
  );
@@ -84,12 +84,14 @@ export interface ChatContextType {
84
84
  input?: Record<string, unknown>;
85
85
  suggestedPrefix?: string;
86
86
  hidePersistentOption?: boolean;
87
+ planContent?: string;
87
88
  };
88
89
  showConfirmation: (
89
90
  toolName: string,
90
91
  toolInput?: Record<string, unknown>,
91
92
  suggestedPrefix?: string,
92
93
  hidePersistentOption?: boolean,
94
+ planContent?: string,
93
95
  ) => Promise<PermissionDecision>;
94
96
  hideConfirmation: () => void;
95
97
  handleConfirmationDecision: (decision: PermissionDecision) => void;
@@ -202,6 +204,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
202
204
  input?: Record<string, unknown>;
203
205
  suggestedPrefix?: string;
204
206
  hidePersistentOption?: boolean;
207
+ planContent?: string;
205
208
  }
206
209
  | undefined
207
210
  >();
@@ -211,6 +214,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
211
214
  toolInput?: Record<string, unknown>;
212
215
  suggestedPrefix?: string;
213
216
  hidePersistentOption?: boolean;
217
+ planContent?: string;
214
218
  resolver: (decision: PermissionDecision) => void;
215
219
  reject: () => void;
216
220
  }>
@@ -220,6 +224,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
220
224
  toolInput?: Record<string, unknown>;
221
225
  suggestedPrefix?: string;
222
226
  hidePersistentOption?: boolean;
227
+ planContent?: string;
223
228
  resolver: (decision: PermissionDecision) => void;
224
229
  reject: () => void;
225
230
  } | null>(null);
@@ -256,6 +261,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
256
261
  toolInput?: Record<string, unknown>,
257
262
  suggestedPrefix?: string,
258
263
  hidePersistentOption?: boolean,
264
+ planContent?: string,
259
265
  ): Promise<PermissionDecision> => {
260
266
  return new Promise<PermissionDecision>((resolve, reject) => {
261
267
  const queueItem = {
@@ -263,6 +269,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
263
269
  toolInput,
264
270
  suggestedPrefix,
265
271
  hidePersistentOption,
272
+ planContent,
266
273
  resolver: resolve,
267
274
  reject,
268
275
  };
@@ -335,6 +342,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
335
342
  context.toolInput,
336
343
  context.suggestedPrefix,
337
344
  context.hidePersistentOption,
345
+ context.planContent,
338
346
  );
339
347
  } catch {
340
348
  // If confirmation was cancelled or failed, deny the operation
@@ -554,6 +562,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
554
562
  input: next.toolInput,
555
563
  suggestedPrefix: next.suggestedPrefix,
556
564
  hidePersistentOption: next.hidePersistentOption,
565
+ planContent: next.planContent,
557
566
  });
558
567
  setIsConfirmationVisible(true);
559
568
  setConfirmationQueue((prev) => prev.slice(1));