@@ -3,12 +3,28 @@ import { create } from "zustand";
33import type { Message } from "./types.js" ;
44import { getNextAssistantResponse } from "./llm.js" ;
55import { runTool } from "./tools/index.js" ;
6- import { loadConfig , type Config } from "@/config.js" ;
6+ import { loadConfig , type Config , HISTORY_PATH , CONFIG_DIR } from "@/config.js" ;
77import type { ToolCallPart } from "ai" ;
88import { FatalError , ToolError , TransientError } from "./errors.js" ;
9+ import fs from "fs" ;
10+ import path from "path" ;
11+
12+ function loadCommandHistory ( ) : string [ ] {
13+ try {
14+ if ( ! fs . existsSync ( HISTORY_PATH ) ) {
15+ fs . mkdirSync ( path . dirname ( HISTORY_PATH ) , { recursive : true } ) ;
16+ }
17+ const historyContent = fs . readFileSync ( HISTORY_PATH , "utf-8" ) ;
18+ return historyContent . split ( "\n" ) . filter ( Boolean ) ;
19+ } catch ( error ) {
20+ return [ ] ;
21+ }
22+ }
923
1024type AppState = {
1125 history : Message [ ] ;
26+ commandHistory : string [ ] ;
27+ commandHistoryIndex : number ;
1228 mode : "idle" | "thinking" | "running-tool" ;
1329 config : Config | null ;
1430 helpMenuOpen : boolean ;
@@ -21,6 +37,9 @@ type AppActions = {
2137 _runAgentLogic : ( retryCount ?: number ) => Promise < void > ;
2238 toggleHelpMenu : ( ) => void ;
2339 clearHistory : ( ) => void ;
40+ addCommandToHistory : ( command : string ) => void ;
41+ getPreviousCommand : ( ) => string | null ;
42+ getNextCommand : ( ) => string | null ;
2443 } ;
2544} ;
2645
@@ -29,6 +48,8 @@ const INITIAL_BACKOFF_MS = 1000;
2948
3049export const useStore = create < AppState & AppActions > ( ( set , get ) => ( {
3150 history : [ ] ,
51+ commandHistory : loadCommandHistory ( ) ,
52+ commandHistoryIndex : loadCommandHistory ( ) . length ,
3253 mode : "idle" ,
3354 config : null ,
3455 helpMenuOpen : false ,
@@ -41,9 +62,52 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
4162 set ( ( state ) => ( { helpMenuOpen : ! state . helpMenuOpen } ) ) ;
4263 } ,
4364 clearHistory : ( ) => {
44- set ( { history : [ ] } ) ;
65+ set ( { history : [ ] , commandHistory : [ ] , commandHistoryIndex : 0 } ) ;
66+ try {
67+ fs . writeFileSync ( HISTORY_PATH , "" ) ;
68+ } catch ( err ) {
69+ // Handle error, e.g., log it
70+ console . error ( "Failed to clear history file:" , err ) ;
71+ }
72+ } ,
73+ addCommandToHistory : ( command ) => {
74+ const { commandHistory } = get ( ) ;
75+ const newCommandHistory = [ ...commandHistory , command ] ;
76+ set ( {
77+ commandHistory : newCommandHistory ,
78+ commandHistoryIndex : newCommandHistory . length ,
79+ } ) ;
80+ try {
81+ fs . appendFileSync ( HISTORY_PATH , command + "\n" ) ;
82+ } catch ( err ) {
83+ // Handle error, e.g., log it
84+ console . error ( "Failed to write to history file:" , err ) ;
85+ }
86+ } ,
87+ getPreviousCommand : ( ) => {
88+ const { commandHistory, commandHistoryIndex } = get ( ) ;
89+ if ( commandHistoryIndex > 0 ) {
90+ const newIndex = commandHistoryIndex - 1 ;
91+ set ( { commandHistoryIndex : newIndex } ) ;
92+ return commandHistory [ newIndex ] ?? null ;
93+ }
94+ return null ;
95+ } ,
96+ getNextCommand : ( ) => {
97+ const { commandHistory, commandHistoryIndex } = get ( ) ;
98+ if ( commandHistoryIndex < commandHistory . length - 1 ) {
99+ const newIndex = commandHistoryIndex + 1 ;
100+ set ( { commandHistoryIndex : newIndex } ) ;
101+ return commandHistory [ newIndex ] ?? null ;
102+ }
103+ if ( commandHistoryIndex === commandHistory . length - 1 ) {
104+ set ( { commandHistoryIndex : commandHistory . length } ) ;
105+ return "" ;
106+ }
107+ return null ;
45108 } ,
46109 startAgent : async ( input ) => {
110+ get ( ) . actions . addCommandToHistory ( input ) ;
47111 const newHistory : Message [ ] = [
48112 ...get ( ) . history ,
49113 { role : "user" , content : input , id : crypto . randomUUID ( ) } ,
0 commit comments