feat: release chat and mindspace UI updates
This commit is contained in:
+63
-7
@@ -1,6 +1,7 @@
|
||||
import express from 'express';
|
||||
import crypto from 'node:crypto';
|
||||
import fs from 'node:fs';
|
||||
import fsPromises from 'node:fs/promises';
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -23,7 +24,7 @@ import {
|
||||
} from './user-auth.mjs';
|
||||
import { createWikiAuth } from './wiki-auth.mjs';
|
||||
import { isLocalDevHostname } from './scripts/local-test-config.mjs';
|
||||
import { PUBLISH_ROOT_DIR, PUBLISH_KEY_UUID, PUBLIC_ZONE_DIR, resolvePublishDir } from './user-publish.mjs';
|
||||
import { PUBLISH_ROOT_DIR, PUBLISH_KEY_UUID, PUBLIC_ZONE_DIR, resolvePublishDir, resolvePublicBaseUrl } from './user-publish.mjs';
|
||||
import { ensureWorkspaceHtmlThumbnail, startWorkspaceThumbnailWatcher, workspaceThumbnailRelativePath } from './mindspace-workspace-thumbnails.mjs';
|
||||
import { startWorkspaceAssetSyncWatcher } from './mindspace-workspace-sync.mjs';
|
||||
import { attachRequestId, sendData, sendError } from './api-response.mjs';
|
||||
@@ -32,7 +33,7 @@ import { assertMindSpaceRoute, mindspaceFlags } from './mindspace-flags.mjs';
|
||||
import { createMindSpaceService, DEFAULT_MAX_FILE_BYTES } from './mindspace.mjs';
|
||||
import { ensureMindSpaceConfig } from './mindspace-config.mjs';
|
||||
import { createAssetService } from './mindspace-assets.mjs';
|
||||
import { createPageService, pageInternals } from './mindspace-pages.mjs';
|
||||
import { createPageService, pageInternals, inlinePrivateAssetsInHtml } from './mindspace-pages.mjs';
|
||||
import { createPageLiveEditService } from './mindspace-page-live-edit.mjs';
|
||||
import { createPageEditSessionService } from './mindspace-page-edit-session.mjs';
|
||||
import { suggestCoverMetaWithAi } from './mindspace-cover-ai.mjs';
|
||||
@@ -520,6 +521,7 @@ async function bootstrapUserAuth() {
|
||||
userAuth,
|
||||
llmProviderService,
|
||||
subscriptionService,
|
||||
sessionSnapshotService,
|
||||
localFetchAsset: mindSpaceAssets
|
||||
? async (userId, assetId) => {
|
||||
const { asset, path: assetPath } = await mindSpaceAssets.readAsset(userId, assetId);
|
||||
@@ -2506,6 +2508,13 @@ api.post('/mindspace/v1/pages/analyze-chat-save', async (req, res) => {
|
||||
thumbnailReady = false;
|
||||
}
|
||||
}
|
||||
const sessionId = String(req.body?.session_id ?? req.body?.sessionId ?? '').trim();
|
||||
const messageId = String(req.body?.message_id ?? req.body?.messageId ?? '').trim();
|
||||
const existingPage = await mindSpacePages.findPageBySourceMessage(
|
||||
req.currentUser.id,
|
||||
sessionId,
|
||||
messageId,
|
||||
).catch(() => null);
|
||||
return sendData(res, req, {
|
||||
contentMode: analysis.contentMode,
|
||||
links: analysis.links,
|
||||
@@ -2524,12 +2533,51 @@ api.post('/mindspace/v1/pages/analyze-chat-save', async (req, res) => {
|
||||
filename: resolvedHtml?.filename ?? analysis.filename,
|
||||
hasHtmlContent: Boolean(resolvedHtml),
|
||||
privacyScan: scanContent(resolvedHtml?.content ?? source.content),
|
||||
existingPage: existingPage
|
||||
? { id: existingPage.id, title: existingPage.title, categoryCode: existingPage.categoryCode }
|
||||
: null,
|
||||
});
|
||||
} catch (error) {
|
||||
return mindSpaceError(res, req, error);
|
||||
}
|
||||
});
|
||||
|
||||
api.post('/mindspace/v1/pages/quick-share-from-chat', async (req, res) => {
|
||||
if (!mindSpacePages) return res.status(503).json({ message: 'MindSpace 未启用' });
|
||||
try {
|
||||
const bundle = await resolveChatSaveBundle(req.currentUser, __dirname, req.body);
|
||||
if (!bundle.resolvedHtml) {
|
||||
throw Object.assign(new Error('无法读取链接页面内容'), { code: 'static_page_not_found' });
|
||||
}
|
||||
|
||||
const storageRoot =
|
||||
process.env.MINDSPACE_STORAGE_ROOT ?? path.join(__dirname, 'data', 'mindspace');
|
||||
const { html: localizedHtml } = await inlinePrivateAssetsInHtml(
|
||||
authPool,
|
||||
storageRoot,
|
||||
req.currentUser.id,
|
||||
bundle.resolvedHtml.content,
|
||||
);
|
||||
|
||||
const publishDir = resolvePublishDir(__dirname, req.currentUser);
|
||||
const sharedDir = path.join(publishDir, PUBLIC_ZONE_DIR, 'shared');
|
||||
await fsPromises.mkdir(sharedDir, { recursive: true });
|
||||
|
||||
const basename = bundle.resolvedHtml.filename.replace(/\.html$/i, '');
|
||||
const filename = `${basename}-${crypto.randomUUID().slice(0, 8)}.html`;
|
||||
const destPath = path.join(sharedDir, filename);
|
||||
await fsPromises.writeFile(destPath, localizedHtml, 'utf8');
|
||||
|
||||
const publishKey = req.currentUser.id;
|
||||
const publicUrl = `${resolvePublicBaseUrl()}/${PUBLISH_ROOT_DIR}/${encodeURIComponent(publishKey)}/${PUBLIC_ZONE_DIR}/shared/${encodeURIComponent(filename)}`;
|
||||
|
||||
return res.status(201).json({ data: { publicUrl, filename } });
|
||||
} catch (error) {
|
||||
console.error('[quick-share] error:', error);
|
||||
return mindSpaceError(res, req, error);
|
||||
}
|
||||
});
|
||||
|
||||
api.post('/mindspace/v1/pages/save-from-chat', async (req, res) => {
|
||||
if (!mindSpacePages || !mindSpaceAssets) {
|
||||
return res.status(503).json({ message: 'MindSpace 未启用' });
|
||||
@@ -2635,11 +2683,19 @@ api.post('/mindspace/v1/pages/save-from-chat', async (req, res) => {
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
const page = await mindSpacePages.createFromChat(req.currentUser.id, pageInput, {
|
||||
sessionId: req.body.session_id,
|
||||
messageId: req.body.message_id,
|
||||
snapshot,
|
||||
});
|
||||
const replacePageId = req.body?.replace_page_id
|
||||
? String(req.body.replace_page_id).trim()
|
||||
: null;
|
||||
let page;
|
||||
if (replacePageId) {
|
||||
page = await mindSpacePages.updatePage(req.currentUser.id, replacePageId, pageInput);
|
||||
} else {
|
||||
page = await mindSpacePages.createFromChat(req.currentUser.id, pageInput, {
|
||||
sessionId: req.body.session_id,
|
||||
messageId: req.body.message_id,
|
||||
snapshot,
|
||||
});
|
||||
}
|
||||
return res.status(201).json({ data: { kind: 'page', categoryCode: 'draft', page } });
|
||||
} catch (error) {
|
||||
return mindSpaceError(res, req, error);
|
||||
|
||||
Reference in New Issue
Block a user