import { stringify } from 'yaml'; interface ProviderConfig { provider: string; model: string; api_key?: string; auth_token?: string; endpoint?: string; } interface EmbeddingConfig { provider: string; api_key?: string; endpoint?: string; } export class ConfigBuilder { private config: Record; constructor() { this.config = { log_level: 'info', models: {}, server: { port: 18800, localhost: true }, hooks: { confirm: ['shell.*', 'file.write', 'file.patch'], log: ['web.*', 'file.read'], silent: ['notify'], }, }; } static fromObject(obj: Record): ConfigBuilder { const builder = new ConfigBuilder(); builder.config = structuredClone(obj); return builder; } setProvider(tier: 'default' | 'fast' | 'complex' | 'local', cfg: ProviderConfig): void { const models = (this.config.models ?? {}) as Record; const entry: Record = { provider: cfg.provider, model: cfg.model }; if (cfg.api_key) {entry.api_key = cfg.api_key;} if (cfg.auth_token) {entry.auth_token = cfg.auth_token;} if (cfg.endpoint) {entry.endpoint = cfg.endpoint;} models[tier] = entry; this.config.models = models; } setTelegram(botToken: string, chatIds: number[]): void { this.config.telegram = { bot_token: botToken, allowed_chat_ids: chatIds }; } setDiscord(botToken: string, guildIds: string[]): void { this.config.discord = { bot_token: botToken, allowed_guild_ids: guildIds }; } setSlack(botToken: string, appToken: string, signingSecret: string, channelIds: string[]): void { this.config.slack = { bot_token: botToken, app_token: appToken, signing_secret: signingSecret, allowed_channel_ids: channelIds }; } setWhatsApp(allowedNumbers: string[]): void { this.config.whatsapp = { allowed_numbers: allowedNumbers }; } setGatewayPort(port: number): void { const server = (this.config.server ?? {}) as Record; server.port = port; this.config.server = server; } setGatewayToken(token: string): void { const server = (this.config.server ?? {}) as Record; server.token = token; this.config.server = server; } setGatewayLock(enabled: boolean): void { const server = (this.config.server ?? {}) as Record; server.lock = enabled; this.config.server = server; } setTailscaleServe(enabled: boolean): void { const server = (this.config.server ?? {}) as Record; const tailscale = (server.tailscale ?? {}) as Record; tailscale.serve = enabled; server.tailscale = tailscale; this.config.server = server; } setMemoryEmbedding(cfg: EmbeddingConfig): void { const memory = (this.config.memory ?? {}) as Record; const embedding: Record = { enabled: true, provider: cfg.provider }; if (cfg.api_key) {embedding.api_key = cfg.api_key;} if (cfg.endpoint) {embedding.endpoint = cfg.endpoint;} memory.embedding = embedding; this.config.memory = memory; } setSandboxEnabled(enabled: boolean): void { this.config.sandbox = { enabled }; } setPairingEnabled(enabled: boolean): void { this.config.pairing = { enabled }; } setToolProfile(profile: string): void { this.config.tools = { profile }; } setWebhooksEnabled(secret?: string): void { const automation = (this.config.automation ?? {}) as Record; if (secret) { automation.webhooks = [{ name: 'default', secret, message: '{{body}}', output: { channel: 'webchat', peer: 'webhook' }, enabled: true }]; } else { automation.webhooks = automation.webhooks ?? []; } this.config.automation = automation; } setGmailEnabled(credentialsFile: string, outputChannel: string, outputPeer: string): void { const automation = (this.config.automation ?? {}) as Record; automation.gmail = { enabled: true, credentials_file: credentialsFile, output: { channel: outputChannel, peer: outputPeer } }; this.config.automation = automation; } setGcalEnabled(credentialsFile: string): void { const automation = (this.config.automation ?? {}) as Record; automation.gcal = { enabled: true, credentials_file: credentialsFile }; this.config.automation = automation; } setGdocsEnabled(credentialsFile: string): void { const automation = (this.config.automation ?? {}) as Record; automation.gdocs = { enabled: true, credentials_file: credentialsFile }; this.config.automation = automation; } setGdriveEnabled(credentialsFile: string): void { const automation = (this.config.automation ?? {}) as Record; automation.gdrive = { enabled: true, credentials_file: credentialsFile }; this.config.automation = automation; } setGtasksEnabled(credentialsFile: string): void { const automation = (this.config.automation ?? {}) as Record; automation.gtasks = { enabled: true, credentials_file: credentialsFile }; this.config.automation = automation; } setCronEnabled(): void { const automation = (this.config.automation ?? {}) as Record; if (!automation.cron) {automation.cron = [];} this.config.automation = automation; } build(): Record { return structuredClone(this.config) as Record; } toYaml(): string { return stringify(this.config, { lineWidth: 120 }); } }