import assert from 'node:assert/strict'; import test from 'node:test'; import { createMindSpaceConversationArtifactService } from './mindspace-conversation-package-artifact-service.mjs'; function createRegistry() { const calls = []; return { calls, async putObjectForSession(input) { calls.push({ kind: 'put', input }); return { packageRecord: { id: 'package-1' }, writeResult: { key: 'packages/object' }, }; }, async recordArtifact(input) { calls.push({ kind: 'record', input }); return input; }, async writeManifestForSession(input) { calls.push({ kind: 'manifest', input }); return { ok: true }; }, }; } test('public HTML artifact registration resolves the physical publish directory inside MindSpace', async () => { const registry = createRegistry(); const calls = []; const service = createMindSpaceConversationArtifactService({ conversationPackageRegistry: registry, h5Root: '/srv/h5', env: { H5_PUBLIC_BASE_URL: 'https://example.com' }, resolveMindSpaceUserPublishDirFn(h5Root, user) { calls.push({ kind: 'resolve', h5Root, user }); return '/srv/h5/MindSpace/user-1'; }, async registerPublicHtmlArtifactsFn(input) { calls.push({ kind: 'register', input }); return [{ artifactId: 'artifact-1' }]; }, }); const result = await service.registerPublicHtmlArtifacts({ userId: 'user-1', sessionId: 'session-1', artifactRefs: [ { relativePath: 'public/page.html', messageId: 'message-1', }, ], }); assert.deepEqual(result, [{ artifactId: 'artifact-1' }]); assert.equal(calls[0].kind, 'resolve'); assert.equal(calls[0].h5Root, '/srv/h5'); assert.equal(calls[1].kind, 'register'); assert.equal( calls[1].input.publishDir, '/srv/h5/MindSpace/user-1', ); assert.equal( calls[1].input.artifactRefs[0].relativePath, 'public/page.html', ); }); test('DOCX artifact registration accepts RPC-revived binary data and delegates to the package helper', async () => { const registry = createRegistry(); const calls = []; const service = createMindSpaceConversationArtifactService({ conversationPackageRegistry: registry, h5Root: '/srv/h5', async registerChatDocxArtifactFn(input) { calls.push(input); return { id: 'docx-1' }; }, }); const body = new Uint8Array([1, 2, 3]); const result = await service.registerChatDocxArtifact({ userId: 'user-1', sessionId: 'session-1', messageId: 'message-1', selectedLinkIndex: 2, title: 'Chat title', filename: 'chat.docx', body, }); assert.deepEqual(result, { id: 'docx-1' }); assert.ok(Buffer.isBuffer(calls[0].buffer)); assert.equal(calls[0].buffer.length, 3); assert.equal( calls[0].requestBody.selected_link_index, 2, ); assert.equal( calls[0].bundle.source.session.name, 'Chat title', ); }); test('published long image registration stores the object, artifact, and refreshed manifest idempotently', async () => { const registry = createRegistry(); const service = createMindSpaceConversationArtifactService({ conversationPackageRegistry: registry, h5Root: '/srv/h5', }); const input = { ownerId: 'user-1', sessionId: 'session-1', messageId: 'message-1', publicationId: 'publication-1', pageId: 'page-1', title: 'Page title', body: Buffer.from('png'), canonicalUrl: 'https://example.com/page.long.png', }; const result = await service.registerPublishedLongImageArtifact(input); const repeated = await service.registerPublishedLongImageArtifact(input); assert.equal(result.artifactKind, 'long_image'); assert.equal(repeated.id, result.id); assert.equal(result.publicationId, 'publication-1'); assert.equal(result.pageId, 'page-1'); assert.equal(result.messageId, 'message-1'); assert.equal(registry.calls[0].kind, 'put'); assert.equal(registry.calls[1].kind, 'record'); assert.equal(registry.calls[2].kind, 'manifest'); assert.equal( registry.calls[0].input.body.toString('utf8'), 'png', ); assert.match( registry.calls[1].input.id, /^ca_long_image_[a-f0-9]{16}$/, ); assert.equal(registry.calls[4].input.id, result.id); }); test('workspace file registration stores every logical write in the conversation package', async () => { const registry = createRegistry(); const service = createMindSpaceConversationArtifactService({ conversationPackageRegistry: registry, h5Root: '/srv/h5', }); const input = { userId: 'user-1', sessionId: 'session-1', messageId: 'message-1', title: 'Workspace output', relativePath: 'oa/notes.txt', body: 'generated notes', }; const result = await service.registerWorkspaceFileArtifact(input); const repeated = await service.registerWorkspaceFileArtifact(input); assert.equal(result.artifactKind, 'generated_file'); assert.equal(result.mimeType, 'text/plain'); assert.equal(result.messageId, 'message-1'); assert.equal(repeated.id, result.id); assert.match( result.id, /^ca_workspace_write_[a-f0-9]{20}$/, ); assert.equal(registry.calls[0].kind, 'put'); assert.equal( registry.calls[0].input.body.toString('utf8'), 'generated notes', ); assert.match( registry.calls[0].input.relativePath, /^artifacts\/ca_workspace_write_[a-f0-9]{20}\/notes\.txt$/, ); assert.equal(registry.calls[1].kind, 'record'); assert.equal(registry.calls[2].kind, 'manifest'); assert.equal(registry.calls[4].input.id, result.id); });