Extract memind_adm admin server, add local dev tooling, and remove image-generation.
Split platform admin and ops APIs into standalone admin-server.mjs with network guards; simplify billing to RMB token pricing, refactor user auth, and add rsync deploy plus local-test scripts and docs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,12 +11,10 @@ import {
|
||||
buildWorkspaceBaseHref,
|
||||
buildWorkspaceThumbnailUrl,
|
||||
extractStaticPageLinks,
|
||||
extractHtmlFilenameHints,
|
||||
findPublishHtml,
|
||||
injectHtmlBaseHref,
|
||||
resolveChatSaveAnalysis,
|
||||
sanitizeMessageContentForSave,
|
||||
fetchPublishHtmlFallback,
|
||||
} from './mindspace-chat-save.mjs';
|
||||
|
||||
const USER_ID = 'a6fb1e97-2b0f-447b-b138-4561d8e5c53e';
|
||||
@@ -44,13 +42,6 @@ test('extractStaticPageLinks accepts legacy username urls when username provided
|
||||
assert.equal(links.length, 1);
|
||||
});
|
||||
|
||||
test('extractStaticPageLinks accepts legacy username urls when userId and username provided', () => {
|
||||
const content = 'https://goo.tkmind.cn/MindSpace/john/report.html';
|
||||
const links = extractStaticPageLinks(content, { userId: USER_ID, username: 'john' });
|
||||
assert.equal(links.length, 1);
|
||||
assert.equal(links[0].relativePath, 'report.html');
|
||||
});
|
||||
|
||||
test('analyzeChatMessageForSave prefers static html mode', () => {
|
||||
const analysis = analyzeChatMessageForSave({
|
||||
content: `链接 https://g2.tkmind.cn/MindSpace/${USER_ID}/report.html`,
|
||||
@@ -105,42 +96,6 @@ test('buildChatSavePreviewUrls use local api routes', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('findPublishHtml resolves html stored only in legacy username directory', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memind-chat-save-legacy-'));
|
||||
const legacyDir = path.join(root, 'MindSpace', 'john', 'public');
|
||||
await fs.mkdir(legacyDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(legacyDir, 'legacy-only.html'),
|
||||
'<!DOCTYPE html><html><head><title>Legacy</title></head><body>legacy</body></html>',
|
||||
'utf8',
|
||||
);
|
||||
const loaded = await findPublishHtml(root, USER_ID, 'public/legacy-only.html', { username: 'john' });
|
||||
assert.equal(loaded.relativePath, 'public/legacy-only.html');
|
||||
assert.match(loaded.content, /Legacy/);
|
||||
const migrated = path.join(root, 'MindSpace', USER_ID, 'public', 'legacy-only.html');
|
||||
assert.ok(await fs.stat(migrated).then(() => true).catch(() => false));
|
||||
});
|
||||
|
||||
test('resolveChatSaveAnalysis resolves uuid link when html exists only in legacy username dir', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memind-chat-save-uuid-link-'));
|
||||
const legacyDir = path.join(root, 'MindSpace', 'john', 'public');
|
||||
await fs.mkdir(legacyDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(legacyDir, 'report.html'),
|
||||
'<!DOCTYPE html><html><head><title>Report</title></head><body>ok</body></html>',
|
||||
'utf8',
|
||||
);
|
||||
const content = `链接 https://g2.tkmind.cn/MindSpace/${USER_ID}/public/report.html`;
|
||||
const result = await resolveChatSaveAnalysis({
|
||||
content,
|
||||
userId: USER_ID,
|
||||
username: 'john',
|
||||
h5Root: root,
|
||||
});
|
||||
assert.equal(result.analysis.contentMode, 'static_html');
|
||||
assert.equal(result.resolvedHtml?.relativePath, 'public/report.html');
|
||||
});
|
||||
|
||||
test('findPublishHtml resolves nested public html by basename', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memind-chat-save-'));
|
||||
const publishDir = path.join(root, 'MindSpace', USER_ID, 'public');
|
||||
@@ -161,11 +116,6 @@ test('injectHtmlBaseHref adds base tag for relative assets', () => {
|
||||
assert.match(next, /<base href="\/MindSpace\//);
|
||||
});
|
||||
|
||||
test('extractHtmlFilenameHints preserves normal hyphenated filenames', () => {
|
||||
const hints = extractHtmlFilenameHints('已生成 training-registration.html');
|
||||
assert.deepEqual(hints, ['training-registration.html']);
|
||||
});
|
||||
|
||||
test('sanitizeMessageContentForSave repairs duplicated streaming urls', () => {
|
||||
const raw =
|
||||
'httpshttps://://gg22.t.tkmkmindind.cn.cn/M/MindSpace/a6fb1e97/public/public/w/welcomeelcome-v-v22.html.html';
|
||||
@@ -194,28 +144,3 @@ test('resolveChatSaveAnalysis falls back to local html filename hints', async ()
|
||||
assert.equal(result.analysis.contentMode, 'static_html');
|
||||
assert.equal(result.resolvedHtml?.relativePath, 'public/welcome-v2.html');
|
||||
});
|
||||
|
||||
test('fetchPublishHtmlFallback mirrors remote html into local MindSpace when disk is missing', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memind-chat-save-fetch-'));
|
||||
const html =
|
||||
'<!DOCTYPE html><html><head><title>Remote</title></head><body>from remote</body></html>';
|
||||
const analysis = analyzeChatMessageForSave({
|
||||
content: `https://g2.tkmind.cn/MindSpace/${USER_ID}/public/remote-page.html`,
|
||||
userId: USER_ID,
|
||||
username: 'john',
|
||||
h5Root: root,
|
||||
});
|
||||
const fetched = await fetchPublishHtmlFallback(analysis, {
|
||||
publicBaseUrl: 'http://127.0.0.1:8081',
|
||||
fetchImpl: async () => ({
|
||||
ok: true,
|
||||
headers: { get: () => 'text/html' },
|
||||
text: async () => html,
|
||||
}),
|
||||
});
|
||||
assert.ok(fetched);
|
||||
assert.equal(fetched.relativePath, 'public/remote-page.html');
|
||||
assert.match(fetched.content, /from remote/);
|
||||
const local = path.join(root, 'MindSpace', USER_ID, 'public', 'remote-page.html');
|
||||
assert.match(await fs.readFile(local, 'utf8'), /from remote/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user