Add page data delivery and publication guards

This commit is contained in:
john
2026-07-08 21:10:47 +08:00
parent 8d629e7a4e
commit eea14c1855
66 changed files with 3035 additions and 413 deletions
+45 -1
View File
@@ -1,5 +1,6 @@
// Keep browser-safe: do not import user-publish.mjs (uses node:fs/path/url).
const PUBLISH_SKILL_NAME = 'static-page-publish';
export const PAGE_DATA_COLLECT_SKILL_NAME = 'page-data-collect';
const WEB_INTENT_PATTERNS = [
/(?:今天|今日|最新|热点|热搜|新闻|头条|头条新闻|最新消息|发生了什么|最近发生)/u,
@@ -27,6 +28,22 @@ const PRODUCT_CAMPAIGN_INTENT_PATTERNS = [
/(?:https?:\/\/|taobao|tmall|jd\.com|商品链接|购买链接|购买按钮)/iu,
];
const PAGE_DATA_INTENT_PATTERNS = [
/(?:问卷|调查|签到表|签到登记|签到收集|投票|意见反馈|数据上报)/u,
/(?:报名表|报名登记|在线报名|收集报名)/u,
/(?:表单|数据采集|数据交互|存数据|保存提交|提交记录)/u,
/(?:后台|管理入口|管理后台).{0,20}(?:查看|记录|数据|提交)/u,
/(?:密码|口令).{0,12}(?:查看|后台|管理|进入)/u,
/(?:sqlite|数据库|page[\s-]?data)/i,
/(?:每个用户|各用户).{0,12}(?:提交|记录)/u,
];
export function isPageDataIntent(text) {
const normalized = String(text ?? '').trim();
if (!normalized) return false;
return PAGE_DATA_INTENT_PATTERNS.some((pattern) => pattern.test(normalized));
}
export function isPageGenerationIntent(text) {
const normalized = String(text ?? '').trim();
if (!normalized) return false;
@@ -76,6 +93,15 @@ export const CHAT_SKILL_DEFINITIONS = [
prefillOnly: true,
promptKey: 'form-builder',
},
{
id: 'page-data-collect',
label: '数据页面',
icon: 'form',
skillName: PAGE_DATA_COLLECT_SKILL_NAME,
requiresSkill: PAGE_DATA_COLLECT_SKILL_NAME,
requiresPublish: true,
promptKey: 'page-data-collect',
},
{
id: 'table-view',
label: '数据表格',
@@ -125,6 +151,13 @@ export function buildChatSkillPrompt(promptKey, skillName) {
return `请使用 ${skillName ?? 'search'} 技能:帮我在工作区中查找代码或文件。我要找的是:`;
case 'form-builder':
return `请使用 ${skillName ?? 'form-builder'} 技能:请用交互式表单收集以下场景所需的结构化字段(字段不超过 8 个):`;
case 'page-data-collect':
return (
`请使用 ${skillName ?? PAGE_DATA_COLLECT_SKILL_NAME} 技能:在 MindSpace 页面中实现可提交、可持久化的数据收集(问卷/报名/台账等),必须使用 Page Data API。` +
'先匹配技能内能力分支(默认 A:匿名前台 public insert + 独立后台 password read,口令默认 88888888);展示方案摘要确认后再开工。' +
'流程:load_skill → private_data_execute 建表 → private_data_register_dataset → write_file/edit_file 写 public/*.html(含 /assets/page-data-client.js)→ private_data_bind_workspace_page 发布并写策略。' +
'禁止自建 Express/独立端口(如 8899)、禁止 HTML 硬编码 127.0.0.1 API、禁止连续空转不调用工具。HTML 视觉规范参照 static-page-publish。完成后返回 workspaceUrl,并说明后台入口与口令。'
);
case 'service-integration-smoke':
return `请使用 ${skillName ?? 'service-integration-smoke'} 技能:按标准联调流程检查当前服务,覆盖身份、普通聊天、记忆读取,以及我本轮明确要求验证的技能/发布链路,并输出通过项、失败项、待确认项:`;
case 'table-viewer':
@@ -160,7 +193,12 @@ export { buildWebNewsSkillPrompt };
export function filterChatSkills(options, ctx) {
return options.filter((skill) => {
if (skill.requiresPublish && !ctx.canPublish) return false;
if (skill.requiresPublish && !ctx.canPublish) {
const pageDataGranted =
skill.skillName === PAGE_DATA_COLLECT_SKILL_NAME &&
ctx.grantedSkills?.includes(PAGE_DATA_COLLECT_SKILL_NAME);
if (!pageDataGranted) return false;
}
if (skill.requiresSkill && !ctx.grantedSkills?.includes(skill.requiresSkill)) return false;
return true;
});
@@ -169,6 +207,12 @@ export function filterChatSkills(options, ctx) {
export function buildAutoChatSkillPrefix(text, grantedSkills = []) {
const trimmed = String(text ?? '').trim();
if (!trimmed) return '';
if (
grantedSkills.includes(PAGE_DATA_COLLECT_SKILL_NAME) &&
isPageDataIntent(trimmed)
) {
return buildChatSkillPrompt('page-data-collect', PAGE_DATA_COLLECT_SKILL_NAME);
}
if (grantedSkills.includes(PUBLISH_SKILL_NAME) && isPageGenerationIntent(trimmed)) {
return buildChatSkillPrompt('generate-page', PUBLISH_SKILL_NAME);
}