Skip to content

Commit 5b6f9b5

Browse files
committed
Persist user message history to config dir message-history.json
1 parent 1f43900 commit 5b6f9b5

File tree

2 files changed

+119
-2
lines changed

2 files changed

+119
-2
lines changed

cli/src/hooks/use-input-history.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { useRef, useCallback } from 'react'
1+
import { useRef, useCallback, useEffect } from 'react'
2+
3+
import {
4+
loadMessageHistory,
5+
saveMessageHistory,
6+
} from '../utils/message-history'
27

38
export const useInputHistory = (
49
inputValue: string,
@@ -7,11 +12,25 @@ export const useInputHistory = (
712
const messageHistoryRef = useRef<string[]>([])
813
const historyIndexRef = useRef<number>(-1)
914
const currentDraftRef = useRef<string>('')
15+
const isInitializedRef = useRef<boolean>(false)
16+
17+
// Load history from disk on mount
18+
useEffect(() => {
19+
if (!isInitializedRef.current) {
20+
isInitializedRef.current = true
21+
const savedHistory = loadMessageHistory()
22+
messageHistoryRef.current = savedHistory
23+
}
24+
}, [])
1025

1126
const saveToHistory = useCallback((message: string) => {
12-
messageHistoryRef.current = [...messageHistoryRef.current, message]
27+
const newHistory = [...messageHistoryRef.current, message]
28+
messageHistoryRef.current = newHistory
1329
historyIndexRef.current = -1
1430
currentDraftRef.current = ''
31+
32+
// Persist to disk
33+
saveMessageHistory(newHistory)
1534
}, [])
1635

1736
const navigateUp = useCallback(() => {

cli/src/utils/message-history.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import fs from 'fs'
2+
import path from 'path'
3+
4+
import { getConfigDir } from './auth'
5+
import { logger } from './logger'
6+
7+
const MAX_HISTORY_SIZE = 1000
8+
9+
/**
10+
* Get the message history file path
11+
*/
12+
export const getMessageHistoryPath = (): string => {
13+
return path.join(getConfigDir(), 'message-history.json')
14+
}
15+
16+
/**
17+
* Load message history from file system
18+
* @returns Array of previous messages, most recent last
19+
*/
20+
export const loadMessageHistory = (): string[] => {
21+
const historyPath = getMessageHistoryPath()
22+
23+
if (!fs.existsSync(historyPath)) {
24+
return []
25+
}
26+
27+
try {
28+
const historyFile = fs.readFileSync(historyPath, 'utf8')
29+
const history = JSON.parse(historyFile)
30+
31+
if (!Array.isArray(history)) {
32+
logger.warn('Message history file has invalid format, resetting')
33+
return []
34+
}
35+
36+
return history.filter((item) => typeof item === 'string')
37+
} catch (error) {
38+
logger.error(
39+
{
40+
error: error instanceof Error ? error.message : String(error),
41+
},
42+
'Error reading message history',
43+
)
44+
return []
45+
}
46+
}
47+
48+
/**
49+
* Save message history to file system
50+
*/
51+
export const saveMessageHistory = (history: string[]): void => {
52+
const configDir = getConfigDir()
53+
const historyPath = getMessageHistoryPath()
54+
55+
try {
56+
// Ensure config directory exists
57+
if (!fs.existsSync(configDir)) {
58+
fs.mkdirSync(configDir, { recursive: true })
59+
}
60+
61+
// Limit history size to prevent file from growing too large
62+
const limitedHistory =
63+
history.length > MAX_HISTORY_SIZE
64+
? history.slice(history.length - MAX_HISTORY_SIZE)
65+
: history
66+
67+
// Save history
68+
fs.writeFileSync(historyPath, JSON.stringify(limitedHistory, null, 2))
69+
} catch (error) {
70+
logger.error(
71+
{
72+
error: error instanceof Error ? error.message : String(error),
73+
},
74+
'Error saving message history',
75+
)
76+
// Don't throw - history persistence is not critical
77+
}
78+
}
79+
80+
/**
81+
* Clear message history from file system
82+
*/
83+
export const clearMessageHistory = (): void => {
84+
const historyPath = getMessageHistoryPath()
85+
86+
try {
87+
if (fs.existsSync(historyPath)) {
88+
fs.unlinkSync(historyPath)
89+
}
90+
} catch (error) {
91+
logger.error(
92+
{
93+
error: error instanceof Error ? error.message : String(error),
94+
},
95+
'Error clearing message history',
96+
)
97+
}
98+
}

0 commit comments

Comments
 (0)