diff --git a/src/agents/definitions/index.ts b/src/agents/definitions/index.ts index 2e6ea670..c310a41e 100644 --- a/src/agents/definitions/index.ts +++ b/src/agents/definitions/index.ts @@ -19,11 +19,11 @@ export { export type { FetchContextParams } from './contextSteps.js'; export { clearDefinitionCache, - getKnownAgentTypes, + getBuiltinAgentTypes, invalidateDefinitionCache, + isBuiltinAgentType, isPMFocusedAgent, - loadAgentDefinition, - loadAllAgentDefinitions, + loadBuiltinDefinition, resolveAgentDefinition, resolveAllAgentDefinitions, resolveKnownAgentTypes, diff --git a/src/agents/definitions/loader.ts b/src/agents/definitions/loader.ts index dabeafff..73ec55db 100644 --- a/src/agents/definitions/loader.ts +++ b/src/agents/definitions/loader.ts @@ -18,12 +18,14 @@ const cache = new Map(); let knownTypes: string[] | null = null; /** - * Load and validate a single agent definition from YAML. + * Load and validate a single built-in agent definition from YAML. * Results are cached after first load. * - * @deprecated Use `resolveAgentDefinition()` instead (checks cache → DB → YAML). + * Use this in sync contexts that genuinely need YAML-only access (seed scripts, + * reset operations, internal fallbacks). For general use prefer `resolveAgentDefinition()` + * which checks the in-memory cache, then the database, then falls back to YAML. */ -export function loadAgentDefinition(agentType: string): AgentDefinition { +export function loadBuiltinDefinition(agentType: string): AgentDefinition { const cached = cache.get(agentType); if (cached) return cached; @@ -47,25 +49,13 @@ export function loadAgentDefinition(agentType: string): AgentDefinition { } /** - * Load all agent definitions discovered from YAML files in the definitions directory. + * Return the list of built-in agent types (derived from YAML filenames). * - * @deprecated Use `resolveAllAgentDefinitions()` instead (checks DB with YAML fallback). + * Use this in sync contexts that genuinely need YAML-only type enumeration. + * For general use prefer `resolveKnownAgentTypes()` which also includes + * custom types stored only in the database. */ -export function loadAllAgentDefinitions(): Map { - const types = getKnownAgentTypes(); - const result = new Map(); - for (const agentType of types) { - result.set(agentType, loadAgentDefinition(agentType)); - } - return result; -} - -/** - * Return the list of known agent types (derived from YAML filenames). - * - * @deprecated Use `resolveKnownAgentTypes()` instead (returns types from both DB and YAML). - */ -export function getKnownAgentTypes(): string[] { +export function getBuiltinAgentTypes(): string[] { if (knownTypes) return knownTypes; const entries = readdirSync(__dirname); @@ -86,11 +76,11 @@ export function clearDefinitionCache(): void { /** * Returns true if the given agentType has a backing YAML file (i.e. is a built-in type). - * Wraps `getKnownAgentTypes().includes()` to avoid repeated deprecated-function calls at each - * call site. + * Wraps `getBuiltinAgentTypes().includes()` to avoid repeated deprecated-function calls at + * each call site. */ export function isBuiltinAgentType(agentType: string): boolean { - return getKnownAgentTypes().includes(agentType); + return getBuiltinAgentTypes().includes(agentType); } // ============================================================================ @@ -123,7 +113,7 @@ export async function resolveAgentDefinition(agentType: string): Promise` covering all known agent types. */ export async function resolveAllAgentDefinitions(): Promise> { - const yamlTypes = getKnownAgentTypes(); + const yamlTypes = getBuiltinAgentTypes(); const result = new Map(); // Fetch all DB entries first @@ -155,7 +145,7 @@ export async function resolveAllAgentDefinitions(): Promise { - const yamlTypes = new Set(getKnownAgentTypes()); + const yamlTypes = new Set(getBuiltinAgentTypes()); try { const { listAgentDefinitions } = await import( diff --git a/src/agents/prompts/index.ts b/src/agents/prompts/index.ts index 0c3cc73e..48a5d75d 100644 --- a/src/agents/prompts/index.ts +++ b/src/agents/prompts/index.ts @@ -3,8 +3,7 @@ import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { Eta } from 'eta'; -import { resolveKnownAgentTypes } from '../definitions/index.js'; -import { loadAgentDefinition } from '../definitions/loader.js'; +import { resolveAgentDefinition, resolveKnownAgentTypes } from '../definitions/index.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); const templatesDir = join(__dirname, 'templates'); @@ -236,13 +235,13 @@ export function renderInlineTaskPrompt( } /** - * Returns the YAML-defined taskPrompt for an agent type (the factory default). - * Does not require initPrompts() — reads directly from YAML. + * Returns the taskPrompt for an agent type (the factory default). + * Checks the database (with YAML fallback) via `resolveAgentDefinition()`. * Returns null if the agent type is unknown or has no taskPrompt defined. */ -export function getDefaultTaskPrompt(agentType: string): string | null { +export async function getDefaultTaskPrompt(agentType: string): Promise { try { - const definition = loadAgentDefinition(agentType); + const definition = await resolveAgentDefinition(agentType); return definition.prompts.taskPrompt ?? null; } catch { return null; diff --git a/src/api/routers/agentConfigs.ts b/src/api/routers/agentConfigs.ts index 39c79586..b6f7cbfd 100644 --- a/src/api/routers/agentConfigs.ts +++ b/src/api/routers/agentConfigs.ts @@ -196,8 +196,8 @@ export const agentConfigsRouter = router({ // No .eta template on disk — skip gracefully } - // 4. YAML-defined task prompt (factory default) - const defaultTaskPrompt = getDefaultTaskPrompt(input.agentType); + // 4. Task prompt factory default (checks DB then YAML fallback) + const defaultTaskPrompt = await getDefaultTaskPrompt(input.agentType); return { projectSystemPrompt, diff --git a/src/api/routers/agentDefinitions.ts b/src/api/routers/agentDefinitions.ts index 3999b969..b4c646b4 100644 --- a/src/api/routers/agentDefinitions.ts +++ b/src/api/routers/agentDefinitions.ts @@ -2,10 +2,10 @@ import { TRPCError } from '@trpc/server'; import { z } from 'zod'; import { CAPABILITIES } from '../../agents/capabilities/index.js'; import { - getKnownAgentTypes, + getBuiltinAgentTypes, invalidateDefinitionCache, isBuiltinAgentType, - loadAgentDefinition, + loadBuiltinDefinition, resolveAgentDefinition, resolveKnownAgentTypes, } from '../../agents/definitions/loader.js'; @@ -60,10 +60,10 @@ export const agentDefinitionsRouter = router({ * resolveAllAgentDefinitions() which would issue its own redundant listAgentDefinitions() call. */ list: superAdminProcedure.query(async () => { - // Intentional: getKnownAgentTypes() (deprecated) is used here to enumerate YAML types - // for the merge loop below. resolveKnownAgentTypes() also hits the DB, which we already - // cover via listAgentDefinitions(); calling both would be redundant. - const yamlTypes = getKnownAgentTypes(); + // getBuiltinAgentTypes() enumerates YAML types for the merge loop below. + // resolveKnownAgentTypes() also hits the DB, which we already cover via + // listAgentDefinitions(); calling both would be redundant. + const yamlTypes = getBuiltinAgentTypes(); const result: Array<{ agentType: string; definition: AgentDefinition; isBuiltin: boolean }> = []; @@ -84,15 +84,15 @@ export const agentDefinitionsRouter = router({ seen.add(row.agentType); } - // Fill in YAML-only types not present in DB - // Intentional: loadAgentDefinition() (deprecated) is used here because this is a - // synchronous fallback path — we already have the YAML type list and just need the - // raw definition content; the async resolveAgentDefinition() would add DB round-trips. + // Fill in YAML-only types not present in DB. + // loadBuiltinDefinition() is used here because this is a synchronous fallback path — + // we already have the YAML type list and just need the raw definition content; + // the async resolveAgentDefinition() would add unnecessary DB round-trips. for (const agentType of yamlTypes) { if (!seen.has(agentType)) { result.push({ agentType, - definition: loadAgentDefinition(agentType), + definition: loadBuiltinDefinition(agentType), isBuiltin: true, // YAML-only types are always builtin }); } @@ -232,11 +232,11 @@ export const agentDefinitionsRouter = router({ } // Re-read the YAML (bypass cache). - // Intentional: loadAgentDefinition() (deprecated) is used here because this endpoint - // explicitly needs the raw YAML definition — the purpose of reset is to bypass any DB - // override and restore the hard-coded YAML defaults. + // loadBuiltinDefinition() is used here because this endpoint explicitly needs the + // raw YAML definition — the purpose of reset is to bypass any DB override and + // restore the hard-coded YAML defaults. invalidateDefinitionCache(); - const yamlDefinition = loadAgentDefinition(input.agentType); + const yamlDefinition = loadBuiltinDefinition(input.agentType); await upsertAgentDefinition(input.agentType, yamlDefinition, true); invalidateDefinitionCache(); return { agentType: input.agentType }; @@ -311,7 +311,7 @@ export const agentDefinitionsRouter = router({ // Load YAML defaults and use its prompts section let yamlDefault: AgentDefinition; try { - yamlDefault = loadAgentDefinition(input.agentType); + yamlDefault = loadBuiltinDefinition(input.agentType); } catch { throw new TRPCError({ code: 'NOT_FOUND', diff --git a/src/api/routers/agentTriggerConfigs.ts b/src/api/routers/agentTriggerConfigs.ts index ae0f0823..0a9453fc 100644 --- a/src/api/routers/agentTriggerConfigs.ts +++ b/src/api/routers/agentTriggerConfigs.ts @@ -1,6 +1,6 @@ import { TRPCError } from '@trpc/server'; import { z } from 'zod'; -import { getKnownAgentTypes, loadAgentDefinition } from '../../agents/definitions/loader.js'; +import { getBuiltinAgentTypes, loadBuiltinDefinition } from '../../agents/definitions/loader.js'; import type { AgentDefinition, SupportedTrigger, @@ -220,7 +220,7 @@ export const agentTriggerConfigsRouter = router({ const enabledAgentTypes = new Set(projectAgentConfigs.map((c) => c.agentType)); // Build a combined list of definitions (DB + YAML) - const yamlTypes = getKnownAgentTypes(); + const yamlTypes = getBuiltinAgentTypes(); const definitions: Array<{ agentType: string; definition: AgentDefinition }> = []; const seen = new Set(); @@ -234,7 +234,7 @@ export const agentTriggerConfigsRouter = router({ for (const agentType of yamlTypes) { if (!seen.has(agentType)) { try { - definitions.push({ agentType, definition: loadAgentDefinition(agentType) }); + definitions.push({ agentType, definition: loadBuiltinDefinition(agentType) }); } catch (err) { logger.warn('Failed to load agent definition from YAML', { agentType, error: err }); } diff --git a/src/db/seeds/seedAgentDefinitions.ts b/src/db/seeds/seedAgentDefinitions.ts index f8abf911..7e6d92b1 100644 --- a/src/db/seeds/seedAgentDefinitions.ts +++ b/src/db/seeds/seedAgentDefinitions.ts @@ -8,17 +8,17 @@ * npx tsx src/db/seeds/seedAgentDefinitions.ts */ -import { getKnownAgentTypes, loadAgentDefinition } from '../../agents/definitions/loader.js'; +import { getBuiltinAgentTypes, loadBuiltinDefinition } from '../../agents/definitions/loader.js'; import { readTemplateFileSync } from '../../agents/prompts/index.js'; import { upsertAgentDefinition } from '../repositories/agentDefinitionsRepository.js'; export async function seedAgentDefinitions(): Promise { - const agentTypes = getKnownAgentTypes(); + const agentTypes = getBuiltinAgentTypes(); console.log(`Seeding ${agentTypes.length} agent definitions...`); for (const agentType of agentTypes) { - const definition = loadAgentDefinition(agentType); + const definition = loadBuiltinDefinition(agentType); const systemPrompt = readTemplateFileSync(agentType); const enriched = systemPrompt ? { ...definition, prompts: { ...definition.prompts, systemPrompt } } diff --git a/tests/unit/agents/definitions/async-resolver.test.ts b/tests/unit/agents/definitions/async-resolver.test.ts index 157bf0fa..fa7eeee9 100644 --- a/tests/unit/agents/definitions/async-resolver.test.ts +++ b/tests/unit/agents/definitions/async-resolver.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { clearDefinitionCache, invalidateDefinitionCache, - loadAgentDefinition, + loadBuiltinDefinition, resolveAgentDefinition, resolveAllAgentDefinitions, resolveKnownAgentTypes, @@ -51,7 +51,7 @@ describe('resolveAgentDefinition', () => { it('returns from in-memory cache when already loaded', async () => { // Prime the cache via the sync loader - const fromYaml = loadAgentDefinition('implementation'); + const fromYaml = loadBuiltinDefinition('implementation'); const { getAgentDefinition } = await getDbMocks(); // resolveAgentDefinition should return the cached value without hitting DB @@ -62,7 +62,7 @@ describe('resolveAgentDefinition', () => { it('fetches from DB when cache is empty and DB has the definition', async () => { const { getAgentDefinition } = await getDbMocks(); - const dbDef = loadAgentDefinition('planning'); + const dbDef = loadBuiltinDefinition('planning'); clearDefinitionCache(); getAgentDefinition.mockResolvedValue(dbDef); @@ -77,7 +77,7 @@ describe('resolveAgentDefinition', () => { getAgentDefinition.mockResolvedValue(null); const result = await resolveAgentDefinition('splitting'); - const expected = loadAgentDefinition('splitting'); + const expected = loadBuiltinDefinition('splitting'); expect(result).toEqual(expected); }); @@ -86,13 +86,13 @@ describe('resolveAgentDefinition', () => { getAgentDefinition.mockRejectedValue(new Error('DB connection failed')); const result = await resolveAgentDefinition('review'); - const expected = loadAgentDefinition('review'); + const expected = loadBuiltinDefinition('review'); expect(result).toEqual(expected); }); it('caches DB result so subsequent calls skip DB', async () => { const { getAgentDefinition } = await getDbMocks(); - const dbDef = loadAgentDefinition('debug'); + const dbDef = loadBuiltinDefinition('debug'); clearDefinitionCache(); getAgentDefinition.mockResolvedValue(dbDef); @@ -127,7 +127,7 @@ describe('resolveAllAgentDefinitions', () => { it('prefers DB definitions over YAML when present in DB', async () => { const { listAgentDefinitions } = await getDbMocks(); - const dbDef = loadAgentDefinition('implementation'); + const dbDef = loadBuiltinDefinition('implementation'); clearDefinitionCache(); // Simulate DB having only "implementation" @@ -172,7 +172,7 @@ describe('resolveKnownAgentTypes', () => { it('merges DB-only types with YAML types', async () => { const { listAgentDefinitions } = await getDbMocks(); - const customDef = loadAgentDefinition('implementation'); + const customDef = loadBuiltinDefinition('implementation'); clearDefinitionCache(); listAgentDefinitions.mockResolvedValue([ @@ -213,8 +213,8 @@ describe('invalidateDefinitionCache', () => { it('clears the in-memory cache so next resolve hits DB', async () => { const { getAgentDefinition } = await getDbMocks(); - const dbDef = loadAgentDefinition('planning'); - // Clear cache after priming via loadAgentDefinition so resolveAgentDefinition hits DB + const dbDef = loadBuiltinDefinition('planning'); + // Clear cache after priming via loadBuiltinDefinition so resolveAgentDefinition hits DB clearDefinitionCache(); getAgentDefinition.mockResolvedValue(dbDef); @@ -229,10 +229,10 @@ describe('invalidateDefinitionCache', () => { }); it('behaves identically to clearDefinitionCache for the sync path', () => { - loadAgentDefinition('splitting'); // prime cache + loadBuiltinDefinition('splitting'); // prime cache invalidateDefinitionCache(); // Sync load still works (reads fresh from YAML) - expect(() => loadAgentDefinition('splitting')).not.toThrow(); + expect(() => loadBuiltinDefinition('splitting')).not.toThrow(); }); }); diff --git a/tests/unit/agents/definitions/loader.test.ts b/tests/unit/agents/definitions/loader.test.ts index 3a2e9a3a..fb4631ed 100644 --- a/tests/unit/agents/definitions/loader.test.ts +++ b/tests/unit/agents/definitions/loader.test.ts @@ -5,11 +5,10 @@ import { } from '../../../../src/agents/capabilities/resolver.js'; import { clearDefinitionCache, - getKnownAgentTypes, + getBuiltinAgentTypes, isBuiltinAgentType, isPMFocusedAgent, - loadAgentDefinition, - loadAllAgentDefinitions, + loadBuiltinDefinition, } from '../../../../src/agents/definitions/loader.js'; import { CONTEXT_STEP_REGISTRY } from '../../../../src/agents/definitions/strategies.js'; import { getAgentCapabilities } from '../../../../src/agents/shared/capabilities.js'; @@ -34,9 +33,9 @@ describe('YAML agent definitions loader', () => { clearDefinitionCache(); }); - describe('getKnownAgentTypes', () => { + describe('getBuiltinAgentTypes', () => { it('discovers all 12 agent types from YAML files', () => { - const types = getKnownAgentTypes(); + const types = getBuiltinAgentTypes(); expect(types).toEqual(ALL_AGENT_TYPES); }); }); @@ -54,46 +53,38 @@ describe('YAML agent definitions loader', () => { }); }); - describe('loadAgentDefinition', () => { + describe('loadBuiltinDefinition', () => { it('loads and parses each agent definition without error', () => { for (const agentType of ALL_AGENT_TYPES) { - expect(() => loadAgentDefinition(agentType)).not.toThrow(); + expect(() => loadBuiltinDefinition(agentType)).not.toThrow(); } }); it('throws for unknown agent type', () => { - expect(() => loadAgentDefinition('nonexistent-agent')).toThrow('Agent definition not found'); + expect(() => loadBuiltinDefinition('nonexistent-agent')).toThrow( + 'Agent definition not found', + ); }); it('caches parsed definitions', () => { - const first = loadAgentDefinition('implementation'); - const second = loadAgentDefinition('implementation'); + const first = loadBuiltinDefinition('implementation'); + const second = loadBuiltinDefinition('implementation'); expect(first).toBe(second); }); it('returns fresh results after cache clear', () => { - const first = loadAgentDefinition('implementation'); + const first = loadBuiltinDefinition('implementation'); clearDefinitionCache(); - const second = loadAgentDefinition('implementation'); + const second = loadBuiltinDefinition('implementation'); expect(first).not.toBe(second); expect(first).toEqual(second); }); }); - describe('loadAllAgentDefinitions', () => { - it('returns a map with all 12 agent types', () => { - const all = loadAllAgentDefinitions(); - expect(all.size).toBe(ALL_AGENT_TYPES.length); - for (const agentType of ALL_AGENT_TYPES) { - expect(all.has(agentType)).toBe(true); - } - }); - }); - describe('strategy references resolve correctly', () => { it('all agents have valid capabilities', () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); expect(Array.isArray(def.capabilities.required)).toBe(true); expect(Array.isArray(def.capabilities.optional)).toBe(true); expect(def.capabilities.required.length).toBeGreaterThan(0); @@ -103,7 +94,7 @@ describe('YAML agent definitions loader', () => { it('agents with fs or shell capabilities derive to non-empty SDK tools', () => { // Only agents with fs:* or shell:exec capabilities need SDK tools. for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); const allCaps = [...def.capabilities.required, ...def.capabilities.optional]; // Check if agent has any capabilities that provide SDK tools @@ -123,7 +114,7 @@ describe('YAML agent definitions loader', () => { it('all trigger contextPipeline step references exist in CONTEXT_STEP_REGISTRY', () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); for (const trigger of def.triggers ?? []) { for (const step of trigger.contextPipeline ?? []) { expect( @@ -137,7 +128,7 @@ describe('YAML agent definitions loader', () => { it('all agents have prompts.taskPrompt defined', () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); expect( typeof def.prompts?.taskPrompt === 'string' && def.prompts.taskPrompt.length > 0, `${agentType}: prompts.taskPrompt is missing or empty`, @@ -148,20 +139,20 @@ describe('YAML agent definitions loader', () => { describe('definition content spot checks', () => { it('implementation has requiresPR flag in hooks.finish.scm', () => { - const def = loadAgentDefinition('implementation'); + const def = loadBuiltinDefinition('implementation'); expect(def.hooks?.finish?.scm?.requiresPR).toBe(true); }); it('non-implementation agents do not have hooks.finish.scm.requiresPR', () => { for (const agentType of ALL_AGENT_TYPES.filter((t) => t !== 'implementation')) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); expect(def.hooks?.finish?.scm?.requiresPR).toBeUndefined(); } }); it('work-item agents have triggers with standard context pipeline', () => { // implementation, splitting, planning triggers include workItem context - const def = loadAgentDefinition('implementation'); + const def = loadBuiltinDefinition('implementation'); const statusChangedTrigger = def.triggers.find((t) => t.event === 'pm:status-changed'); expect(statusChangedTrigger?.contextPipeline).toEqual([ 'directoryListing', @@ -173,19 +164,19 @@ describe('YAML agent definitions loader', () => { }); it('review agent triggers use PR context pipeline', () => { - const def = loadAgentDefinition('review'); + const def = loadBuiltinDefinition('review'); const ciPassedTrigger = def.triggers.find((t) => t.event === 'scm:check-suite-success'); expect(ciPassedTrigger?.contextPipeline).toEqual(['prContext', 'contextFiles', 'squint']); }); it('planning agent does not have pm:comment-mention trigger (routed to respond-to-planning-comment)', () => { - const def = loadAgentDefinition('planning'); + const def = loadBuiltinDefinition('planning'); const commentMentionTrigger = def.triggers.find((t) => t.event === 'pm:comment-mention'); expect(commentMentionTrigger).toBeUndefined(); }); it('review agent does not have lifecycle triggers (scm:pr-ready-to-merge, scm:pr-merged)', () => { - const def = loadAgentDefinition('review'); + const def = loadBuiltinDefinition('review'); const prReadyTrigger = def.triggers.find((t) => t.event === 'scm:pr-ready-to-merge'); const prMergedTrigger = def.triggers.find((t) => t.event === 'scm:pr-merged'); expect(prReadyTrigger).toBeUndefined(); @@ -193,7 +184,7 @@ describe('YAML agent definitions loader', () => { }); it('respond-to-ci trigger uses combined PR + work-item pipeline', () => { - const def = loadAgentDefinition('respond-to-ci'); + const def = loadBuiltinDefinition('respond-to-ci'); const ciFailureTrigger = def.triggers.find((t) => t.event === 'scm:check-suite-failure'); expect(ciFailureTrigger?.contextPipeline).toEqual([ 'prContext', @@ -205,7 +196,7 @@ describe('YAML agent definitions loader', () => { }); it('PR comment agents have triggers with conversation pipeline', () => { - const def = loadAgentDefinition('respond-to-pr-comment'); + const def = loadBuiltinDefinition('respond-to-pr-comment'); const prCommentTrigger = def.triggers.find((t) => t.event === 'scm:pr-comment-mention'); expect(prCommentTrigger?.contextPipeline).toEqual([ 'prContext', @@ -217,13 +208,13 @@ describe('YAML agent definitions loader', () => { }); it('planning has read-only capabilities (no fs:write)', () => { - const def = loadAgentDefinition('planning'); + const def = loadBuiltinDefinition('planning'); expect(def.capabilities.required).toContain('fs:read'); expect(def.capabilities.required).not.toContain('fs:write'); }); it('implementation has trailing hooks with all flags', () => { - const def = loadAgentDefinition('implementation'); + const def = loadBuiltinDefinition('implementation'); expect(def.hooks?.trailing).toEqual({ scm: { gitStatus: true, prStatus: true }, builtin: { diagnostics: true, todoProgress: true, reminder: true }, @@ -231,37 +222,37 @@ describe('YAML agent definitions loader', () => { }); it('respond-to-review has diagnostics-only trailing hooks', () => { - const def = loadAgentDefinition('respond-to-review'); + const def = loadBuiltinDefinition('respond-to-review'); expect(def.hooks?.trailing).toEqual({ builtin: { diagnostics: true }, }); }); it('respond-to-ci has diagnostics-only trailing hooks', () => { - const def = loadAgentDefinition('respond-to-ci'); + const def = loadBuiltinDefinition('respond-to-ci'); expect(def.hooks?.trailing).toEqual({ builtin: { diagnostics: true }, }); }); it('splitting has no hooks', () => { - const def = loadAgentDefinition('splitting'); + const def = loadBuiltinDefinition('splitting'); expect(def.hooks).toBeUndefined(); }); it('respond-to-review includes review comment gadget options', () => { - const def = loadAgentDefinition('respond-to-review'); + const def = loadBuiltinDefinition('respond-to-review'); expect(def.strategies.gadgetOptions).toEqual({ includeReviewComments: true }); }); it('respond-to-pr-comment includes review comment gadget options', () => { - const def = loadAgentDefinition('respond-to-pr-comment'); + const def = loadBuiltinDefinition('respond-to-pr-comment'); expect(def.strategies.gadgetOptions).toEqual({ includeReviewComments: true }); }); it('all agents have non-empty identity fields', () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); expect(def.identity.emoji.length).toBeGreaterThan(0); expect(def.identity.label.length).toBeGreaterThan(0); expect(def.identity.roleHint.length).toBeGreaterThan(0); @@ -271,13 +262,13 @@ describe('YAML agent definitions loader', () => { it('all agents have non-empty hints', () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); expect(def.hint.length).toBeGreaterThan(0); } }); it('backlog-manager has pm:status-changed, scm:pr-merged, and internal:auto-chain triggers', () => { - const def = loadAgentDefinition('backlog-manager'); + const def = loadBuiltinDefinition('backlog-manager'); const statusChangedTrigger = def.triggers.find((t) => t.event === 'pm:status-changed'); const prMergedTrigger = def.triggers.find((t) => t.event === 'scm:pr-merged'); const autoChainTrigger = def.triggers.find((t) => t.event === 'internal:auto-chain'); @@ -287,7 +278,7 @@ describe('YAML agent definitions loader', () => { }); it('backlog-manager integration triggers are defaultEnabled: false (opt-in)', () => { - const def = loadAgentDefinition('backlog-manager'); + const def = loadBuiltinDefinition('backlog-manager'); const integrationTriggers = def.triggers.filter((t) => !t.event.startsWith('internal:')); for (const trigger of integrationTriggers) { expect(trigger.defaultEnabled).toBe(false); @@ -295,13 +286,13 @@ describe('YAML agent definitions loader', () => { }); it('backlog-manager internal:auto-chain trigger is defaultEnabled: false (all triggers off by default)', () => { - const def = loadAgentDefinition('backlog-manager'); + const def = loadBuiltinDefinition('backlog-manager'); const autoChainTrigger = def.triggers.find((t) => t.event === 'internal:auto-chain'); expect(autoChainTrigger?.defaultEnabled).toBe(false); }); it('backlog-manager requires only pm integration', () => { - const def = loadAgentDefinition('backlog-manager'); + const def = loadBuiltinDefinition('backlog-manager'); expect(def.integrations?.required).toContain('pm'); expect(def.integrations?.optional ?? []).not.toContain('scm'); }); @@ -309,7 +300,7 @@ describe('YAML agent definitions loader', () => { describe('roundtrip: YAML definition → profile properties', () => { it('implementation agent has full capabilities and stop hooks', async () => { - const def = loadAgentDefinition('implementation'); + const def = loadBuiltinDefinition('implementation'); const caps = await getAgentCapabilities('implementation'); expect(caps.canEditFiles).toBe(true); @@ -321,7 +312,7 @@ describe('YAML agent definitions loader', () => { }); it('review agent is read-only', async () => { - const def = loadAgentDefinition('review'); + const def = loadBuiltinDefinition('review'); const caps = await getAgentCapabilities('review'); expect(caps.canEditFiles).toBe(false); @@ -331,7 +322,7 @@ describe('YAML agent definitions loader', () => { }); it('respond-to-ci agent requires scm integration', async () => { - const def = loadAgentDefinition('respond-to-ci'); + const def = loadBuiltinDefinition('respond-to-ci'); const caps = await getAgentCapabilities('respond-to-ci'); expect(caps.canEditFiles).toBe(true); @@ -340,7 +331,7 @@ describe('YAML agent definitions loader', () => { it('capabilities from getAgentCapabilities are derived correctly for all agents', async () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); const caps = await getAgentCapabilities(agentType); const allCaps = [...def.capabilities.required, ...def.capabilities.optional]; @@ -408,14 +399,14 @@ describe('YAML agent definitions loader', () => { describe('integration requirements (derived from capabilities)', () => { it('all agents have valid capabilities with required array', () => { for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); expect(Array.isArray(def.capabilities.required)).toBe(true); expect(Array.isArray(def.capabilities.optional)).toBe(true); } }); it('implementation agent requires scm and pm (derived from capabilities)', () => { - const def = loadAgentDefinition('implementation'); + const def = loadBuiltinDefinition('implementation'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); // Order may vary - use set comparison expect(new Set(integrations.required)).toEqual(new Set(['scm', 'pm'])); @@ -423,56 +414,56 @@ describe('YAML agent definitions loader', () => { }); it('splitting agent requires pm only', () => { - const def = loadAgentDefinition('splitting'); + const def = loadBuiltinDefinition('splitting'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['pm']); expect(integrations.optional).toEqual([]); }); it('planning agent requires pm only', () => { - const def = loadAgentDefinition('planning'); + const def = loadBuiltinDefinition('planning'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['pm']); expect(integrations.optional).toEqual([]); }); it('review agent requires scm, pm is optional', () => { - const def = loadAgentDefinition('review'); + const def = loadBuiltinDefinition('review'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['scm']); expect(integrations.optional).toEqual(['pm']); }); it('respond-to-review agent requires scm, pm is optional', () => { - const def = loadAgentDefinition('respond-to-review'); + const def = loadBuiltinDefinition('respond-to-review'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['scm']); expect(integrations.optional).toEqual(['pm']); }); it('respond-to-ci agent requires scm, pm is optional', () => { - const def = loadAgentDefinition('respond-to-ci'); + const def = loadBuiltinDefinition('respond-to-ci'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['scm']); expect(integrations.optional).toEqual(['pm']); }); it('respond-to-pr-comment agent requires scm, pm is optional', () => { - const def = loadAgentDefinition('respond-to-pr-comment'); + const def = loadBuiltinDefinition('respond-to-pr-comment'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['scm']); expect(integrations.optional).toEqual(['pm']); }); it('respond-to-planning-comment agent requires pm only', () => { - const def = loadAgentDefinition('respond-to-planning-comment'); + const def = loadBuiltinDefinition('respond-to-planning-comment'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['pm']); expect(integrations.optional).toEqual([]); }); it('debug agent requires pm only', () => { - const def = loadAgentDefinition('debug'); + const def = loadBuiltinDefinition('debug'); const integrations = deriveIntegrations(def.capabilities.required, def.capabilities.optional); expect(integrations.required).toEqual(['pm']); expect(integrations.optional).toEqual([]); @@ -481,7 +472,7 @@ describe('YAML agent definitions loader', () => { it('all derived integration categories are valid', () => { const validCategories = ['pm', 'scm', 'email', 'alerting']; for (const agentType of ALL_AGENT_TYPES) { - const def = loadAgentDefinition(agentType); + const def = loadBuiltinDefinition(agentType); const integrations = deriveIntegrations( def.capabilities.required, def.capabilities.optional, diff --git a/tests/unit/agents/shared/modelResolution.test.ts b/tests/unit/agents/shared/modelResolution.test.ts index 88474f6b..4dce9605 100644 --- a/tests/unit/agents/shared/modelResolution.test.ts +++ b/tests/unit/agents/shared/modelResolution.test.ts @@ -44,7 +44,7 @@ vi.mock('../../../../src/agents/definitions/loader.js', () => ({ 'respond-to-planning-comment', 'debug', ]), - getKnownAgentTypes: vi.fn().mockReturnValue([]), + getBuiltinAgentTypes: vi.fn().mockReturnValue([]), })); // Also mock the index re-export @@ -63,7 +63,7 @@ vi.mock('../../../../src/agents/definitions/index.js', () => ({ 'respond-to-planning-comment', 'debug', ]), - getKnownAgentTypes: vi.fn().mockReturnValue([]), + getBuiltinAgentTypes: vi.fn().mockReturnValue([]), })); // Mock getAgentConfigPrompts (project-level prompt lookup) diff --git a/tests/unit/api/routers/agentConfigs.test.ts b/tests/unit/api/routers/agentConfigs.test.ts index 561f8a6e..92aecc4a 100644 --- a/tests/unit/api/routers/agentConfigs.test.ts +++ b/tests/unit/api/routers/agentConfigs.test.ts @@ -33,7 +33,7 @@ const { mockLoadPartials: vi.fn(), mockResolveAgentDefinition: vi.fn(), mockGetRawTemplate: vi.fn(), - mockGetDefaultTaskPrompt: vi.fn().mockReturnValue(null), + mockGetDefaultTaskPrompt: vi.fn().mockResolvedValue(null), })); vi.mock('../../../../src/db/repositories/settingsRepository.js', () => ({ @@ -612,7 +612,7 @@ describe('agentConfigsRouter', () => { }, }); mockGetRawTemplate.mockReturnValue('raw disk template content'); - mockGetDefaultTaskPrompt.mockReturnValue('yaml default task prompt'); + mockGetDefaultTaskPrompt.mockResolvedValue('yaml default task prompt'); const caller = createCaller({ user: mockUser, effectiveOrgId: mockUser.orgId }); const result = await caller.getPrompts({ projectId: 'proj-1', agentType: 'implementation' }); diff --git a/tests/unit/api/routers/agentDefinitions.test.ts b/tests/unit/api/routers/agentDefinitions.test.ts index 55c1c23c..b04a2655 100644 --- a/tests/unit/api/routers/agentDefinitions.test.ts +++ b/tests/unit/api/routers/agentDefinitions.test.ts @@ -8,10 +8,10 @@ import { createCallerFor, expectTRPCError } from '../../../helpers/trpcTestHarne // --------------------------------------------------------------------------- const { - mockGetKnownAgentTypes, + mockGetBuiltinAgentTypes, mockIsBuiltinAgentType, mockInvalidateDefinitionCache, - mockLoadAgentDefinition, + mockLoadBuiltinDefinition, mockResolveAgentDefinition, mockResolveKnownAgentTypes, mockListAgentDefinitions, @@ -22,10 +22,10 @@ const { mockValidateTemplate, mockLoadPartials, } = vi.hoisted(() => ({ - mockGetKnownAgentTypes: vi.fn<() => string[]>(), + mockGetBuiltinAgentTypes: vi.fn<() => string[]>(), mockIsBuiltinAgentType: vi.fn<(agentType: string) => boolean>(), mockInvalidateDefinitionCache: vi.fn(), - mockLoadAgentDefinition: vi.fn<(agentType: string) => AgentDefinition>(), + mockLoadBuiltinDefinition: vi.fn<(agentType: string) => AgentDefinition>(), mockResolveAgentDefinition: vi.fn<(agentType: string) => Promise>(), mockResolveKnownAgentTypes: vi.fn<() => Promise>(), mockListAgentDefinitions: vi.fn(), @@ -38,10 +38,10 @@ const { })); vi.mock('../../../../src/agents/definitions/loader.js', () => ({ - getKnownAgentTypes: mockGetKnownAgentTypes, + getBuiltinAgentTypes: mockGetBuiltinAgentTypes, isBuiltinAgentType: mockIsBuiltinAgentType, invalidateDefinitionCache: mockInvalidateDefinitionCache, - loadAgentDefinition: mockLoadAgentDefinition, + loadBuiltinDefinition: mockLoadBuiltinDefinition, resolveAgentDefinition: mockResolveAgentDefinition, resolveKnownAgentTypes: mockResolveKnownAgentTypes, })); @@ -111,7 +111,7 @@ function createMockDefinition(overrides?: Partial): AgentDefini describe('agentDefinitionsRouter', () => { beforeEach(() => { - mockGetKnownAgentTypes.mockReturnValue(['implementation', 'review']); + mockGetBuiltinAgentTypes.mockReturnValue(['implementation', 'review']); mockIsBuiltinAgentType.mockImplementation((agentType: string) => ['implementation', 'review'].includes(agentType), ); @@ -129,7 +129,7 @@ describe('agentDefinitionsRouter', () => { { agentType: 'implementation', definition: dbDef, isBuiltin: true }, ]); const yamlDef = createMockDefinition({ hint: 'from yaml' }); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); const result = await caller.list(); @@ -152,7 +152,7 @@ describe('agentDefinitionsRouter', () => { it('falls back to YAML only when DB fails', async () => { mockListAgentDefinitions.mockRejectedValue(new Error('DB down')); const yamlDef = createMockDefinition(); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); const result = await caller.list(); @@ -169,7 +169,7 @@ describe('agentDefinitionsRouter', () => { { agentType: 'custom-agent', definition: customDef, isBuiltin: false }, ]); const yamlDef = createMockDefinition(); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); const result = await caller.list(); @@ -184,7 +184,7 @@ describe('agentDefinitionsRouter', () => { it('does not call listAgentDefinitions twice (no redundant DB query)', async () => { mockListAgentDefinitions.mockResolvedValue([]); - mockLoadAgentDefinition.mockReturnValue(createMockDefinition()); + mockLoadBuiltinDefinition.mockReturnValue(createMockDefinition()); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); await caller.list(); @@ -349,7 +349,7 @@ describe('agentDefinitionsRouter', () => { describe('delete', () => { it('deletes a non-builtin definition (superadmin)', async () => { mockGetAgentDefinition.mockResolvedValue(createMockDefinition()); - mockGetKnownAgentTypes.mockReturnValue(['implementation', 'review']); // custom-agent is NOT in this list + mockGetBuiltinAgentTypes.mockReturnValue(['implementation', 'review']); // custom-agent is NOT in this list mockDeleteAgentDefinition.mockResolvedValue(undefined); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); @@ -397,14 +397,14 @@ describe('agentDefinitionsRouter', () => { describe('reset', () => { it('resets a builtin definition to YAML default (superadmin)', async () => { const yamlDef = createMockDefinition({ hint: 'yaml default' }); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); mockUpsertAgentDefinition.mockResolvedValue(undefined); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); const result = await caller.reset({ agentType: 'implementation' }); expect(result).toEqual({ agentType: 'implementation' }); - expect(mockLoadAgentDefinition).toHaveBeenCalledWith('implementation'); + expect(mockLoadBuiltinDefinition).toHaveBeenCalledWith('implementation'); expect(mockUpsertAgentDefinition).toHaveBeenCalledWith('implementation', yamlDef, true); // Cache should be invalidated twice (before YAML reload and after upsert) expect(mockInvalidateDefinitionCache).toHaveBeenCalledTimes(2); @@ -564,7 +564,7 @@ describe('agentDefinitionsRouter', () => { }); mockResolveAgentDefinition.mockResolvedValue(current); const yamlDef = createMockDefinition({ prompts: { taskPrompt: 'yaml task' } }); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); mockGetRawTemplate.mockReturnValue('## System prompt from .eta'); mockUpsertAgentDefinition.mockResolvedValue(undefined); @@ -590,7 +590,7 @@ describe('agentDefinitionsRouter', () => { const yamlDef = createMockDefinition({ prompts: { taskPrompt: 'yaml task', systemPrompt: 'yaml system' }, }); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); mockUpsertAgentDefinition.mockResolvedValue(undefined); const caller = createCaller({ user: mockSuperAdmin, effectiveOrgId: mockSuperAdmin.orgId }); @@ -610,7 +610,7 @@ describe('agentDefinitionsRouter', () => { const current = createMockDefinition(); mockResolveAgentDefinition.mockResolvedValue(current); const yamlDef = createMockDefinition({ prompts: { taskPrompt: 'yaml task' } }); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); mockGetRawTemplate.mockImplementation(() => { throw new Error('no .eta file'); }); @@ -640,7 +640,7 @@ describe('agentDefinitionsRouter', () => { it('throws NOT_FOUND when YAML default does not exist', async () => { const current = createMockDefinition(); mockResolveAgentDefinition.mockResolvedValue(current); - mockLoadAgentDefinition.mockImplementation(() => { + mockLoadBuiltinDefinition.mockImplementation(() => { throw new Error('yaml not found'); }); @@ -667,7 +667,7 @@ describe('agentDefinitionsRouter', () => { const current = createMockDefinition(); mockResolveAgentDefinition.mockResolvedValue(current); const yamlDef = createMockDefinition({ prompts: { taskPrompt: 'yaml task' } }); - mockLoadAgentDefinition.mockReturnValue(yamlDef); + mockLoadBuiltinDefinition.mockReturnValue(yamlDef); mockGetRawTemplate.mockReturnValue('system prompt'); mockUpsertAgentDefinition.mockResolvedValue(undefined); diff --git a/tests/unit/api/routers/agentTriggerConfigs.getProjectTriggersView.test.ts b/tests/unit/api/routers/agentTriggerConfigs.getProjectTriggersView.test.ts index 240086bd..d2ab21e2 100644 --- a/tests/unit/api/routers/agentTriggerConfigs.getProjectTriggersView.test.ts +++ b/tests/unit/api/routers/agentTriggerConfigs.getProjectTriggersView.test.ts @@ -10,16 +10,16 @@ const { mockListAgentDefinitions, mockGetTriggerConfigsByProject, mockListProjectIntegrations, - mockGetKnownAgentTypes, - mockLoadAgentDefinition, + mockGetBuiltinAgentTypes, + mockLoadBuiltinDefinition, mockListAgentConfigs, mockVerifyProjectOrgAccess, } = vi.hoisted(() => ({ mockListAgentDefinitions: vi.fn(), mockGetTriggerConfigsByProject: vi.fn(), mockListProjectIntegrations: vi.fn(), - mockGetKnownAgentTypes: vi.fn(), - mockLoadAgentDefinition: vi.fn(), + mockGetBuiltinAgentTypes: vi.fn(), + mockLoadBuiltinDefinition: vi.fn(), mockListAgentConfigs: vi.fn(), mockVerifyProjectOrgAccess: vi.fn(), })); @@ -48,8 +48,8 @@ vi.mock('../../../../src/db/repositories/agentConfigsRepository.js', () => ({ })); vi.mock('../../../../src/agents/definitions/loader.js', () => ({ - getKnownAgentTypes: mockGetKnownAgentTypes, - loadAgentDefinition: mockLoadAgentDefinition, + getBuiltinAgentTypes: mockGetBuiltinAgentTypes, + loadBuiltinDefinition: mockLoadBuiltinDefinition, })); vi.mock('../../../../src/api/routers/_shared/projectAccess.js', () => ({ @@ -97,8 +97,8 @@ describe('agentTriggerConfigsRouter — getProjectTriggersView', () => { mockGetTriggerConfigsByProject.mockResolvedValue([]); mockListProjectIntegrations.mockResolvedValue([]); mockListAgentDefinitions.mockResolvedValue([]); - mockGetKnownAgentTypes.mockReturnValue([]); - mockLoadAgentDefinition.mockReturnValue(makeAgentDefinition()); + mockGetBuiltinAgentTypes.mockReturnValue([]); + mockLoadBuiltinDefinition.mockReturnValue(makeAgentDefinition()); // Default: no agent configs (all agents are unconfigured / available) mockListAgentConfigs.mockResolvedValue([]); }); @@ -286,8 +286,8 @@ describe('agentTriggerConfigsRouter — getProjectTriggersView', () => { it('is resilient to DB failure when loading agent definitions', async () => { mockListAgentDefinitions.mockRejectedValue(new Error('DB connection failed')); // Falls back to YAML — need some types for that - mockGetKnownAgentTypes.mockReturnValue(['implementation']); - mockLoadAgentDefinition.mockReturnValue(makeAgentDefinition()); + mockGetBuiltinAgentTypes.mockReturnValue(['implementation']); + mockLoadBuiltinDefinition.mockReturnValue(makeAgentDefinition()); mockListAgentConfigs.mockResolvedValue([{ agentType: 'implementation', id: 1 }]); const caller = createCaller(mockCtx); @@ -302,7 +302,7 @@ describe('agentTriggerConfigsRouter — getProjectTriggersView', () => { const definition = makeAgentDefinition(); mockListAgentDefinitions.mockResolvedValue([{ agentType: 'implementation', definition }]); // YAML also has 'implementation' - mockGetKnownAgentTypes.mockReturnValue(['implementation']); + mockGetBuiltinAgentTypes.mockReturnValue(['implementation']); mockListAgentConfigs.mockResolvedValue([{ agentType: 'implementation', id: 1 }]); const caller = createCaller(mockCtx); @@ -314,8 +314,8 @@ describe('agentTriggerConfigsRouter — getProjectTriggersView', () => { it('enabled agents appear in enabledAgents; unconfigured appear in availableAgents', async () => { mockListAgentDefinitions.mockResolvedValue([]); // no DB definitions - mockGetKnownAgentTypes.mockReturnValue(['splitting', 'planning']); - mockLoadAgentDefinition.mockReturnValue(makeAgentDefinition()); + mockGetBuiltinAgentTypes.mockReturnValue(['splitting', 'planning']); + mockLoadBuiltinDefinition.mockReturnValue(makeAgentDefinition()); // Only 'splitting' is enabled mockListAgentConfigs.mockResolvedValue([{ agentType: 'splitting', id: 1 }]); @@ -329,8 +329,8 @@ describe('agentTriggerConfigsRouter — getProjectTriggersView', () => { }); it('handles YAML load failure gracefully (skips that agent)', async () => { - mockGetKnownAgentTypes.mockReturnValue(['implementation', 'failing-agent']); - mockLoadAgentDefinition + mockGetBuiltinAgentTypes.mockReturnValue(['implementation', 'failing-agent']); + mockLoadBuiltinDefinition .mockReturnValueOnce(makeAgentDefinition()) .mockImplementationOnce(() => { throw new Error('YAML parse error'); diff --git a/tests/unit/backends/llmist.test.ts b/tests/unit/backends/llmist.test.ts index 1e2ecc08..d1f88167 100644 --- a/tests/unit/backends/llmist.test.ts +++ b/tests/unit/backends/llmist.test.ts @@ -15,7 +15,7 @@ vi.mock('../../../src/agents/capabilities/index.js', () => ({ // backends/llmist → definitions → strategies → gadgets → pm/ → webhook-handler // → triggers/agent-execution → agents/registry → new LlmistEngine() (still loading) vi.mock('../../../src/agents/definitions/index.js', () => ({ - loadAgentDefinition: vi.fn(() => ({ engine: {} })), + loadBuiltinDefinition: vi.fn(() => ({ engine: {} })), resolveAgentDefinition: vi.fn(async () => ({ engine: {} })), }));