diff options
| author | Adam Malczewski <[email protected]> | 2026-05-29 14:24:55 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-29 14:24:55 +0900 |
| commit | aa230050f4edb7bfc8d3e4d59d95c68c36264b41 (patch) | |
| tree | ee9c4b4d2087618f41bf7bdcaed6a145fc0f0125 | |
| parent | 520c9e30cc58b40d3b1ee9e7895f003c4f873206 (diff) | |
| download | dispatch-aa230050f4edb7bfc8d3e4d59d95c68c36264b41.tar.gz dispatch-aa230050f4edb7bfc8d3e4d59d95c68c36264b41.zip | |
fix: refresh agent config on send; widen fallback retry detection
- Refresh agent config from API before sending a message so edits
in AgentBuilder (changed keyId/modelId/agentModels) take effect
immediately on existing tabs instead of using stale snapshots
- Broaden isRetryable check to also match 'usage limit' and
'exhausted' so fallback keys are actually tried on quota errors
| -rw-r--r-- | packages/api/src/agent-manager.ts | 4 | ||||
| -rw-r--r-- | packages/frontend/src/lib/tabs.svelte.ts | 44 |
2 files changed, 46 insertions, 2 deletions
diff --git a/packages/api/src/agent-manager.ts b/packages/api/src/agent-manager.ts index 88503f3..9ed2f51 100644 --- a/packages/api/src/agent-manager.ts +++ b/packages/api/src/agent-manager.ts @@ -1248,7 +1248,9 @@ export class AgentManager { const isRetryable = attemptError.includes("status=429") || attemptError.toLowerCase().includes("rate limit") || - attemptError.toLowerCase().includes("rate_limit"); + attemptError.toLowerCase().includes("rate_limit") || + attemptError.toLowerCase().includes("usage limit") || + attemptError.toLowerCase().includes("exhausted"); if (isRetryable && this.modelRegistry && tabAgent.keyId) { this.modelRegistry.markKeyExhausted(tabAgent.keyId, attemptError); diff --git a/packages/frontend/src/lib/tabs.svelte.ts b/packages/frontend/src/lib/tabs.svelte.ts index b2c4480..9b31b3f 100644 --- a/packages/frontend/src/lib/tabs.svelte.ts +++ b/packages/frontend/src/lib/tabs.svelte.ts @@ -1194,6 +1194,41 @@ export function createTabStore() { } } + async function refreshAgentConfig(tabId: string): Promise<void> { + const tab = getTabById(tabId); + if (!tab?.agentSlug || !tab.agentScope) return; + try { + const res = await fetch(`${config.apiBase}/agents`); + if (!res.ok) return; + const data = (await res.json()) as { + agents?: Array<{ + slug: string; + scope: string; + models: Array<{ key_id: string; model_id: string }>; + cwd?: string; + }>; + }; + const agents = data.agents ?? []; + const freshAgent = agents.find((a) => a.slug === tab.agentSlug && a.scope === tab.agentScope); + if (!freshAgent) return; + const firstModel = freshAgent.models[0]; + const patch: Partial<Tab> = { + agentModels: freshAgent.models, + workingDirectory: freshAgent.cwd || null, + }; + if (firstModel) { + patch.keyId = firstModel.key_id; + patch.modelId = firstModel.model_id; + } else { + patch.keyId = null; + patch.modelId = null; + } + updateTab(tabId, patch); + } catch { + // Silently fall back to stale values + } + } + async function fetchSkillContent(scope: string, name: string): Promise<string | null> { try { const res = await fetch( @@ -1208,9 +1243,16 @@ export function createTabStore() { } async function sendMessage(text: string): Promise<void> { - const tab = getActiveTab(); + let tab = getActiveTab(); if (!tab) return; + // Refresh agent config to pick up any changes made in AgentBuilder + if (tab.agentSlug && tab.agentScope) { + await refreshAgentConfig(tab.id); + tab = getActiveTab(); + if (!tab) return; + } + // Fetch content for checked skills and build the message to send let messageToSend = text; const checkedKeys = Object.entries(appSettings.skillChecks) |
