feat: add AgentConfigRegistry for named agent configurations
This commit is contained in:
@@ -0,0 +1,64 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { AgentConfigRegistry, type AgentConfig } from './registry.js';
|
||||||
|
|
||||||
|
describe('AgentConfigRegistry', () => {
|
||||||
|
describe('register()', () => {
|
||||||
|
it('registers a named agent config', () => {
|
||||||
|
const registry = new AgentConfigRegistry();
|
||||||
|
const config: AgentConfig = { name: 'assistant', systemPrompt: 'Be helpful.' };
|
||||||
|
registry.register(config);
|
||||||
|
|
||||||
|
expect(registry.get('assistant')).toEqual(config);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws on duplicate name', () => {
|
||||||
|
const registry = new AgentConfigRegistry();
|
||||||
|
registry.register({ name: 'assistant' });
|
||||||
|
expect(() => registry.register({ name: 'assistant' })).toThrow('already registered');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('get()', () => {
|
||||||
|
it('returns undefined for unknown name', () => {
|
||||||
|
const registry = new AgentConfigRegistry();
|
||||||
|
expect(registry.get('nonexistent')).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('list()', () => {
|
||||||
|
it('returns all registered configs', () => {
|
||||||
|
const registry = new AgentConfigRegistry();
|
||||||
|
registry.register({ name: 'a' });
|
||||||
|
registry.register({ name: 'b' });
|
||||||
|
expect(registry.list().map(c => c.name).sort()).toEqual(['a', 'b']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('loadFromConfig()', () => {
|
||||||
|
it('loads configs from a raw config object', () => {
|
||||||
|
const registry = new AgentConfigRegistry();
|
||||||
|
registry.loadFromConfig({
|
||||||
|
assistant: {
|
||||||
|
system_prompt: 'Be helpful.',
|
||||||
|
model_tier: 'default',
|
||||||
|
tool_profile: 'messaging',
|
||||||
|
sandbox: false,
|
||||||
|
},
|
||||||
|
coder: {
|
||||||
|
model_tier: 'complex',
|
||||||
|
tool_profile: 'coding',
|
||||||
|
sandbox: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(registry.list()).toHaveLength(2);
|
||||||
|
const assistant = registry.get('assistant')!;
|
||||||
|
expect(assistant.systemPrompt).toBe('Be helpful.');
|
||||||
|
expect(assistant.modelTier).toBe('default');
|
||||||
|
expect(assistant.toolProfile).toBe('messaging');
|
||||||
|
|
||||||
|
const coder = registry.get('coder')!;
|
||||||
|
expect(coder.sandbox).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import type { ToolProfile, ToolOverrideConfig } from '../config/schema.js';
|
||||||
|
import type { ModelTier } from '../models/router.js';
|
||||||
|
|
||||||
|
export interface AgentConfig {
|
||||||
|
name: string;
|
||||||
|
systemPrompt?: string;
|
||||||
|
modelTier?: ModelTier;
|
||||||
|
toolProfile?: ToolProfile;
|
||||||
|
toolOverrides?: ToolOverrideConfig;
|
||||||
|
sandbox?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AgentConfigRegistry — stores named agent configurations.
|
||||||
|
* Loaded from YAML config at startup.
|
||||||
|
*/
|
||||||
|
export class AgentConfigRegistry {
|
||||||
|
private configs = new Map<string, AgentConfig>();
|
||||||
|
|
||||||
|
register(config: AgentConfig): void {
|
||||||
|
if (this.configs.has(config.name)) {
|
||||||
|
throw new Error(`Agent config '${config.name}' is already registered`);
|
||||||
|
}
|
||||||
|
this.configs.set(config.name, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(name: string): AgentConfig | undefined {
|
||||||
|
return this.configs.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
list(): AgentConfig[] {
|
||||||
|
return Array.from(this.configs.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load agent configs from the parsed YAML config.
|
||||||
|
* Maps from the config schema format to the internal AgentConfig format.
|
||||||
|
*/
|
||||||
|
loadFromConfig(rawConfigs: Record<string, {
|
||||||
|
system_prompt?: string;
|
||||||
|
model_tier?: string;
|
||||||
|
tool_profile?: string;
|
||||||
|
tool_overrides?: ToolOverrideConfig;
|
||||||
|
sandbox?: boolean;
|
||||||
|
}>): void {
|
||||||
|
for (const [name, raw] of Object.entries(rawConfigs)) {
|
||||||
|
this.register({
|
||||||
|
name,
|
||||||
|
systemPrompt: raw.system_prompt,
|
||||||
|
modelTier: raw.model_tier as ModelTier | undefined,
|
||||||
|
toolProfile: raw.tool_profile as ToolProfile | undefined,
|
||||||
|
toolOverrides: raw.tool_overrides,
|
||||||
|
sandbox: raw.sandbox,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user