import assert from 'node:assert/strict'; import test from 'node:test'; import type { ParseObject } from '../src/db/parse-rest.client.js'; import { VOC_PARSE_CLASSES } from '../src/db/parse-rest.schema.js'; import { ParseRestAiPromptConfigStore, type AiPromptConfigRecord, } from '../src/modules/ai-gateway/prompt-config.repository.js'; type StoredPrompt = AiPromptConfigRecord & ParseObject; class FakePromptClient { readonly records: StoredPrompt[] = []; private nextId = 1; async findAll(className: string, where: Record = {}): Promise> { assert.equal(className, VOC_PARSE_CLASSES.promptConfig); return this.records.filter((record) => matches(record, where)) as unknown as Array; } async findOne(className: string, where: Record): Promise<(T & ParseObject) | null> { assert.equal(className, VOC_PARSE_CLASSES.promptConfig); return (this.records.find((record) => matches(record, where)) ?? null) as (T & ParseObject) | null; } async create>(className: string, object: T): Promise { assert.equal(className, VOC_PARSE_CLASSES.promptConfig); const now = '2026-07-27T00:00:00.000Z'; const stored = { ...object, objectId: `prompt-${this.nextId++}`, createdAt: now, updatedAt: now, } as unknown as StoredPrompt; this.records.push(stored); return stored; } async update>( className: string, objectId: string, patch: T, ): Promise<{ updatedAt: string }> { assert.equal(className, VOC_PARSE_CLASSES.promptConfig); const record = this.records.find((item) => item.objectId === objectId); assert.ok(record); const updatedAt = '2026-07-27T01:00:00.000Z'; Object.assign(record, patch, { updatedAt }); return { updatedAt }; } } function matches(record: StoredPrompt, where: Record): boolean { return Object.entries(where).every(([key, value]) => record[key as keyof StoredPrompt] === value); } function prompt(promptKey: string, template: string): AiPromptConfigRecord { return { promptKey, name: promptKey, module: 'test', scope: 'analysis', template, enabled: true, variables: [], dataSources: [], }; } test('AI prompt store isolates workspaces and seeds defaults idempotently', async () => { const client = new FakePromptClient(); const otherWorkspace = new ParseRestAiPromptConfigStore(client, 'other'); const demashi = new ParseRestAiPromptConfigStore(client, 'demashi'); await otherWorkspace.upsert('shared.analysisPanel.defaultSystem', prompt('shared.analysisPanel.defaultSystem', 'other')); const first = await demashi.ensureDefaults([ prompt('shared.analysisPanel.defaultSystem', 'demashi default'), prompt('global.analysis.defaultModel', 'deepseek-v4-pro'), ]); const second = await demashi.ensureDefaults([ prompt('shared.analysisPanel.defaultSystem', 'must not overwrite'), prompt('global.analysis.defaultModel', 'must not overwrite'), ]); assert.deepEqual(first, { created: 2, existing: 0 }); assert.deepEqual(second, { created: 0, existing: 2 }); assert.equal((await demashi.list()).length, 2); assert.equal((await otherWorkspace.list())[0]?.template, 'other'); assert.equal((await demashi.list())[0]?.workspaceId, 'demashi'); assert.equal((await demashi.list())[0]?.revision, 1); assert.equal((await demashi.list())[1]?.model, 'deepseek-v4-pro'); const updated = await demashi.upsert( 'shared.analysisPanel.defaultSystem', prompt('shared.analysisPanel.defaultSystem', 'customized'), ); assert.equal(updated.template, 'customized'); assert.equal(updated.revision, 2); assert.equal(client.records.length, 3); });