import assert from 'node:assert/strict'; import test from 'node:test'; import { createMemoryV2AdminConfigService, memoryV2AdminConfigInternals, } from './memory-v2-admin-config.mjs'; function createPool(seedRow = null) { const state = { row: seedRow }; return { state, async query(sql, params) { if (sql.includes('CREATE TABLE')) return [[], []]; if (sql.includes('SELECT config_json')) { return [state.row ? [state.row] : [], []]; } if (sql.includes('INSERT INTO h5_memory_v2_admin_config')) { state.row = { config_json: params[1], secrets_ciphertext: params[2], secrets_iv: params[3], secrets_tag: params[4], updated_by: params[5], updated_at: params[6], }; return [[], []]; } throw new Error(`Unexpected query: ${sql}`); }, }; } test('memory v2 admin config service loads defaults from env and masks secrets', async () => { const service = createMemoryV2AdminConfigService(createPool(), { env: { MEMORY_ENABLED: '1', MEMORY_BACKEND: 'pgvector', MEMIND_CHAT_LLM_ROUTER_ENABLED: '1', MEMIND_CHAT_ROUTER_MODEL_PROVIDER_KEY_ID: 'key-router', MEMIND_CHAT_ROUTER_MODEL: 'deepseek-chat', MEMORY_PGVECTOR_DATABASE_URL: 'postgresql://user:pass@127.0.0.1:5432/memory', MEMORY_QDRANT_API_KEY: 'secret-qdrant', }, }); const result = await service.getAdminConfig(); assert.equal(result.config.global.enabled, true); assert.equal(result.config.global.backend, 'pgvector'); assert.equal(result.config.chatIntentRouter.enabled, true); assert.equal(result.config.chatIntentRouter.modelProviderKeyId, 'key-router'); assert.equal(result.config.chatIntentRouter.model, 'deepseek-chat'); assert.equal(result.config.pgvector.databaseUrlConfigured, true); assert.match(result.config.pgvector.databaseUrlMasked, /^post\*+/); assert.equal(result.config.qdrant.apiKeyConfigured, true); }); test('memory v2 admin config service persists non-secret and secret patches', async () => { const pool = createPool(); const service = createMemoryV2AdminConfigService(pool, { env: { MEMORY_ENABLED: '0', MEMORY_BACKEND: 'legacy', }, }); const updated = await service.updateAdminConfig({ global: { enabled: true, backend: 'qdrant' }, chatIntentRouter: { enabled: true, modelProviderKeyId: 'key-router', model: 'deepseek-chat', minConfidence: '0.7', memoryResolveEnabled: true, memoryResolveLimit: '8', timeoutMs: '1500', fallbackRoute: 'agent_orchestration', }, qdrant: { enabled: true, url: 'http://127.0.0.1:6333', apiKey: 'secret-qdrant', }, }, { updatedBy: 'admin-1' }); assert.equal(updated.config.global.enabled, true); assert.equal(updated.config.global.backend, 'qdrant'); assert.equal(updated.config.chatIntentRouter.enabled, true); assert.equal(updated.config.chatIntentRouter.modelProviderKeyId, 'key-router'); assert.equal(updated.config.chatIntentRouter.minConfidence, '0.7'); assert.equal(updated.config.qdrant.enabled, true); assert.equal(updated.config.qdrant.url, 'http://127.0.0.1:6333'); assert.equal(updated.config.qdrant.apiKeyConfigured, true); assert.equal(updated.updatedBy, 'admin-1'); const runtimeState = await service.getRuntimeState(); assert.equal(runtimeState.overrides.MEMORY_ENABLED, '1'); assert.equal(runtimeState.overrides.MEMORY_BACKEND, 'qdrant'); assert.equal(runtimeState.overrides.MEMIND_CHAT_LLM_ROUTER_ENABLED, '1'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_MODEL_PROVIDER_KEY_ID, 'key-router'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_MODEL, 'deepseek-chat'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_MIN_CONFIDENCE, '0.7'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_MEMORY_ENABLED, '1'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_MEMORY_LIMIT, '8'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_TIMEOUT_MS, '1500'); assert.equal(runtimeState.overrides.MEMIND_CHAT_ROUTER_FALLBACK_ROUTE, 'agent_orchestration'); assert.equal(runtimeState.overrides.MEMORY_QDRANT_ENABLED, '1'); assert.equal(runtimeState.overrides.MEMORY_QDRANT_URL, 'http://127.0.0.1:6333'); assert.equal(runtimeState.overrides.MEMORY_QDRANT_API_KEY, 'secret-qdrant'); }); test('memory v2 admin config internals flatten booleans and numbers consistently', () => { const env = memoryV2AdminConfigInternals.flattenConfig( { ...memoryV2AdminConfigInternals.defaultConfigShape(), global: { enabled: true, backend: 'pgvector', vectorEnabled: true }, chatIntentRouter: { enabled: true, minConfidence: '0.65', memoryResolveEnabled: true, memoryResolveLimit: '8', timeoutMs: '1500', }, pgvector: { enabled: true, poolMax: '5', limit: '8' }, }, { ...memoryV2AdminConfigInternals.defaultConfigShape(), pgvector: { databaseUrl: 'postgresql://local/memory' }, }, ); assert.equal(env.MEMORY_ENABLED, '1'); assert.equal(env.MEMORY_BACKEND, 'pgvector'); assert.equal(env.MEMIND_CHAT_LLM_ROUTER_ENABLED, '1'); assert.equal(env.MEMIND_CHAT_ROUTER_MIN_CONFIDENCE, '0.65'); assert.equal(env.MEMIND_CHAT_ROUTER_MEMORY_ENABLED, '1'); assert.equal(env.MEMIND_CHAT_ROUTER_MEMORY_LIMIT, '8'); assert.equal(env.MEMIND_CHAT_ROUTER_TIMEOUT_MS, '1500'); assert.equal(env.MEMORY_VECTOR_ENABLED, '1'); assert.equal(env.MEMORY_PGVECTOR_ENABLED, '1'); assert.equal(env.MEMORY_PGVECTOR_POOL_MAX, '5'); assert.equal(env.MEMORY_PGVECTOR_LIMIT, '8'); });