wave-code 0.12.10 → 0.13.0
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.
- package/dist/acp/agent.d.ts.map +1 -1
- package/dist/acp/agent.js +49 -1
- package/dist/components/BangDisplay.js +2 -2
- package/dist/components/ConfirmationDetails.d.ts.map +1 -1
- package/dist/components/ConfirmationDetails.js +4 -1
- package/dist/components/ConfirmationSelector.d.ts.map +1 -1
- package/dist/components/ConfirmationSelector.js +14 -2
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +29 -6
- package/dist/components/ToolDisplay.d.ts.map +1 -1
- package/dist/components/ToolDisplay.js +7 -1
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +10 -4
- package/package.json +2 -2
- package/src/acp/agent.ts +48 -0
- package/src/components/BangDisplay.tsx +2 -2
- package/src/components/ConfirmationDetails.tsx +4 -0
- package/src/components/ConfirmationSelector.tsx +15 -1
- package/src/components/MessageList.tsx +43 -12
- package/src/components/ToolDisplay.tsx +12 -1
- package/src/contexts/useChat.tsx +19 -4
package/dist/acp/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAqBA,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;YAmCjB,gBAAgB;IASxB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAwBzC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAI5C,WAAW;IAkEnB,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;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;IAwGtB,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,eAAe;CA+MxB"}
|
package/dist/acp/agent.js
CHANGED
|
@@ -1,4 +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, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
|
|
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, ENTER_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
|
|
2
2
|
import { logger } from "../utils/logger.js";
|
|
3
3
|
import { AGENT_METHODS, } from "@agentclientprotocol/sdk";
|
|
4
4
|
export class WaveAcpAgent {
|
|
@@ -39,10 +39,13 @@ export class WaveAcpAgent {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
getSessionConfigOptions(agent) {
|
|
42
|
+
const configuredModels = agent.getConfiguredModels();
|
|
43
|
+
const currentModel = agent.getModelConfig().model;
|
|
42
44
|
return [
|
|
43
45
|
{
|
|
44
46
|
id: "permission_mode",
|
|
45
47
|
name: "Permission Mode",
|
|
48
|
+
description: "Controls how the agent requests permission",
|
|
46
49
|
type: "select",
|
|
47
50
|
category: "mode",
|
|
48
51
|
currentValue: agent.getPermissionMode(),
|
|
@@ -54,6 +57,18 @@ export class WaveAcpAgent {
|
|
|
54
57
|
{ value: "dontAsk", name: "Don't Ask" },
|
|
55
58
|
],
|
|
56
59
|
},
|
|
60
|
+
{
|
|
61
|
+
id: "model",
|
|
62
|
+
name: "Model",
|
|
63
|
+
description: "The AI model to use for this session",
|
|
64
|
+
type: "select",
|
|
65
|
+
category: "model",
|
|
66
|
+
currentValue: currentModel,
|
|
67
|
+
options: configuredModels.map((m) => ({
|
|
68
|
+
value: m,
|
|
69
|
+
name: m,
|
|
70
|
+
})),
|
|
71
|
+
},
|
|
57
72
|
];
|
|
58
73
|
}
|
|
59
74
|
async cleanupAllAgents() {
|
|
@@ -110,6 +125,7 @@ export class WaveAcpAgent {
|
|
|
110
125
|
},
|
|
111
126
|
onTasksChange: (tasks) => callbacks.onTasksChange?.(tasks),
|
|
112
127
|
onPermissionModeChange: (mode) => callbacks.onPermissionModeChange?.(mode),
|
|
128
|
+
onModelChange: (model) => callbacks.onModelChange?.(model),
|
|
113
129
|
},
|
|
114
130
|
});
|
|
115
131
|
agentRef.instance = agent;
|
|
@@ -211,6 +227,9 @@ export class WaveAcpAgent {
|
|
|
211
227
|
if (configId === "permission_mode") {
|
|
212
228
|
agent.setPermissionMode(value);
|
|
213
229
|
}
|
|
230
|
+
else if (configId === "model" && typeof value === "string") {
|
|
231
|
+
agent.setModel(value);
|
|
232
|
+
}
|
|
214
233
|
return {
|
|
215
234
|
configOptions: this.getSessionConfigOptions(agent),
|
|
216
235
|
};
|
|
@@ -366,6 +385,20 @@ export class WaveAcpAgent {
|
|
|
366
385
|
},
|
|
367
386
|
];
|
|
368
387
|
}
|
|
388
|
+
else if (context.toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
389
|
+
options = [
|
|
390
|
+
{
|
|
391
|
+
optionId: "allow_once",
|
|
392
|
+
name: "Yes, enter plan mode",
|
|
393
|
+
kind: "allow_once",
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
optionId: "reject_once",
|
|
397
|
+
name: "No, start implementing now",
|
|
398
|
+
kind: "reject_once",
|
|
399
|
+
},
|
|
400
|
+
];
|
|
401
|
+
}
|
|
369
402
|
else if (context.toolName === ASK_USER_QUESTION_TOOL_NAME) {
|
|
370
403
|
options = [];
|
|
371
404
|
}
|
|
@@ -429,6 +462,9 @@ export class WaveAcpAgent {
|
|
|
429
462
|
if (context.toolName === EXIT_PLAN_MODE_TOOL_NAME) {
|
|
430
463
|
return { behavior: "allow", newPermissionMode: "default" };
|
|
431
464
|
}
|
|
465
|
+
if (context.toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
466
|
+
return { behavior: "allow", newPermissionMode: "plan" };
|
|
467
|
+
}
|
|
432
468
|
return { behavior: "allow" };
|
|
433
469
|
case "reject_once":
|
|
434
470
|
return { behavior: "deny", message: "Rejected by user" };
|
|
@@ -729,6 +765,18 @@ export class WaveAcpAgent {
|
|
|
729
765
|
});
|
|
730
766
|
}
|
|
731
767
|
},
|
|
768
|
+
onModelChange: () => {
|
|
769
|
+
const agent = getAgent();
|
|
770
|
+
if (agent) {
|
|
771
|
+
this.connection.sessionUpdate({
|
|
772
|
+
sessionId: sessionId,
|
|
773
|
+
update: {
|
|
774
|
+
sessionUpdate: "config_option_update",
|
|
775
|
+
configOptions: this.getSessionConfigOptions(agent),
|
|
776
|
+
},
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
},
|
|
732
780
|
};
|
|
733
781
|
}
|
|
734
782
|
}
|
|
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { getLastLines } from "wave-agent-sdk";
|
|
4
4
|
export const BangDisplay = ({ block, isExpanded = false, }) => {
|
|
5
|
-
const { command, output,
|
|
5
|
+
const { command, output, stage, exitCode } = block;
|
|
6
6
|
const MAX_LINES = 3; // Set maximum display lines
|
|
7
7
|
const getStatusColor = () => {
|
|
8
|
-
if (
|
|
8
|
+
if (stage === "running")
|
|
9
9
|
return "yellow";
|
|
10
10
|
if (exitCode === 0)
|
|
11
11
|
return "green";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAyC1B,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;CACtB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAqDlE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
import { BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
|
|
3
|
+
import { BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
|
|
4
4
|
import { DiffDisplay } from "./DiffDisplay.js";
|
|
5
5
|
import { PlanDisplay } from "./PlanDisplay.js";
|
|
6
6
|
import { highlightToAnsi } from "../utils/highlightUtils.js";
|
|
@@ -18,6 +18,8 @@ const getActionDescription = (toolName, toolInput) => {
|
|
|
18
18
|
return `Write to file: ${toolInput.file_path || "unknown file"}`;
|
|
19
19
|
case EXIT_PLAN_MODE_TOOL_NAME:
|
|
20
20
|
return "Review and approve the plan";
|
|
21
|
+
case ENTER_PLAN_MODE_TOOL_NAME:
|
|
22
|
+
return "Enter plan mode for complex task planning";
|
|
21
23
|
case ASK_USER_QUESTION_TOOL_NAME:
|
|
22
24
|
return "Answer questions to clarify intent";
|
|
23
25
|
default:
|
|
@@ -30,6 +32,7 @@ export const ConfirmationDetails = ({ toolName, toolInput, planContent, isExpand
|
|
|
30
32
|
const content = (_jsxs(Box, { 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 !== WRITE_TOOL_NAME &&
|
|
31
33
|
toolName !== EDIT_TOOL_NAME &&
|
|
32
34
|
toolName !== EXIT_PLAN_MODE_TOOL_NAME &&
|
|
35
|
+
toolName !== ENTER_PLAN_MODE_TOOL_NAME &&
|
|
33
36
|
toolName !== ASK_USER_QUESTION_TOOL_NAME &&
|
|
34
37
|
toolName !== BASH_TOOL_NAME &&
|
|
35
38
|
!!toolInput && (_jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "cyan", children: _jsx(Text, { children: highlightToAnsi(JSON.stringify(toolInput, null, 2), "json") }) })), toolName !== ASK_USER_QUESTION_TOOL_NAME &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;AAiB/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AASD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA6nBpE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Box, Text, useInput } from "ink";
|
|
4
|
-
import { BASH_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
|
|
4
|
+
import { BASH_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
|
|
5
5
|
const getHeaderColor = (header) => {
|
|
6
6
|
const colors = ["red", "green", "blue", "magenta", "cyan"];
|
|
7
7
|
let hash = 0;
|
|
@@ -285,6 +285,9 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
|
|
|
285
285
|
if (toolName === EXIT_PLAN_MODE_TOOL_NAME) {
|
|
286
286
|
onDecision({ behavior: "allow", newPermissionMode: "default" });
|
|
287
287
|
}
|
|
288
|
+
else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
289
|
+
onDecision({ behavior: "allow", newPermissionMode: "plan" });
|
|
290
|
+
}
|
|
288
291
|
else {
|
|
289
292
|
onDecision({ behavior: "allow" });
|
|
290
293
|
}
|
|
@@ -302,6 +305,9 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
|
|
|
302
305
|
onDecision({ behavior: "allow", newPermissionRule: rule });
|
|
303
306
|
}
|
|
304
307
|
}
|
|
308
|
+
else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
309
|
+
onDecision({ behavior: "allow", newPermissionMode: "plan" });
|
|
310
|
+
}
|
|
305
311
|
else if (toolName.startsWith("mcp__")) {
|
|
306
312
|
onDecision({ behavior: "allow", newPermissionRule: toolName });
|
|
307
313
|
}
|
|
@@ -312,6 +318,12 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
|
|
|
312
318
|
else if (state.alternativeText.trim()) {
|
|
313
319
|
onDecision({ behavior: "deny", message: state.alternativeText.trim() });
|
|
314
320
|
}
|
|
321
|
+
else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
322
|
+
onDecision({
|
|
323
|
+
behavior: "deny",
|
|
324
|
+
message: "User chose not to enter plan mode",
|
|
325
|
+
});
|
|
326
|
+
}
|
|
315
327
|
return;
|
|
316
328
|
}
|
|
317
329
|
if (state.selectedOption === "alternative") {
|
|
@@ -421,6 +433,6 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
|
|
|
421
433
|
: "", option.label, option.description ? ` - ${option.description}` : "", isOther && isSelected && (_jsxs(Text, { children: [":", " ", questionState.otherText ? (_jsxs(_Fragment, { children: [questionState.otherText.slice(0, questionState.otherCursorPosition), _jsx(Text, { backgroundColor: "white", color: "black", children: questionState.otherText[questionState.otherCursorPosition] || " " }), questionState.otherText.slice(questionState.otherCursorPosition + 1)] })) : (_jsx(Text, { color: "gray", dimColor: true, children: "[Type your answer...]" }))] }))] }) }, index));
|
|
422
434
|
}) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Question ", questionState.currentQuestionIndex + 1, " of", " ", questions.length, " \u2022", currentQuestion.multiSelect ? " Space to toggle •" : "", " Use \u2191\u2193 or Tab to navigate \u2022 Enter to confirm"] }) })] })), toolName !== ASK_USER_QUESTION_TOOL_NAME && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Do you want to proceed?" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [toolName === EXIT_PLAN_MODE_TOOL_NAME && (_jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "clear" ? "black" : "white", backgroundColor: state.selectedOption === "clear" ? "yellow" : undefined, bold: state.selectedOption === "clear", children: [state.selectedOption === "clear" ? "> " : " ", "Yes, clear context and auto-accept edits"] }) }, "clear-option")), _jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "allow" ? "black" : "white", backgroundColor: state.selectedOption === "allow" ? "yellow" : undefined, bold: state.selectedOption === "allow", children: [state.selectedOption === "allow" ? "> " : " ", toolName === EXIT_PLAN_MODE_TOOL_NAME
|
|
423
435
|
? "Yes, manually approve edits"
|
|
424
|
-
: "Yes, proceed"] }) }, "allow-option"), !hidePersistentOption && (_jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "auto" ? "black" : "white", backgroundColor: state.selectedOption === "auto" ? "yellow" : undefined, bold: state.selectedOption === "auto", children: [state.selectedOption === "auto" ? "> " : " ", getAutoOptionText()] }) }, "auto-option")), _jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "alternative" ? "black" : "white", backgroundColor: state.selectedOption === "alternative" ? "yellow" : undefined, bold: state.selectedOption === "alternative", children: [state.selectedOption === "alternative" ? "> " : " ", showPlaceholder ? (_jsx(Text, { color: "gray", dimColor: true, children: placeholderText })) : (_jsx(Text, { children: state.alternativeText ? (_jsxs(_Fragment, { children: [state.alternativeText.slice(0, state.alternativeCursorPosition), _jsx(Text, { backgroundColor: "white", color: "black", children: state.alternativeText[state.alternativeCursorPosition] || " " }), state.alternativeText.slice(state.alternativeCursorPosition + 1)] })) : ("Type here to tell Wave what to change") }))] }) }, "alternative-option")] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 or Tab to navigate \u2022 ESC to cancel" }) })] }))] }));
|
|
436
|
+
: "Yes, proceed"] }) }, "allow-option"), !hidePersistentOption && (_jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "auto" ? "black" : "white", backgroundColor: state.selectedOption === "auto" ? "yellow" : undefined, bold: state.selectedOption === "auto", children: [state.selectedOption === "auto" ? "> " : " ", getAutoOptionText()] }) }, "auto-option")), _jsx(Box, { children: _jsxs(Text, { color: state.selectedOption === "alternative" ? "black" : "white", backgroundColor: state.selectedOption === "alternative" ? "yellow" : undefined, bold: state.selectedOption === "alternative", children: [state.selectedOption === "alternative" ? "> " : " ", toolName === ENTER_PLAN_MODE_TOOL_NAME && showPlaceholder ? (_jsx(Text, { color: "gray", dimColor: true, children: "No, start implementing now" })) : showPlaceholder ? (_jsx(Text, { color: "gray", dimColor: true, children: placeholderText })) : (_jsx(Text, { children: state.alternativeText ? (_jsxs(_Fragment, { children: [state.alternativeText.slice(0, state.alternativeCursorPosition), _jsx(Text, { backgroundColor: "white", color: "black", children: state.alternativeText[state.alternativeCursorPosition] || " " }), state.alternativeText.slice(state.alternativeCursorPosition + 1)] })) : ("Type here to tell Wave what to change") }))] }) }, "alternative-option")] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 or Tab to navigate \u2022 ESC to cancel" }) })] }))] }));
|
|
425
437
|
};
|
|
426
438
|
ConfirmationSelector.displayName = "ConfirmationSelector";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,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;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,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;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,6CAuIpB,CAAC"}
|
|
@@ -9,11 +9,18 @@ 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" &&
|
|
13
|
-
(b.
|
|
12
|
+
const isRunning = (b) => (b.type === "tool" &&
|
|
13
|
+
(b.stage === "running" ||
|
|
14
|
+
b.stage === "streaming" ||
|
|
15
|
+
b.stage === "start")) ||
|
|
16
|
+
(b.type === "bang" && b.stage === "running");
|
|
14
17
|
// Flatten messages into blocks with metadata
|
|
18
|
+
// Filter out streaming text/reasoning blocks to avoid frequent height changes
|
|
15
19
|
const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
|
|
16
|
-
return message.blocks
|
|
20
|
+
return message.blocks
|
|
21
|
+
.filter((block) => !((block.type === "text" || block.type === "reasoning") &&
|
|
22
|
+
block.stage === "streaming"))
|
|
23
|
+
.map((block, blockIndex) => ({
|
|
17
24
|
block,
|
|
18
25
|
message,
|
|
19
26
|
messageIndex,
|
|
@@ -21,11 +28,27 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
|
|
|
21
28
|
key: `${message.id}-${blockIndex}`,
|
|
22
29
|
}));
|
|
23
30
|
});
|
|
31
|
+
// Find message indices that have any running/streaming block
|
|
32
|
+
const runningMessageIndices = new Set();
|
|
33
|
+
for (const item of allBlocks) {
|
|
34
|
+
if (isRunning(item.block)) {
|
|
35
|
+
runningMessageIndices.add(item.messageIndex);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
24
38
|
// Determine which blocks are static vs dynamic
|
|
25
|
-
//
|
|
39
|
+
// Blocks not in the last message are always static.
|
|
40
|
+
// For the last message: if any block is running/streaming, blocks in that message are dynamic,
|
|
41
|
+
// except text/reasoning blocks that have already completed (stage === "end")
|
|
42
|
+
const lastMessageIndex = visibleMessages.length - 1;
|
|
26
43
|
const blocksWithStatus = allBlocks.map((item) => {
|
|
27
|
-
const
|
|
28
|
-
const
|
|
44
|
+
const isInLastMessage = item.messageIndex === lastMessageIndex;
|
|
45
|
+
const isBlockCompleted = (item.block.type === "text" || item.block.type === "reasoning") &&
|
|
46
|
+
item.block.stage === "end";
|
|
47
|
+
const isDynamic = !forceStatic &&
|
|
48
|
+
!isExpanded &&
|
|
49
|
+
isInLastMessage &&
|
|
50
|
+
!isBlockCompleted &&
|
|
51
|
+
runningMessageIndices.has(item.messageIndex);
|
|
29
52
|
return { ...item, isDynamic };
|
|
30
53
|
});
|
|
31
54
|
const staticBlocks = blocksWithStatus.filter((b) => !b.isDynamic);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ToolDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"ToolDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ToolDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA0IlD,CAAC"}
|
|
@@ -37,5 +37,11 @@ export const ToolDisplay = ({ block, isExpanded = false, }) => {
|
|
|
37
37
|
return null;
|
|
38
38
|
};
|
|
39
39
|
const shortResult = getShortResult();
|
|
40
|
-
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] })),
|
|
40
|
+
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] })), !isExpanded &&
|
|
41
|
+
stage === "streaming" &&
|
|
42
|
+
parameters &&
|
|
43
|
+
!compactParams && (_jsx(Text, { color: "gray", wrap: "truncate-end", children: ` ${(() => {
|
|
44
|
+
const flat = parameters.replace(/\n/g, "\\n");
|
|
45
|
+
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
46
|
+
})()}` })), 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 }))] }));
|
|
41
47
|
};
|
|
@@ -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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"}
|
package/dist/contexts/useChat.js
CHANGED
|
@@ -29,17 +29,22 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
29
29
|
setMessages([...agentRef.current.messages]);
|
|
30
30
|
}
|
|
31
31
|
}, 300, { leading: true, trailing: true }), []);
|
|
32
|
+
const throttledSetTokens = useMemo(() => throttle(((tokens) => {
|
|
33
|
+
setlatestTotalTokens(tokens);
|
|
34
|
+
}), 300, { leading: true, trailing: true }), []);
|
|
32
35
|
useEffect(() => {
|
|
33
36
|
isExpandedRef.current = isExpanded;
|
|
34
37
|
if (isExpanded) {
|
|
35
38
|
throttledSetMessages.cancel();
|
|
39
|
+
throttledSetTokens.cancel();
|
|
36
40
|
}
|
|
37
|
-
}, [isExpanded, throttledSetMessages]);
|
|
41
|
+
}, [isExpanded, throttledSetMessages, throttledSetTokens]);
|
|
38
42
|
useEffect(() => {
|
|
39
43
|
return () => {
|
|
40
44
|
throttledSetMessages.cancel();
|
|
45
|
+
throttledSetTokens.cancel();
|
|
41
46
|
};
|
|
42
|
-
}, [throttledSetMessages]);
|
|
47
|
+
}, [throttledSetMessages, throttledSetTokens]);
|
|
43
48
|
const [isLoading, setIsLoading] = useState(false);
|
|
44
49
|
const [latestTotalTokens, setlatestTotalTokens] = useState(0);
|
|
45
50
|
const [sessionId, setSessionId] = useState("");
|
|
@@ -122,7 +127,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
122
127
|
setSessionId(sessionId);
|
|
123
128
|
},
|
|
124
129
|
onLatestTotalTokensChange: (tokens) => {
|
|
125
|
-
|
|
130
|
+
throttledSetTokens(tokens);
|
|
126
131
|
},
|
|
127
132
|
onCompressionStateChange: (isCompressingState) => {
|
|
128
133
|
setIsCompressing(isCompressingState);
|
|
@@ -167,7 +172,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
167
172
|
permissionMode: initialPermissionMode ||
|
|
168
173
|
(bypassPermissions ? "bypassPermissions" : undefined),
|
|
169
174
|
canUseTool: permissionCallback,
|
|
170
|
-
stream:
|
|
175
|
+
stream: true,
|
|
171
176
|
plugins: pluginDirs?.map((path) => ({ type: "local", path })),
|
|
172
177
|
tools,
|
|
173
178
|
allowedTools,
|
|
@@ -215,6 +220,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
215
220
|
model,
|
|
216
221
|
initialPermissionMode,
|
|
217
222
|
throttledSetMessages,
|
|
223
|
+
throttledSetTokens,
|
|
218
224
|
]);
|
|
219
225
|
// Cleanup on unmount
|
|
220
226
|
useEffect(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
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.
|
|
45
|
+
"wave-agent-sdk": "0.13.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.1.8",
|
package/src/acp/agent.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
EDIT_TOOL_NAME,
|
|
14
14
|
WRITE_TOOL_NAME,
|
|
15
15
|
EXIT_PLAN_MODE_TOOL_NAME,
|
|
16
|
+
ENTER_PLAN_MODE_TOOL_NAME,
|
|
16
17
|
ASK_USER_QUESTION_TOOL_NAME,
|
|
17
18
|
AskUserQuestion,
|
|
18
19
|
AskUserQuestionOption,
|
|
@@ -94,10 +95,14 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
private getSessionConfigOptions(agent: WaveAgent): SessionConfigOption[] {
|
|
98
|
+
const configuredModels = agent.getConfiguredModels();
|
|
99
|
+
const currentModel = agent.getModelConfig().model;
|
|
100
|
+
|
|
97
101
|
return [
|
|
98
102
|
{
|
|
99
103
|
id: "permission_mode",
|
|
100
104
|
name: "Permission Mode",
|
|
105
|
+
description: "Controls how the agent requests permission",
|
|
101
106
|
type: "select",
|
|
102
107
|
category: "mode",
|
|
103
108
|
currentValue: agent.getPermissionMode(),
|
|
@@ -109,6 +114,18 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
109
114
|
{ value: "dontAsk", name: "Don't Ask" },
|
|
110
115
|
],
|
|
111
116
|
},
|
|
117
|
+
{
|
|
118
|
+
id: "model",
|
|
119
|
+
name: "Model",
|
|
120
|
+
description: "The AI model to use for this session",
|
|
121
|
+
type: "select",
|
|
122
|
+
category: "model",
|
|
123
|
+
currentValue: currentModel,
|
|
124
|
+
options: configuredModels.map((m) => ({
|
|
125
|
+
value: m,
|
|
126
|
+
name: m,
|
|
127
|
+
})),
|
|
128
|
+
},
|
|
112
129
|
];
|
|
113
130
|
}
|
|
114
131
|
|
|
@@ -183,6 +200,7 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
183
200
|
onTasksChange: (tasks) => callbacks.onTasksChange?.(tasks as Task[]),
|
|
184
201
|
onPermissionModeChange: (mode) =>
|
|
185
202
|
callbacks.onPermissionModeChange?.(mode),
|
|
203
|
+
onModelChange: (model) => callbacks.onModelChange?.(model),
|
|
186
204
|
},
|
|
187
205
|
});
|
|
188
206
|
|
|
@@ -319,6 +337,8 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
319
337
|
| "bypassPermissions"
|
|
320
338
|
| "dontAsk",
|
|
321
339
|
);
|
|
340
|
+
} else if (configId === "model" && typeof value === "string") {
|
|
341
|
+
agent.setModel(value);
|
|
322
342
|
}
|
|
323
343
|
|
|
324
344
|
return {
|
|
@@ -502,6 +522,19 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
502
522
|
kind: "allow_always",
|
|
503
523
|
},
|
|
504
524
|
];
|
|
525
|
+
} else if (context.toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
526
|
+
options = [
|
|
527
|
+
{
|
|
528
|
+
optionId: "allow_once",
|
|
529
|
+
name: "Yes, enter plan mode",
|
|
530
|
+
kind: "allow_once",
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
optionId: "reject_once",
|
|
534
|
+
name: "No, start implementing now",
|
|
535
|
+
kind: "reject_once",
|
|
536
|
+
},
|
|
537
|
+
];
|
|
505
538
|
} else if (context.toolName === ASK_USER_QUESTION_TOOL_NAME) {
|
|
506
539
|
options = [];
|
|
507
540
|
}
|
|
@@ -578,6 +611,9 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
578
611
|
if (context.toolName === EXIT_PLAN_MODE_TOOL_NAME) {
|
|
579
612
|
return { behavior: "allow", newPermissionMode: "default" };
|
|
580
613
|
}
|
|
614
|
+
if (context.toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
615
|
+
return { behavior: "allow", newPermissionMode: "plan" };
|
|
616
|
+
}
|
|
581
617
|
return { behavior: "allow" };
|
|
582
618
|
case "reject_once":
|
|
583
619
|
return { behavior: "deny", message: "Rejected by user" };
|
|
@@ -944,6 +980,18 @@ export class WaveAcpAgent implements AcpAgent {
|
|
|
944
980
|
});
|
|
945
981
|
}
|
|
946
982
|
},
|
|
983
|
+
onModelChange: () => {
|
|
984
|
+
const agent = getAgent();
|
|
985
|
+
if (agent) {
|
|
986
|
+
this.connection.sessionUpdate({
|
|
987
|
+
sessionId: sessionId as AcpSessionId,
|
|
988
|
+
update: {
|
|
989
|
+
sessionUpdate: "config_option_update",
|
|
990
|
+
configOptions: this.getSessionConfigOptions(agent),
|
|
991
|
+
},
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
},
|
|
947
995
|
};
|
|
948
996
|
}
|
|
949
997
|
}
|
|
@@ -12,11 +12,11 @@ export const BangDisplay: React.FC<BangDisplayProps> = ({
|
|
|
12
12
|
block,
|
|
13
13
|
isExpanded = false,
|
|
14
14
|
}) => {
|
|
15
|
-
const { command, output,
|
|
15
|
+
const { command, output, stage, exitCode } = block;
|
|
16
16
|
const MAX_LINES = 3; // Set maximum display lines
|
|
17
17
|
|
|
18
18
|
const getStatusColor = () => {
|
|
19
|
-
if (
|
|
19
|
+
if (stage === "running") return "yellow";
|
|
20
20
|
if (exitCode === 0) return "green";
|
|
21
21
|
if (exitCode !== null && exitCode !== 0) return "red";
|
|
22
22
|
return "gray"; // Unknown state
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
EDIT_TOOL_NAME,
|
|
6
6
|
WRITE_TOOL_NAME,
|
|
7
7
|
EXIT_PLAN_MODE_TOOL_NAME,
|
|
8
|
+
ENTER_PLAN_MODE_TOOL_NAME,
|
|
8
9
|
ASK_USER_QUESTION_TOOL_NAME,
|
|
9
10
|
} from "wave-agent-sdk";
|
|
10
11
|
import { DiffDisplay } from "./DiffDisplay.js";
|
|
@@ -29,6 +30,8 @@ const getActionDescription = (
|
|
|
29
30
|
return `Write to file: ${toolInput.file_path || "unknown file"}`;
|
|
30
31
|
case EXIT_PLAN_MODE_TOOL_NAME:
|
|
31
32
|
return "Review and approve the plan";
|
|
33
|
+
case ENTER_PLAN_MODE_TOOL_NAME:
|
|
34
|
+
return "Enter plan mode for complex task planning";
|
|
32
35
|
case ASK_USER_QUESTION_TOOL_NAME:
|
|
33
36
|
return "Answer questions to clarify intent";
|
|
34
37
|
default:
|
|
@@ -76,6 +79,7 @@ export const ConfirmationDetails: React.FC<ConfirmationDetailsProps> = ({
|
|
|
76
79
|
{toolName !== WRITE_TOOL_NAME &&
|
|
77
80
|
toolName !== EDIT_TOOL_NAME &&
|
|
78
81
|
toolName !== EXIT_PLAN_MODE_TOOL_NAME &&
|
|
82
|
+
toolName !== ENTER_PLAN_MODE_TOOL_NAME &&
|
|
79
83
|
toolName !== ASK_USER_QUESTION_TOOL_NAME &&
|
|
80
84
|
toolName !== BASH_TOOL_NAME &&
|
|
81
85
|
!!toolInput && (
|
|
@@ -4,6 +4,7 @@ import type { PermissionDecision, AskUserQuestionInput } from "wave-agent-sdk";
|
|
|
4
4
|
import {
|
|
5
5
|
BASH_TOOL_NAME,
|
|
6
6
|
EXIT_PLAN_MODE_TOOL_NAME,
|
|
7
|
+
ENTER_PLAN_MODE_TOOL_NAME,
|
|
7
8
|
ASK_USER_QUESTION_TOOL_NAME,
|
|
8
9
|
} from "wave-agent-sdk";
|
|
9
10
|
|
|
@@ -353,6 +354,8 @@ export const ConfirmationSelector: React.FC<ConfirmationSelectorProps> = ({
|
|
|
353
354
|
} else if (state.selectedOption === "allow") {
|
|
354
355
|
if (toolName === EXIT_PLAN_MODE_TOOL_NAME) {
|
|
355
356
|
onDecision({ behavior: "allow", newPermissionMode: "default" });
|
|
357
|
+
} else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
358
|
+
onDecision({ behavior: "allow", newPermissionMode: "plan" });
|
|
356
359
|
} else {
|
|
357
360
|
onDecision({ behavior: "allow" });
|
|
358
361
|
}
|
|
@@ -367,6 +370,8 @@ export const ConfirmationSelector: React.FC<ConfirmationSelectorProps> = ({
|
|
|
367
370
|
: `Bash(${toolInput?.command})`;
|
|
368
371
|
onDecision({ behavior: "allow", newPermissionRule: rule });
|
|
369
372
|
}
|
|
373
|
+
} else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
374
|
+
onDecision({ behavior: "allow", newPermissionMode: "plan" });
|
|
370
375
|
} else if (toolName.startsWith("mcp__")) {
|
|
371
376
|
onDecision({ behavior: "allow", newPermissionRule: toolName });
|
|
372
377
|
} else {
|
|
@@ -374,6 +379,11 @@ export const ConfirmationSelector: React.FC<ConfirmationSelectorProps> = ({
|
|
|
374
379
|
}
|
|
375
380
|
} else if (state.alternativeText.trim()) {
|
|
376
381
|
onDecision({ behavior: "deny", message: state.alternativeText.trim() });
|
|
382
|
+
} else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
|
|
383
|
+
onDecision({
|
|
384
|
+
behavior: "deny",
|
|
385
|
+
message: "User chose not to enter plan mode",
|
|
386
|
+
});
|
|
377
387
|
}
|
|
378
388
|
return;
|
|
379
389
|
}
|
|
@@ -622,7 +632,11 @@ export const ConfirmationSelector: React.FC<ConfirmationSelectorProps> = ({
|
|
|
622
632
|
bold={state.selectedOption === "alternative"}
|
|
623
633
|
>
|
|
624
634
|
{state.selectedOption === "alternative" ? "> " : " "}
|
|
625
|
-
{showPlaceholder ? (
|
|
635
|
+
{toolName === ENTER_PLAN_MODE_TOOL_NAME && showPlaceholder ? (
|
|
636
|
+
<Text color="gray" dimColor>
|
|
637
|
+
No, start implementing now
|
|
638
|
+
</Text>
|
|
639
|
+
) : showPlaceholder ? (
|
|
626
640
|
<Text color="gray" dimColor>
|
|
627
641
|
{placeholderText}
|
|
628
642
|
</Text>
|
|
@@ -38,25 +38,56 @@ export const MessageList = React.memo(
|
|
|
38
38
|
const visibleMessages = messages.filter((m) => !m.isMeta);
|
|
39
39
|
|
|
40
40
|
const isRunning = (b: MessageBlock) =>
|
|
41
|
-
(b.type === "tool" &&
|
|
42
|
-
|
|
41
|
+
(b.type === "tool" &&
|
|
42
|
+
(b.stage === "running" ||
|
|
43
|
+
b.stage === "streaming" ||
|
|
44
|
+
b.stage === "start")) ||
|
|
45
|
+
(b.type === "bang" && b.stage === "running");
|
|
43
46
|
|
|
44
47
|
// Flatten messages into blocks with metadata
|
|
48
|
+
// Filter out streaming text/reasoning blocks to avoid frequent height changes
|
|
45
49
|
const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
|
|
46
|
-
return message.blocks
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
return message.blocks
|
|
51
|
+
.filter(
|
|
52
|
+
(block) =>
|
|
53
|
+
!(
|
|
54
|
+
(block.type === "text" || block.type === "reasoning") &&
|
|
55
|
+
block.stage === "streaming"
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
.map((block, blockIndex) => ({
|
|
59
|
+
block,
|
|
60
|
+
message,
|
|
61
|
+
messageIndex,
|
|
62
|
+
// Unique key for each block to help Static component
|
|
63
|
+
key: `${message.id}-${blockIndex}`,
|
|
64
|
+
}));
|
|
53
65
|
});
|
|
54
66
|
|
|
67
|
+
// Find message indices that have any running/streaming block
|
|
68
|
+
const runningMessageIndices = new Set<number>();
|
|
69
|
+
for (const item of allBlocks) {
|
|
70
|
+
if (isRunning(item.block)) {
|
|
71
|
+
runningMessageIndices.add(item.messageIndex);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
55
75
|
// Determine which blocks are static vs dynamic
|
|
56
|
-
//
|
|
76
|
+
// Blocks not in the last message are always static.
|
|
77
|
+
// For the last message: if any block is running/streaming, blocks in that message are dynamic,
|
|
78
|
+
// except text/reasoning blocks that have already completed (stage === "end")
|
|
79
|
+
const lastMessageIndex = visibleMessages.length - 1;
|
|
57
80
|
const blocksWithStatus = allBlocks.map((item) => {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
81
|
+
const isInLastMessage = item.messageIndex === lastMessageIndex;
|
|
82
|
+
const isBlockCompleted =
|
|
83
|
+
(item.block.type === "text" || item.block.type === "reasoning") &&
|
|
84
|
+
item.block.stage === "end";
|
|
85
|
+
const isDynamic =
|
|
86
|
+
!forceStatic &&
|
|
87
|
+
!isExpanded &&
|
|
88
|
+
isInLastMessage &&
|
|
89
|
+
!isBlockCompleted &&
|
|
90
|
+
runningMessageIndices.has(item.messageIndex);
|
|
60
91
|
return { ...item, isDynamic };
|
|
61
92
|
});
|
|
62
93
|
|
|
@@ -61,10 +61,21 @@ export const ToolDisplay: React.FC<ToolDisplayProps> = ({
|
|
|
61
61
|
<Text color={getStatusColor()}>● </Text>
|
|
62
62
|
<Text color="white">{toolName}</Text>
|
|
63
63
|
</Box>
|
|
64
|
-
{/* Display compactParams in collapsed state */}
|
|
64
|
+
{/* Display compactParams or streaming parameters in collapsed state */}
|
|
65
65
|
{!isExpanded && compactParams && (
|
|
66
66
|
<Text color="gray"> {compactParams}</Text>
|
|
67
67
|
)}
|
|
68
|
+
{!isExpanded &&
|
|
69
|
+
stage === "streaming" &&
|
|
70
|
+
parameters &&
|
|
71
|
+
!compactParams && (
|
|
72
|
+
<Text color="gray" wrap="truncate-end">
|
|
73
|
+
{` ${(() => {
|
|
74
|
+
const flat = parameters.replace(/\n/g, "\\n");
|
|
75
|
+
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
76
|
+
})()}`}
|
|
77
|
+
</Text>
|
|
78
|
+
)}
|
|
68
79
|
{/* Display image indicator */}
|
|
69
80
|
{hasImages() && <Text color="blue"> {getImageIndicator()}</Text>}
|
|
70
81
|
</Box>
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -182,18 +182,32 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
182
182
|
[],
|
|
183
183
|
);
|
|
184
184
|
|
|
185
|
+
const throttledSetTokens = useMemo(
|
|
186
|
+
() =>
|
|
187
|
+
throttle(
|
|
188
|
+
((tokens: number) => {
|
|
189
|
+
setlatestTotalTokens(tokens);
|
|
190
|
+
}) as (...args: unknown[]) => void,
|
|
191
|
+
300,
|
|
192
|
+
{ leading: true, trailing: true },
|
|
193
|
+
),
|
|
194
|
+
[],
|
|
195
|
+
);
|
|
196
|
+
|
|
185
197
|
useEffect(() => {
|
|
186
198
|
isExpandedRef.current = isExpanded;
|
|
187
199
|
if (isExpanded) {
|
|
188
200
|
throttledSetMessages.cancel();
|
|
201
|
+
throttledSetTokens.cancel();
|
|
189
202
|
}
|
|
190
|
-
}, [isExpanded, throttledSetMessages]);
|
|
203
|
+
}, [isExpanded, throttledSetMessages, throttledSetTokens]);
|
|
191
204
|
|
|
192
205
|
useEffect(() => {
|
|
193
206
|
return () => {
|
|
194
207
|
throttledSetMessages.cancel();
|
|
208
|
+
throttledSetTokens.cancel();
|
|
195
209
|
};
|
|
196
|
-
}, [throttledSetMessages]);
|
|
210
|
+
}, [throttledSetMessages, throttledSetTokens]);
|
|
197
211
|
|
|
198
212
|
const [isLoading, setIsLoading] = useState(false);
|
|
199
213
|
const [latestTotalTokens, setlatestTotalTokens] = useState(0);
|
|
@@ -341,7 +355,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
341
355
|
setSessionId(sessionId);
|
|
342
356
|
},
|
|
343
357
|
onLatestTotalTokensChange: (tokens) => {
|
|
344
|
-
|
|
358
|
+
throttledSetTokens(tokens);
|
|
345
359
|
},
|
|
346
360
|
onCompressionStateChange: (isCompressingState) => {
|
|
347
361
|
setIsCompressing(isCompressingState);
|
|
@@ -396,7 +410,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
396
410
|
initialPermissionMode ||
|
|
397
411
|
(bypassPermissions ? "bypassPermissions" : undefined),
|
|
398
412
|
canUseTool: permissionCallback,
|
|
399
|
-
stream:
|
|
413
|
+
stream: true,
|
|
400
414
|
plugins: pluginDirs?.map((path) => ({ type: "local", path })),
|
|
401
415
|
tools,
|
|
402
416
|
allowedTools,
|
|
@@ -448,6 +462,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
448
462
|
model,
|
|
449
463
|
initialPermissionMode,
|
|
450
464
|
throttledSetMessages,
|
|
465
|
+
throttledSetTokens,
|
|
451
466
|
]);
|
|
452
467
|
|
|
453
468
|
// Cleanup on unmount
|