Skip to content

Commit 1b6b595

Browse files
committed
fix(apps): remove local storage for llm api
1 parent 9736a76 commit 1b6b595

File tree

1 file changed

+129
-87
lines changed

1 file changed

+129
-87
lines changed

apps/playground/app/config/page.tsx

Lines changed: 129 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -131,106 +131,152 @@ export default function ConfigPage() {
131131
loadChains()
132132
}, [])
133133

134+
// Prefill from persisted store config (Polkadot) when available
135+
useEffect(() => {
136+
if (config) {
137+
setAgentConfig((prev) => ({
138+
...prev,
139+
privateKey: config.privateKey || prev.privateKey,
140+
keyType: (config.keyType as string) || prev.keyType,
141+
chains: (config.chains as string[]) || prev.chains,
142+
}))
143+
}
144+
}, [config])
145+
146+
// Prefill LLM config from localStorage when available
147+
useEffect(() => {
148+
try {
149+
const saved = localStorage.getItem("llm_config")
150+
if (saved) {
151+
const { provider, model, apiKey } = JSON.parse(saved)
152+
setAgentConfig((prev) => ({
153+
...prev,
154+
llmProvider: provider || prev.llmProvider,
155+
llmModel: model || prev.llmModel,
156+
apiKey: apiKey || prev.apiKey,
157+
}))
158+
}
159+
} catch (e) {
160+
// ignore
161+
}
162+
}, [])
163+
134164
const handleConfigureAgent = async () => {
135165
const needsApiKey = agentConfig.llmProvider === "openai"
136-
if (!agentConfig.llmProvider) {
137-
alert("Please select an LLM provider")
138-
return
166+
167+
// Determine what changed vs persisted values
168+
const prevLlmRaw = typeof window !== 'undefined' ? localStorage.getItem("llm_config") : null
169+
const prevLlm = prevLlmRaw ? JSON.parse(prevLlmRaw) : null
170+
const prevAgent = config
171+
172+
const llmChanged = (() => {
173+
const prevProvider = prevLlm?.provider || ""
174+
const prevModel = prevLlm?.model || ""
175+
const prevApiKey = prevLlm?.apiKey || ""
176+
return (
177+
prevProvider !== agentConfig.llmProvider ||
178+
prevModel !== agentConfig.llmModel ||
179+
(needsApiKey && (prevApiKey || "") !== (agentConfig.apiKey || ""))
180+
)
181+
})()
182+
183+
const chainsEqual = (a: string[] = [], b: string[] = []) => {
184+
if (a.length !== b.length) return false
185+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false
186+
return true
139187
}
140-
141-
// For OpenAI, check if API key is provided or use environment variable
142-
if (needsApiKey) {
143-
const apiKey = agentConfig.apiKey || process.env.NEXT_PUBLIC_OPENAI_KEY
144-
if (!apiKey) {
145-
alert("API key is required for OpenAI. Please provide it in the input field or set NEXT_PUBLIC_OPENAI_KEY environment variable.")
188+
const polkadotChanged = (() => {
189+
if (!prevAgent) return true
190+
return (
191+
prevAgent.privateKey !== agentConfig.privateKey ||
192+
prevAgent.keyType !== (agentConfig.keyType as any) ||
193+
!chainsEqual(prevAgent.chains as any, agentConfig.chains)
194+
)
195+
})()
196+
197+
// Validate only the parts that changed
198+
if (llmChanged) {
199+
if (!agentConfig.llmProvider) {
200+
alert("Please select an LLM provider")
146201
return
147202
}
148-
// Update the config with the API key (either from input or env)
149-
agentConfig.apiKey = apiKey
150-
}
151-
if (!agentConfig.privateKey) {
152-
alert("Private key is required")
153-
return
154-
}
155-
if (!agentConfig.keyType) {
156-
alert("Please select a key type")
157-
return
203+
if (needsApiKey) {
204+
const apiKey = agentConfig.apiKey || process.env.NEXT_PUBLIC_OPENAI_KEY
205+
if (!apiKey) {
206+
alert("API key is required for OpenAI. Provide it or set NEXT_PUBLIC_OPENAI_KEY.")
207+
return
208+
}
209+
agentConfig.apiKey = apiKey
210+
}
158211
}
159-
if (!agentConfig.chains || agentConfig.chains.length === 0) {
160-
alert("Please select at least one chain")
161-
return
212+
213+
if (polkadotChanged) {
214+
if (!agentConfig.privateKey) {
215+
alert("Private key is required")
216+
return
217+
}
218+
if (!agentConfig.keyType) {
219+
alert("Please select a key type")
220+
return
221+
}
222+
if (!agentConfig.chains || agentConfig.chains.length === 0) {
223+
alert("Please select at least one chain")
224+
return
225+
}
162226
}
163227

164228
setInitializing(true)
165229
setLlmConnected("idle")
166230

167231
try {
168-
// Save API key temporarily in localStorage (client-side only)
169-
if (needsApiKey) {
170-
localStorage.setItem("llm_api_key", agentConfig.apiKey)
171-
} else {
172-
localStorage.removeItem("llm_api_key")
173-
}
232+
// If LLM changed, persist LLM config and (optionally) validate
233+
if (llmChanged) {
234+
localStorage.setItem("llm_config", JSON.stringify({
235+
provider: agentConfig.llmProvider,
236+
model: agentConfig.llmModel,
237+
apiKey: agentConfig.llmProvider === "openai" ? agentConfig.apiKey : null
238+
}))
174239

175-
// Save LLM config to localStorage
176-
localStorage.setItem("llm_config", JSON.stringify({
177-
provider: agentConfig.llmProvider,
178-
model: agentConfig.llmModel,
179-
apiKey: agentConfig.apiKey
180-
}))
181-
182-
// Create config for Zustand store
183-
const storeConfig = {
184-
privateKey: agentConfig.privateKey,
185-
keyType: agentConfig.keyType as "Sr25519" | "Ed25519",
186-
chains: agentConfig.chains,
187-
isConfigured: true
188-
}
189-
190-
191-
try {
192-
setConfig(storeConfig)
193-
194-
// Check store state after setConfig
195-
setTimeout(() => {
196-
console.log('[ConfigPage] Store state after setConfig:', { config, isConfigured })
197-
}, 100)
198-
} catch (error) {
199-
console.error('[ConfigPage] Error calling setConfig:', error)
240+
if (agentConfig.llmProvider === "ollama") {
241+
const controller = new AbortController()
242+
const timeout = setTimeout(() => controller.abort(), 2500)
243+
try {
244+
const res = await fetch("http://127.0.0.1:11434/api/tags", { signal: controller.signal })
245+
setLlmConnected(res.ok ? "ok" : "error")
246+
} catch (_) {
247+
setLlmConnected("error")
248+
} finally {
249+
clearTimeout(timeout)
250+
}
251+
} else if (agentConfig.llmProvider === "openai") {
252+
try {
253+
const validation = await validateOpenAIKey(agentConfig.apiKey)
254+
setLlmConnected(validation.isValid ? "ok" : "error")
255+
if (!validation.isValid) {
256+
console.warn("OpenAI validation failed:", validation.error)
257+
alert(`OpenAI validation failed: ${validation.error}`)
258+
}
259+
} catch (e: any) {
260+
console.warn("OpenAI validation error:", e?.message || e)
261+
setLlmConnected("error")
262+
}
263+
}
200264
}
201265

202-
// Initialize agent using Zustand store
203-
await initializeAgent()
204-
205-
// Check LLM connectivity
206-
if (agentConfig.llmProvider === "ollama") {
207-
// Try ping local Ollama
208-
const controller = new AbortController()
209-
const timeout = setTimeout(() => controller.abort(), 2500)
210-
try {
211-
const res = await fetch("http://127.0.0.1:11434/api/tags", { signal: controller.signal })
212-
setLlmConnected(res.ok ? "ok" : "error")
213-
} catch (_) {
214-
setLlmConnected("error")
215-
} finally {
216-
clearTimeout(timeout)
266+
// If Polkadot config changed, update store and (re)initialize agent
267+
if (polkadotChanged) {
268+
const storeConfig = {
269+
privateKey: agentConfig.privateKey,
270+
keyType: agentConfig.keyType as "Sr25519" | "Ed25519",
271+
chains: agentConfig.chains,
272+
isConfigured: true
217273
}
218-
} else if (agentConfig.llmProvider === "openai") {
219-
// Validate OpenAI API key and check gpt-4o-mini availability
220-
// Note: OpenAI may block browser requests (CORS). Treat failures as non-fatal
221-
// for agent initialization so the Polkadot Agent can still be used.
222274
try {
223-
const validation = await validateOpenAIKey(agentConfig.apiKey)
224-
setLlmConnected(validation.isValid ? "ok" : "error")
225-
if (!validation.isValid) {
226-
console.warn("OpenAI validation failed:", validation.error)
227-
alert(`OpenAI validation failed: ${validation.error}`)
228-
}
229-
} catch (e: any) {
230-
console.warn("OpenAI validation error:", e?.message || e)
231-
setLlmConnected("error")
232-
// continue without throwing to keep agent initialized
275+
setConfig(storeConfig)
276+
} catch (error) {
277+
console.error('[ConfigPage] Error calling setConfig:', error)
233278
}
279+
await initializeAgent()
234280
}
235281

236282
const updatedConfig = { ...agentConfig, isConfigured: true }
@@ -420,11 +466,7 @@ export default function ConfigPage() {
420466
<Button
421467
onClick={handleConfigureAgent}
422468
disabled={
423-
isInitializing ||
424-
!agentConfig.llmProvider ||
425-
!agentConfig.privateKey ||
426-
agentConfig.chains.length === 0 ||
427-
(agentConfig.llmProvider === "openai" && !agentConfig.apiKey && !process.env.NEXT_PUBLIC_OPENAI_KEY)
469+
isInitializing
428470
}
429471
className="mt-6 sm:mt-8 px-6 sm:px-8 h-10 sm:h-12 text-sm sm:text-base font-medium modern-button-primary w-full sm:w-auto"
430472
>

0 commit comments

Comments
 (0)