From 2e85e979e785511bc73c8ad9240d0e78ebe52782 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Tue, 24 Mar 2026 20:29:03 +1100 Subject: [PATCH] fix: graceful rate limit handling for LLM enhancement Detect 429/rate-limit errors and wait the appropriate duration before retrying instead of using the fixed 3s stagger. Shows a user-friendly message when rate limited instead of dumping raw API errors. --- src/agent/clis/index.ts | 44 +++++++++++++++++++++++++++++++++---- src/commands/sync-shared.ts | 5 ++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/agent/clis/index.ts b/src/agent/clis/index.ts index 51d090ba..1f3338e0 100644 --- a/src/agent/clis/index.ts +++ b/src/agent/clis/index.ts @@ -715,10 +715,21 @@ export async function optimizeDocs(opts: OptimizeDocsOptions): Promise): string | undefined { + if (result.status === 'rejected') + return String(result.reason) + return result.value.error +} + /** Shorten absolute paths for display: /home/user/project/.claude/skills/vue/SKILL.md → .claude/.../SKILL.md */ function shortenPath(p: string): string { const refIdx = p.indexOf('.skilld/') diff --git a/src/commands/sync-shared.ts b/src/commands/sync-shared.ts index 5b0bd544..d396459b 100644 --- a/src/commands/sync-shared.ts +++ b/src/commands/sync-shared.ts @@ -1452,7 +1452,10 @@ export async function enhanceSkillWithLLM(opts: EnhanceOptions): Promise { writeFileSync(join(skillDir, 'SKILL.md'), skillMd) } else { - llmLog.error(`Enhancement failed${error ? `: ${error}` : ''}`) + if (error && /\b429\b|rate.?limit|exhausted.*capacity|quota.*reset/i.test(error)) + llmLog.error(`Rate limited by LLM provider. Try again shortly or use a different model via \`skilld config\``) + else + llmLog.error(`Enhancement failed${error ? `: ${error}` : ''}`) } }