Files
memind/tkmind-proxy-vision.test.mjs
T
john 32fb2cdeaf feat: chat uploads, vision turn isolation, and MindSpace agent improvements
Add chat file/image upload UX, attachment proxying, vision thumbnails, and per-turn image scoping so agents only use the current upload. Extend MindSpace asset context, billing token state, OA/scenario verify scripts, and related runtime config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-11 00:23:01 +08:00

107 lines
3.6 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { buildVisionPayload, extractImageUrlsFromMessage } from './tkmind-proxy.mjs';
test('extractImageUrlsFromMessage reads metadata image urls', () => {
const urls = extractImageUrlsFromMessage({
metadata: {
imageUrls: ['/api/mindspace/v1/assets/asset-1/download?inline=1'],
},
content: [{ type: 'text', text: '根据图片生成页面' }],
});
assert.deepEqual(urls, ['/api/mindspace/v1/assets/asset-1/download?inline=1']);
});
test('extractImageUrlsFromMessage falls back to formatted image lines', () => {
const urls = extractImageUrlsFromMessage({
metadata: { userVisible: true, agentVisible: true },
content: [
{
type: 'text',
text:
'根据图片生成一个主题页面\n\n' +
'[图片1]: https://m.tkmind.cn/api/mindspace/v1/assets/asset-2/download?inline=1&v=123',
},
],
});
assert.deepEqual(urls, [
'https://m.tkmind.cn/api/mindspace/v1/assets/asset-2/download?inline=1&v=123',
]);
});
test('extractImageUrlsFromMessage deduplicates image urls', () => {
const url = '/api/mindspace/v1/assets/asset-3/download?inline=1';
const urls = extractImageUrlsFromMessage({
metadata: { imageUrls: [url] },
content: [{ type: 'text', text: `[图片1]: ${url}` }],
});
assert.deepEqual(urls, [url]);
});
test('extractImageUrlsFromMessage ignores content aliases when metadata is present', () => {
const urls = extractImageUrlsFromMessage({
metadata: {
imageUrls: ['/api/mindspace/v1/assets/asset-4/download?inline=1'],
},
content: [
{
type: 'text',
text:
'[图片1]: https://m.tkmind.cn/MindSpace/user/public/images/2026-07-10/asset-4.jpg',
},
],
});
assert.deepEqual(urls, ['/api/mindspace/v1/assets/asset-4/download?inline=1']);
});
test('buildVisionPayload marks one billable image analysis when vision succeeds', async () => {
const result = await buildVisionPayload({
userId: 'user-1',
publishLayout: { publicUrl: 'https://m.tkmind.cn/MindSpace/user-1' },
userMessage: {
content: [{ type: 'text', text: '根据图片生成页面\n\n[图片1]: /api/mindspace/v1/assets/asset-1/download?inline=1' }],
},
localFetchAsset: async () => ({
buffer: Buffer.from('fake-image'),
mimeType: 'image/png',
}),
llmProviderService: {
analyzeImagesWithVision: async () => '一位小女孩正在餐厅里开心地吃饭',
},
});
assert.equal(result?.billableImageCount, 1);
assert.match(result?.userMessage?.content?.[0]?.text ?? '', /Qwen VL 图片描述/);
assert.match(result?.userMessage?.content?.[0]?.text ?? '', /本轮图片主题/);
assert.equal(
result?.userMessage?.metadata?.displayText,
'根据图片生成页面\n\n[图片1]: /api/mindspace/v1/assets/asset-1/download?inline=1',
);
});
test('buildVisionPayload does not mark billable usage when vision analysis fails', async () => {
const result = await buildVisionPayload({
userId: 'user-1',
publishLayout: { publicUrl: 'https://m.tkmind.cn/MindSpace/user-1' },
userMessage: {
content: [{ type: 'text', text: '根据图片生成页面\n\n[图片1]: /api/mindspace/v1/assets/asset-1/download?inline=1' }],
},
localFetchAsset: async () => ({
buffer: Buffer.from('fake-image'),
mimeType: 'image/png',
}),
llmProviderService: {
analyzeImagesWithVision: async () => {
throw new Error('vision unavailable');
},
},
});
assert.equal(result?.billableImageCount, 0);
assert.doesNotMatch(result?.userMessage?.content?.[0]?.text ?? '', /Qwen VL 图片描述/);
});