@testany/hephos 0.3.9 → 0.3.12
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/out/repl/ReplModeInk.d.ts.map +1 -1
- package/out/repl/ReplModeInk.js +221 -4
- package/out/repl/ReplModeInk.js.map +1 -1
- package/out/repl/components/HistoryOverlay.d.ts +22 -0
- package/out/repl/components/HistoryOverlay.d.ts.map +1 -0
- package/out/repl/components/HistoryOverlay.js +82 -0
- package/out/repl/components/HistoryOverlay.js.map +1 -0
- package/out/repl/hooks/useHistory.d.ts +76 -0
- package/out/repl/hooks/useHistory.d.ts.map +1 -0
- package/out/repl/hooks/useHistory.js +562 -0
- package/out/repl/hooks/useHistory.js.map +1 -0
- package/package.json +4 -1
- package/patches/ink-text-input+6.0.0.patch +30 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReplModeInk.d.ts","sourceRoot":"","sources":["../../src/repl/ReplModeInk.tsx"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"ReplModeInk.d.ts","sourceRoot":"","sources":["../../src/repl/ReplModeInk.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAq3FH,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,QAMjF"}
|
package/out/repl/ReplModeInk.js
CHANGED
|
@@ -25,6 +25,8 @@ import { SessionStorageService } from '@testany/agent-chatter-core';
|
|
|
25
25
|
import { RestorePrompt } from './components/RestorePrompt.js';
|
|
26
26
|
import { QueueDisplay } from './components/QueueDisplay.js';
|
|
27
27
|
import { TipsBar } from './components/TipsBar.js';
|
|
28
|
+
import { HistoryOverlay } from './components/HistoryOverlay.js';
|
|
29
|
+
import { useHistory } from './hooks/useHistory.js';
|
|
28
30
|
// Read version from package.json
|
|
29
31
|
const __filename = fileURLToPath(import.meta.url);
|
|
30
32
|
const __dirname = path.dirname(__filename);
|
|
@@ -230,6 +232,8 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
230
232
|
const [isExiting, setIsExiting] = useState(false);
|
|
231
233
|
const [queueState, setQueueState] = useState(null);
|
|
232
234
|
const [showTips, setShowTips] = useState(true); // Tips bar visibility (default: on)
|
|
235
|
+
// Command history management
|
|
236
|
+
const history = useHistory();
|
|
233
237
|
// Track previous queue size to detect DROP-triggered clears
|
|
234
238
|
const prevQueueSizeRef = useRef(0);
|
|
235
239
|
// Streaming event handling
|
|
@@ -560,7 +564,31 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
560
564
|
};
|
|
561
565
|
// Handle input submission (Enter key)
|
|
562
566
|
const handleInputSubmit = (value) => {
|
|
563
|
-
|
|
567
|
+
let submittedValue = value;
|
|
568
|
+
// Exit search mode if active (user submitted with Enter while in search mode)
|
|
569
|
+
// Use the selected history entry as the submitted value for consistency
|
|
570
|
+
if (history.searchMode) {
|
|
571
|
+
const selectedEntry = history.acceptSearch();
|
|
572
|
+
if (selectedEntry !== null) {
|
|
573
|
+
submittedValue = selectedEntry;
|
|
574
|
+
setInput(selectedEntry); // Sync input state
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
// Exit history mode if active (user submitted with Enter while browsing history)
|
|
578
|
+
// Use the selected history entry as the submitted value for consistency
|
|
579
|
+
else if (history.isActive) {
|
|
580
|
+
const selectedEntry = history.acceptHistory();
|
|
581
|
+
if (selectedEntry !== null) {
|
|
582
|
+
submittedValue = selectedEntry;
|
|
583
|
+
setInput(selectedEntry); // Sync input state
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
const trimmed = submittedValue.trim();
|
|
587
|
+
// Add to history with mode (filtering handled by hook)
|
|
588
|
+
if (trimmed) {
|
|
589
|
+
const historyMode = mode === 'conversation' ? 'conversation' : 'normal';
|
|
590
|
+
history.addEntry(trimmed, historyMode);
|
|
591
|
+
}
|
|
564
592
|
// Handle / commands
|
|
565
593
|
if (trimmed.startsWith('/')) {
|
|
566
594
|
const cmd = trimmed.split(' ')[0].toLowerCase();
|
|
@@ -645,8 +673,21 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
645
673
|
}
|
|
646
674
|
return;
|
|
647
675
|
}
|
|
648
|
-
// ESC key -
|
|
676
|
+
// ESC key - Exit search/history mode or cancel agent execution
|
|
649
677
|
if (key.escape) {
|
|
678
|
+
// First, check if we're in search mode
|
|
679
|
+
if (history.searchMode) {
|
|
680
|
+
const savedInput = history.exitSearchMode();
|
|
681
|
+
setInput(savedInput);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
// Then check if we're in history browsing mode
|
|
685
|
+
if (history.isActive) {
|
|
686
|
+
const savedInput = history.exitHistory();
|
|
687
|
+
setInput(savedInput);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
// Cancel agent execution in conversation mode
|
|
650
691
|
if (mode === 'conversation' && activeCoordinator && executingAgent) {
|
|
651
692
|
// Check if ESC cancellation is allowed (LLD-05: use uiPrefs)
|
|
652
693
|
if (uiPrefs.allowEscCancel) {
|
|
@@ -660,8 +701,83 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
660
701
|
}
|
|
661
702
|
}
|
|
662
703
|
}
|
|
704
|
+
// Ctrl+R - Enter search mode or search backward
|
|
705
|
+
if (key.ctrl && inputChar === 'r') {
|
|
706
|
+
if (mode === 'normal' || mode === 'conversation') {
|
|
707
|
+
const historyMode = mode === 'conversation' ? 'conversation' : 'normal';
|
|
708
|
+
if (history.searchMode) {
|
|
709
|
+
// Already in search mode - search backward
|
|
710
|
+
const result = history.searchBackward();
|
|
711
|
+
if (result !== null) {
|
|
712
|
+
setInput(result);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
// Enter search mode
|
|
717
|
+
history.enterSearchMode(input, historyMode);
|
|
718
|
+
}
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
// Ctrl+S - Search forward (only in search mode)
|
|
723
|
+
if (key.ctrl && inputChar === 's') {
|
|
724
|
+
if (history.searchMode) {
|
|
725
|
+
const result = history.searchForward();
|
|
726
|
+
if (result !== null) {
|
|
727
|
+
setInput(result);
|
|
728
|
+
}
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
// Ctrl+P - Navigate to previous (older) history entry (same as ↑)
|
|
733
|
+
if (key.ctrl && inputChar === 'p') {
|
|
734
|
+
if (mode === 'normal' || mode === 'conversation') {
|
|
735
|
+
const historyMode = mode === 'conversation' ? 'conversation' : 'normal';
|
|
736
|
+
// In search mode, navigate search results
|
|
737
|
+
if (history.searchMode) {
|
|
738
|
+
const result = history.searchBackward();
|
|
739
|
+
if (result !== null) {
|
|
740
|
+
setInput(result);
|
|
741
|
+
}
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
// Regular history navigation
|
|
745
|
+
const historyEntry = history.navigateUp(input, historyMode);
|
|
746
|
+
if (historyEntry !== null) {
|
|
747
|
+
setInput(historyEntry);
|
|
748
|
+
}
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
// Ctrl+N - Navigate to next (newer) history entry (same as ↓)
|
|
753
|
+
if (key.ctrl && inputChar === 'n') {
|
|
754
|
+
if (mode === 'normal' || mode === 'conversation') {
|
|
755
|
+
const historyMode = mode === 'conversation' ? 'conversation' : 'normal';
|
|
756
|
+
// In search mode, navigate search results
|
|
757
|
+
if (history.searchMode) {
|
|
758
|
+
const result = history.searchForward();
|
|
759
|
+
if (result !== null) {
|
|
760
|
+
setInput(result);
|
|
761
|
+
}
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
// Regular history navigation
|
|
765
|
+
const historyEntry = history.navigateDown(historyMode);
|
|
766
|
+
if (historyEntry !== null) {
|
|
767
|
+
setInput(historyEntry);
|
|
768
|
+
}
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
663
772
|
// Ctrl+C 退出或取消
|
|
664
773
|
if (key.ctrl && inputChar === 'c') {
|
|
774
|
+
// First, clean up any search/history state
|
|
775
|
+
if (history.searchMode) {
|
|
776
|
+
history.exitSearchMode();
|
|
777
|
+
}
|
|
778
|
+
else if (history.isActive) {
|
|
779
|
+
history.exitHistory();
|
|
780
|
+
}
|
|
665
781
|
if (mode === 'conversation' && activeCoordinator) {
|
|
666
782
|
// 退出对话模式
|
|
667
783
|
// stop() is async, fire-and-forget for UI responsiveness
|
|
@@ -741,14 +857,71 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
741
857
|
// normal/conversation/wizard/form 由 TextInput 的 onSubmit 处理
|
|
742
858
|
return;
|
|
743
859
|
}
|
|
860
|
+
// Alt+↑ - Large jump backward (skip 5 entries)
|
|
861
|
+
// Cross-platform: key.meta captures Option key on macOS, Alt key on Windows/Linux
|
|
862
|
+
// in most modern terminal emulators (Windows Terminal, iTerm2, etc.)
|
|
863
|
+
if (key.meta && key.upArrow) {
|
|
864
|
+
if ((mode === 'normal' || mode === 'conversation') && !history.searchMode) {
|
|
865
|
+
const historyMode = mode === 'conversation' ? 'conversation' : 'normal';
|
|
866
|
+
const historyEntry = history.jumpUp(input, historyMode);
|
|
867
|
+
if (historyEntry !== null) {
|
|
868
|
+
setInput(historyEntry);
|
|
869
|
+
}
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
// Alt+↓ - Large jump forward (skip 5 entries)
|
|
874
|
+
// Cross-platform: key.meta captures Option key on macOS, Alt key on Windows/Linux
|
|
875
|
+
if (key.meta && key.downArrow) {
|
|
876
|
+
if ((mode === 'normal' || mode === 'conversation') && !history.searchMode && history.isActive) {
|
|
877
|
+
const historyMode = mode === 'conversation' ? 'conversation' : 'normal';
|
|
878
|
+
const historyEntry = history.jumpDown(historyMode);
|
|
879
|
+
if (historyEntry !== null) {
|
|
880
|
+
setInput(historyEntry);
|
|
881
|
+
}
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
744
885
|
// 处理不同模式下的上下键导航
|
|
745
886
|
if (key.upArrow) {
|
|
887
|
+
// Search mode takes priority - navigate search results
|
|
888
|
+
if (history.searchMode) {
|
|
889
|
+
const result = history.searchBackward();
|
|
890
|
+
if (result !== null) {
|
|
891
|
+
setInput(result);
|
|
892
|
+
}
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
746
895
|
if (mode === 'normal') {
|
|
896
|
+
// If already in history mode, continue history navigation (disable command hints)
|
|
897
|
+
if (history.isActive) {
|
|
898
|
+
const historyEntry = history.navigateUp(input, 'normal');
|
|
899
|
+
if (historyEntry !== null) {
|
|
900
|
+
setInput(historyEntry);
|
|
901
|
+
}
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
// Not in history mode - check for command hints first
|
|
747
905
|
const matches = getMatches();
|
|
748
906
|
if (matches.length > 0) {
|
|
907
|
+
// Command hint navigation has priority when not in history mode
|
|
749
908
|
setSelectedIndex(prev => (prev > 0 ? prev - 1 : matches.length - 1));
|
|
750
909
|
return;
|
|
751
910
|
}
|
|
911
|
+
// No command hints - enter history mode
|
|
912
|
+
const historyEntry = history.navigateUp(input, 'normal');
|
|
913
|
+
if (historyEntry !== null) {
|
|
914
|
+
setInput(historyEntry);
|
|
915
|
+
}
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
else if (mode === 'conversation') {
|
|
919
|
+
// Regular history navigation in conversation mode
|
|
920
|
+
const historyEntry = history.navigateUp(input, 'conversation');
|
|
921
|
+
if (historyEntry !== null) {
|
|
922
|
+
setInput(historyEntry);
|
|
923
|
+
}
|
|
924
|
+
return;
|
|
752
925
|
}
|
|
753
926
|
else if (mode === 'menu' && menuItems.length > 0) {
|
|
754
927
|
setSelectedIndex(prev => (prev > 0 ? prev - 1 : menuItems.length - 1));
|
|
@@ -760,12 +933,43 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
760
933
|
}
|
|
761
934
|
}
|
|
762
935
|
if (key.downArrow) {
|
|
936
|
+
// Search mode takes priority - navigate search results
|
|
937
|
+
if (history.searchMode) {
|
|
938
|
+
const result = history.searchForward();
|
|
939
|
+
if (result !== null) {
|
|
940
|
+
setInput(result);
|
|
941
|
+
}
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
763
944
|
if (mode === 'normal') {
|
|
945
|
+
// If already in history mode, continue history navigation (disable command hints)
|
|
946
|
+
if (history.isActive) {
|
|
947
|
+
const historyEntry = history.navigateDown('normal');
|
|
948
|
+
if (historyEntry !== null) {
|
|
949
|
+
setInput(historyEntry);
|
|
950
|
+
}
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
// Not in history mode - check for command hints first
|
|
764
954
|
const matches = getMatches();
|
|
765
955
|
if (matches.length > 0) {
|
|
956
|
+
// Command hint navigation has priority when not in history mode
|
|
766
957
|
setSelectedIndex(prev => (prev < matches.length - 1 ? prev + 1 : 0));
|
|
767
958
|
return;
|
|
768
959
|
}
|
|
960
|
+
// No command hints and not in history mode - ↓ does nothing
|
|
961
|
+
// (history mode is entered via ↑, not ↓)
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
else if (mode === 'conversation') {
|
|
965
|
+
// If in history mode, continue navigation; otherwise ↓ does nothing
|
|
966
|
+
if (history.isActive) {
|
|
967
|
+
const historyEntry = history.navigateDown('conversation');
|
|
968
|
+
if (historyEntry !== null) {
|
|
969
|
+
setInput(historyEntry);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return;
|
|
769
973
|
}
|
|
770
974
|
else if (mode === 'menu' && menuItems.length > 0) {
|
|
771
975
|
setSelectedIndex(prev => (prev < menuItems.length - 1 ? prev + 1 : 0));
|
|
@@ -1620,6 +1824,13 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
1620
1824
|
}
|
|
1621
1825
|
}
|
|
1622
1826
|
}
|
|
1827
|
+
// Show search/history mode indicator in conversation mode
|
|
1828
|
+
if (history.searchMode) {
|
|
1829
|
+
return _jsxs(Text, { color: "yellow", children: ["[search:", teamName, "] ", history.searchQuery ? `"${history.searchQuery}"` : '', "> "] });
|
|
1830
|
+
}
|
|
1831
|
+
if (history.isActive) {
|
|
1832
|
+
return _jsxs(Text, { color: "green", bold: true, children: ["[history:", teamName, "] ", memberPrompt, "> "] });
|
|
1833
|
+
}
|
|
1623
1834
|
return _jsxs(Text, { color: "green", bold: true, children: ["[conversation:", teamName, "] ", memberPrompt, "> "] });
|
|
1624
1835
|
}
|
|
1625
1836
|
case 'wizard':
|
|
@@ -1627,10 +1838,16 @@ function App({ registryPath, debug = false, proxyUrl }) {
|
|
|
1627
1838
|
case 'form':
|
|
1628
1839
|
return _jsx(Text, { color: "cyan", bold: true, children: "[form] input> " });
|
|
1629
1840
|
default:
|
|
1630
|
-
// 'normal' mode
|
|
1841
|
+
// 'normal' mode - show search/history mode indicator
|
|
1842
|
+
if (history.searchMode) {
|
|
1843
|
+
return _jsxs(Text, { color: "yellow", children: ["[search] ", history.searchQuery ? `"${history.searchQuery}"` : '', "> "] });
|
|
1844
|
+
}
|
|
1845
|
+
if (history.isActive) {
|
|
1846
|
+
return _jsx(Text, { color: "cyan", children: "[history] hephos> " });
|
|
1847
|
+
}
|
|
1631
1848
|
return _jsx(Text, { color: "cyan", children: "[normal] hephos> " });
|
|
1632
1849
|
}
|
|
1633
|
-
})(), _jsx(TextInput, { value: input, onChange: setInput, onSubmit: handleInputSubmit, placeholder: " " })] }), _jsx(Text, { color: mode === 'conversation' ? 'green' : 'cyan', dimColor: true, children: '─'.repeat(terminalWidth - 4) })] })), !isExiting && mode === 'normal' && _jsx(CommandHints, { input: input, selectedIndex: selectedIndex }), !isExiting && mode === 'conversation' && (_jsx(TipsBar, { visible: showTips, terminalWidth: terminalWidth }))] }));
|
|
1850
|
+
})(), _jsx(TextInput, { value: input, onChange: setInput, onSubmit: handleInputSubmit, placeholder: " " })] }), _jsx(Text, { color: mode === 'conversation' ? 'green' : 'cyan', dimColor: true, children: '─'.repeat(terminalWidth - 4) })] })), !isExiting && (mode === 'normal' || mode === 'conversation') && (history.isActive || history.searchMode) && (_jsx(HistoryOverlay, { visible: true, entries: history.entries, currentIndex: history.currentIndex, activeMode: history.activeMode, searchMode: history.searchMode, searchQuery: history.searchQuery, terminalWidth: terminalWidth })), !isExiting && mode === 'normal' && !history.isActive && !history.searchMode && _jsx(CommandHints, { input: input, selectedIndex: selectedIndex }), !isExiting && mode === 'conversation' && !history.isActive && !history.searchMode && (_jsx(TipsBar, { visible: showTips, terminalWidth: terminalWidth }))] }));
|
|
1634
1851
|
}
|
|
1635
1852
|
export function startReplInk(registryPath, options = {}) {
|
|
1636
1853
|
render(_jsx(App, { registryPath: registryPath, debug: options.debug, proxyUrl: options.proxyUrl }), {
|