133 lines
4.4 KiB
JavaScript
133 lines
4.4 KiB
JavaScript
import crypto from 'node:crypto';
|
|
import fsPromises from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import {
|
|
collectOwnPublicHtmlArtifactRefs,
|
|
normalizePublicHtmlRelativePath,
|
|
} from './mindspace-public-finish-sync.mjs';
|
|
import {
|
|
buildMindSpacePublicUrlForUser,
|
|
resolveMindSpaceUserPublishDir,
|
|
} from './mindspace-runtime-config.mjs';
|
|
|
|
export async function registerPublicHtmlArtifactsForConversationPackage({
|
|
conversationPackageRegistry,
|
|
h5Root,
|
|
env = process.env,
|
|
user,
|
|
publishDir,
|
|
sessionId,
|
|
title = null,
|
|
relativePaths = [],
|
|
artifactRefs = [],
|
|
} = {}) {
|
|
if (
|
|
!conversationPackageRegistry ||
|
|
!user?.id ||
|
|
!publishDir ||
|
|
!sessionId ||
|
|
((!Array.isArray(relativePaths) || relativePaths.length === 0) &&
|
|
(!Array.isArray(artifactRefs) || artifactRefs.length === 0))
|
|
) {
|
|
return [];
|
|
}
|
|
try {
|
|
const publishRoot = path.resolve(publishDir);
|
|
const packageTitle = String(title ?? '').trim() || null;
|
|
const existingManifest = await conversationPackageRegistry
|
|
.readManifestForSession({ userId: user.id, sessionId })
|
|
.catch(() => null);
|
|
const packageRecord =
|
|
existingManifest?.packageId && existingManifest.title
|
|
? { id: existingManifest.packageId }
|
|
: await conversationPackageRegistry.ensurePackage({
|
|
userId: user.id,
|
|
sessionId,
|
|
title: packageTitle ?? existingManifest?.title ?? null,
|
|
});
|
|
const recorded = [];
|
|
const now = Date.now();
|
|
const refs =
|
|
Array.isArray(artifactRefs) && artifactRefs.length > 0
|
|
? artifactRefs
|
|
: relativePaths.map((relativePath) => ({ relativePath }));
|
|
for (const ref of refs) {
|
|
const relativePath = typeof ref === 'string' ? ref : ref?.relativePath;
|
|
const normalized = normalizePublicHtmlRelativePath(relativePath);
|
|
if (!normalized || !normalized.toLowerCase().endsWith('.html')) continue;
|
|
const absolutePath = path.resolve(publishRoot, normalized);
|
|
if (absolutePath !== publishRoot && !absolutePath.startsWith(`${publishRoot}${path.sep}`)) continue;
|
|
let stat = null;
|
|
try {
|
|
stat = await fsPromises.stat(absolutePath);
|
|
} catch {
|
|
continue;
|
|
}
|
|
if (!stat.isFile()) continue;
|
|
const hash = crypto
|
|
.createHash('sha256')
|
|
.update(`${user.id}:${sessionId}:${normalized}`)
|
|
.digest('hex')
|
|
.slice(0, 16);
|
|
const artifactId = `ca_public_html_${hash}`;
|
|
await conversationPackageRegistry.recordArtifact({
|
|
id: artifactId,
|
|
packageId: packageRecord.id,
|
|
artifactKind: 'public_html',
|
|
role: 'assistant',
|
|
messageId:
|
|
typeof ref?.messageId === 'string' && ref.messageId.trim() ? ref.messageId.trim() : null,
|
|
displayName: path.posix.basename(normalized),
|
|
mimeType: 'text/html',
|
|
sizeBytes: stat.size,
|
|
canonicalUrl: buildMindSpacePublicUrlForUser({
|
|
h5Root,
|
|
env,
|
|
user,
|
|
relativePath: normalized,
|
|
}),
|
|
sortOrder: Number.isFinite(stat.mtimeMs) ? Math.round(stat.mtimeMs) : now,
|
|
now,
|
|
});
|
|
recorded.push({ artifactId, relativePath: normalized });
|
|
}
|
|
if (recorded.length > 0) {
|
|
await conversationPackageRegistry.writeManifestForSession({
|
|
userId: user.id,
|
|
sessionId,
|
|
});
|
|
}
|
|
return recorded;
|
|
} catch (error) {
|
|
console.warn('[MindSpace] failed to record public html artifacts:', error?.message ?? error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export function createConversationPackagePublicHtmlHydrator({
|
|
h5Root,
|
|
resolveSessionSnapshot,
|
|
registerPublicHtmlArtifactsForConversation,
|
|
} = {}) {
|
|
return async function hydrateConversationPackagePublicHtmlArtifacts({ user, sessionId }) {
|
|
if (!user?.id || !sessionId || typeof resolveSessionSnapshot !== 'function') return [];
|
|
const snapshot = await resolveSessionSnapshot(sessionId).catch(() => null);
|
|
const messages = Array.isArray(snapshot?.messages) ? snapshot.messages : [];
|
|
const publishDir = resolveMindSpaceUserPublishDir(h5Root, { id: user.id });
|
|
const artifactRefs = collectOwnPublicHtmlArtifactRefs({
|
|
messages,
|
|
currentUser: user,
|
|
publishDir,
|
|
});
|
|
return (
|
|
(await registerPublicHtmlArtifactsForConversation?.({
|
|
user,
|
|
publishDir,
|
|
sessionId,
|
|
title: snapshot?.session?.name,
|
|
artifactRefs,
|
|
})) ?? []
|
|
);
|
|
};
|
|
}
|