diff --git a/src/openrouter-status.test.ts b/src/openrouter-status.test.ts new file mode 100644 index 0000000..cbdd690 --- /dev/null +++ b/src/openrouter-status.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it } from 'vitest'; + +import { formatOpenRouterStatusLine } from './openrouter-status.js'; + +describe('formatOpenRouterStatusLine', () => { + it('reports missing when key is absent', () => { + expect(formatOpenRouterStatusLine({ status: 'missing' })).toBe('OpenRouter: missing key'); + }); + + it('reports unknown when status is unknown', () => { + expect(formatOpenRouterStatusLine({ status: 'unknown' })).toBe('OpenRouter: unknown'); + }); + + it('reports error message when status is error', () => { + expect(formatOpenRouterStatusLine({ status: 'error', error: 'http_401' })).toBe( + 'OpenRouter: http_401', + ); + }); + + it('reports ok with no details when ok but all fields absent', () => { + expect(formatOpenRouterStatusLine({ status: 'ok' })).toBe('OpenRouter: ok'); + }); + + it('includes remaining balance when present', () => { + const line = formatOpenRouterStatusLine({ status: 'ok', remainingUsd: 4.5 }); + expect(line).toContain('$4.50 remaining'); + }); + + it('includes limit when present', () => { + const line = formatOpenRouterStatusLine({ status: 'ok', limitUsd: 10.0 }); + expect(line).toContain('$10.00 limit'); + }); + + it('includes free-tier label when isFreeTier is true', () => { + const line = formatOpenRouterStatusLine({ status: 'ok', isFreeTier: true }); + expect(line).toContain('free-tier'); + }); + + it('combines all fields with dots', () => { + const line = formatOpenRouterStatusLine({ + status: 'ok', + remainingUsd: 3.25, + limitUsd: 10.0, + isFreeTier: false, + }); + expect(line).toBe('OpenRouter: $3.25 remaining ยท $10.00 limit'); + }); + + it('omits undefined numeric fields from output', () => { + const line = formatOpenRouterStatusLine({ status: 'ok', remainingUsd: 2.0 }); + expect(line).not.toContain('limit'); + expect(line).not.toContain('free-tier'); + }); +}); diff --git a/src/split-brain-status.test.ts b/src/split-brain-status.test.ts index 4720361..cbd7f5b 100644 --- a/src/split-brain-status.test.ts +++ b/src/split-brain-status.test.ts @@ -129,4 +129,14 @@ describe('buildSplitBrainFixHints', () => { const hints = buildSplitBrainFixHints({ ...readyStatus(), skillsRuntimeLookup: 'missing' }); expect(hints).toContain('Restore runtime lookup: just setup -- --step skills-init'); }); + + it('does not emit an artifact hint when skills db is down (unavailable is implied by the db hint)', () => { + const hints = buildSplitBrainFixHints({ + ...readyStatus(), + skillsDb: 'missing', + skillsArtifact: 'unavailable', + }); + expect(hints).toContain('Fix skills DB: check PostgreSQL, then run: just setup-db'); + expect(hints).not.toContain('Refresh knowledge artifact: just setup -- --step skills-memory'); + }); }); diff --git a/src/split-brain-status.ts b/src/split-brain-status.ts index dcef5f9..6a9cae2 100644 --- a/src/split-brain-status.ts +++ b/src/split-brain-status.ts @@ -234,7 +234,7 @@ export function buildSplitBrainFixHints(status: SplitBrainStatus): string[] { if (status.memoryDb !== 'available') { hints.push('Fix memory DB: check PostgreSQL, then run: just setup-db'); } - if (status.skillsArtifact !== 'ready') { + if (status.skillsArtifact !== 'ready' && status.skillsArtifact !== 'unavailable') { if ( status.skillsArtifactSql !== 'present' || status.skillsArtifactMetadata !== 'present'