Files
memind/chat-skills.test.mjs
T
john fde6503bdf
Memind CI / Test, build, and release guards (push) Has been cancelled
feat(mindspace): add SEO/GEO delivery, page template catalog, and admin hooks
Enable optional SEO/GEO injection and discovery routes for confirmed public pages while keeping private pages noindex. Add premium page template skills, portal catalog API, template shop UI, and Baidu push gated by memind_adm config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 08:06:12 +08:00

296 lines
14 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {
buildAutoChatSkillPrefix,
buildChatSkillPrompt,
CHAT_SKILL_DEFINITIONS,
filterChatSkills,
extractAiderDevelopmentTask,
isExcelAnalysisIntent,
isPageDataDevIntent,
isPageDataIntent,
isPageGenerationIntent,
isGenericPageGenerationRequest,
mergeChatSkillPromptWithInput,
applyPageTemplatePrefill,
} from './chat-skills.mjs';
test('filterChatSkills shows summarize and analyze without granted skills', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, { canPublish: false });
assert.ok(visible.some((item) => item.id === 'summarize'));
assert.ok(visible.some((item) => item.id === 'analyze'));
assert.equal(visible.some((item) => item.id === 'generate-page'), false);
});
test('filterChatSkills gates platform skills by grantedSkills', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: false,
grantedSkills: ['web', 'search'],
});
assert.ok(visible.some((item) => item.id === 'web-search'));
assert.ok(visible.some((item) => item.id === 'code-search'));
assert.equal(visible.some((item) => item.id === 'form-collect'), false);
assert.equal(visible.some((item) => item.id === 'service-integration-smoke'), false);
assert.equal(visible.some((item) => item.id === 'product-campaign-page'), false);
});
test('filterChatSkills shows product campaign page when granted', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: false,
grantedSkills: ['product-campaign-page'],
});
assert.ok(visible.some((item) => item.id === 'product-campaign-page'));
});
test('filterChatSkills shows service integration smoke when granted', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: false,
grantedSkills: ['service-integration-smoke'],
});
assert.ok(visible.some((item) => item.id === 'service-integration-smoke'));
});
test('Aider development skill prefills instead of submitting an empty template', () => {
const aider = CHAT_SKILL_DEFINITIONS.find((item) => item.id === 'aider-development');
assert.equal(aider?.prefillOnly, true);
});
test('mergeChatSkillPromptWithInput preserves an existing user task', () => {
const prompt = buildChatSkillPrompt('aider-development', 'aider-development');
const task = '帮我设计一个简单下单系统,不要支付,可以有简单后台';
assert.equal(mergeChatSkillPromptWithInput(prompt, task), `${prompt}${task}`);
assert.equal(mergeChatSkillPromptWithInput(prompt, `${prompt}${task}`), `${prompt}${task}`);
});
test('applyPageTemplatePrefill replaces previous template prompt instead of stacking', () => {
const travel = buildChatSkillPrompt('page-template-travel', 'page-template-travel');
const restaurant = buildChatSkillPrompt('page-template-restaurant', 'page-template-restaurant');
const userTask = '周末去杭州';
const withTravel = applyPageTemplatePrefill(travel, userTask);
assert.equal(withTravel, `${travel}${userTask}`);
const switched = applyPageTemplatePrefill(restaurant, withTravel);
assert.equal(switched, `${restaurant}${userTask}`);
assert.equal(applyPageTemplatePrefill('', switched), userTask);
});
test('extractAiderDevelopmentTask rejects the template-only submission', () => {
const prompt = buildChatSkillPrompt('aider-development', 'aider-development');
assert.equal(
extractAiderDevelopmentTask({
metadata: { displayText: prompt },
content: [{ type: 'text', text: prompt }],
}),
'',
);
assert.equal(
extractAiderDevelopmentTask({
metadata: { displayText: `${prompt}修复页面` },
content: [{ type: 'text', text: `${prompt}修复页面` }],
}),
'修复页面',
);
});
test('filterChatSkills only shows Aider development when granted', () => {
const hidden = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: false,
grantedSkills: [],
});
assert.equal(hidden.some((item) => item.id === 'aider-development'), false);
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: false,
grantedSkills: ['aider-development'],
});
assert.ok(visible.some((item) => item.id === 'aider-development'));
});
test('filterChatSkills shows page-data-collect when granted without static publish', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: false,
grantedSkills: ['page-data-collect'],
});
assert.ok(visible.some((item) => item.id === 'page-data-collect'));
});
test('filterChatSkills shows generate-page when publish is allowed', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, { canPublish: true });
assert.ok(visible.some((item) => item.id === 'generate-page'));
});
test('filterChatSkills shows page templates when granted', () => {
const visible = filterChatSkills(CHAT_SKILL_DEFINITIONS, {
canPublish: true,
grantedSkills: ['page-template-travel', 'page-template-campaign'],
});
assert.ok(visible.some((item) => item.id === 'page-template-travel'));
assert.ok(visible.some((item) => item.id === 'page-template-campaign'));
assert.equal(visible.some((item) => item.id === 'page-template-survey'), false);
});
test('buildChatSkillPrompt includes skill name for platform skills', () => {
const webPrompt = buildChatSkillPrompt('web', 'web');
assert.match(webPrompt, /请使用 web 技能/);
assert.match(webPrompt, /tkmind_search/);
assert.match(webPrompt, /web_search/);
const enhancedPrompt = buildChatSkillPrompt('search-enhanced', 'search-enhanced');
assert.match(enhancedPrompt, /tkmind_search/);
assert.match(enhancedPrompt, /web_search/);
assert.match(buildChatSkillPrompt('service-integration-smoke'), /标准联调流程/);
assert.match(buildChatSkillPrompt('aider-development'), /必须由 Aider code run/);
assert.match(buildChatSkillPrompt('aider-development'), /禁止回退/);
assert.match(buildChatSkillPrompt('product-campaign-page'), /商品宣传 \/ 活动页/);
assert.match(buildChatSkillPrompt('image-generation'), /asset\.htmlSrc/);
assert.match(buildChatSkillPrompt('image-generation'), /workspaceRelativePath 只用于文件操作/);
assert.match(buildChatSkillPrompt('generate-page'), /static-page-publish/);
assert.match(buildChatSkillPrompt('generate-page'), /docx-generate/);
assert.match(buildChatSkillPrompt('generate-page'), /public\/\*\.docx/);
assert.match(buildChatSkillPrompt('generate-page'), /long-image-download/);
assert.match(buildChatSkillPrompt('generate-page'), /generate_long_image/);
assert.match(buildChatSkillPrompt('page-data-collect'), /Page Data API/);
assert.match(buildChatSkillPrompt('page-data-collect'), /禁止自建 Express/);
assert.match(buildChatSkillPrompt('page-template-travel'), /travel-hero/);
assert.match(buildChatSkillPrompt('page-template-campaign'), /campaign-cta/);
assert.match(buildChatSkillPrompt('page-template-survey'), /page-data-collect/);
});
test('prefillOnly is set for open-ended chat skills', () => {
assert.equal(CHAT_SKILL_DEFINITIONS.find((item) => item.id === 'web-search')?.prefillOnly, true);
assert.equal(CHAT_SKILL_DEFINITIONS.find((item) => item.id === 'generate-page')?.prefillOnly, true);
});
test('generate-page selection preserves an existing news-page request for the next submit', () => {
const skill = CHAT_SKILL_DEFINITIONS.find((item) => item.id === 'generate-page');
const prompt = buildChatSkillPrompt(skill?.promptKey, skill?.skillName);
const task = '帮我整理今天的新闻做成页面';
assert.equal(skill?.prefillOnly, true);
assert.equal(mergeChatSkillPromptWithInput(prompt, task), `${prompt}${task}`);
});
test('buildAutoChatSkillPrefix routes scheduled automation when skill is granted', () => {
assert.match(
buildAutoChatSkillPrefix('每天6点帮我做今日新闻页面', ['scheduled-task-automation']),
/scheduled-task-automation/,
);
assert.equal(buildAutoChatSkillPrefix('每天6点帮我做今日新闻页面', []), '');
});
test('buildAutoChatSkillPrefix enables web for news-like queries', () => {
assert.match(
buildAutoChatSkillPrefix('帮我搜索今天热点新闻', ['web', 'search']),
/先搜索今天\/最新相关的新闻与热点/,
);
assert.equal(buildAutoChatSkillPrefix('帮我总结一下这段话', ['web', 'search']), '');
assert.equal(buildAutoChatSkillPrefix('帮我搜索今天热点新闻', ['search']), '');
});
test('buildAutoChatSkillPrefix routes an uploaded xlsx only when Excel Analyst is granted', () => {
const text = '帮我分析一下\n\n[文件1: sales.xlsx]: /api/mindspace/v1/assets/asset-1/download';
assert.match(
buildAutoChatSkillPrefix(text, ['excel-analyst']),
/excel_inspect/,
);
assert.equal(buildAutoChatSkillPrefix(text, []), '');
assert.equal(isExcelAnalysisIntent('请分析这份工作簿的销售趋势'), true);
assert.equal(isExcelAnalysisIntent('请总结这段普通文字'), false);
});
test('manifest enhanced search route is opt-in and uses the MindSearch skill prompt', () => {
const routes = [{ skillName: 'search-enhanced', promptKey: 'search-enhanced', keywords: ['最新资料'], priority: 30 }];
assert.match(buildAutoChatSkillPrefix('请搜索最新资料:Goose MCP', ['search-enhanced'], { skillRouterV2: true, manifestRoutes: routes }), /tkmind_search/);
assert.equal(buildAutoChatSkillPrefix('请搜索最新资料:Goose MCP', [], { skillRouterV2: true, manifestRoutes: routes }), '');
});
test('buildAutoChatSkillPrefix enables publish for page generation requests', () => {
const prefix = buildAutoChatSkillPrefix('帮我做一个 Hello 糖的 H5 页面', ['static-page-publish']);
assert.match(prefix, /static-page-publish/);
assert.match(prefix, /write_file\/edit_file/);
assert.match(prefix, /禁止只给本地路径/);
assert.equal(buildAutoChatSkillPrefix('帮我做一个 Hello 糖的 H5 页面', []), '');
});
test('isPageGenerationIntent matches implicit travel guide page requests', () => {
assert.equal(isPageGenerationIntent('苏州攻略页面'), true);
assert.equal(isPageGenerationIntent('帮我看看苏州攻略,1日攻略,做一个页面'), true);
assert.equal(isPageGenerationIntent('你好'), false);
});
test('isGenericPageGenerationRequest only matches page requests without a subject', () => {
assert.equal(isGenericPageGenerationRequest('帮我生成一个页面吧'), true);
assert.equal(isGenericPageGenerationRequest('Please create a web page'), true);
assert.equal(isGenericPageGenerationRequest('帮我做一个秋夜诗的 H5 页面'), false);
assert.equal(isGenericPageGenerationRequest('苏州攻略页面'), false);
assert.equal(isGenericPageGenerationRequest('你好'), false);
});
test('buildAutoChatSkillPrefix prefers page-data-collect for survey requests', () => {
const text = '帮我在这个页面增加一个调查问卷,出三个问题,密码 888 查看提交记录';
const prefix = buildAutoChatSkillPrefix(text, ['page-data-collect', 'static-page-publish']);
assert.match(prefix, /page-data-collect/);
assert.doesNotMatch(prefix, /static-page-publish 技能:在我的专属 MindSpace 发布目录生成静态 HTML/);
});
test('isPageDataIntent matches survey and backend keywords', () => {
assert.equal(isPageDataIntent('增加调查问卷和后台入口,密码 888'), true);
assert.equal(
isPageDataIntent('帮我做一个家庭记账页面,我每天可以记录日期、收入、支出、分类和备注,日期默认当天。再做一个管理页面,可以查看所有记录和收支汇总。'),
true,
);
assert.equal(isPageDataIntent('帮我做一个苏州攻略页面'), false);
});
test('isPageDataIntent treats storefront ordering plus product administration as Page Data', () => {
assert.equal(
isPageDataIntent('我要做一个页面,里面可以下单,后台可以上架产品'),
true,
);
assert.equal(
isPageDataIntent('做一个后台上架和管理库存的商城,顾客可以购物车下单'),
true,
);
});
test('isPageDataIntent recognizes order systems with an admin backend', () => {
assert.equal(
isPageDataIntent('帮我设计一个简单下单系统,不要支付,可以有简单后台管理订单'),
true,
);
});
test('isPageDataIntent matches implicit interactive sticky-note app requests', () => {
const text = '帮我设计一个便签提醒,可以写便签提交,时间轴来显示';
assert.equal(isPageDataIntent(text), true);
assert.match(
buildAutoChatSkillPrefix(text, ['page-data-collect', 'static-page-publish']),
/page-data-collect/,
);
});
test('isPageDataIntent does not steal a simple schedule reminder', () => {
assert.equal(isPageDataIntent('明天上午9点提醒我开会'), false);
assert.equal(isPageDataIntent('创建一个待办'), false);
});
test('buildAutoChatSkillPrefix routes ordinary household ledger language to Page Data', () => {
const text = '帮我做一个家庭记账页面,我每天可以记录日期、收入、支出、分类和备注,日期默认当天。再做一个管理页面,可以查看所有记录和收支汇总。';
const prefix = buildAutoChatSkillPrefix(text, ['page-data-collect', 'static-page-publish']);
assert.match(prefix, /page-data-collect/);
assert.match(prefix, /同一轮继续执行/);
assert.match(prefix, /禁止 localStorage/);
assert.doesNotMatch(prefix, /static-page-publish 技能/);
});
test('buildAutoChatSkillPrefix enables publish for implicit page requests', () => {
const prefix = buildAutoChatSkillPrefix('苏州攻略页面', ['static-page-publish']);
assert.match(prefix, /static-page-publish/);
assert.match(prefix, /禁止询问是否还要发布/);
});
test('isPageDataDevIntent matches repair phrases but not new survey creation', () => {
assert.equal(isPageDataDevIntent('修复问卷 insert 403 columns_not_allowed'), true);
assert.equal(isPageDataDevIntent('page-data-dev 修 policy 白名单'), true);
assert.equal(isPageDataDevIntent('帮我做一个报名问卷'), false);
assert.equal(isPageDataIntent('帮我做一个报名问卷'), true);
assert.equal(isPageDataIntent('修复问卷 insert 403 columns_not_allowed'), false);
});