|
1 | 1 | import type { KeyEvent } from "@opentui/core"; |
2 | 2 | import { useKeyboard } from "@opentui/react"; |
3 | 3 | import { useEffect, useState } from "react"; |
| 4 | +import { getMemoryManager, isMemoryAvailable } from "../ai/memory"; |
4 | 5 | import type { |
5 | 6 | AppPreferences, |
6 | 7 | InteractionMode, |
@@ -80,13 +81,77 @@ export function SettingsMenu({ |
80 | 81 | persistPreferences, |
81 | 82 | }: SettingsMenuProps) { |
82 | 83 | const [selectedIdx, setSelectedIdx] = useState(0); |
| 84 | + const [storedMemoryCount, setStoredMemoryCount] = useState<number | null>(null); |
83 | 85 | const manager = getDaemonManager(); |
| 86 | + const openAiKeyMissing = !process.env.OPENAI_API_KEY; |
| 87 | + const openRouterKeyMissing = !process.env.OPENROUTER_API_KEY; |
| 88 | + const hasStoredMemories = (storedMemoryCount ?? 0) > 0; |
| 89 | + const memoryCountKnown = storedMemoryCount !== null; |
| 90 | + const memoryToggleDisabled = |
| 91 | + openAiKeyMissing || (openRouterKeyMissing && (!memoryCountKnown || storedMemoryCount === 0)); |
| 92 | + |
| 93 | + useEffect(() => { |
| 94 | + if (!openAiKeyMissing || !memoryEnabled) { |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + manager.memoryEnabled = false; |
| 99 | + setMemoryEnabled(false); |
| 100 | + persistPreferences({ memoryEnabled: false }); |
| 101 | + }, [manager, memoryEnabled, openAiKeyMissing, persistPreferences, setMemoryEnabled]); |
| 102 | + |
| 103 | + useEffect(() => { |
| 104 | + let cancelled = false; |
| 105 | + |
| 106 | + const loadStoredMemoryCount = async () => { |
| 107 | + if (!isMemoryAvailable()) { |
| 108 | + if (!cancelled) { |
| 109 | + setStoredMemoryCount(0); |
| 110 | + } |
| 111 | + return; |
| 112 | + } |
| 113 | + |
| 114 | + try { |
| 115 | + const memoryManager = getMemoryManager(); |
| 116 | + await memoryManager.initialize(); |
| 117 | + if (!memoryManager.isAvailable) { |
| 118 | + if (!cancelled) { |
| 119 | + setStoredMemoryCount(0); |
| 120 | + } |
| 121 | + return; |
| 122 | + } |
| 123 | + const storedMemories = await memoryManager.getAll(); |
| 124 | + if (!cancelled) { |
| 125 | + setStoredMemoryCount(storedMemories.length); |
| 126 | + } |
| 127 | + } catch { |
| 128 | + if (!cancelled) { |
| 129 | + setStoredMemoryCount(0); |
| 130 | + } |
| 131 | + } |
| 132 | + }; |
| 133 | + |
| 134 | + void loadStoredMemoryCount(); |
| 135 | + return () => { |
| 136 | + cancelled = true; |
| 137 | + }; |
| 138 | + }, []); |
| 139 | + |
84 | 140 | const interactionModeLocked = !canEnableVoiceOutput && interactionMode === "text"; |
85 | 141 | const interactionModeDescription = interactionModeLocked |
86 | 142 | ? "[LOCKED] OpenAI key required for voice output" |
87 | 143 | : interactionMode === "voice" |
88 | 144 | ? "Conversational responses and speech output" |
89 | 145 | : "Markdown responses for terminal"; |
| 146 | + const memoryDescription = openAiKeyMissing |
| 147 | + ? "[LOCKED] OPENAI_API_KEY is required for memory" |
| 148 | + : openRouterKeyMissing && !memoryCountKnown |
| 149 | + ? "[LOCKED] Checking stored memories... OPENROUTER_API_KEY missing: no new memories added" |
| 150 | + : memoryToggleDisabled |
| 151 | + ? "[LOCKED] No stored memories and OPENROUTER_API_KEY is missing, so no new memories can be added" |
| 152 | + : openRouterKeyMissing && hasStoredMemories |
| 153 | + ? "Inject stored memories only (OPENROUTER_API_KEY missing: no new memories added)" |
| 154 | + : "Auto-save messages + inject relevant memories"; |
90 | 155 |
|
91 | 156 | const items: SettingsMenuItem[] = [ |
92 | 157 | { |
@@ -146,8 +211,9 @@ export function SettingsMenu({ |
146 | 211 | id: "memory-enabled", |
147 | 212 | label: "Memory", |
148 | 213 | value: memoryEnabled ? "ON" : "OFF", |
149 | | - description: "Auto-save messages + inject relevant memories", |
| 214 | + description: memoryDescription, |
150 | 215 | isToggle: true, |
| 216 | + disabled: memoryToggleDisabled, |
151 | 217 | }, |
152 | 218 | ]; |
153 | 219 |
|
@@ -221,6 +287,7 @@ export function SettingsMenu({ |
221 | 287 | showFullReasoning, |
222 | 288 | showToolOutput, |
223 | 289 | memoryEnabled, |
| 290 | + memoryToggleDisabled, |
224 | 291 | setSelectedIdx, |
225 | 292 | toggleInteractionMode, |
226 | 293 | cycleModelProvider, |
|
0 commit comments