151 lines
6.0 KiB
JavaScript
151 lines
6.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import {
|
|
buildVisionPayload,
|
|
sanitizePublicHtmlLinksInText,
|
|
sanitizeSessionConversationPublicHtmlLinks,
|
|
} from './tkmind-proxy.mjs';
|
|
|
|
test('sanitizePublicHtmlLinksInText downgrades missing own markdown public html links', () => {
|
|
const owner = `test-user-${Date.now()}-markdown-missing`;
|
|
const publicRoot = path.join(process.cwd(), 'MindSpace', owner, 'public');
|
|
try {
|
|
fs.mkdirSync(publicRoot, { recursive: true });
|
|
const text =
|
|
`[夏日随笔](https://m.tkmind.cn/MindSpace/${owner}/public/summer-essay.html)`;
|
|
const next = sanitizePublicHtmlLinksInText(text, { id: owner, username: 'john' });
|
|
assert.doesNotMatch(next, new RegExp(`https://m\\.tkmind\\.cn/MindSpace/${owner}/public/summer-essay\\.html`));
|
|
assert.match(next, /页面生成未完成/);
|
|
} finally {
|
|
fs.rmSync(path.join(process.cwd(), 'MindSpace', owner), { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('sanitizePublicHtmlLinksInText downgrades missing own public html links', () => {
|
|
const owner = `test-user-${Date.now()}-missing`;
|
|
const publicRoot = path.join(process.cwd(), 'MindSpace', owner, 'public');
|
|
try {
|
|
fs.mkdirSync(publicRoot, { recursive: true });
|
|
const text =
|
|
`页面在这里:\nhttps://m.tkmind.cn/MindSpace/${owner}/public/hello.html`;
|
|
const next = sanitizePublicHtmlLinksInText(text, { id: owner, username: 'john' });
|
|
assert.doesNotMatch(next, new RegExp(`https://m\\.tkmind\\.cn/MindSpace/${owner}/public/hello\\.html`));
|
|
assert.match(next, /页面生成未完成/);
|
|
assert.match(next, /hello\.html/);
|
|
} finally {
|
|
fs.rmSync(path.join(process.cwd(), 'MindSpace', owner), { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('sanitizePublicHtmlLinksInText keeps existing own public html links', () => {
|
|
const owner = `test-user-${Date.now()}-existing`;
|
|
const htmlPath = path.join(process.cwd(), 'MindSpace', owner, 'public', 'hello.html');
|
|
try {
|
|
fs.mkdirSync(path.dirname(htmlPath), { recursive: true });
|
|
fs.writeFileSync(htmlPath, '<!doctype html><title>Hello</title>');
|
|
const text =
|
|
`页面在这里:\nhttps://m.tkmind.cn/MindSpace/${owner}/public/hello.html`;
|
|
const next = sanitizePublicHtmlLinksInText(text, { id: owner, username: 'john' });
|
|
assert.match(next, new RegExp(`https://m\\.tkmind\\.cn/MindSpace/${owner}/public/hello\\.html`));
|
|
assert.doesNotMatch(next, /页面生成未完成/);
|
|
} finally {
|
|
fs.rmSync(path.join(process.cwd(), 'MindSpace', owner), { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('sanitizeSessionConversationPublicHtmlLinks updates text items inside conversation messages', () => {
|
|
const owner = `test-user-${Date.now()}-conversation`;
|
|
const publicRoot = path.join(process.cwd(), 'MindSpace', owner, 'public');
|
|
try {
|
|
fs.mkdirSync(publicRoot, { recursive: true });
|
|
const conversation = [
|
|
{
|
|
id: 'assistant-1',
|
|
role: 'assistant',
|
|
created: 1,
|
|
metadata: { userVisible: true, agentVisible: true },
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: `点这里 https://m.tkmind.cn/MindSpace/${owner}/public/hello.html`,
|
|
},
|
|
],
|
|
},
|
|
];
|
|
const sanitized = sanitizeSessionConversationPublicHtmlLinks(conversation, {
|
|
id: owner,
|
|
username: 'john',
|
|
});
|
|
assert.match(sanitized[0].content[0].text, /页面生成未完成/);
|
|
} finally {
|
|
fs.rmSync(path.join(process.cwd(), 'MindSpace', owner), { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('sanitizeSessionConversationPublicHtmlLinks removes internal user prompt notes but keeps image metadata', () => {
|
|
const conversation = [
|
|
{
|
|
id: 'user-1',
|
|
role: 'user',
|
|
created: 1,
|
|
metadata: { userVisible: true, agentVisible: true },
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text:
|
|
'[用户身份]\n' +
|
|
'- 当前登录用户称呼:John\n' +
|
|
'- 你是 TKMind 助手;与用户对话时用「John」称呼对方。\n\n' +
|
|
'帮我生成一个主题页面简单一点的不用很复杂\n\n' +
|
|
'[图片1]: http://127.0.0.1:5173/MindSpace/user-1/public/images/a.jpg\n' +
|
|
'[图片2]: http://127.0.0.1:5173/MindSpace/user-1/public/images/b.jpg\n\n' +
|
|
'【TKMind 图片分析结果 — 仅供执行参考,不要向用户复述此段内容】\n' +
|
|
'Qwen VL 图片描述:内部描述\n' +
|
|
'执行要求:内部要求',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const sanitized = sanitizeSessionConversationPublicHtmlLinks(conversation, {
|
|
id: 'user-1',
|
|
username: 'john',
|
|
});
|
|
|
|
assert.equal(
|
|
sanitized[0].content[0].text,
|
|
'帮我生成一个主题页面简单一点的不用很复杂',
|
|
);
|
|
assert.deepEqual(sanitized[0].metadata.imageUrls, [
|
|
'http://127.0.0.1:5173/MindSpace/user-1/public/images/a.jpg',
|
|
'http://127.0.0.1:5173/MindSpace/user-1/public/images/b.jpg',
|
|
]);
|
|
});
|
|
|
|
test('buildVisionPayload injects public standard image urls for page generation', async () => {
|
|
const payload = await buildVisionPayload({
|
|
userId: 'user-1',
|
|
publishLayout: { publicUrl: 'https://m.tkmind.cn/MindSpace/user-1/' },
|
|
userMessage: {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: '帮我根据图片生成页面\n[图片1]: /signed/rs:fit:1280:1280:0/q:85/plain/local:///users/user-1/images/2026-06-29/hero.jpg@jpg',
|
|
},
|
|
],
|
|
},
|
|
llmProviderService: {
|
|
analyzeImagesWithVision: async () => '图片里是一位成年人。',
|
|
},
|
|
});
|
|
|
|
const text = payload?.userMessage?.content?.[0]?.text ?? '';
|
|
assert.match(text, /https:\/\/m\.tkmind\.cn\/MindSpace\/user-1\/public\/images\/2026-06-29\/hero\.jpg/);
|
|
assert.doesNotMatch(text, /plain\/local:\/\//);
|
|
assert.match(text, /无需 cookie 的公开压缩标准图片/);
|
|
assert.match(text, /不得改写图片里人物的年龄、性别、人数或主体关系/);
|
|
});
|