wave-code 0.0.6 → 0.0.8
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/README.md +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/components/App.d.ts +1 -0
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +4 -4
- package/dist/components/BashHistorySelector.d.ts.map +1 -1
- package/dist/components/BashHistorySelector.js +17 -3
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +4 -2
- package/dist/components/Confirmation.d.ts +11 -0
- package/dist/components/Confirmation.d.ts.map +1 -0
- package/dist/components/Confirmation.js +148 -0
- package/dist/components/DiffDisplay.d.ts +8 -0
- package/dist/components/DiffDisplay.d.ts.map +1 -0
- package/dist/components/DiffDisplay.js +168 -0
- package/dist/components/FileSelector.d.ts +2 -4
- package/dist/components/FileSelector.d.ts.map +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +10 -1
- package/dist/components/MemoryDisplay.js +1 -1
- package/dist/components/MessageItem.d.ts +1 -2
- package/dist/components/MessageItem.d.ts.map +1 -1
- package/dist/components/MessageItem.js +3 -3
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +2 -2
- package/dist/components/ReasoningDisplay.d.ts +8 -0
- package/dist/components/ReasoningDisplay.d.ts.map +1 -0
- package/dist/components/ReasoningDisplay.js +10 -0
- package/dist/components/ToolResultDisplay.d.ts.map +1 -1
- package/dist/components/ToolResultDisplay.js +2 -1
- package/dist/contexts/useChat.d.ts +13 -1
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +117 -15
- package/dist/hooks/useInputManager.d.ts +3 -0
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -4
- package/dist/managers/InputManager.d.ts +8 -0
- package/dist/managers/InputManager.d.ts.map +1 -1
- package/dist/managers/InputManager.js +33 -2
- package/dist/print-cli.d.ts +1 -0
- package/dist/print-cli.d.ts.map +1 -1
- package/dist/print-cli.js +36 -3
- package/dist/utils/toolParameterTransforms.d.ts +23 -0
- package/dist/utils/toolParameterTransforms.d.ts.map +1 -0
- package/dist/utils/toolParameterTransforms.js +77 -0
- package/package.json +6 -5
- package/src/cli.tsx +3 -1
- package/src/components/App.tsx +7 -3
- package/src/components/BashHistorySelector.tsx +26 -3
- package/src/components/ChatInterface.tsx +29 -15
- package/src/components/Confirmation.tsx +253 -0
- package/src/components/DiffDisplay.tsx +300 -0
- package/src/components/FileSelector.tsx +2 -4
- package/src/components/InputBox.tsx +37 -14
- package/src/components/MemoryDisplay.tsx +1 -1
- package/src/components/MessageItem.tsx +4 -12
- package/src/components/MessageList.tsx +0 -2
- package/src/components/ReasoningDisplay.tsx +33 -0
- package/src/components/ToolResultDisplay.tsx +4 -0
- package/src/contexts/useChat.tsx +178 -14
- package/src/hooks/useInputManager.ts +19 -0
- package/src/index.ts +34 -4
- package/src/managers/InputManager.ts +46 -2
- package/src/print-cli.ts +42 -2
- package/src/utils/toolParameterTransforms.ts +104 -0
- package/dist/components/DiffViewer.d.ts +0 -9
- package/dist/components/DiffViewer.d.ts.map +0 -1
- package/dist/components/DiffViewer.js +0 -221
- package/dist/utils/fileSearch.d.ts +0 -20
- package/dist/utils/fileSearch.d.ts.map +0 -1
- package/dist/utils/fileSearch.js +0 -102
- package/src/components/DiffViewer.tsx +0 -323
- package/src/utils/fileSearch.ts +0 -133
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { searchFiles as searchFilesUtil } from "
|
|
1
|
+
import { searchFiles as searchFilesUtil, } from "wave-agent-sdk";
|
|
2
2
|
import { readClipboardImage } from "../utils/clipboard.js";
|
|
3
3
|
export class InputManager {
|
|
4
4
|
constructor(callbacks = {}) {
|
|
@@ -40,13 +40,19 @@ export class InputManager {
|
|
|
40
40
|
// Additional UI state
|
|
41
41
|
this.showBashManager = false;
|
|
42
42
|
this.showMcpManager = false;
|
|
43
|
+
// Permission mode state
|
|
44
|
+
this.permissionMode = "default";
|
|
43
45
|
// Flag to prevent handleInput conflicts when selector selection occurs
|
|
44
46
|
this.selectorJustUsed = false;
|
|
45
47
|
this.callbacks = callbacks;
|
|
48
|
+
this.logger = callbacks.logger;
|
|
46
49
|
}
|
|
47
50
|
// Update callbacks
|
|
48
51
|
updateCallbacks(callbacks) {
|
|
49
52
|
this.callbacks = { ...this.callbacks, ...callbacks };
|
|
53
|
+
if (callbacks.logger) {
|
|
54
|
+
this.logger = callbacks.logger;
|
|
55
|
+
}
|
|
50
56
|
}
|
|
51
57
|
// Core input methods
|
|
52
58
|
getInputText() {
|
|
@@ -619,6 +625,25 @@ export class InputManager {
|
|
|
619
625
|
this.showMcpManager = show;
|
|
620
626
|
this.callbacks.onMcpManagerStateChange?.(show);
|
|
621
627
|
}
|
|
628
|
+
// Permission mode methods
|
|
629
|
+
getPermissionMode() {
|
|
630
|
+
return this.permissionMode;
|
|
631
|
+
}
|
|
632
|
+
setPermissionMode(mode) {
|
|
633
|
+
this.permissionMode = mode;
|
|
634
|
+
}
|
|
635
|
+
cyclePermissionMode() {
|
|
636
|
+
const modes = ["default", "acceptEdits"];
|
|
637
|
+
const currentIndex = modes.indexOf(this.permissionMode);
|
|
638
|
+
const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % modes.length;
|
|
639
|
+
const nextMode = modes[nextIndex];
|
|
640
|
+
this.logger?.debug("Cycling permission mode", {
|
|
641
|
+
from: this.permissionMode,
|
|
642
|
+
to: nextMode,
|
|
643
|
+
});
|
|
644
|
+
this.permissionMode = nextMode;
|
|
645
|
+
this.callbacks.onPermissionModeChange?.(this.permissionMode);
|
|
646
|
+
}
|
|
622
647
|
// Handle submit logic
|
|
623
648
|
async handleSubmit(attachedImages, isLoading = false, isCommandRunning = false) {
|
|
624
649
|
// Prevent submission during loading or command execution
|
|
@@ -655,7 +680,7 @@ export class InputManager {
|
|
|
655
680
|
}
|
|
656
681
|
// Handle selector input (when any selector is active)
|
|
657
682
|
handleSelectorInput(input, key) {
|
|
658
|
-
if (key.backspace || key.delete) {
|
|
683
|
+
if (key.backspace || (key.delete && !this.showBashHistorySelector)) {
|
|
659
684
|
if (this.cursorPosition > 0) {
|
|
660
685
|
this.deleteCharAtCursor((newInput, newCursorPosition) => {
|
|
661
686
|
// Check for special character deletion
|
|
@@ -793,6 +818,12 @@ export class InputManager {
|
|
|
793
818
|
this.callbacks.onAbortMessage?.();
|
|
794
819
|
return true;
|
|
795
820
|
}
|
|
821
|
+
// Handle Shift+Tab for permission mode cycling
|
|
822
|
+
if (key.tab && key.shift) {
|
|
823
|
+
this.logger?.debug("Shift+Tab detected, cycling permission mode");
|
|
824
|
+
this.cyclePermissionMode();
|
|
825
|
+
return true;
|
|
826
|
+
}
|
|
796
827
|
// Check if any selector is active
|
|
797
828
|
if (this.showFileSelector ||
|
|
798
829
|
this.showCommandSelector ||
|
package/dist/print-cli.d.ts
CHANGED
package/dist/print-cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-cli.d.ts","sourceRoot":"","sources":["../src/print-cli.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"print-cli.d.ts","sourceRoot":"","sources":["../src/print-cli.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAgBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA8K3E"}
|
package/dist/print-cli.js
CHANGED
|
@@ -13,7 +13,7 @@ function displayTimingInfo(startTime, showStats) {
|
|
|
13
13
|
}
|
|
14
14
|
export async function startPrintCli(options) {
|
|
15
15
|
const startTime = new Date();
|
|
16
|
-
const { restoreSessionId, continueLastSession, message, showStats = false, } = options;
|
|
16
|
+
const { restoreSessionId, continueLastSession, message, showStats = false, bypassPermissions, } = options;
|
|
17
17
|
if ((!message || message.trim() === "") &&
|
|
18
18
|
!continueLastSession &&
|
|
19
19
|
!restoreSessionId) {
|
|
@@ -21,13 +21,30 @@ export async function startPrintCli(options) {
|
|
|
21
21
|
process.exit(1);
|
|
22
22
|
}
|
|
23
23
|
let agent;
|
|
24
|
+
let isReasoning = false;
|
|
25
|
+
let isContent = false;
|
|
26
|
+
const subagentReasoningStates = new Map();
|
|
27
|
+
const subagentContentStates = new Map();
|
|
24
28
|
// Setup callbacks for agent
|
|
25
29
|
const callbacks = {
|
|
26
30
|
onAssistantMessageAdded: () => {
|
|
31
|
+
isReasoning = false;
|
|
32
|
+
isContent = false;
|
|
27
33
|
// Assistant message started - no content to output yet
|
|
28
34
|
process.stdout.write("\n");
|
|
29
35
|
},
|
|
36
|
+
onAssistantReasoningUpdated: (chunk) => {
|
|
37
|
+
if (!isReasoning) {
|
|
38
|
+
process.stdout.write("💭 Reasoning:\n");
|
|
39
|
+
isReasoning = true;
|
|
40
|
+
}
|
|
41
|
+
process.stdout.write(chunk);
|
|
42
|
+
},
|
|
30
43
|
onAssistantContentUpdated: (chunk) => {
|
|
44
|
+
if (isReasoning && !isContent) {
|
|
45
|
+
process.stdout.write("\n\n📝 Response:\n");
|
|
46
|
+
isContent = true;
|
|
47
|
+
}
|
|
31
48
|
// FR-001: Stream content updates for real-time display - output only the new chunk
|
|
32
49
|
process.stdout.write(chunk);
|
|
33
50
|
},
|
|
@@ -59,11 +76,25 @@ export async function startPrintCli(options) {
|
|
|
59
76
|
process.stdout.write(` ${statusIcon} Subagent status: ${status}\n`);
|
|
60
77
|
},
|
|
61
78
|
// Subagent message callbacks
|
|
62
|
-
onSubagentAssistantMessageAdded: () => {
|
|
79
|
+
onSubagentAssistantMessageAdded: (subagentId) => {
|
|
80
|
+
subagentReasoningStates.set(subagentId, false);
|
|
81
|
+
subagentContentStates.set(subagentId, false);
|
|
63
82
|
// Subagent assistant message started - add indentation
|
|
64
83
|
process.stdout.write("\n ");
|
|
65
84
|
},
|
|
66
|
-
|
|
85
|
+
onSubagentAssistantReasoningUpdated: (subagentId, chunk) => {
|
|
86
|
+
if (!subagentReasoningStates.get(subagentId)) {
|
|
87
|
+
process.stdout.write("💭 Reasoning: ");
|
|
88
|
+
subagentReasoningStates.set(subagentId, true);
|
|
89
|
+
}
|
|
90
|
+
process.stdout.write(chunk);
|
|
91
|
+
},
|
|
92
|
+
onSubagentAssistantContentUpdated: (subagentId, chunk) => {
|
|
93
|
+
if (subagentReasoningStates.get(subagentId) &&
|
|
94
|
+
!subagentContentStates.get(subagentId)) {
|
|
95
|
+
process.stdout.write("\n 📝 Response: ");
|
|
96
|
+
subagentContentStates.set(subagentId, true);
|
|
97
|
+
}
|
|
67
98
|
// Stream subagent content with indentation - output only the new chunk
|
|
68
99
|
process.stdout.write(chunk);
|
|
69
100
|
},
|
|
@@ -83,6 +114,8 @@ export async function startPrintCli(options) {
|
|
|
83
114
|
callbacks,
|
|
84
115
|
restoreSessionId,
|
|
85
116
|
continueLastSession,
|
|
117
|
+
permissionMode: bypassPermissions ? "bypassPermissions" : undefined,
|
|
118
|
+
// 保持流式模式以获得更好的命令行用户体验
|
|
86
119
|
});
|
|
87
120
|
// Send message if provided and not empty
|
|
88
121
|
if (message && message.trim() !== "") {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool parameter transformation utilities for UI rendering
|
|
3
|
+
* Forces type judgment based on tool name using type assertions
|
|
4
|
+
*/
|
|
5
|
+
import { type Change, type WriteToolParameters, type EditToolParameters, type MultiEditToolParameters } from "wave-agent-sdk";
|
|
6
|
+
/**
|
|
7
|
+
* Transform Write tool parameters to changes
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformWriteParameters(parameters: WriteToolParameters): Change[];
|
|
10
|
+
/**
|
|
11
|
+
* Transform Edit tool parameters to changes
|
|
12
|
+
*/
|
|
13
|
+
export declare function transformEditParameters(parameters: EditToolParameters): Change[];
|
|
14
|
+
/**
|
|
15
|
+
* Transform MultiEdit tool parameters to changes
|
|
16
|
+
*/
|
|
17
|
+
export declare function transformMultiEditParameters(parameters: MultiEditToolParameters): Change[];
|
|
18
|
+
/**
|
|
19
|
+
* Transform tool block parameters into standardized Change[] array for diff display
|
|
20
|
+
* Forces type judgment based on tool name using type assertions
|
|
21
|
+
*/
|
|
22
|
+
export declare function transformToolBlockToChanges(toolName: string, parameters: string): Change[];
|
|
23
|
+
//# sourceMappingURL=toolParameterTransforms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolParameterTransforms.d.ts","sourceRoot":"","sources":["../../src/utils/toolParameterTransforms.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,KAAK,MAAM,EACX,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC;AAmBxB;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,mBAAmB,GAC9B,MAAM,EAAE,CAOV;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,kBAAkB,GAC7B,MAAM,EAAE,CAOV;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,uBAAuB,GAClC,MAAM,EAAE,CAKV;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CA2BV"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool parameter transformation utilities for UI rendering
|
|
3
|
+
* Forces type judgment based on tool name using type assertions
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from "./logger.js";
|
|
6
|
+
/**
|
|
7
|
+
* Parse tool block parameters
|
|
8
|
+
*/
|
|
9
|
+
function parseToolParameters(parameters) {
|
|
10
|
+
if (!parameters) {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(parameters);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
logger.warn("Failed to parse tool parameters:", error);
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Transform Write tool parameters to changes
|
|
23
|
+
*/
|
|
24
|
+
export function transformWriteParameters(parameters) {
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
oldContent: "", // No previous content for write operations
|
|
28
|
+
newContent: parameters.content,
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Transform Edit tool parameters to changes
|
|
34
|
+
*/
|
|
35
|
+
export function transformEditParameters(parameters) {
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
oldContent: parameters.old_string,
|
|
39
|
+
newContent: parameters.new_string,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Transform MultiEdit tool parameters to changes
|
|
45
|
+
*/
|
|
46
|
+
export function transformMultiEditParameters(parameters) {
|
|
47
|
+
return parameters.edits.map((edit) => ({
|
|
48
|
+
oldContent: edit.old_string,
|
|
49
|
+
newContent: edit.new_string,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Transform tool block parameters into standardized Change[] array for diff display
|
|
54
|
+
* Forces type judgment based on tool name using type assertions
|
|
55
|
+
*/
|
|
56
|
+
export function transformToolBlockToChanges(toolName, parameters) {
|
|
57
|
+
try {
|
|
58
|
+
if (!toolName) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const parsedParams = parseToolParameters(parameters);
|
|
62
|
+
switch (toolName) {
|
|
63
|
+
case "Write":
|
|
64
|
+
return transformWriteParameters(parsedParams);
|
|
65
|
+
case "Edit":
|
|
66
|
+
return transformEditParameters(parsedParams);
|
|
67
|
+
case "MultiEdit":
|
|
68
|
+
return transformMultiEditParameters(parsedParams);
|
|
69
|
+
default:
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger.warn("Failed to transform tool block to changes:", error);
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "CLI-based code assistant powered by AI, built with React and Ink",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"chalk": "^5.6.2",
|
|
28
28
|
"diff": "^8.0.2",
|
|
29
|
-
"glob": "^
|
|
29
|
+
"glob": "^13.0.0",
|
|
30
30
|
"ink": "^6.5.1",
|
|
31
31
|
"marked": "^11.2.0",
|
|
32
32
|
"marked-terminal": "^7.3.0",
|
|
33
33
|
"react": "^19.1.0",
|
|
34
34
|
"yargs": "^17.7.2",
|
|
35
|
-
"wave-agent-sdk": "0.0.
|
|
35
|
+
"wave-agent-sdk": "0.0.10"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/marked-terminal": "^6.1.1",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"eslint-plugin-react": "^7.37.5",
|
|
42
42
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
43
43
|
"ink-testing-library": "^4.0.0",
|
|
44
|
-
"rimraf": "^6.
|
|
44
|
+
"rimraf": "^6.1.2",
|
|
45
45
|
"tsc-alias": "^1.8.16",
|
|
46
46
|
"tsx": "^4.20.4",
|
|
47
47
|
"vitest": "^3.2.4"
|
|
@@ -50,10 +50,11 @@
|
|
|
50
50
|
"react": ">=18.0.0"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
|
-
"node": ">=
|
|
53
|
+
"node": ">=22.0.0"
|
|
54
54
|
},
|
|
55
55
|
"license": "MIT",
|
|
56
56
|
"scripts": {
|
|
57
|
+
"wave": "tsx src/index.ts",
|
|
57
58
|
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
58
59
|
"type-check": "tsc --noEmit --incremental",
|
|
59
60
|
"watch": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
package/src/cli.tsx
CHANGED
|
@@ -6,10 +6,11 @@ import { cleanupLogs } from "./utils/logger.js";
|
|
|
6
6
|
export interface CliOptions {
|
|
7
7
|
restoreSessionId?: string;
|
|
8
8
|
continueLastSession?: boolean;
|
|
9
|
+
bypassPermissions?: boolean;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export async function startCli(options: CliOptions): Promise<void> {
|
|
12
|
-
const { restoreSessionId, continueLastSession } = options;
|
|
13
|
+
const { restoreSessionId, continueLastSession, bypassPermissions } = options;
|
|
13
14
|
|
|
14
15
|
// Continue with ink-based UI for normal mode
|
|
15
16
|
// Global cleanup tracker
|
|
@@ -63,6 +64,7 @@ export async function startCli(options: CliOptions): Promise<void> {
|
|
|
63
64
|
<App
|
|
64
65
|
restoreSessionId={restoreSessionId}
|
|
65
66
|
continueLastSession={continueLastSession}
|
|
67
|
+
bypassPermissions={bypassPermissions}
|
|
66
68
|
/>,
|
|
67
69
|
);
|
|
68
70
|
|
package/src/components/App.tsx
CHANGED
|
@@ -6,11 +6,14 @@ import { AppProvider } from "../contexts/useAppConfig.js";
|
|
|
6
6
|
interface AppProps {
|
|
7
7
|
restoreSessionId?: string;
|
|
8
8
|
continueLastSession?: boolean;
|
|
9
|
+
bypassPermissions?: boolean;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
const AppWithProviders: React.FC = (
|
|
12
|
+
const AppWithProviders: React.FC<{ bypassPermissions?: boolean }> = ({
|
|
13
|
+
bypassPermissions,
|
|
14
|
+
}) => {
|
|
12
15
|
return (
|
|
13
|
-
<ChatProvider>
|
|
16
|
+
<ChatProvider bypassPermissions={bypassPermissions}>
|
|
14
17
|
<ChatInterface />
|
|
15
18
|
</ChatProvider>
|
|
16
19
|
);
|
|
@@ -19,13 +22,14 @@ const AppWithProviders: React.FC = () => {
|
|
|
19
22
|
export const App: React.FC<AppProps> = ({
|
|
20
23
|
restoreSessionId,
|
|
21
24
|
continueLastSession,
|
|
25
|
+
bypassPermissions,
|
|
22
26
|
}) => {
|
|
23
27
|
return (
|
|
24
28
|
<AppProvider
|
|
25
29
|
restoreSessionId={restoreSessionId}
|
|
26
30
|
continueLastSession={continueLastSession}
|
|
27
31
|
>
|
|
28
|
-
<AppWithProviders />
|
|
32
|
+
<AppWithProviders bypassPermissions={bypassPermissions} />
|
|
29
33
|
</AppProvider>
|
|
30
34
|
);
|
|
31
35
|
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
searchBashHistory,
|
|
5
|
+
deleteBashCommandFromHistory,
|
|
6
|
+
type BashHistoryEntry,
|
|
7
|
+
} from "wave-agent-sdk";
|
|
4
8
|
import { logger } from "../utils/logger.js";
|
|
5
9
|
|
|
6
10
|
export interface BashHistorySelectorProps {
|
|
@@ -20,6 +24,7 @@ export const BashHistorySelector: React.FC<BashHistorySelectorProps> = ({
|
|
|
20
24
|
}) => {
|
|
21
25
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
22
26
|
const [commands, setCommands] = useState<BashHistoryEntry[]>([]);
|
|
27
|
+
const [refreshCounter, setRefreshCounter] = useState(0);
|
|
23
28
|
|
|
24
29
|
// Search bash history
|
|
25
30
|
useEffect(() => {
|
|
@@ -30,8 +35,9 @@ export const BashHistorySelector: React.FC<BashHistorySelectorProps> = ({
|
|
|
30
35
|
searchQuery,
|
|
31
36
|
workdir,
|
|
32
37
|
resultCount: results.length,
|
|
38
|
+
refreshCounter,
|
|
33
39
|
});
|
|
34
|
-
}, [searchQuery, workdir]);
|
|
40
|
+
}, [searchQuery, workdir, refreshCounter]);
|
|
35
41
|
|
|
36
42
|
useInput((input, key) => {
|
|
37
43
|
logger.debug("BashHistorySelector useInput:", {
|
|
@@ -77,6 +83,22 @@ export const BashHistorySelector: React.FC<BashHistorySelectorProps> = ({
|
|
|
77
83
|
setSelectedIndex(Math.min(commands.length - 1, selectedIndex + 1));
|
|
78
84
|
return;
|
|
79
85
|
}
|
|
86
|
+
|
|
87
|
+
if (key.delete) {
|
|
88
|
+
if (commands.length > 0 && selectedIndex < commands.length) {
|
|
89
|
+
const selectedCommand = commands[selectedIndex];
|
|
90
|
+
deleteBashCommandFromHistory(
|
|
91
|
+
selectedCommand.command,
|
|
92
|
+
selectedCommand.workdir,
|
|
93
|
+
);
|
|
94
|
+
setRefreshCounter((prev) => prev + 1);
|
|
95
|
+
// Adjust selectedIndex if we deleted the last item
|
|
96
|
+
if (selectedIndex >= commands.length - 1 && selectedIndex > 0) {
|
|
97
|
+
setSelectedIndex(selectedIndex - 1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
80
102
|
});
|
|
81
103
|
|
|
82
104
|
if (commands.length === 0) {
|
|
@@ -155,7 +177,8 @@ export const BashHistorySelector: React.FC<BashHistorySelectorProps> = ({
|
|
|
155
177
|
|
|
156
178
|
<Box>
|
|
157
179
|
<Text dimColor>
|
|
158
|
-
Use ↑↓ to navigate, Enter to execute, Tab to insert,
|
|
180
|
+
Use ↑↓ to navigate, Enter to execute, Tab to insert, Delete to remove,
|
|
181
|
+
Escape to cancel
|
|
159
182
|
</Text>
|
|
160
183
|
</Box>
|
|
161
184
|
</Box>
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { Box } from "ink";
|
|
3
3
|
import { MessageList } from "./MessageList.js";
|
|
4
4
|
import { InputBox } from "./InputBox.js";
|
|
5
|
+
import { Confirmation } from "./Confirmation.js";
|
|
5
6
|
import { useChat } from "../contexts/useChat.js";
|
|
6
7
|
|
|
7
8
|
export const ChatInterface: React.FC = () => {
|
|
@@ -22,6 +23,10 @@ export const ChatInterface: React.FC = () => {
|
|
|
22
23
|
latestTotalTokens,
|
|
23
24
|
slashCommands,
|
|
24
25
|
hasSlashCommand,
|
|
26
|
+
isConfirmationVisible,
|
|
27
|
+
confirmingTool,
|
|
28
|
+
handleConfirmationDecision,
|
|
29
|
+
handleConfirmationCancel,
|
|
25
30
|
} = useChat();
|
|
26
31
|
|
|
27
32
|
if (!sessionId) return null;
|
|
@@ -38,21 +43,30 @@ export const ChatInterface: React.FC = () => {
|
|
|
38
43
|
key={String(isExpanded) + sessionId}
|
|
39
44
|
/>
|
|
40
45
|
|
|
41
|
-
{!isExpanded &&
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
{!isExpanded &&
|
|
47
|
+
(isConfirmationVisible ? (
|
|
48
|
+
<Confirmation
|
|
49
|
+
toolName={confirmingTool!.name}
|
|
50
|
+
toolInput={confirmingTool!.input}
|
|
51
|
+
onDecision={handleConfirmationDecision}
|
|
52
|
+
onCancel={handleConfirmationCancel}
|
|
53
|
+
onAbort={abortMessage}
|
|
54
|
+
/>
|
|
55
|
+
) : (
|
|
56
|
+
<InputBox
|
|
57
|
+
isLoading={isLoading}
|
|
58
|
+
isCommandRunning={isCommandRunning}
|
|
59
|
+
userInputHistory={userInputHistory}
|
|
60
|
+
sendMessage={sendMessage}
|
|
61
|
+
abortMessage={abortMessage}
|
|
62
|
+
saveMemory={saveMemory}
|
|
63
|
+
mcpServers={mcpServers}
|
|
64
|
+
connectMcpServer={connectMcpServer}
|
|
65
|
+
disconnectMcpServer={disconnectMcpServer}
|
|
66
|
+
slashCommands={slashCommands}
|
|
67
|
+
hasSlashCommand={hasSlashCommand}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
56
70
|
</Box>
|
|
57
71
|
);
|
|
58
72
|
};
|