wave-code 0.17.4 → 0.17.6

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.
@@ -2,6 +2,7 @@ import { type Agent as AcpAgent, type AgentSideConnection, type InitializeRespon
2
2
  export declare class WaveAcpAgent implements AcpAgent {
3
3
  private agents;
4
4
  private connection;
5
+ private taskCache;
5
6
  constructor(connection: AgentSideConnection);
6
7
  private getSessionModeState;
7
8
  private getSessionConfigOptions;
@@ -19,6 +20,8 @@ export declare class WaveAcpAgent implements AcpAgent {
19
20
  prompt(params: PromptRequest): Promise<PromptResponse>;
20
21
  cancel(params: CancelNotification): Promise<void>;
21
22
  private getAllowAlwaysName;
23
+ private handleAskQuestion;
24
+ private handleCreatePlan;
22
25
  private handlePermissionRequest;
23
26
  private getToolContent;
24
27
  private getToolLocations;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAyBA,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,EAOpC,MAAM,0BAA0B,CAAC;AAGlC,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;YAmCjB,gBAAgB;IASxB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAyBzC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAI5C,WAAW;IA2EnB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAalE,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAcrE,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;IAuBpC,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;IA8LrC,OAAO,CAAC,cAAc;IA6FtB,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,WAAW;YAmBL,yBAAyB;IAiIvC,OAAO,CAAC,eAAe;CAyOxB"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAyBA,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,EAOpC,MAAM,0BAA0B,CAAC;AAwBlC,qBAAa,YAAa,YAAW,QAAQ;IAC3C,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,SAAS,CAA6B;gBAElC,UAAU,EAAE,mBAAmB;IAI3C,OAAO,CAAC,mBAAmB;IAkC3B,OAAO,CAAC,uBAAuB;YAmCjB,gBAAgB;IASxB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAyBzC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAI5C,WAAW;IA2EnB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAalE,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAcrE,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;IAuBpC,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,iBAAiB;YAsEjB,gBAAgB;YAgDhB,uBAAuB;IAmNrC,OAAO,CAAC,cAAc;IA6FtB,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,WAAW;YAmBL,yBAAyB;IAiIvC,OAAO,CAAC,eAAe;CA4OxB"}
package/dist/acp/agent.js CHANGED
@@ -4,6 +4,7 @@ import { AGENT_METHODS, } from "@agentclientprotocol/sdk";
4
4
  export class WaveAcpAgent {
5
5
  constructor(connection) {
6
6
  this.agents = new Map();
7
+ this.taskCache = new Map();
7
8
  this.connection = connection;
8
9
  }
9
10
  getSessionModeState(agent) {
@@ -327,6 +328,83 @@ export class WaveAcpAgent {
327
328
  }
328
329
  return "Allow Always";
329
330
  }
331
+ async handleAskQuestion(sessionId, toolCallId, context) {
332
+ try {
333
+ const questions = context.toolInput?.questions || [];
334
+ const request = {
335
+ toolCallId,
336
+ title: questions.length === 1 ? questions[0].header : undefined,
337
+ questions: questions.map((q, qi) => ({
338
+ id: `q${qi}`,
339
+ prompt: q.question,
340
+ options: q.options.map((opt, oi) => ({
341
+ id: String(oi),
342
+ label: opt.label,
343
+ description: opt.description,
344
+ })),
345
+ allowMultiple: q.multiSelect,
346
+ })),
347
+ };
348
+ const response = await this.connection.extMethod("wave/ask_question", request);
349
+ const outcome = response.outcome;
350
+ if (outcome === "cancelled") {
351
+ return { behavior: "deny", message: "Cancelled by user" };
352
+ }
353
+ // outcome === "answered"
354
+ const answers = response.answers || [];
355
+ const answerMap = {};
356
+ for (const answer of answers) {
357
+ const qIndex = parseInt(answer.questionId.replace("q", ""), 10);
358
+ const question = questions[qIndex];
359
+ if (!question)
360
+ continue;
361
+ const selectedLabels = answer.selectedOptionIds
362
+ .map((id) => question.options[parseInt(id, 10)]?.label)
363
+ .filter(Boolean);
364
+ answerMap[question.question] = selectedLabels.join(", ");
365
+ }
366
+ return { behavior: "allow", message: JSON.stringify(answerMap) };
367
+ }
368
+ catch (error) {
369
+ logger.warn("wave/ask_question extMethod failed, falling back to requestPermission", { error });
370
+ return null;
371
+ }
372
+ }
373
+ async handleCreatePlan(sessionId, toolCallId, context) {
374
+ try {
375
+ const cachedTasks = this.taskCache.get(sessionId) || [];
376
+ const request = {
377
+ toolCallId,
378
+ plan: context.planContent || "",
379
+ todos: cachedTasks
380
+ .filter((t) => t.status !== "deleted")
381
+ .map((t) => ({
382
+ id: t.id,
383
+ content: t.subject,
384
+ status: t.status === "completed"
385
+ ? "completed"
386
+ : t.status === "in_progress"
387
+ ? "in_progress"
388
+ : "pending",
389
+ })),
390
+ };
391
+ const response = await this.connection.extMethod("wave/create_plan", request);
392
+ const outcome = response.outcome;
393
+ if (outcome === "accepted") {
394
+ return { behavior: "allow", newPermissionMode: "default" };
395
+ }
396
+ if (outcome === "rejected") {
397
+ const reason = response.reason;
398
+ return { behavior: "deny", message: reason || "Plan rejected" };
399
+ }
400
+ // cancelled or unknown outcome
401
+ return { behavior: "deny", message: "Cancelled by user" };
402
+ }
403
+ catch (error) {
404
+ logger.warn("wave/create_plan extMethod failed, falling back to requestPermission", { error });
405
+ return null;
406
+ }
407
+ }
330
408
  async handlePermissionRequest(sessionId, context) {
331
409
  logger.info(`Handling permission request for ${context.toolName} in session ${sessionId}`);
332
410
  const agent = this.agents.get(sessionId);
@@ -420,6 +498,19 @@ export class WaveAcpAgent {
420
498
  const kind = context.toolName
421
499
  ? this.getToolKind(context.toolName)
422
500
  : undefined;
501
+ // Try extension methods first, fall back to requestPermission
502
+ if (context.toolName === ASK_USER_QUESTION_TOOL_NAME) {
503
+ const extResult = await this.handleAskQuestion(sessionId, toolCallId, context);
504
+ if (extResult !== null)
505
+ return extResult;
506
+ // Fall through to existing requestPermission logic
507
+ }
508
+ if (context.toolName === EXIT_PLAN_MODE_TOOL_NAME) {
509
+ const extResult = await this.handleCreatePlan(sessionId, toolCallId, context);
510
+ if (extResult !== null)
511
+ return extResult;
512
+ // Fall through to existing requestPermission logic
513
+ }
423
514
  try {
424
515
  const response = await this.connection.requestPermission({
425
516
  sessionId: sessionId,
@@ -842,11 +933,14 @@ export class WaveAcpAgent {
842
933
  }
843
934
  },
844
935
  onTasksChange: (tasks) => {
936
+ this.taskCache.set(sessionId, tasks);
845
937
  this.connection.sessionUpdate({
846
938
  sessionId: sessionId,
847
939
  update: {
848
940
  sessionUpdate: "plan",
849
- entries: tasks.map((task) => ({
941
+ entries: tasks
942
+ .filter((t) => t.status !== "deleted")
943
+ .map((task) => ({
850
944
  content: task.subject,
851
945
  status: task.status === "completed"
852
946
  ? "completed"
@@ -1 +1 @@
1
- {"version":3,"file":"BtwDisplay.d.ts","sourceRoot":"","sources":["../../src/components/BtwDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,UAAU,eAAe;IACvB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAuBhD,CAAC"}
1
+ {"version":3,"file":"BtwDisplay.d.ts","sourceRoot":"","sources":["../../src/components/BtwDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,UAAU,eAAe;IACvB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0BhD,CAAC"}
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from "ink";
3
3
  import { Markdown } from "./Markdown.js";
4
4
  export const BtwDisplay = ({ btwState }) => {
5
- if (!btwState.isActive) {
5
+ if (!btwState.question) {
6
6
  return null;
7
7
  }
8
- return (_jsxs(Box, { flexDirection: "column", marginTop: 0, marginBottom: 0, children: [btwState.question && (_jsxs(Box, { children: [_jsx(Text, { color: btwState.isLoading ? "yellow" : "green", children: "/ " }), _jsxs(Text, { italic: true, color: "gray", children: ["btw ", btwState.question] })] })), btwState.answer && (_jsx(Box, { flexDirection: "column", children: _jsx(Markdown, { children: btwState.answer }) }))] }));
8
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 0, marginBottom: 0, children: [btwState.question && (_jsxs(Box, { children: [_jsx(Text, { color: btwState.isLoading ? "yellow" : "green", children: "/ " }), _jsxs(Text, { italic: true, color: "gray", children: ["btw ", btwState.question] })] })), btwState.answer && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Markdown, { children: btwState.answer }), _jsx(Text, { color: "gray", dimColor: true, children: "ESC to dismiss" })] }))] }));
9
9
  };
@@ -1 +1 @@
1
- {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAoB9D,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,CACZ,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,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAEjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoU5C,CAAC"}
1
+ {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAoB9D,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,CACZ,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,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAEjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA8T5C,CAAC"}
@@ -136,12 +136,14 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
136
136
  if (showModelSelector) {
137
137
  return (_jsx(ModelSelector, { onCancel: () => setShowModelSelector(false), currentModel: currentModel, configuredModels: configuredModels, onSelectModel: setModel }));
138
138
  }
139
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BtwDisplay, { btwState: btwState }), showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, isLoading: isFileSearching, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showHistorySearch && (_jsx(HistorySearch, { searchQuery: historySearchQuery, onSelect: handleHistorySearchSelect, onCancel: handleCancelHistorySearch })), showBackgroundTaskManager && (_jsx(BackgroundTaskManager, { onCancel: () => setShowBackgroundTaskManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showWorkflowManager && (_jsx(WorkflowManager, { onCancel: () => setShowWorkflowManager(false) })), showBackgroundTaskManager ||
140
- showMcpManager ||
141
- showRewindManager ||
142
- showHelp ||
143
- showStatusCommand ||
144
- showLoginCommand ||
145
- showPluginManager ||
146
- showWorkflowManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: btwState.isActive ? "cyan" : "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: btwState.isActive && isPlaceholder ? (_jsxs(_Fragment, { children: [_jsx(Text, { backgroundColor: "white", color: "black", children: " " }), _jsx(Text, { color: "cyan", children: "Type your side question..." })] })) : shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(StatusLine, { permissionMode: permissionMode, isShellCommand: isShellCommand, isBtwActive: btwState.isActive, isGoalActive: isGoalActive, goalElapsed: goalElapsed, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens })] }))] }));
139
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BtwDisplay, { btwState: btwState }), showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, isLoading: isFileSearching, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showHistorySearch && (_jsx(HistorySearch, { searchQuery: historySearchQuery, onSelect: handleHistorySearchSelect, onCancel: handleCancelHistorySearch })), showBackgroundTaskManager && (_jsx(BackgroundTaskManager, { onCancel: () => setShowBackgroundTaskManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showWorkflowManager && (_jsx(WorkflowManager, { onCancel: () => setShowWorkflowManager(false) })), btwState.question
140
+ ? null
141
+ : showBackgroundTaskManager ||
142
+ showMcpManager ||
143
+ showRewindManager ||
144
+ showHelp ||
145
+ showStatusCommand ||
146
+ showLoginCommand ||
147
+ showPluginManager ||
148
+ showWorkflowManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(StatusLine, { permissionMode: permissionMode, isShellCommand: isShellCommand, isGoalActive: isGoalActive, goalElapsed: goalElapsed, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens })] }))] }));
147
149
  };
@@ -2,7 +2,6 @@ import React from "react";
2
2
  export interface StatusLineProps {
3
3
  permissionMode: string;
4
4
  isShellCommand: boolean;
5
- isBtwActive: boolean;
6
5
  isGoalActive?: boolean;
7
6
  goalElapsed?: string;
8
7
  latestTotalTokens?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../src/components/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0DhD,CAAC"}
1
+ {"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../src/components/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAqDhD,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from "ink";
3
- export const StatusLine = ({ permissionMode, isShellCommand, isBtwActive, isGoalActive, goalElapsed, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
3
+ export const StatusLine = ({ permissionMode, isShellCommand, isGoalActive, goalElapsed, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
4
4
  const percentage = latestTotalTokens > 0
5
5
  ? Math.min(Math.round((latestTotalTokens / maxInputTokens) * 100), 100)
6
6
  : 0;
7
7
  const contextColor = percentage > 95 ? "red" : percentage > 80 ? "yellow" : "gray";
8
- return (_jsxs(Box, { paddingRight: 1, justifyContent: "space-between", width: "100%", children: [isBtwActive ? (_jsxs(Text, { color: "gray", children: ["Mode: ", _jsx(Text, { color: "cyan", children: "BTW" }), " (ESC to dismiss)"] })) : isShellCommand ? (_jsxs(Text, { color: "gray", children: ["Shell: ", _jsx(Text, { color: "yellow", children: "Run shell command" })] })) : (_jsxs(Box, { children: [isGoalActive && (_jsxs(Text, { color: "gray", children: [_jsx(Text, { color: "cyan", children: "\u25CE /goal" }), " active", " ", goalElapsed && _jsxs(Text, { children: ["(", goalElapsed, ")"] }), " |", " "] })), _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan"
8
+ return (_jsxs(Box, { paddingRight: 1, justifyContent: "space-between", width: "100%", children: [isShellCommand ? (_jsxs(Text, { color: "gray", children: ["Shell: ", _jsx(Text, { color: "yellow", children: "Run shell command" })] })) : (_jsxs(Box, { children: [isGoalActive && (_jsxs(Text, { color: "gray", children: [_jsx(Text, { color: "cyan", children: "\u25CE /goal" }), " active", " ", goalElapsed && _jsxs(Text, { children: ["(", goalElapsed, ")"] }), " |", " "] })), _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan"
9
9
  ? "yellow"
10
10
  : permissionMode === "bypassPermissions"
11
11
  ? "red"
@@ -1 +1 @@
1
- {"version":3,"file":"useInputManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useInputManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAGL,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,cAAc,EACd,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAGxB,eAAO,MAAM,eAAe,GAC1B,YAAW,OAAO,CAAC,qBAAqB,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;+BAqVA,MAAM;;;;;qCAoBA,MAAM;iCAIV,MAAM;;mCAQJ,MAAM;oCAK1C,MAAM;wCAQmC,MAAM;mCAIX,MAAM;mCAIN,MAAM;;sCAQH,MAAM;uCAK7C,MAAM;uCAMkC,WAAW;;iCASxD,MAAM;yCAcyC,OAAO;8BAIlB,OAAO;iCAIJ,OAAO;wBAIhB,OAAO;iCAIE,OAAO;gCAIR,OAAO;iCAIN,OAAO;iCAIP,OAAO;mCAIL,OAAO;8BAKhD,cAAc;2BAQX,OAAO,CAAC,OAAO,6BAA6B,EAAE,QAAQ,CAAC;0BAM1B,MAAM,YAAY,MAAM;2BAIvB,MAAM;;;8BAatC,MAAM;;uCA2BP,MAAM;;yBAYJ,MAAM,OACR,GAAG,mBACS,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,gBACxD,MAAM,IAAI;yBAtHY,MAAM;kCAIG,MAAM;;CAmOxD,CAAC"}
1
+ {"version":3,"file":"useInputManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useInputManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAGL,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,cAAc,EACd,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAGxB,eAAO,MAAM,eAAe,GAC1B,YAAW,OAAO,CAAC,qBAAqB,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;+BAgTA,MAAM;;;;;qCAoBA,MAAM;iCAIV,MAAM;;mCAQJ,MAAM;oCAK1C,MAAM;wCAQmC,MAAM;mCAIX,MAAM;mCAIN,MAAM;;sCAQH,MAAM;uCAK7C,MAAM;uCAMkC,WAAW;;iCASxD,MAAM;yCAcyC,OAAO;8BAIlB,OAAO;iCAIJ,OAAO;wBAIhB,OAAO;iCAIE,OAAO;gCAIR,OAAO;iCAIN,OAAO;iCAIP,OAAO;mCAIL,OAAO;8BAKhD,cAAc;2BAQX,OAAO,CAAC,OAAO,6BAA6B,EAAE,QAAQ,CAAC;0BAM1B,MAAM,YAAY,MAAM;2BAIvB,MAAM;;;8BAatC,MAAM;;uCA2BP,MAAM;;yBAYJ,MAAM,OACR,GAAG,mBACS,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,gBACxD,MAAM,IAAI;yBAtHY,MAAM;kCAIG,MAAM;;CAmOxD,CAAC"}
@@ -165,12 +165,6 @@ export const useInputManager = (callbacks = {}) => {
165
165
  else if (command === "workflows") {
166
166
  dispatch({ type: "SET_SHOW_WORKFLOW_MANAGER", payload: true });
167
167
  }
168
- else if (command === "btw") {
169
- dispatch({
170
- type: "SET_BTW_STATE",
171
- payload: { isActive: true, question: "", isLoading: false },
172
- });
173
- }
174
168
  }
175
169
  break;
176
170
  case "RECALL_QUEUED_MESSAGE":
@@ -248,38 +242,7 @@ export const useInputManager = (callbacks = {}) => {
248
242
  useEffect(() => {
249
243
  onImagesStateChange?.(state.attachedImages);
250
244
  }, [state.attachedImages, onImagesStateChange]);
251
- // Handle /btw side question
252
- useEffect(() => {
253
- if (state.btwState.isActive &&
254
- state.btwState.isLoading &&
255
- state.btwState.question) {
256
- const askBtw = async () => {
257
- try {
258
- const answer = await onAskBtw?.(state.btwState.question);
259
- dispatch({
260
- type: "SET_BTW_STATE",
261
- payload: { answer, isLoading: false },
262
- });
263
- }
264
- catch (error) {
265
- console.error("Failed to ask side question:", error);
266
- dispatch({
267
- type: "SET_BTW_STATE",
268
- payload: {
269
- answer: "Error: Failed to get an answer for your side question.",
270
- isLoading: false,
271
- },
272
- });
273
- }
274
- };
275
- askBtw();
276
- }
277
- }, [
278
- state.btwState.isActive,
279
- state.btwState.isLoading,
280
- state.btwState.question,
281
- onAskBtw,
282
- ]);
245
+ // /btw side question is handled via pendingEffect "ASK_BTW" above
283
246
  // Methods
284
247
  const insertTextAtCursor = useCallback((text) => {
285
248
  dispatch({ type: "INSERT_TEXT", payload: text });
@@ -1 +1 @@
1
- {"version":3,"file":"inputHandlers.d.ts","sourceRoot":"","sources":["../../src/managers/inputHandlers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inputHandlers.d.ts","sourceRoot":"","sources":["../../src/managers/inputHandlers.ts"],"names":[],"mappings":"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"}
@@ -273,12 +273,6 @@ export const handleCommandSelect = (state, dispatch, callbacks, command) => {
273
273
  else if (command === "workflows") {
274
274
  dispatch({ type: "SET_SHOW_WORKFLOW_MANAGER", payload: true });
275
275
  }
276
- else if (command === "btw") {
277
- dispatch({
278
- type: "SET_BTW_STATE",
279
- payload: { isActive: true, question: "", isLoading: false },
280
- });
281
- }
282
276
  }
283
277
  })();
284
278
  dispatch({ type: "CANCEL_COMMAND_SELECTOR" });
@@ -507,35 +501,17 @@ export const handleNormalInput = async (state, dispatch, callbacks, input, key,
507
501
  return false;
508
502
  };
509
503
  export const handleInput = async (state, dispatch, callbacks, input, key, clearImages) => {
510
- if (state.btwState.isActive) {
511
- if (key.escape) {
512
- dispatch({
513
- type: "SET_BTW_STATE",
514
- payload: {
515
- isActive: false,
516
- question: "",
517
- answer: undefined,
518
- isLoading: false,
519
- },
520
- });
521
- return true;
522
- }
523
- if (key.return) {
524
- if (state.inputText.trim() && !state.btwState.isLoading) {
525
- dispatch({
526
- type: "SET_BTW_STATE",
527
- payload: {
528
- question: state.inputText.trim(),
529
- isLoading: true,
530
- answer: undefined,
531
- },
532
- });
533
- dispatch({ type: "CLEAR_INPUT" });
534
- }
535
- return true;
536
- }
537
- // Handle normal input for the question
538
- return await handleNormalInput(state, dispatch, callbacks, input, key, clearImages);
504
+ // Handle ESC to dismiss btw answer
505
+ if (key.escape && state.btwState.question && !state.btwState.isLoading) {
506
+ dispatch({
507
+ type: "SET_BTW_STATE",
508
+ payload: {
509
+ question: "",
510
+ answer: undefined,
511
+ isLoading: false,
512
+ },
513
+ });
514
+ return true;
539
515
  }
540
516
  if (key.escape) {
541
517
  if (!(state.showFileSelector ||
@@ -548,8 +524,7 @@ export const handleInput = async (state, dispatch, callbacks, input, key, clearI
548
524
  state.showStatusCommand ||
549
525
  state.showPluginManager ||
550
526
  state.showModelSelector ||
551
- state.showWorkflowManager ||
552
- state.btwState.isActive)) {
527
+ state.showWorkflowManager)) {
553
528
  callbacks.onAbortMessage?.();
554
529
  return true;
555
530
  }
@@ -568,8 +543,7 @@ export const handleInput = async (state, dispatch, callbacks, input, key, clearI
568
543
  state.showStatusCommand ||
569
544
  state.showPluginManager ||
570
545
  state.showModelSelector ||
571
- state.showWorkflowManager ||
572
- state.btwState.isActive) {
546
+ state.showWorkflowManager) {
573
547
  if (state.showBackgroundTaskManager ||
574
548
  state.showMcpManager ||
575
549
  state.showRewindManager ||
@@ -577,8 +551,7 @@ export const handleInput = async (state, dispatch, callbacks, input, key, clearI
577
551
  state.showStatusCommand ||
578
552
  state.showPluginManager ||
579
553
  state.showModelSelector ||
580
- state.showWorkflowManager ||
581
- state.btwState.isActive) {
554
+ state.showWorkflowManager) {
582
555
  return true;
583
556
  }
584
557
  if (state.showHistorySearch) {
@@ -6,7 +6,6 @@ export interface AttachedImage {
6
6
  mimeType: string;
7
7
  }
8
8
  export interface BtwState {
9
- isActive: boolean;
10
9
  question: string;
11
10
  answer?: string;
12
11
  isLoading: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"inputReducer.d.ts","sourceRoot":"","sources":["../../src/managers/inputReducer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inputReducer.d.ts","sourceRoot":"","sources":["../../src/managers/inputReducer.ts"],"names":[],"mappings":"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"}
@@ -36,7 +36,6 @@ export const initialState = {
36
36
  originalLongTextMap: {},
37
37
  isFileSearching: false,
38
38
  btwState: {
39
- isActive: false,
40
39
  question: "",
41
40
  isLoading: false,
42
41
  },
@@ -466,40 +465,19 @@ export function inputReducer(state, action) {
466
465
  case "HANDLE_KEY": {
467
466
  const { input, key } = action.payload;
468
467
  const hasQueuedMessages = action.payload.hasQueuedMessages ?? false;
469
- // 1. BTW State Handling
470
- if (state.btwState.isActive) {
471
- if (key.escape) {
468
+ // 1. Escape Handling
469
+ if (key.escape) {
470
+ // Dismiss btw answer
471
+ if (state.btwState.question && !state.btwState.isLoading) {
472
472
  return {
473
473
  ...state,
474
474
  btwState: {
475
- isActive: false,
476
475
  question: "",
477
476
  answer: undefined,
478
477
  isLoading: false,
479
478
  },
480
479
  };
481
480
  }
482
- if (key.return) {
483
- const question = state.inputText.trim();
484
- if (question && !state.btwState.isLoading) {
485
- return {
486
- ...state,
487
- inputText: "",
488
- cursorPosition: 0,
489
- btwState: {
490
- ...state.btwState,
491
- question,
492
- isLoading: true,
493
- answer: undefined,
494
- },
495
- pendingEffect: { type: "ASK_BTW", question },
496
- };
497
- }
498
- return state;
499
- }
500
- }
501
- // 2. Escape Handling
502
- if (key.escape) {
503
481
  if (state.showFileSelector) {
504
482
  return {
505
483
  ...state,
@@ -748,11 +726,12 @@ export function inputReducer(state, action) {
748
726
  const contentWithPlaceholders = state.inputText
749
727
  .replace(imageRegex, "")
750
728
  .trim();
751
- if (contentWithPlaceholders === "/btw" ||
752
- contentWithPlaceholders.startsWith("/btw ")) {
753
- const question = contentWithPlaceholders.startsWith("/btw ")
754
- ? contentWithPlaceholders.substring(5).trim()
755
- : "";
729
+ if (contentWithPlaceholders.startsWith("/btw ")) {
730
+ const question = contentWithPlaceholders.substring(5).trim();
731
+ if (!question) {
732
+ // Bare /btw with no question text — ignore
733
+ return state;
734
+ }
756
735
  return {
757
736
  ...state,
758
737
  inputText: "",
@@ -760,14 +739,17 @@ export function inputReducer(state, action) {
760
739
  historyIndex: -1,
761
740
  longTextMap: {},
762
741
  btwState: {
763
- isActive: true,
764
742
  question,
765
- isLoading: question !== "",
743
+ isLoading: true,
766
744
  answer: undefined,
767
745
  },
768
- pendingEffect: question ? { type: "ASK_BTW", question } : null,
746
+ pendingEffect: { type: "ASK_BTW", question },
769
747
  };
770
748
  }
749
+ if (contentWithPlaceholders === "/btw") {
750
+ // Bare /btw — ignore
751
+ return state;
752
+ }
771
753
  // Check if the content is a CLI-internal slash command (help, tasks,
772
754
  // etc.) that should be executed locally rather than sent as a message.
773
755
  // Agent slash commands and unknown /commands always go to SEND_MESSAGE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-code",
3
- "version": "0.17.4",
3
+ "version": "0.17.6",
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.17.4"
45
+ "wave-agent-sdk": "0.17.6"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/react": "^19.1.8",
package/src/acp/agent.ts CHANGED
@@ -58,9 +58,31 @@ import {
58
58
  } from "@agentclientprotocol/sdk";
59
59
  import type { McpServerConfig, McpServerStatus } from "wave-agent-sdk";
60
60
 
61
+ interface WaveAskQuestionRequest {
62
+ toolCallId: string;
63
+ title?: string;
64
+ questions: Array<{
65
+ id: string;
66
+ prompt: string;
67
+ options: Array<{ id: string; label: string; description?: string }>;
68
+ allowMultiple?: boolean;
69
+ }>;
70
+ }
71
+
72
+ interface WaveCreatePlanRequest {
73
+ toolCallId: string;
74
+ plan: string;
75
+ todos?: Array<{
76
+ id: string;
77
+ content: string;
78
+ status: "pending" | "in_progress" | "completed";
79
+ }>;
80
+ }
81
+
61
82
  export class WaveAcpAgent implements AcpAgent {
62
83
  private agents: Map<string, WaveAgent> = new Map();
63
84
  private connection: AgentSideConnection;
85
+ private taskCache = new Map<string, Task[]>();
64
86
 
65
87
  constructor(connection: AgentSideConnection) {
66
88
  this.connection = connection;
@@ -458,6 +480,124 @@ export class WaveAcpAgent implements AcpAgent {
458
480
  return "Allow Always";
459
481
  }
460
482
 
483
+ private async handleAskQuestion(
484
+ sessionId: string,
485
+ toolCallId: string,
486
+ context: ToolPermissionContext,
487
+ ): Promise<PermissionDecision | null> {
488
+ try {
489
+ const questions =
490
+ (context.toolInput?.questions as Array<{
491
+ question: string;
492
+ header?: string;
493
+ options: Array<{ label: string; description?: string }>;
494
+ multiSelect?: boolean;
495
+ }>) || [];
496
+
497
+ const request: WaveAskQuestionRequest = {
498
+ toolCallId,
499
+ title: questions.length === 1 ? questions[0].header : undefined,
500
+ questions: questions.map((q, qi) => ({
501
+ id: `q${qi}`,
502
+ prompt: q.question,
503
+ options: q.options.map((opt, oi) => ({
504
+ id: String(oi),
505
+ label: opt.label,
506
+ description: opt.description,
507
+ })),
508
+ allowMultiple: q.multiSelect,
509
+ })),
510
+ };
511
+
512
+ const response = await this.connection.extMethod(
513
+ "wave/ask_question",
514
+ request as unknown as Record<string, unknown>,
515
+ );
516
+
517
+ const outcome = (response as { outcome?: string }).outcome;
518
+ if (outcome === "cancelled") {
519
+ return { behavior: "deny", message: "Cancelled by user" };
520
+ }
521
+
522
+ // outcome === "answered"
523
+ const answers =
524
+ (
525
+ response as {
526
+ answers?: Array<{
527
+ questionId: string;
528
+ selectedOptionIds: string[];
529
+ }>;
530
+ }
531
+ ).answers || [];
532
+ const answerMap: Record<string, string> = {};
533
+ for (const answer of answers) {
534
+ const qIndex = parseInt(answer.questionId.replace("q", ""), 10);
535
+ const question = questions[qIndex];
536
+ if (!question) continue;
537
+ const selectedLabels = answer.selectedOptionIds
538
+ .map((id) => question.options[parseInt(id, 10)]?.label)
539
+ .filter(Boolean);
540
+ answerMap[question.question] = selectedLabels.join(", ");
541
+ }
542
+
543
+ return { behavior: "allow", message: JSON.stringify(answerMap) };
544
+ } catch (error) {
545
+ logger.warn(
546
+ "wave/ask_question extMethod failed, falling back to requestPermission",
547
+ { error },
548
+ );
549
+ return null;
550
+ }
551
+ }
552
+
553
+ private async handleCreatePlan(
554
+ sessionId: string,
555
+ toolCallId: string,
556
+ context: ToolPermissionContext,
557
+ ): Promise<PermissionDecision | null> {
558
+ try {
559
+ const cachedTasks = this.taskCache.get(sessionId) || [];
560
+ const request: WaveCreatePlanRequest = {
561
+ toolCallId,
562
+ plan: context.planContent || "",
563
+ todos: cachedTasks
564
+ .filter((t) => t.status !== "deleted")
565
+ .map((t) => ({
566
+ id: t.id,
567
+ content: t.subject,
568
+ status:
569
+ t.status === "completed"
570
+ ? ("completed" as const)
571
+ : t.status === "in_progress"
572
+ ? ("in_progress" as const)
573
+ : ("pending" as const),
574
+ })),
575
+ };
576
+
577
+ const response = await this.connection.extMethod(
578
+ "wave/create_plan",
579
+ request as unknown as Record<string, unknown>,
580
+ );
581
+
582
+ const outcome = (response as { outcome?: string }).outcome;
583
+ if (outcome === "accepted") {
584
+ return { behavior: "allow", newPermissionMode: "default" };
585
+ }
586
+ if (outcome === "rejected") {
587
+ const reason = (response as { reason?: string }).reason;
588
+ return { behavior: "deny", message: reason || "Plan rejected" };
589
+ }
590
+ // cancelled or unknown outcome
591
+ return { behavior: "deny", message: "Cancelled by user" };
592
+ } catch (error) {
593
+ logger.warn(
594
+ "wave/create_plan extMethod failed, falling back to requestPermission",
595
+ { error },
596
+ );
597
+ return null;
598
+ }
599
+ }
600
+
461
601
  private async handlePermissionRequest(
462
602
  sessionId: string,
463
603
  context: ToolPermissionContext,
@@ -573,6 +713,27 @@ export class WaveAcpAgent implements AcpAgent {
573
713
  ? this.getToolKind(context.toolName)
574
714
  : undefined;
575
715
 
716
+ // Try extension methods first, fall back to requestPermission
717
+ if (context.toolName === ASK_USER_QUESTION_TOOL_NAME) {
718
+ const extResult = await this.handleAskQuestion(
719
+ sessionId,
720
+ toolCallId,
721
+ context,
722
+ );
723
+ if (extResult !== null) return extResult;
724
+ // Fall through to existing requestPermission logic
725
+ }
726
+
727
+ if (context.toolName === EXIT_PLAN_MODE_TOOL_NAME) {
728
+ const extResult = await this.handleCreatePlan(
729
+ sessionId,
730
+ toolCallId,
731
+ context,
732
+ );
733
+ if (extResult !== null) return extResult;
734
+ // Fall through to existing requestPermission logic
735
+ }
736
+
576
737
  try {
577
738
  const response = await this.connection.requestPermission({
578
739
  sessionId: sessionId as AcpSessionId,
@@ -1081,20 +1242,23 @@ export class WaveAcpAgent implements AcpAgent {
1081
1242
  }
1082
1243
  },
1083
1244
  onTasksChange: (tasks) => {
1245
+ this.taskCache.set(sessionId, tasks);
1084
1246
  this.connection.sessionUpdate({
1085
1247
  sessionId: sessionId as AcpSessionId,
1086
1248
  update: {
1087
1249
  sessionUpdate: "plan",
1088
- entries: tasks.map((task) => ({
1089
- content: task.subject,
1090
- status:
1091
- task.status === "completed"
1092
- ? "completed"
1093
- : task.status === "in_progress"
1094
- ? "in_progress"
1095
- : "pending",
1096
- priority: "medium",
1097
- })),
1250
+ entries: tasks
1251
+ .filter((t) => t.status !== "deleted")
1252
+ .map((task) => ({
1253
+ content: task.subject,
1254
+ status:
1255
+ task.status === "completed"
1256
+ ? "completed"
1257
+ : task.status === "in_progress"
1258
+ ? "in_progress"
1259
+ : "pending",
1260
+ priority: "medium" as const,
1261
+ })),
1098
1262
  },
1099
1263
  });
1100
1264
  },
@@ -8,7 +8,7 @@ interface BtwDisplayProps {
8
8
  }
9
9
 
10
10
  export const BtwDisplay: React.FC<BtwDisplayProps> = ({ btwState }) => {
11
- if (!btwState.isActive) {
11
+ if (!btwState.question) {
12
12
  return null;
13
13
  }
14
14
 
@@ -26,6 +26,9 @@ export const BtwDisplay: React.FC<BtwDisplayProps> = ({ btwState }) => {
26
26
  {btwState.answer && (
27
27
  <Box flexDirection="column">
28
28
  <Markdown>{btwState.answer}</Markdown>
29
+ <Text color="gray" dimColor>
30
+ ESC to dismiss
31
+ </Text>
29
32
  </Box>
30
33
  )}
31
34
  </Box>
@@ -328,53 +328,47 @@ export const InputBox: React.FC<InputBoxProps> = ({
328
328
  <WorkflowManager onCancel={() => setShowWorkflowManager(false)} />
329
329
  )}
330
330
 
331
- {showBackgroundTaskManager ||
332
- showMcpManager ||
333
- showRewindManager ||
334
- showHelp ||
335
- showStatusCommand ||
336
- showLoginCommand ||
337
- showPluginManager ||
338
- showWorkflowManager || (
339
- <Box flexDirection="column">
340
- <Box
341
- borderStyle="single"
342
- borderColor={btwState.isActive ? "cyan" : "gray"}
343
- borderLeft={false}
344
- borderRight={false}
345
- >
346
- <Text color={isPlaceholder ? "gray" : "white"}>
347
- {btwState.isActive && isPlaceholder ? (
348
- <>
349
- <Text backgroundColor="white" color="black">
350
- {" "}
351
- </Text>
352
- <Text color="cyan">Type your side question...</Text>
353
- </>
354
- ) : shouldShowCursor ? (
355
- <>
356
- {beforeCursor}
357
- <Text backgroundColor="white" color="black">
358
- {atCursor}
359
- </Text>
360
- {afterCursor}
361
- </>
362
- ) : (
363
- displayText
364
- )}
365
- </Text>
331
+ {btwState.question
332
+ ? null
333
+ : showBackgroundTaskManager ||
334
+ showMcpManager ||
335
+ showRewindManager ||
336
+ showHelp ||
337
+ showStatusCommand ||
338
+ showLoginCommand ||
339
+ showPluginManager ||
340
+ showWorkflowManager || (
341
+ <Box flexDirection="column">
342
+ <Box
343
+ borderStyle="single"
344
+ borderColor="gray"
345
+ borderLeft={false}
346
+ borderRight={false}
347
+ >
348
+ <Text color={isPlaceholder ? "gray" : "white"}>
349
+ {shouldShowCursor ? (
350
+ <>
351
+ {beforeCursor}
352
+ <Text backgroundColor="white" color="black">
353
+ {atCursor}
354
+ </Text>
355
+ {afterCursor}
356
+ </>
357
+ ) : (
358
+ displayText
359
+ )}
360
+ </Text>
361
+ </Box>
362
+ <StatusLine
363
+ permissionMode={permissionMode}
364
+ isShellCommand={isShellCommand}
365
+ isGoalActive={isGoalActive}
366
+ goalElapsed={goalElapsed}
367
+ latestTotalTokens={latestTotalTokens}
368
+ maxInputTokens={maxInputTokens}
369
+ />
366
370
  </Box>
367
- <StatusLine
368
- permissionMode={permissionMode}
369
- isShellCommand={isShellCommand}
370
- isBtwActive={btwState.isActive}
371
- isGoalActive={isGoalActive}
372
- goalElapsed={goalElapsed}
373
- latestTotalTokens={latestTotalTokens}
374
- maxInputTokens={maxInputTokens}
375
- />
376
- </Box>
377
- )}
371
+ )}
378
372
  </Box>
379
373
  );
380
374
  };
@@ -4,7 +4,6 @@ import { Box, Text } from "ink";
4
4
  export interface StatusLineProps {
5
5
  permissionMode: string;
6
6
  isShellCommand: boolean;
7
- isBtwActive: boolean;
8
7
  isGoalActive?: boolean;
9
8
  goalElapsed?: string;
10
9
  latestTotalTokens?: number;
@@ -14,7 +13,6 @@ export interface StatusLineProps {
14
13
  export const StatusLine: React.FC<StatusLineProps> = ({
15
14
  permissionMode,
16
15
  isShellCommand,
17
- isBtwActive,
18
16
  isGoalActive,
19
17
  goalElapsed,
20
18
  latestTotalTokens = 0,
@@ -30,11 +28,7 @@ export const StatusLine: React.FC<StatusLineProps> = ({
30
28
 
31
29
  return (
32
30
  <Box paddingRight={1} justifyContent="space-between" width="100%">
33
- {isBtwActive ? (
34
- <Text color="gray">
35
- Mode: <Text color="cyan">BTW</Text> (ESC to dismiss)
36
- </Text>
37
- ) : isShellCommand ? (
31
+ {isShellCommand ? (
38
32
  <Text color="gray">
39
33
  Shell: <Text color="yellow">Run shell command</Text>
40
34
  </Text>
@@ -212,11 +212,6 @@ export const useInputManager = (
212
212
  dispatch({ type: "SET_SHOW_MODEL_SELECTOR", payload: true });
213
213
  } else if (command === "workflows") {
214
214
  dispatch({ type: "SET_SHOW_WORKFLOW_MANAGER", payload: true });
215
- } else if (command === "btw") {
216
- dispatch({
217
- type: "SET_BTW_STATE",
218
- payload: { isActive: true, question: "", isLoading: false },
219
- });
220
215
  }
221
216
  }
222
217
  break;
@@ -320,39 +315,7 @@ export const useInputManager = (
320
315
  onImagesStateChange?.(state.attachedImages);
321
316
  }, [state.attachedImages, onImagesStateChange]);
322
317
 
323
- // Handle /btw side question
324
- useEffect(() => {
325
- if (
326
- state.btwState.isActive &&
327
- state.btwState.isLoading &&
328
- state.btwState.question
329
- ) {
330
- const askBtw = async () => {
331
- try {
332
- const answer = await onAskBtw?.(state.btwState.question);
333
- dispatch({
334
- type: "SET_BTW_STATE",
335
- payload: { answer, isLoading: false },
336
- });
337
- } catch (error) {
338
- console.error("Failed to ask side question:", error);
339
- dispatch({
340
- type: "SET_BTW_STATE",
341
- payload: {
342
- answer: "Error: Failed to get an answer for your side question.",
343
- isLoading: false,
344
- },
345
- });
346
- }
347
- };
348
- askBtw();
349
- }
350
- }, [
351
- state.btwState.isActive,
352
- state.btwState.isLoading,
353
- state.btwState.question,
354
- onAskBtw,
355
- ]);
318
+ // /btw side question is handled via pendingEffect "ASK_BTW" above
356
319
 
357
320
  // Methods
358
321
  const insertTextAtCursor = useCallback((text: string) => {
@@ -373,11 +373,6 @@ export const handleCommandSelect = (
373
373
  dispatch({ type: "SET_SHOW_MODEL_SELECTOR", payload: true });
374
374
  } else if (command === "workflows") {
375
375
  dispatch({ type: "SET_SHOW_WORKFLOW_MANAGER", payload: true });
376
- } else if (command === "btw") {
377
- dispatch({
378
- type: "SET_BTW_STATE",
379
- payload: { isActive: true, question: "", isLoading: false },
380
- });
381
376
  }
382
377
  }
383
378
  })();
@@ -701,44 +696,17 @@ export const handleInput = async (
701
696
  key: Key,
702
697
  clearImages?: () => void,
703
698
  ): Promise<boolean> => {
704
- if (state.btwState.isActive) {
705
- if (key.escape) {
706
- dispatch({
707
- type: "SET_BTW_STATE",
708
- payload: {
709
- isActive: false,
710
- question: "",
711
- answer: undefined,
712
- isLoading: false,
713
- },
714
- });
715
- return true;
716
- }
717
-
718
- if (key.return) {
719
- if (state.inputText.trim() && !state.btwState.isLoading) {
720
- dispatch({
721
- type: "SET_BTW_STATE",
722
- payload: {
723
- question: state.inputText.trim(),
724
- isLoading: true,
725
- answer: undefined,
726
- },
727
- });
728
- dispatch({ type: "CLEAR_INPUT" });
729
- }
730
- return true;
731
- }
732
-
733
- // Handle normal input for the question
734
- return await handleNormalInput(
735
- state,
736
- dispatch,
737
- callbacks,
738
- input,
739
- key,
740
- clearImages,
741
- );
699
+ // Handle ESC to dismiss btw answer
700
+ if (key.escape && state.btwState.question && !state.btwState.isLoading) {
701
+ dispatch({
702
+ type: "SET_BTW_STATE",
703
+ payload: {
704
+ question: "",
705
+ answer: undefined,
706
+ isLoading: false,
707
+ },
708
+ });
709
+ return true;
742
710
  }
743
711
 
744
712
  if (key.escape) {
@@ -754,8 +722,7 @@ export const handleInput = async (
754
722
  state.showStatusCommand ||
755
723
  state.showPluginManager ||
756
724
  state.showModelSelector ||
757
- state.showWorkflowManager ||
758
- state.btwState.isActive
725
+ state.showWorkflowManager
759
726
  )
760
727
  ) {
761
728
  callbacks.onAbortMessage?.();
@@ -779,8 +746,7 @@ export const handleInput = async (
779
746
  state.showStatusCommand ||
780
747
  state.showPluginManager ||
781
748
  state.showModelSelector ||
782
- state.showWorkflowManager ||
783
- state.btwState.isActive
749
+ state.showWorkflowManager
784
750
  ) {
785
751
  if (
786
752
  state.showBackgroundTaskManager ||
@@ -790,8 +756,7 @@ export const handleInput = async (
790
756
  state.showStatusCommand ||
791
757
  state.showPluginManager ||
792
758
  state.showModelSelector ||
793
- state.showWorkflowManager ||
794
- state.btwState.isActive
759
+ state.showWorkflowManager
795
760
  ) {
796
761
  return true;
797
762
  }
@@ -22,7 +22,6 @@ export interface AttachedImage {
22
22
  }
23
23
 
24
24
  export interface BtwState {
25
- isActive: boolean;
26
25
  question: string;
27
26
  answer?: string;
28
27
  isLoading: boolean;
@@ -164,7 +163,6 @@ export const initialState: InputState = {
164
163
  originalLongTextMap: {},
165
164
  isFileSearching: false,
166
165
  btwState: {
167
- isActive: false,
168
166
  question: "",
169
167
  isLoading: false,
170
168
  },
@@ -688,42 +686,19 @@ export function inputReducer(
688
686
  const { input, key } = action.payload;
689
687
  const hasQueuedMessages = action.payload.hasQueuedMessages ?? false;
690
688
 
691
- // 1. BTW State Handling
692
- if (state.btwState.isActive) {
693
- if (key.escape) {
689
+ // 1. Escape Handling
690
+ if (key.escape) {
691
+ // Dismiss btw answer
692
+ if (state.btwState.question && !state.btwState.isLoading) {
694
693
  return {
695
694
  ...state,
696
695
  btwState: {
697
- isActive: false,
698
696
  question: "",
699
697
  answer: undefined,
700
698
  isLoading: false,
701
699
  },
702
700
  };
703
701
  }
704
-
705
- if (key.return) {
706
- const question = state.inputText.trim();
707
- if (question && !state.btwState.isLoading) {
708
- return {
709
- ...state,
710
- inputText: "",
711
- cursorPosition: 0,
712
- btwState: {
713
- ...state.btwState,
714
- question,
715
- isLoading: true,
716
- answer: undefined,
717
- },
718
- pendingEffect: { type: "ASK_BTW", question },
719
- };
720
- }
721
- return state;
722
- }
723
- }
724
-
725
- // 2. Escape Handling
726
- if (key.escape) {
727
702
  if (state.showFileSelector) {
728
703
  return {
729
704
  ...state,
@@ -1017,13 +992,12 @@ export function inputReducer(
1017
992
  .replace(imageRegex, "")
1018
993
  .trim();
1019
994
 
1020
- if (
1021
- contentWithPlaceholders === "/btw" ||
1022
- contentWithPlaceholders.startsWith("/btw ")
1023
- ) {
1024
- const question = contentWithPlaceholders.startsWith("/btw ")
1025
- ? contentWithPlaceholders.substring(5).trim()
1026
- : "";
995
+ if (contentWithPlaceholders.startsWith("/btw ")) {
996
+ const question = contentWithPlaceholders.substring(5).trim();
997
+ if (!question) {
998
+ // Bare /btw with no question text — ignore
999
+ return state;
1000
+ }
1027
1001
 
1028
1002
  return {
1029
1003
  ...state,
@@ -1032,15 +1006,19 @@ export function inputReducer(
1032
1006
  historyIndex: -1,
1033
1007
  longTextMap: {},
1034
1008
  btwState: {
1035
- isActive: true,
1036
1009
  question,
1037
- isLoading: question !== "",
1010
+ isLoading: true,
1038
1011
  answer: undefined,
1039
1012
  },
1040
- pendingEffect: question ? { type: "ASK_BTW", question } : null,
1013
+ pendingEffect: { type: "ASK_BTW", question },
1041
1014
  };
1042
1015
  }
1043
1016
 
1017
+ if (contentWithPlaceholders === "/btw") {
1018
+ // Bare /btw — ignore
1019
+ return state;
1020
+ }
1021
+
1044
1022
  // Check if the content is a CLI-internal slash command (help, tasks,
1045
1023
  // etc.) that should be executed locally rather than sent as a message.
1046
1024
  // Agent slash commands and unknown /commands always go to SEND_MESSAGE.