diff --git a/src/config/schema.test.ts b/src/config/schema.test.ts index 021a6d8..4b4e0c0 100644 --- a/src/config/schema.test.ts +++ b/src/config/schema.test.ts @@ -181,6 +181,47 @@ describe('configSchema — models auth_mode', () => { }); }); +describe('configSchema — matrix', () => { + const minimalConfig = { + telegram: { bot_token: 'test', allowed_chat_ids: [1] }, + models: { default: { provider: 'anthropic', model: 'claude-3' } }, + }; + + it('accepts matrix config and defaults sync_timeout_ms', () => { + const result = configSchema.parse({ + ...minimalConfig, + matrix: { + homeserver_url: 'https://matrix.example.org', + access_token: 'syt_test_token', + allowed_room_ids: ['!room1:example.org'], + require_mention: true, + }, + }); + + expect(result.matrix).toBeDefined(); + expect(result.matrix!.homeserver_url).toBe('https://matrix.example.org'); + expect(result.matrix!.access_token).toBe('syt_test_token'); + expect(result.matrix!.sync_timeout_ms).toBe(30000); + }); + + it('matrix config is optional', () => { + const result = configSchema.parse(minimalConfig); + expect(result.matrix).toBeUndefined(); + }); + + it('rejects invalid homeserver_url', () => { + expect(() => { + configSchema.parse({ + ...minimalConfig, + matrix: { + homeserver_url: 'not-a-url', + access_token: 'token', + }, + }); + }).toThrow(/homeserver/i); + }); +}); + describe('configSchema — skills watcher', () => { const minimalConfig = { telegram: { bot_token: 'test', allowed_chat_ids: [1] }, diff --git a/src/config/schema.ts b/src/config/schema.ts index 04695ef..b50d47c 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -349,6 +349,15 @@ const whatsappSchema = z.object({ data_dir: z.string().optional(), }).optional(); +const matrixSchema = z.object({ + homeserver_url: z.string().url('Homeserver URL is required'), + access_token: z.string().min(1, 'Access token is required'), + allowed_room_ids: z.array(z.string()).default([]), + require_mention: z.boolean().default(true), + sync_timeout_ms: z.number().min(1000).max(120000).default(30000), + display_name: z.string().optional(), +}).optional(); + const browserSchema = z.object({ enabled: z.boolean().default(false), executable_path: z.string().optional(), @@ -514,6 +523,7 @@ export const configSchema = z.object({ discord: discordSchema, slack: slackSchema, whatsapp: whatsappSchema, + matrix: matrixSchema, server: serverSchema.default({}), models: modelsSchema, backends: backendsSchema.default({}), @@ -557,6 +567,7 @@ export type BrowserConfig = z.infer; export type DiscordConfig = z.infer; export type SlackConfig = z.infer; export type WhatsAppConfig = z.infer; +export type MatrixConfig = z.infer; export type RetryPolicyConfig = z.infer; export type ContextLevel = z.infer; export type PromptConfig = z.infer;