import { describe, it, expect, beforeEach, afterEach } from 'vitest' import fs from 'node:fs' import path from 'node:path' import os from 'node:os' import { loadAgents, findAgent } from '../../src/agent/agents-store.js' // We'll point the agents dir to a temp directory by monkey-patching os.homedir // during tests that need a real directory. For most tests we can rely on the // behaviour when ~/.squeezr-code/agents does NOT exist. let tmpHome: string let origHomedir: () => string beforeEach(() => { tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'sq-agents-test-')) origHomedir = os.homedir // Override homedir so agents-store reads our tmpHome ;(os as { homedir: () => string }).homedir = () => tmpHome }) afterEach(() => { ;(os as { homedir: () => string }).homedir = origHomedir fs.rmSync(tmpHome, { recursive: true, force: true }) }) function agentsDir(): string { return path.join(tmpHome, '.squeezr-code', 'agents') } function writeAgent(name: string, content: string): void { fs.mkdirSync(agentsDir(), { recursive: true }) fs.writeFileSync(path.join(agentsDir(), `${name}.md`), content, 'utf-8') } describe('loadAgents', () => { it('returns empty array when agents dir does not exist', () => { expect(loadAgents()).toEqual([]) }) it('returns empty array when agents dir is empty', () => { fs.mkdirSync(agentsDir(), { recursive: true }) expect(loadAgents()).toEqual([]) }) it('ignores non-.md files', () => { fs.mkdirSync(agentsDir(), { recursive: true }) fs.writeFileSync(path.join(agentsDir(), 'readme.txt'), 'ignore me') expect(loadAgents()).toHaveLength(0) }) it('parses a simple agent without frontmatter', () => { writeAgent('simple', 'You are a helpful assistant.') const agents = loadAgents() expect(agents).toHaveLength(1) expect(agents[0].name).toBe('simple') expect(agents[0].systemPrompt).toContain('You are a helpful assistant.') // description defaults to first line expect(agents[0].description).toBe('You are a helpful assistant.') }) it('parses an agent with full frontmatter', () => { const content = `--- description: Security-focused code reviewer tools: Read, Grep, Glob model: opus --- You are a security-focused code reviewer. Look for SQL injection and XSS vulnerabilities.` writeAgent('security-reviewer', content) const agents = loadAgents() expect(agents).toHaveLength(1) const spec = agents[0] expect(spec.name).toBe('security-reviewer') expect(spec.description).toBe('Security-focused code reviewer') expect(spec.tools).toEqual(['Read', 'Grep', 'Glob']) expect(spec.model).toBe('opus') expect(spec.systemPrompt).toContain('You are a security-focused code reviewer.') expect(spec.systemPrompt).not.toContain('---') }) it('parses multiple agents', () => { writeAgent('agent-a', '---\ndescription: Agent A\n---\nDo A things.') writeAgent('agent-b', '---\ndescription: Agent B\n---\nDo B things.') const agents = loadAgents() expect(agents).toHaveLength(2) const names = agents.map(a => a.name).sort() expect(names).toEqual(['agent-a', 'agent-b']) }) it('description truncates to 80 chars when no frontmatter', () => { const longLine = 'A'.repeat(100) writeAgent('long-desc', longLine) const agents = loadAgents() expect(agents[0].description).toHaveLength(80) }) it('tools is undefined when not in frontmatter', () => { writeAgent('no-tools', '---\ndescription: No tools\n---\nSystem prompt.') const agents = loadAgents() expect(agents[0].tools).toBeUndefined() }) it('model is undefined when not in frontmatter', () => { writeAgent('no-model', '---\ndescription: No model\n---\nSystem prompt.') const agents = loadAgents() expect(agents[0].model).toBeUndefined() }) }) describe('findAgent', () => { it('returns null when agent does not exist', () => { expect(findAgent('nonexistent')).toBeNull() }) it('returns null when agents dir does not exist', () => { expect(findAgent('anything')).toBeNull() }) it('finds an existing agent by name', () => { writeAgent('my-agent', '---\ndescription: My agent\n---\nDo things.') const spec = findAgent('my-agent') expect(spec).not.toBeNull() expect(spec?.name).toBe('my-agent') expect(spec?.description).toBe('My agent') }) it('returns null for a different name', () => { writeAgent('my-agent', '---\ndescription: My agent\n---\nDo things.') expect(findAgent('other-agent')).toBeNull() }) })