wave-code 0.2.0 → 0.4.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/commands/plugin/disable.d.ts +2 -1
- package/dist/commands/plugin/disable.d.ts.map +1 -1
- package/dist/commands/plugin/disable.js +3 -2
- package/dist/commands/plugin/enable.d.ts +2 -1
- package/dist/commands/plugin/enable.d.ts.map +1 -1
- package/dist/commands/plugin/enable.js +3 -2
- package/dist/commands/plugin/install.d.ts +2 -1
- package/dist/commands/plugin/install.d.ts.map +1 -1
- package/dist/commands/plugin/list.d.ts.map +1 -1
- package/dist/commands/plugin/list.js +15 -3
- package/dist/commands/plugin/marketplace.d.ts +3 -0
- package/dist/commands/plugin/marketplace.d.ts.map +1 -1
- package/dist/commands/plugin/marketplace.js +15 -1
- package/dist/commands/plugin/uninstall.d.ts +4 -0
- package/dist/commands/plugin/uninstall.d.ts.map +1 -0
- package/dist/commands/plugin/uninstall.js +29 -0
- package/dist/commands/plugin/update.d.ts +4 -0
- package/dist/commands/plugin/update.d.ts.map +1 -0
- package/dist/commands/plugin/update.js +15 -0
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +2 -2
- package/dist/components/CommandSelector.d.ts.map +1 -1
- package/dist/components/CommandSelector.js +6 -0
- package/dist/components/Confirmation.js +1 -1
- package/dist/components/DiscoverView.d.ts +3 -0
- package/dist/components/DiscoverView.d.ts.map +1 -0
- package/dist/components/DiscoverView.js +25 -0
- package/dist/components/FileSelector.js +1 -1
- package/dist/components/HistorySearch.d.ts +8 -0
- package/dist/components/HistorySearch.d.ts.map +1 -0
- package/dist/components/HistorySearch.js +67 -0
- package/dist/components/InputBox.d.ts +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +26 -17
- package/dist/components/InstalledView.d.ts +3 -0
- package/dist/components/InstalledView.d.ts.map +1 -0
- package/dist/components/InstalledView.js +30 -0
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown.js +22 -9
- package/dist/components/MarketplaceAddForm.d.ts +3 -0
- package/dist/components/MarketplaceAddForm.d.ts.map +1 -0
- package/dist/components/MarketplaceAddForm.js +26 -0
- package/dist/components/MarketplaceDetail.d.ts +3 -0
- package/dist/components/MarketplaceDetail.d.ts.map +1 -0
- package/dist/components/MarketplaceDetail.js +38 -0
- package/dist/components/MarketplaceList.d.ts +9 -0
- package/dist/components/MarketplaceList.d.ts.map +1 -0
- package/dist/components/MarketplaceList.js +16 -0
- package/dist/components/MarketplaceView.d.ts +3 -0
- package/dist/components/MarketplaceView.d.ts.map +1 -0
- package/dist/components/MarketplaceView.js +28 -0
- package/dist/components/PluginDetail.d.ts +3 -0
- package/dist/components/PluginDetail.d.ts.map +1 -0
- package/dist/components/PluginDetail.js +63 -0
- package/dist/components/PluginList.d.ts +14 -0
- package/dist/components/PluginList.d.ts.map +1 -0
- package/dist/components/PluginList.js +12 -0
- package/dist/components/PluginManagerShell.d.ts +5 -0
- package/dist/components/PluginManagerShell.d.ts.map +1 -0
- package/dist/components/PluginManagerShell.js +89 -0
- package/dist/components/PluginManagerTypes.d.ts +33 -0
- package/dist/components/PluginManagerTypes.d.ts.map +1 -0
- package/dist/components/PluginManagerTypes.js +1 -0
- package/dist/components/RewindCommand.d.ts +9 -0
- package/dist/components/RewindCommand.d.ts.map +1 -0
- package/dist/components/RewindCommand.js +42 -0
- package/dist/components/SessionSelector.d.ts +11 -0
- package/dist/components/SessionSelector.d.ts.map +1 -0
- package/dist/components/SessionSelector.js +38 -0
- package/dist/components/SubagentBlock.d.ts.map +1 -1
- package/dist/components/SubagentBlock.js +20 -1
- package/dist/components/ToolResultDisplay.js +1 -1
- package/dist/contexts/PluginManagerContext.d.ts +4 -0
- package/dist/contexts/PluginManagerContext.d.ts.map +1 -0
- package/dist/contexts/PluginManagerContext.js +9 -0
- package/dist/contexts/useChat.d.ts +2 -0
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +21 -0
- package/dist/hooks/useInputManager.d.ts +6 -14
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +29 -45
- package/dist/hooks/usePluginManager.d.ts +3 -0
- package/dist/hooks/usePluginManager.d.ts.map +1 -0
- package/dist/hooks/usePluginManager.js +223 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +150 -177
- package/dist/managers/InputManager.d.ts +12 -21
- package/dist/managers/InputManager.d.ts.map +1 -1
- package/dist/managers/InputManager.js +77 -108
- package/dist/plugin-manager-cli.d.ts +6 -0
- package/dist/plugin-manager-cli.d.ts.map +1 -0
- package/dist/plugin-manager-cli.js +12 -0
- package/dist/session-selector-cli.d.ts +2 -0
- package/dist/session-selector-cli.d.ts.map +1 -0
- package/dist/session-selector-cli.js +25 -0
- package/package.json +7 -3
- package/src/commands/plugin/disable.ts +7 -3
- package/src/commands/plugin/enable.ts +7 -3
- package/src/commands/plugin/install.ts +2 -1
- package/src/commands/plugin/list.ts +21 -3
- package/src/commands/plugin/marketplace.ts +17 -1
- package/src/commands/plugin/uninstall.ts +39 -0
- package/src/commands/plugin/update.ts +19 -0
- package/src/components/ChatInterface.tsx +2 -1
- package/src/components/CommandSelector.tsx +7 -0
- package/src/components/Confirmation.tsx +1 -1
- package/src/components/DiscoverView.tsx +31 -0
- package/src/components/FileSelector.tsx +1 -1
- package/src/components/HistorySearch.tsx +148 -0
- package/src/components/InputBox.tsx +43 -28
- package/src/components/InstalledView.tsx +61 -0
- package/src/components/Markdown.tsx +37 -26
- package/src/components/MarketplaceAddForm.tsx +39 -0
- package/src/components/MarketplaceDetail.tsx +79 -0
- package/src/components/MarketplaceList.tsx +52 -0
- package/src/components/MarketplaceView.tsx +43 -0
- package/src/components/PluginDetail.tsx +147 -0
- package/src/components/PluginList.tsx +51 -0
- package/src/components/PluginManagerShell.tsx +189 -0
- package/src/components/PluginManagerTypes.ts +47 -0
- package/src/components/RewindCommand.tsx +114 -0
- package/src/components/SessionSelector.tsx +127 -0
- package/src/components/SubagentBlock.tsx +29 -1
- package/src/components/ToolResultDisplay.tsx +2 -2
- package/src/contexts/PluginManagerContext.ts +15 -0
- package/src/contexts/useChat.tsx +26 -0
- package/src/hooks/useInputManager.ts +29 -61
- package/src/hooks/usePluginManager.ts +296 -0
- package/src/index.ts +241 -280
- package/src/managers/InputManager.ts +93 -149
- package/src/plugin-manager-cli.tsx +13 -0
- package/src/session-selector-cli.tsx +37 -0
- package/dist/components/BashHistorySelector.d.ts +0 -11
- package/dist/components/BashHistorySelector.d.ts.map +0 -1
- package/dist/components/BashHistorySelector.js +0 -93
- package/dist/hooks/usePagination.d.ts +0 -20
- package/dist/hooks/usePagination.d.ts.map +0 -1
- package/dist/hooks/usePagination.js +0 -168
- package/src/components/BashHistorySelector.tsx +0 -181
- package/src/hooks/usePagination.ts +0 -203
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FileItem } from "../components/FileSelector.js";
|
|
2
2
|
import {
|
|
3
3
|
searchFiles as searchFilesUtil,
|
|
4
|
-
deleteBashCommandFromHistory,
|
|
5
4
|
PermissionMode,
|
|
6
5
|
Logger,
|
|
6
|
+
PromptHistoryManager,
|
|
7
7
|
} from "wave-agent-sdk";
|
|
8
8
|
import { readClipboardImage } from "../utils/clipboard.js";
|
|
9
9
|
import type { Key } from "ink";
|
|
@@ -28,16 +28,14 @@ export interface InputManagerCallbacks {
|
|
|
28
28
|
query: string,
|
|
29
29
|
position: number,
|
|
30
30
|
) => void;
|
|
31
|
-
|
|
32
|
-
show: boolean,
|
|
33
|
-
query: string,
|
|
34
|
-
position: number,
|
|
35
|
-
) => void;
|
|
31
|
+
onHistorySearchStateChange?: (show: boolean, query: string) => void;
|
|
36
32
|
onMemoryTypeSelectorStateChange?: (show: boolean, message: string) => void;
|
|
37
33
|
onShowBashManager?: () => void;
|
|
38
34
|
onShowMcpManager?: () => void;
|
|
35
|
+
onShowRewindManager?: () => void;
|
|
39
36
|
onBashManagerStateChange?: (show: boolean) => void;
|
|
40
37
|
onMcpManagerStateChange?: (show: boolean) => void;
|
|
38
|
+
onRewindManagerStateChange?: (show: boolean) => void;
|
|
41
39
|
onImagesStateChange?: (images: AttachedImage[]) => void;
|
|
42
40
|
onSendMessage?: (
|
|
43
41
|
content: string,
|
|
@@ -68,10 +66,9 @@ export class InputManager {
|
|
|
68
66
|
private slashPosition: number = -1;
|
|
69
67
|
private commandSearchQuery: string = "";
|
|
70
68
|
|
|
71
|
-
//
|
|
72
|
-
private
|
|
73
|
-
private
|
|
74
|
-
private bashHistorySearchQuery: string = "";
|
|
69
|
+
// History search state
|
|
70
|
+
private showHistorySearch: boolean = false;
|
|
71
|
+
private historySearchQuery: string = "";
|
|
75
72
|
|
|
76
73
|
// Memory type selector state
|
|
77
74
|
private showMemoryTypeSelector: boolean = false;
|
|
@@ -99,6 +96,7 @@ export class InputManager {
|
|
|
99
96
|
// Additional UI state
|
|
100
97
|
private showBashManager: boolean = false;
|
|
101
98
|
private showMcpManager: boolean = false;
|
|
99
|
+
private showRewindManager: boolean = false;
|
|
102
100
|
|
|
103
101
|
// Permission mode state
|
|
104
102
|
private permissionMode: PermissionMode = "default";
|
|
@@ -369,6 +367,12 @@ export class InputManager {
|
|
|
369
367
|
} else if (command === "mcp" && this.callbacks.onShowMcpManager) {
|
|
370
368
|
this.callbacks.onShowMcpManager();
|
|
371
369
|
commandExecuted = true;
|
|
370
|
+
} else if (
|
|
371
|
+
command === "rewind" &&
|
|
372
|
+
this.callbacks.onShowRewindManager
|
|
373
|
+
) {
|
|
374
|
+
this.callbacks.onShowRewindManager();
|
|
375
|
+
commandExecuted = true;
|
|
372
376
|
}
|
|
373
377
|
}
|
|
374
378
|
})();
|
|
@@ -434,105 +438,6 @@ export class InputManager {
|
|
|
434
438
|
return false;
|
|
435
439
|
}
|
|
436
440
|
|
|
437
|
-
// Bash history selector methods
|
|
438
|
-
activateBashHistorySelector(position: number): void {
|
|
439
|
-
this.showBashHistorySelector = true;
|
|
440
|
-
this.exclamationPosition = position;
|
|
441
|
-
this.bashHistorySearchQuery = "";
|
|
442
|
-
|
|
443
|
-
this.callbacks.onBashHistorySelectorStateChange?.(true, "", position);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
updateBashHistorySearchQuery(query: string): void {
|
|
447
|
-
this.bashHistorySearchQuery = query;
|
|
448
|
-
this.callbacks.onBashHistorySelectorStateChange?.(
|
|
449
|
-
this.showBashHistorySelector,
|
|
450
|
-
query,
|
|
451
|
-
this.exclamationPosition,
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
handleBashHistorySelect(command: string): {
|
|
456
|
-
newInput: string;
|
|
457
|
-
newCursorPosition: number;
|
|
458
|
-
} {
|
|
459
|
-
if (this.exclamationPosition >= 0) {
|
|
460
|
-
const beforeExclamation = this.inputText.substring(
|
|
461
|
-
0,
|
|
462
|
-
this.exclamationPosition,
|
|
463
|
-
);
|
|
464
|
-
const afterQuery = this.inputText.substring(this.cursorPosition);
|
|
465
|
-
const newInput = beforeExclamation + `!${command}` + afterQuery;
|
|
466
|
-
const newCursorPosition = beforeExclamation.length + command.length + 1;
|
|
467
|
-
|
|
468
|
-
this.inputText = newInput;
|
|
469
|
-
this.cursorPosition = newCursorPosition;
|
|
470
|
-
|
|
471
|
-
this.handleCancelBashHistorySelect();
|
|
472
|
-
|
|
473
|
-
// Set flag to prevent handleInput from processing the same Enter key
|
|
474
|
-
this.selectorJustUsed = true;
|
|
475
|
-
setTimeout(() => {
|
|
476
|
-
this.selectorJustUsed = false;
|
|
477
|
-
}, 0);
|
|
478
|
-
|
|
479
|
-
this.callbacks.onInputTextChange?.(newInput);
|
|
480
|
-
this.callbacks.onCursorPositionChange?.(newCursorPosition);
|
|
481
|
-
|
|
482
|
-
return { newInput, newCursorPosition };
|
|
483
|
-
}
|
|
484
|
-
return { newInput: this.inputText, newCursorPosition: this.cursorPosition };
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
handleCancelBashHistorySelect(): void {
|
|
488
|
-
this.showBashHistorySelector = false;
|
|
489
|
-
this.exclamationPosition = -1;
|
|
490
|
-
this.bashHistorySearchQuery = "";
|
|
491
|
-
|
|
492
|
-
this.callbacks.onBashHistorySelectorStateChange?.(false, "", -1);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
handleBashHistoryExecute(command: string): string {
|
|
496
|
-
this.showBashHistorySelector = false;
|
|
497
|
-
this.exclamationPosition = -1;
|
|
498
|
-
this.bashHistorySearchQuery = "";
|
|
499
|
-
|
|
500
|
-
this.callbacks.onBashHistorySelectorStateChange?.(false, "", -1);
|
|
501
|
-
|
|
502
|
-
return command; // Return command to execute
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
handleBashHistoryExecuteAndSend(command: string): void {
|
|
506
|
-
const commandToExecute = this.handleBashHistoryExecute(command);
|
|
507
|
-
// Clear input box and execute command, ensure command starts with !
|
|
508
|
-
const bashCommand = commandToExecute.startsWith("!")
|
|
509
|
-
? commandToExecute
|
|
510
|
-
: `!${commandToExecute}`;
|
|
511
|
-
this.clearInput();
|
|
512
|
-
this.callbacks.onSendMessage?.(bashCommand);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
handleBashHistoryDelete(command: string, workdir?: string): void {
|
|
516
|
-
deleteBashCommandFromHistory(command, workdir);
|
|
517
|
-
// Trigger a refresh of the selector state to force re-render of BashHistorySelector
|
|
518
|
-
this.callbacks.onBashHistorySelectorStateChange?.(
|
|
519
|
-
this.showBashHistorySelector,
|
|
520
|
-
this.bashHistorySearchQuery,
|
|
521
|
-
this.exclamationPosition,
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
checkForExclamationDeletion(cursorPosition: number): boolean {
|
|
526
|
-
if (
|
|
527
|
-
this.showBashHistorySelector &&
|
|
528
|
-
cursorPosition <= this.exclamationPosition
|
|
529
|
-
) {
|
|
530
|
-
this.handleCancelBashHistorySelect();
|
|
531
|
-
return true;
|
|
532
|
-
}
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
441
|
// Memory type selector methods
|
|
537
442
|
activateMemoryTypeSelector(message: string): void {
|
|
538
443
|
this.showMemoryTypeSelector = true;
|
|
@@ -631,10 +536,6 @@ export class InputManager {
|
|
|
631
536
|
return this.showCommandSelector;
|
|
632
537
|
}
|
|
633
538
|
|
|
634
|
-
isBashHistorySelectorActive(): boolean {
|
|
635
|
-
return this.showBashHistorySelector;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
539
|
isMemoryTypeSelectorActive(): boolean {
|
|
639
540
|
return this.showMemoryTypeSelector;
|
|
640
541
|
}
|
|
@@ -656,14 +557,6 @@ export class InputManager {
|
|
|
656
557
|
};
|
|
657
558
|
}
|
|
658
559
|
|
|
659
|
-
getBashHistorySelectorState() {
|
|
660
|
-
return {
|
|
661
|
-
show: this.showBashHistorySelector,
|
|
662
|
-
query: this.bashHistorySearchQuery,
|
|
663
|
-
position: this.exclamationPosition,
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
|
|
667
560
|
getMemoryTypeSelectorState() {
|
|
668
561
|
return {
|
|
669
562
|
show: this.showMemoryTypeSelector,
|
|
@@ -686,11 +579,6 @@ export class InputManager {
|
|
|
686
579
|
const queryEnd = cursorPosition;
|
|
687
580
|
const newQuery = inputText.substring(queryStart, queryEnd);
|
|
688
581
|
this.updateCommandSearchQuery(newQuery);
|
|
689
|
-
} else if (this.showBashHistorySelector && this.exclamationPosition >= 0) {
|
|
690
|
-
const queryStart = this.exclamationPosition + 1;
|
|
691
|
-
const queryEnd = cursorPosition;
|
|
692
|
-
const newQuery = inputText.substring(queryStart, queryEnd);
|
|
693
|
-
this.updateBashHistorySearchQuery(newQuery);
|
|
694
582
|
}
|
|
695
583
|
}
|
|
696
584
|
|
|
@@ -698,11 +586,14 @@ export class InputManager {
|
|
|
698
586
|
handleSpecialCharInput(char: string): void {
|
|
699
587
|
if (char === "@") {
|
|
700
588
|
this.activateFileSelector(this.cursorPosition - 1);
|
|
701
|
-
} else if (
|
|
589
|
+
} else if (
|
|
590
|
+
char === "/" &&
|
|
591
|
+
!this.showFileSelector &&
|
|
592
|
+
this.cursorPosition === 1
|
|
593
|
+
) {
|
|
702
594
|
// Don't activate command selector when file selector is active
|
|
595
|
+
// Only activate command selector if '/' is at the start of input
|
|
703
596
|
this.activateCommandSelector(this.cursorPosition - 1);
|
|
704
|
-
} else if (char === "!" && this.cursorPosition === 1) {
|
|
705
|
-
this.activateBashHistorySelector(0);
|
|
706
597
|
} else if (char === "#" && this.cursorPosition === 1) {
|
|
707
598
|
// Memory message detection will be handled in submit
|
|
708
599
|
} else {
|
|
@@ -879,6 +770,15 @@ export class InputManager {
|
|
|
879
770
|
this.callbacks.onMcpManagerStateChange?.(show);
|
|
880
771
|
}
|
|
881
772
|
|
|
773
|
+
getShowRewindManager(): boolean {
|
|
774
|
+
return this.showRewindManager;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
setShowRewindManager(show: boolean): void {
|
|
778
|
+
this.showRewindManager = show;
|
|
779
|
+
this.callbacks.onRewindManagerStateChange?.(show);
|
|
780
|
+
}
|
|
781
|
+
|
|
882
782
|
// Permission mode methods
|
|
883
783
|
getPermissionMode(): PermissionMode {
|
|
884
784
|
return this.permissionMode;
|
|
@@ -941,6 +841,11 @@ export class InputManager {
|
|
|
941
841
|
let cleanContent = this.inputText.replace(imageRegex, "").trim();
|
|
942
842
|
cleanContent = this.expandLongTextPlaceholders(cleanContent);
|
|
943
843
|
|
|
844
|
+
// Save to prompt history
|
|
845
|
+
PromptHistoryManager.addEntry(cleanContent).catch((err: unknown) => {
|
|
846
|
+
this.logger?.error("Failed to save prompt history", err);
|
|
847
|
+
});
|
|
848
|
+
|
|
944
849
|
this.callbacks.onSendMessage?.(
|
|
945
850
|
cleanContent,
|
|
946
851
|
referencedImages.length > 0 ? referencedImages : undefined,
|
|
@@ -961,7 +866,6 @@ export class InputManager {
|
|
|
961
866
|
// Check for special character deletion
|
|
962
867
|
this.checkForAtDeletion(newCursorPosition);
|
|
963
868
|
this.checkForSlashDeletion(newCursorPosition);
|
|
964
|
-
this.checkForExclamationDeletion(newCursorPosition);
|
|
965
869
|
|
|
966
870
|
// Update search queries using the same logic as character input
|
|
967
871
|
this.updateSearchQueriesForActiveSelectors(
|
|
@@ -1004,6 +908,32 @@ export class InputManager {
|
|
|
1004
908
|
return false;
|
|
1005
909
|
}
|
|
1006
910
|
|
|
911
|
+
// History search methods
|
|
912
|
+
activateHistorySearch(): void {
|
|
913
|
+
this.showHistorySearch = true;
|
|
914
|
+
this.historySearchQuery = "";
|
|
915
|
+
this.callbacks.onHistorySearchStateChange?.(true, "");
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
updateHistorySearchQuery(query: string): void {
|
|
919
|
+
this.historySearchQuery = query;
|
|
920
|
+
this.callbacks.onHistorySearchStateChange?.(true, query);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
handleHistorySearchSelect(prompt: string): void {
|
|
924
|
+
this.inputText = prompt;
|
|
925
|
+
this.cursorPosition = prompt.length;
|
|
926
|
+
this.callbacks.onInputTextChange?.(prompt);
|
|
927
|
+
this.callbacks.onCursorPositionChange?.(prompt.length);
|
|
928
|
+
this.handleCancelHistorySearch();
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
handleCancelHistorySearch(): void {
|
|
932
|
+
this.showHistorySearch = false;
|
|
933
|
+
this.historySearchQuery = "";
|
|
934
|
+
this.callbacks.onHistorySearchStateChange?.(false, "");
|
|
935
|
+
}
|
|
936
|
+
|
|
1007
937
|
// Handle normal input (when no selector is active)
|
|
1008
938
|
async handleNormalInput(
|
|
1009
939
|
input: string,
|
|
@@ -1024,8 +954,6 @@ export class InputManager {
|
|
|
1024
954
|
this.handleCancelFileSelect();
|
|
1025
955
|
} else if (this.showCommandSelector) {
|
|
1026
956
|
this.handleCancelCommandSelect();
|
|
1027
|
-
} else if (this.showBashHistorySelector) {
|
|
1028
|
-
this.handleCancelBashHistorySelect();
|
|
1029
957
|
}
|
|
1030
958
|
return true;
|
|
1031
959
|
}
|
|
@@ -1039,7 +967,6 @@ export class InputManager {
|
|
|
1039
967
|
const newCursorPosition = this.cursorPosition - 1;
|
|
1040
968
|
this.checkForAtDeletion(newCursorPosition);
|
|
1041
969
|
this.checkForSlashDeletion(newCursorPosition);
|
|
1042
|
-
this.checkForExclamationDeletion(newCursorPosition);
|
|
1043
970
|
}
|
|
1044
971
|
return true;
|
|
1045
972
|
}
|
|
@@ -1072,23 +999,19 @@ export class InputManager {
|
|
|
1072
999
|
return true;
|
|
1073
1000
|
}
|
|
1074
1001
|
|
|
1002
|
+
// Handle Ctrl+R for history search
|
|
1003
|
+
if (key.ctrl && input === "r") {
|
|
1004
|
+
this.activateHistorySearch();
|
|
1005
|
+
return true;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1075
1008
|
// Handle up/down keys for history navigation (only when no selector is active)
|
|
1076
|
-
if (
|
|
1077
|
-
key.upArrow &&
|
|
1078
|
-
!this.showFileSelector &&
|
|
1079
|
-
!this.showCommandSelector &&
|
|
1080
|
-
!this.showBashHistorySelector
|
|
1081
|
-
) {
|
|
1009
|
+
if (key.upArrow && !this.showFileSelector && !this.showCommandSelector) {
|
|
1082
1010
|
this.navigateHistory("up", this.inputText);
|
|
1083
1011
|
return true;
|
|
1084
1012
|
}
|
|
1085
1013
|
|
|
1086
|
-
if (
|
|
1087
|
-
key.downArrow &&
|
|
1088
|
-
!this.showFileSelector &&
|
|
1089
|
-
!this.showCommandSelector &&
|
|
1090
|
-
!this.showBashHistorySelector
|
|
1091
|
-
) {
|
|
1014
|
+
if (key.downArrow && !this.showFileSelector && !this.showCommandSelector) {
|
|
1092
1015
|
this.navigateHistory("down", this.inputText);
|
|
1093
1016
|
return true;
|
|
1094
1017
|
}
|
|
@@ -1147,19 +1070,40 @@ export class InputManager {
|
|
|
1147
1070
|
if (
|
|
1148
1071
|
this.showFileSelector ||
|
|
1149
1072
|
this.showCommandSelector ||
|
|
1150
|
-
this.
|
|
1073
|
+
this.showHistorySearch ||
|
|
1151
1074
|
this.showMemoryTypeSelector ||
|
|
1152
1075
|
this.showBashManager ||
|
|
1153
|
-
this.showMcpManager
|
|
1076
|
+
this.showMcpManager ||
|
|
1077
|
+
this.showRewindManager
|
|
1154
1078
|
) {
|
|
1155
1079
|
if (
|
|
1156
1080
|
this.showMemoryTypeSelector ||
|
|
1157
1081
|
this.showBashManager ||
|
|
1158
|
-
this.showMcpManager
|
|
1082
|
+
this.showMcpManager ||
|
|
1083
|
+
this.showRewindManager
|
|
1159
1084
|
) {
|
|
1160
|
-
// Memory type selector, bash manager
|
|
1085
|
+
// Memory type selector, bash manager, MCP manager and Rewind don't need to handle input, handled by component itself
|
|
1161
1086
|
return false;
|
|
1162
1087
|
}
|
|
1088
|
+
|
|
1089
|
+
if (this.showHistorySearch) {
|
|
1090
|
+
if (key.escape) {
|
|
1091
|
+
this.handleCancelHistorySearch();
|
|
1092
|
+
return true;
|
|
1093
|
+
}
|
|
1094
|
+
if (key.backspace || key.delete) {
|
|
1095
|
+
if (this.historySearchQuery.length > 0) {
|
|
1096
|
+
this.updateHistorySearchQuery(this.historySearchQuery.slice(0, -1));
|
|
1097
|
+
}
|
|
1098
|
+
return true;
|
|
1099
|
+
}
|
|
1100
|
+
if (input && !key.ctrl && !key.meta && !key.return && !key.tab) {
|
|
1101
|
+
this.updateHistorySearchQuery(this.historySearchQuery + input);
|
|
1102
|
+
return true;
|
|
1103
|
+
}
|
|
1104
|
+
return true; // Let HistorySearch component handle arrows and Enter
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1163
1107
|
return this.handleSelectorInput(input, key);
|
|
1164
1108
|
} else {
|
|
1165
1109
|
return await this.handleNormalInput(
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "ink";
|
|
3
|
+
import { PluginManagerShell } from "./components/PluginManagerShell.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Entry point for the Plugin Manager CLI.
|
|
7
|
+
* Renders the Ink component and handles the lifecycle.
|
|
8
|
+
*/
|
|
9
|
+
export async function startPluginManagerCli(): Promise<boolean> {
|
|
10
|
+
const { waitUntilExit } = render(<PluginManagerShell />);
|
|
11
|
+
await waitUntilExit();
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, Box } from "ink";
|
|
3
|
+
import { listSessions, truncateContent } from "wave-agent-sdk";
|
|
4
|
+
import { SessionSelector } from "./components/SessionSelector.js";
|
|
5
|
+
|
|
6
|
+
export async function startSessionSelectorCli(): Promise<string | null> {
|
|
7
|
+
const currentWorkdir = process.cwd();
|
|
8
|
+
const sessions = await listSessions(currentWorkdir);
|
|
9
|
+
|
|
10
|
+
if (sessions.length === 0) {
|
|
11
|
+
console.log(`No sessions found for workdir: ${currentWorkdir}`);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const sessionsWithContent = sessions.map((s) => ({
|
|
16
|
+
...s,
|
|
17
|
+
firstMessage: truncateContent(s.firstMessage || "No content", 80),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const { unmount } = render(
|
|
22
|
+
<Box padding={1}>
|
|
23
|
+
<SessionSelector
|
|
24
|
+
sessions={sessionsWithContent}
|
|
25
|
+
onSelect={(sessionId) => {
|
|
26
|
+
unmount();
|
|
27
|
+
resolve(sessionId);
|
|
28
|
+
}}
|
|
29
|
+
onCancel={() => {
|
|
30
|
+
unmount();
|
|
31
|
+
resolve(null);
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
</Box>,
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface BashHistorySelectorProps {
|
|
3
|
-
searchQuery: string;
|
|
4
|
-
workdir: string;
|
|
5
|
-
onSelect: (command: string) => void;
|
|
6
|
-
onExecute: (command: string) => void;
|
|
7
|
-
onDelete: (command: string, workdir?: string) => void;
|
|
8
|
-
onCancel: () => void;
|
|
9
|
-
}
|
|
10
|
-
export declare const BashHistorySelector: React.FC<BashHistorySelectorProps>;
|
|
11
|
-
//# sourceMappingURL=BashHistorySelector.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BashHistorySelector.d.ts","sourceRoot":"","sources":["../../src/components/BashHistorySelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAsKlE,CAAC"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useEffect } from "react";
|
|
3
|
-
import { Box, Text, useInput } from "ink";
|
|
4
|
-
import { searchBashHistory } from "wave-agent-sdk";
|
|
5
|
-
import { logger } from "../utils/logger.js";
|
|
6
|
-
export const BashHistorySelector = ({ searchQuery, workdir, onSelect, onExecute, onDelete, onCancel, }) => {
|
|
7
|
-
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
8
|
-
const [commands, setCommands] = useState([]);
|
|
9
|
-
const [refreshCounter, setRefreshCounter] = useState(0);
|
|
10
|
-
// Search bash history
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
const results = searchBashHistory(searchQuery, 10);
|
|
13
|
-
setCommands(results);
|
|
14
|
-
setSelectedIndex(0);
|
|
15
|
-
logger.debug("Bash history search:", {
|
|
16
|
-
searchQuery,
|
|
17
|
-
workdir,
|
|
18
|
-
resultCount: results.length,
|
|
19
|
-
refreshCounter,
|
|
20
|
-
});
|
|
21
|
-
}, [searchQuery, workdir, refreshCounter]);
|
|
22
|
-
useInput((input, key) => {
|
|
23
|
-
logger.debug("BashHistorySelector useInput:", {
|
|
24
|
-
input,
|
|
25
|
-
key,
|
|
26
|
-
commandsLength: commands.length,
|
|
27
|
-
selectedIndex,
|
|
28
|
-
});
|
|
29
|
-
if (key.return) {
|
|
30
|
-
if (commands.length > 0 && selectedIndex < commands.length) {
|
|
31
|
-
const selectedCommand = commands[selectedIndex];
|
|
32
|
-
onExecute(selectedCommand.command);
|
|
33
|
-
}
|
|
34
|
-
else if (commands.length === 0 && searchQuery.trim()) {
|
|
35
|
-
// When no history records match, execute the search query as a new command
|
|
36
|
-
onExecute(searchQuery.trim());
|
|
37
|
-
}
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (key.tab) {
|
|
41
|
-
if (commands.length > 0 && selectedIndex < commands.length) {
|
|
42
|
-
const selectedCommand = commands[selectedIndex];
|
|
43
|
-
onSelect(selectedCommand.command);
|
|
44
|
-
}
|
|
45
|
-
else if (commands.length === 0 && searchQuery.trim()) {
|
|
46
|
-
// When no history records match, insert the search query
|
|
47
|
-
onSelect(searchQuery.trim());
|
|
48
|
-
}
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (key.escape) {
|
|
52
|
-
onCancel();
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (key.ctrl && input === "d") {
|
|
56
|
-
if (commands.length > 0 && selectedIndex < commands.length) {
|
|
57
|
-
const selectedCommand = commands[selectedIndex];
|
|
58
|
-
onDelete(selectedCommand.command, selectedCommand.workdir);
|
|
59
|
-
setRefreshCounter((prev) => prev + 1);
|
|
60
|
-
}
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (key.upArrow) {
|
|
64
|
-
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (key.downArrow) {
|
|
68
|
-
setSelectedIndex(Math.min(commands.length - 1, selectedIndex + 1));
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
if (commands.length === 0) {
|
|
73
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "yellow", children: ["No bash history found ", searchQuery && `for "${searchQuery}"`] }), searchQuery.trim() && (_jsxs(Text, { color: "green", children: ["Press Enter to execute: ", searchQuery] })), searchQuery.trim() && (_jsxs(Text, { color: "blue", children: ["Press Tab to insert: ", searchQuery] })), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
|
|
74
|
-
}
|
|
75
|
-
const formatTimestamp = (timestamp) => {
|
|
76
|
-
const date = new Date(timestamp);
|
|
77
|
-
const now = new Date();
|
|
78
|
-
const diffMs = now.getTime() - date.getTime();
|
|
79
|
-
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
80
|
-
const diffDays = Math.floor(diffHours / 24);
|
|
81
|
-
if (diffDays > 0) {
|
|
82
|
-
return `${diffDays}d ago`;
|
|
83
|
-
}
|
|
84
|
-
else if (diffHours > 0) {
|
|
85
|
-
return `${diffHours}h ago`;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
89
|
-
return diffMinutes > 0 ? `${diffMinutes}m ago` : "just now";
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "blue", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "blue", bold: true, children: ["Bash History ", searchQuery && `(filtering: "${searchQuery}")`] }) }), commands.map((cmd, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "blue" : undefined, children: cmd.command }), index === selectedIndex && (_jsx(Box, { marginLeft: 4, flexDirection: "column", children: _jsxs(Text, { color: "gray", dimColor: true, children: [formatTimestamp(cmd.timestamp), cmd.workdir !== workdir && ` • in ${cmd.workdir}`] }) }))] }, index))), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to execute, Tab to insert, Ctrl+d to remove, Escape to cancel" }) })] }));
|
|
93
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Message } from "wave-agent-sdk";
|
|
2
|
-
interface PaginationInfo {
|
|
3
|
-
currentPage: number;
|
|
4
|
-
totalPages: number;
|
|
5
|
-
startIndex: number;
|
|
6
|
-
endIndex: number;
|
|
7
|
-
messagesPerPage: number;
|
|
8
|
-
}
|
|
9
|
-
export declare const usePagination: (messages: Message[]) => {
|
|
10
|
-
displayInfo: PaginationInfo;
|
|
11
|
-
manualPage: number | null;
|
|
12
|
-
setManualPage: import("react").Dispatch<import("react").SetStateAction<number | null>>;
|
|
13
|
-
goToPage: (page: number | null) => void;
|
|
14
|
-
goToPrevPage: () => void;
|
|
15
|
-
goToNextPage: () => void;
|
|
16
|
-
goToFirstPage: () => void;
|
|
17
|
-
goToLastPage: () => void;
|
|
18
|
-
};
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=usePagination.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePagination.d.ts","sourceRoot":"","sources":["../../src/hooks/usePagination.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,aAAa,GAAI,UAAU,OAAO,EAAE;;;;qBAwIvB,MAAM,GAAG,IAAI;;;;;CAqDtC,CAAC"}
|