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