import type { AgentImageResponse } from './agent-api-contracts'; import { SQLITE_SCHEMA, SqliteAgentStateStore } from './agent-state-sqlite'; import { hashAgentPayload, type AgentArtifactRecord } from './agent-state-store'; import Database from 'better-sqlite3'; import assert from 'node:assert/strict'; import { access, mkdir, mkdtemp, readdir, rm, writeFile } from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import { after, before, describe, it } from 'node:test'; describe('SqliteAgentStateStore', () => { let tempDir = ''; let store: SqliteAgentStateStore; before(async () => { tempDir = await mkdtemp(path.join(os.tmpdir(), 'agent-state-sqlite-')); store = new SqliteAgentStateStore(path.join(tempDir, 'agent.sqlite')); await store.init(); }); after(async () => { await store.close(); await rm(tempDir, { recursive: true, force: true }); }); it('acquires, completes, and replays idempotent requests', async () => { const requestJson = { prompt: 'test' }; const requestHash = hashAgentPayload(requestJson); const begin = await store.beginRequest({ idempotencyKey: 'idem-1', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); const artifact: AgentArtifactRecord = { id: 'artifact-1', requestId: begin.record.requestId, filename: '1715400000000-abcdef1234567890-0.png', filepath: '/tmp/image.png', contentUrl: '/api/agent/artifacts/artifact-1/content', metadataUrl: '/api/agent/artifacts/artifact-1', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 4, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:01.000Z' }; const response: AgentImageResponse = { request_id: begin.record.requestId, idempotency_key: 'idem-1', cached: false, images: [], created_at: '2026-05-12T00:00:01.000Z' }; await store.completeRequest({ requestId: begin.record.requestId, response, artifacts: [artifact] }); const replay = await store.beginRequest({ idempotencyKey: 'idem-1', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60, now: new Date('2026-05-12T00:00:02.000Z') }); assert.equal(replay.type, 'replay'); if (replay.type !== 'replay') throw new Error('expected replay'); assert.equal(replay.response.request_id, begin.record.requestId); assert.deepEqual(await store.getArtifact('artifact-1'), artifact); }); it('rejects the same idempotency key with a different request hash', async () => { const result = await store.beginRequest({ idempotencyKey: 'idem-1', requestHash: hashAgentPayload({ prompt: 'different' }), mode: 'generate', requestJson: { prompt: 'different' }, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(result.type, 'conflict'); }); it('rejects artifact metadata for unknown requests', async () => { await assert.rejects( () => store.saveArtifacts([ { id: 'artifact-missing-request', requestId: 'missing-request', filename: '1715400000000-missing-0.png', filepath: '/tmp/missing.png', contentUrl: '/api/agent/artifacts/artifact-missing-request/content', metadataUrl: '/api/agent/artifacts/artifact-missing-request', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 1, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:00.000Z' } ]), /FOREIGN KEY/ ); }); it('lists sorted artifact filepaths for cleanup protection', async () => { const requestJson = { prompt: 'sqlite cleanup protection' }; const begin = await store.beginRequest({ idempotencyKey: 'idem-sqlite-cleanup-protection', requestHash: hashAgentPayload(requestJson), mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); const firstPath = path.join(tempDir, 'generated-images', 'cleanup-a.png'); const secondPath = path.join(tempDir, 'generated-images', 'cleanup-b.png'); await store.saveArtifacts([ { ...buildArtifact({ id: 'artifact-sqlite-cleanup-b', requestId: begin.record.requestId, filename: 'cleanup-b.png' }), filepath: secondPath }, { ...buildArtifact({ id: 'artifact-sqlite-cleanup-a', requestId: begin.record.requestId, filename: 'cleanup-a.png' }), filepath: firstPath } ]); const protectedPaths = (await store.listArtifactFilepaths()).filter( (filepath) => filepath === firstPath || filepath === secondPath ); assert.deepEqual(protectedPaths, [firstPath, secondPath]); }); it('upserts feedback rows by target type and id', async () => { const first = { targetType: 'page_request' as const, targetId: 'web-sqlite-feedback', value: 'usable' as const, note: 'works for review', source: 'webui' as const, updatedAt: '2026-05-12T00:00:00.000Z' }; const second = { ...first, value: 'needs_revision' as const, note: 'needs crop fix', updatedAt: '2026-05-12T00:02:00.000Z' }; await store.upsertFeedbackBatch([first, second, { ...first, note: 'stale retry' }]); assert.deepEqual(await store.readFeedback('page_request', 'web-sqlite-feedback'), second); assert.equal( await store.deleteFeedbackByTargets([{ targetType: 'page_request', targetId: 'web-sqlite-feedback' }], { deletedAt: '2026-05-12T00:01:00.000Z' }), 0 ); assert.deepEqual(await store.readFeedback('page_request', 'web-sqlite-feedback'), second); assert.equal( await store.deleteFeedbackByTargets([{ targetType: 'page_request', targetId: 'web-sqlite-feedback' }]), 1 ); assert.equal(await store.readFeedback('page_request', 'web-sqlite-feedback'), undefined); }); it('replays stored failures without reacquiring the same idempotency key', async () => { const requestJson = { prompt: 'stored failure' }; const requestHash = hashAgentPayload(requestJson); const begin = await store.beginRequest({ idempotencyKey: 'idem-stored-failure', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.failRequest({ requestId: begin.record.requestId, error: { error: { code: 'unexpected_error', message: 'stored failure', retryable: true, request_id: begin.record.requestId } } }); const replay = await store.beginRequest({ idempotencyKey: 'idem-stored-failure', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(replay.type, 'failed'); if (replay.type !== 'failed') throw new Error('expected failed'); assert.equal(replay.error.error.message, 'stored failure'); }); it('marks expired running requests as orphaned', async () => { const begin = await store.beginRequest({ idempotencyKey: 'idem-expired', requestHash: hashAgentPayload({ prompt: 'expired' }), mode: 'generate', requestJson: { prompt: 'expired' }, leaseMs: 1000, ttlSeconds: 60, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); const recovered = await store.recoverExpiredRequests(new Date('2026-05-12T00:00:02.000Z')); assert.ok(recovered >= 1); const reacquired = await store.beginRequest({ idempotencyKey: 'idem-expired', requestHash: hashAgentPayload({ prompt: 'expired' }), mode: 'generate', requestJson: { prompt: 'expired' }, leaseMs: 1000, ttlSeconds: 60, now: new Date('2026-05-12T00:00:03.000Z') }); assert.equal(reacquired.type, 'acquired'); }); it('keeps refreshed running requests out of recovery', async () => { const requestJson = { prompt: 'sqlite lease refresh' }; const requestHash = hashAgentPayload(requestJson); const begin = await store.beginRequest({ idempotencyKey: 'idem-sqlite-refresh', requestHash, mode: 'generate', requestJson, leaseMs: 100, ttlSeconds: 60, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); assert.equal( await store.refreshRequestLease({ requestId: begin.record.requestId, leaseMs: 1000, now: new Date('2026-05-12T00:00:00.050Z') }), true ); await store.recoverExpiredRequests(new Date('2026-05-12T00:00:00.200Z')); const retry = await store.beginRequest({ idempotencyKey: 'idem-sqlite-refresh', requestHash, mode: 'generate', requestJson, leaseMs: 100, ttlSeconds: 60, now: new Date('2026-05-12T00:00:00.200Z') }); assert.equal(retry.type, 'in_progress'); }); it('recovers expired running requests with artifact metadata as succeeded', async () => { const requestJson = { prompt: 'recover artifact' }; const requestHash = hashAgentPayload(requestJson); const begin = await store.beginRequest({ idempotencyKey: 'idem-recover-artifact', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.saveArtifacts([ { id: 'artifact-recovered', requestId: begin.record.requestId, filename: '1715400000000-recovered-0.png', filepath: '/tmp/recovered.png', contentUrl: '/api/agent/artifacts/artifact-recovered/content', metadataUrl: '/api/agent/artifacts/artifact-recovered', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 8, width: 2, height: 2, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:01.000Z' } ]); const recovered = await store.recoverExpiredRequests(new Date('2026-05-12T00:00:02.000Z')); assert.ok(recovered >= 1); const replay = await store.beginRequest({ idempotencyKey: 'idem-recover-artifact', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60, now: new Date('2026-05-12T00:00:03.000Z') }); assert.equal(replay.type, 'replay'); if (replay.type !== 'replay') throw new Error('expected replay'); assert.equal(replay.response.request_id, begin.record.requestId); assert.equal(replay.response.images[0].id, 'artifact-recovered'); }); it('purges expired terminal requests and their artifact metadata', async () => { const requestJson = { prompt: 'purge expired' }; const requestHash = hashAgentPayload(requestJson); const begin = await store.beginRequest({ idempotencyKey: 'idem-purge-expired', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 1, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.completeRequest({ requestId: begin.record.requestId, response: { request_id: begin.record.requestId, idempotency_key: 'idem-purge-expired', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [ { id: 'artifact-purge-expired', requestId: begin.record.requestId, filename: '1715400000000-purge-0.png', filepath: '/tmp/purge.png', contentUrl: '/api/agent/artifacts/artifact-purge-expired/content', metadataUrl: '/api/agent/artifacts/artifact-purge-expired', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 1, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:00.500Z' } ], now: new Date('2026-05-12T00:00:00.500Z') }); const purged = await store.purgeExpiredRequests(new Date('2026-05-12T00:00:02.000Z')); assert.equal(purged, 1); assert.equal(await store.getArtifact('artifact-purge-expired'), undefined); }); it('purges feedback rows for expired agent requests and artifacts', async () => { const requestJson = { prompt: 'sqlite feedback purge' }; const begin = await store.beginRequest({ idempotencyKey: 'idem-sqlite-feedback-purge', requestHash: hashAgentPayload(requestJson), mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 1, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); const artifact = buildArtifact({ id: 'artifact-sqlite-feedback-purge', requestId: begin.record.requestId, filename: 'sqlite-feedback-purge.png' }); await store.completeRequest({ requestId: begin.record.requestId, response: { request_id: begin.record.requestId, idempotency_key: 'idem-sqlite-feedback-purge', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [artifact], now: new Date('2026-05-12T00:00:00.500Z') }); await store.upsertFeedback({ targetType: 'agent_request', targetId: begin.record.requestId, value: 'usable', source: 'agent', updatedAt: '2026-05-12T00:00:00.600Z' }); await store.upsertFeedback({ targetType: 'agent_artifact', targetId: artifact.id, value: 'needs_revision', source: 'agent', updatedAt: '2026-05-12T00:00:00.700Z' }); assert.equal(await store.purgeExpiredRequests(new Date('2026-05-12T00:00:02.000Z')), 1); assert.equal(await store.readFeedback('agent_request', begin.record.requestId), undefined); assert.equal(await store.readFeedback('agent_artifact', artifact.id), undefined); }); it('deletes artifact feedback when deleting artifact metadata', async () => { const requestJson = { prompt: 'sqlite artifact feedback delete' }; const begin = await store.beginRequest({ idempotencyKey: 'idem-sqlite-artifact-feedback-delete', requestHash: hashAgentPayload(requestJson), mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); const artifact = buildArtifact({ id: 'artifact-sqlite-feedback-delete', requestId: begin.record.requestId, filename: 'sqlite-feedback-delete.png' }); await store.saveArtifacts([artifact]); await store.upsertFeedback({ targetType: 'agent_artifact', targetId: artifact.id, value: 'usable', source: 'agent', updatedAt: '2026-05-12T00:00:00.000Z' }); assert.equal(await store.deleteArtifact(artifact.id), true); assert.equal(await store.readFeedback('agent_artifact', artifact.id), undefined); }); it('deletes artifact files when purging expired terminal requests', async () => { const requestJson = { prompt: 'purge file' }; const requestHash = hashAgentPayload(requestJson); const artifactPath = path.join(process.cwd(), 'generated-images', 'purge-file.png'); await mkdir(path.dirname(artifactPath), { recursive: true }); await writeFile(artifactPath, 'stale image'); const begin = await store.beginRequest({ idempotencyKey: 'idem-purge-file', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 1, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.completeRequest({ requestId: begin.record.requestId, response: { request_id: begin.record.requestId, idempotency_key: 'idem-purge-file', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [ { id: 'artifact-purge-file', requestId: begin.record.requestId, filename: 'purge-file.png', filepath: artifactPath, contentUrl: '/api/agent/artifacts/artifact-purge-file/content', metadataUrl: '/api/agent/artifacts/artifact-purge-file', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 10, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:00.500Z' } ], now: new Date('2026-05-12T00:00:00.500Z') }); const purged = await store.purgeExpiredRequests(new Date('2026-05-12T00:00:02.000Z')); assert.equal(purged, 1); await assert.rejects(() => access(artifactPath)); }); it('purges directory artifact paths through the same relocation flow', async () => { const requestJson = { prompt: 'purge directory artifact' }; const requestHash = hashAgentPayload(requestJson); const artifactBaseName = `purge-directory-artifact-${crypto.randomUUID()}`; const artifactParentPath = path.join(process.cwd(), 'generated-images', '.sqlite-purge-dir-test'); const artifactPath = path.join(artifactParentPath, artifactBaseName); await mkdir(artifactPath, { recursive: true }); const begin = await store.beginRequest({ idempotencyKey: 'idem-purge-directory-artifact', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 1, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.completeRequest({ requestId: begin.record.requestId, response: { request_id: begin.record.requestId, idempotency_key: 'idem-purge-directory-artifact', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [ { id: 'artifact-purge-directory-artifact', requestId: begin.record.requestId, filename: 'purge-directory-artifact', filepath: artifactPath, contentUrl: '/api/agent/artifacts/artifact-purge-directory-artifact/content', metadataUrl: '/api/agent/artifacts/artifact-purge-directory-artifact', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 10, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:00.500Z' } ], now: new Date('2026-05-12T00:00:00.500Z') }); try { const purged = await store.purgeExpiredRequests(new Date('2026-05-12T00:00:02.000Z')); assert.equal(purged, 1); await assert.rejects(() => access(artifactPath)); assert.equal(await store.getArtifact('artifact-purge-directory-artifact'), undefined); const entries = await readdir(artifactParentPath); assert.deepEqual( entries.filter((entry) => entry.startsWith(`${artifactBaseName}.purge-`)), [] ); } finally { await rm(artifactParentPath, { recursive: true, force: true }); } }); it('does not replace a different artifact row when filename collides', async () => { const requestJsonA = { prompt: 'file collision A' }; const requestJsonB = { prompt: 'file collision B' }; const beginA = await store.beginRequest({ idempotencyKey: 'idem-collision-a', requestHash: hashAgentPayload(requestJsonA), mode: 'generate', requestJson: requestJsonA, leaseMs: 1000, ttlSeconds: 60 }); const beginB = await store.beginRequest({ idempotencyKey: 'idem-collision-b', requestHash: hashAgentPayload(requestJsonB), mode: 'generate', requestJson: requestJsonB, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(beginA.type, 'acquired'); assert.equal(beginB.type, 'acquired'); if (beginA.type !== 'acquired' || beginB.type !== 'acquired') throw new Error('expected acquired'); const sharedFilename = 'shared-name.png'; await store.completeRequest({ requestId: beginA.record.requestId, response: { request_id: beginA.record.requestId, idempotency_key: 'idem-collision-a', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [ buildArtifact({ id: 'artifact-collision-a', requestId: beginA.record.requestId, filename: sharedFilename }) ] }); await assert.rejects( () => store.completeRequest({ requestId: beginB.record.requestId, response: { request_id: beginB.record.requestId, idempotency_key: 'idem-collision-b', cached: false, images: [], created_at: '2026-05-12T00:00:00.600Z' }, artifacts: [ buildArtifact({ id: 'artifact-collision-b', requestId: beginB.record.requestId, filename: sharedFilename }) ] }), /UNIQUE/ ); assert.ok(await store.getArtifact('artifact-collision-a')); assert.equal(await store.getArtifact('artifact-collision-b'), undefined); }); it('restores moved artifact files when purge fails after file relocation', async () => { const requestJson = { prompt: 'purge restore on failure' }; const requestHash = hashAgentPayload(requestJson); const artifactPath = path.join( process.cwd(), 'generated-images', '.sqlite-purge-test', `${crypto.randomUUID()}.png` ); await mkdir(path.dirname(artifactPath), { recursive: true }); await writeFile(artifactPath, 'stale image'); const begin = await store.beginRequest({ idempotencyKey: 'idem-purge-restore-file', requestHash, mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 1, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.completeRequest({ requestId: begin.record.requestId, response: { request_id: begin.record.requestId, idempotency_key: 'idem-purge-restore-file', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [ { id: 'artifact-purge-restore-file', requestId: begin.record.requestId, filename: 'sqlite-purge-restore.png', filepath: artifactPath, contentUrl: '/api/agent/artifacts/artifact-purge-restore-file/content', metadataUrl: '/api/agent/artifacts/artifact-purge-restore-file', outputFormat: 'png', mimeType: 'image/png', sizeBytes: 1, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:00.500Z' } ], now: new Date('2026-05-12T00:00:00.500Z') }); try { const db = ( store as unknown as { db: { exec(sql: string): void; prepare(sql: string): { run(...args: unknown[]): void } }; } ).db; db.exec( "CREATE TRIGGER purge_fail_guard BEFORE DELETE ON agent_requests BEGIN SELECT RAISE(ABORT, 'purge failed'); END;" ); await assert.rejects( () => store.purgeExpiredRequests(new Date('2026-05-12T00:00:02.000Z')), /purge failed/ ); await assert.doesNotReject(() => access(artifactPath)); assert.ok(await store.getArtifact('artifact-purge-restore-file')); } finally { const db = (store as unknown as { db: { exec(sql: string): void } }).db; db.exec('DROP TRIGGER IF EXISTS purge_fail_guard'); await rm(path.dirname(artifactPath), { recursive: true, force: true }); } }); it('continues purging expired requests after a guarded purge failure', async () => { const requestJson = { prompt: 'purge after guarded failure' }; const begin = await store.beginRequest({ idempotencyKey: 'idem-purge-after-guarded-failure', requestHash: hashAgentPayload(requestJson), mode: 'generate', requestJson, leaseMs: 1000, ttlSeconds: 1, now: new Date('2026-05-12T00:00:00.000Z') }); assert.equal(begin.type, 'acquired'); if (begin.type !== 'acquired') throw new Error('expected acquired'); await store.completeRequest({ requestId: begin.record.requestId, response: { request_id: begin.record.requestId, idempotency_key: 'idem-purge-after-guarded-failure', cached: false, images: [], created_at: '2026-05-12T00:00:00.500Z' }, artifacts: [], now: new Date('2026-05-12T00:00:00.500Z') }); await assert.doesNotReject(() => store.purgeExpiredRequests(new Date('2026-05-12T00:00:02.000Z'))); }); it('stores and reads image share metadata', async () => { await store.createImageShareRecord({ token: 'b'.repeat(24), sourceFilename: 'source.png', contentFilename: `${'b'.repeat(24)}.png`, mimeType: 'image/png', sizeBytes: 12, createdAt: '2026-05-14T08:00:00.000Z', accessCodeRequired: true, expiresAt: '2026-05-14T09:00:00.000Z', accessCodeSalt: 'salt', accessCodeHash: 'hash' }); const record = await store.readImageShareRecord('b'.repeat(24)); assert.ok(record); assert.equal(record.sourceFilename, 'source.png'); assert.equal(record.accessCodeRequired, true); assert.equal(record.expiresAt, '2026-05-14T09:00:00.000Z'); }); it('rejects invalid protected image share metadata at the schema boundary', async () => { const db = new Database(path.join(tempDir, 'invalid-share-schema.sqlite')); db.exec(SQLITE_SCHEMA); try { assert.throws( () => db .prepare( `INSERT INTO image_shares (token, source_filename, content_filename, mime_type, size_bytes, created_at, access_code_required) VALUES (?, ?, ?, ?, ?, ?, ?)` ) .run( 'f'.repeat(24), 'source.png', `${'f'.repeat(24)}.png`, 'image/png', 12, '2026-05-14T08:00:00.000Z', 1 ), /CHECK/ ); } finally { db.close(); } }); it('rejects applied migration checksum drift', async () => { const dbPath = path.join(tempDir, 'migration-checksum-drift.sqlite'); const db = new Database(dbPath); db.exec(` CREATE TABLE state_schema_migrations ( id TEXT PRIMARY KEY, checksum TEXT NOT NULL, applied_at TEXT NOT NULL ); INSERT INTO state_schema_migrations (id, checksum, applied_at) VALUES ('001_agent_state_core', 'bad-checksum', '2026-05-14T08:00:00.000Z'); `); db.close(); const drifted = new SqliteAgentStateStore(dbPath); await assert.rejects(() => drifted.init(), /checksum/); }); it('rejects attempts to rewrite an existing artifact id with different metadata', async () => { const requestJsonA = { prompt: 'stable artifact A' }; const requestJsonB = { prompt: 'stable artifact B' }; const beginA = await store.beginRequest({ idempotencyKey: 'idem-stable-artifact-a', requestHash: hashAgentPayload(requestJsonA), mode: 'generate', requestJson: requestJsonA, leaseMs: 1000, ttlSeconds: 60 }); const beginB = await store.beginRequest({ idempotencyKey: 'idem-stable-artifact-b', requestHash: hashAgentPayload(requestJsonB), mode: 'generate', requestJson: requestJsonB, leaseMs: 1000, ttlSeconds: 60 }); assert.equal(beginA.type, 'acquired'); assert.equal(beginB.type, 'acquired'); if (beginA.type !== 'acquired' || beginB.type !== 'acquired') throw new Error('expected acquired'); const first = buildArtifact({ id: 'artifact-stable-sqlite', requestId: beginA.record.requestId, filename: 'stable-sqlite-a.png' }); const rewritten = buildArtifact({ id: 'artifact-stable-sqlite', requestId: beginB.record.requestId, filename: 'stable-sqlite-b.png' }); await store.saveArtifacts([first]); await assert.rejects(() => store.saveArtifacts([rewritten]), /artifact metadata conflict/); assert.deepEqual(await store.getArtifact('artifact-stable-sqlite'), first); }); it('deletes expired image share records and lists active share records', async () => { await store.createImageShareRecord({ token: 'd'.repeat(24), sourceFilename: 'expired.png', contentFilename: `${'d'.repeat(24)}.png`, mimeType: 'image/png', sizeBytes: 12, createdAt: '2026-05-14T08:00:00.000Z', accessCodeRequired: false, expiresAt: '2026-05-14T09:00:00.000Z' }); await store.createImageShareRecord({ token: 'e'.repeat(24), sourceFilename: 'active.png', contentFilename: `${'e'.repeat(24)}.png`, mimeType: 'image/png', sizeBytes: 12, createdAt: '2026-05-14T08:00:00.000Z', accessCodeRequired: false, expiresAt: '2026-05-14T10:00:00.000Z' }); const expired = await store.deleteExpiredImageShareRecords('2026-05-14T09:00:01.000Z'); const active = await store.listImageShareRecords(); assert.equal( expired.some((record) => record.token === 'd'.repeat(24)), true ); assert.equal( active.some((record) => record.token === 'e'.repeat(24)), true ); }); it('records schema migrations and keeps repeated init idempotent', async () => { const dbPath = path.join(tempDir, 'migration-idempotent.sqlite'); const first = new SqliteAgentStateStore(dbPath); await first.init(); const second = new SqliteAgentStateStore(dbPath); await second.init(); const db = new Database(dbPath, { readonly: true }); try { const rows = db.prepare('SELECT id FROM state_schema_migrations ORDER BY id ASC').all() as Array<{ id: string; }>; assert.deepEqual( rows.map((row) => row.id), ['001_agent_state_core', '002_image_shares', '003_result_feedback'] ); } finally { db.close(); } }); }); function buildArtifact(input: { id: string; requestId: string; filename: string }): AgentArtifactRecord { return { id: input.id, requestId: input.requestId, filename: input.filename, filepath: path.join(process.cwd(), 'generated-images', `${input.id}.png`), contentUrl: `/api/agent/artifacts/${input.id}/content`, metadataUrl: `/api/agent/artifacts/${input.id}`, outputFormat: 'png', mimeType: 'image/png', sizeBytes: 1, width: 1, height: 1, model: 'gpt-image-2', promptHash: 'hash', createdAt: '2026-05-12T00:00:00.500Z' }; }