fix: require docx generation for downloadable pages
This commit is contained in:
@@ -5,9 +5,11 @@ import { fileURLToPath } from 'node:url';
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export const PUBLISH_SKILL_NAME = 'static-page-publish';
|
||||
export const DOCX_SKILL_NAME = 'docx-generate';
|
||||
export const PUBLISH_ROOT_DIR = 'MindSpace';
|
||||
export const PUBLIC_ZONE_DIR = 'public';
|
||||
export const PUBLISH_SKILL_DIR = path.join(__dirname, 'skills', PUBLISH_SKILL_NAME);
|
||||
export const DOCX_SKILL_DIR = path.join(__dirname, 'skills', DOCX_SKILL_NAME);
|
||||
export const WORKSPACE_HINTS_FILENAME = '.tkmindhints';
|
||||
export const LEGACY_WORKSPACE_HINTS_FILENAME = '.goosehints';
|
||||
|
||||
@@ -155,6 +157,14 @@ description: 在专属 MindSpace 目录生成可公开访问的静态 HTML 报
|
||||
5. 保存 HTML 后,服务端会**立即**生成同名预览图 \`<文件名>.thumbnail.svg\`(Agent 交互阶段即生效,无需等用户保存到「我的空间」)
|
||||
6. 完成后按「回复格式」返回可点击链接
|
||||
|
||||
## Word 下载页(必须)
|
||||
|
||||
- 如果用户明确要求页面里**可下载 Word / docx**,必须先 \`load_skill\` → \`docx-generate\`
|
||||
- 用 \`.agents/skills/docx-generate/generate_docx.py\` 生成 \`public/文件名.docx\`
|
||||
- 生成后必须用 \`list_dir public\`(或等价方式)确认目标 \`.docx\` 已存在,再写 \`public/页面.html\`
|
||||
- HTML 中只能使用同目录相对路径链接文档,例如 \`<a href="report.docx" download>下载 Word 文档</a>\`
|
||||
- **禁止**只写下载按钮或 \`.docx\` 链接,却没有先把目标文档落盘
|
||||
|
||||
## 回复格式(必须)
|
||||
|
||||
向用户交付页面时,**必须使用 Markdown 可点击链接**,让用户在聊天里直接点开预览:
|
||||
@@ -222,6 +232,7 @@ description: 在专属 MindSpace 目录生成可公开访问的静态 HTML 报
|
||||
- 不要写入当前工作区以外的任何目录
|
||||
- shell 仅用于本目录内整理文件/简单脚本;不要 \`rm -rf\` 越界路径、不要安装系统级依赖
|
||||
- **禁止**在 HTML 中用 \`data:...;base64,...\` 内嵌 Word/PDF;二进制文件单独落盘后用相对路径链接(见 \`docx-generate\` 技能)
|
||||
- 用户要求 Word / docx 下载时,禁止跳过 \`docx-generate\` 直接在 HTML 中伪造下载链接
|
||||
|
||||
## 示例
|
||||
|
||||
@@ -257,6 +268,12 @@ ${renderBrandingBlock(addressName)}
|
||||
- **禁止**用公网 URL、curl、wget 或 read_image 去「列目录」「读 CSV」——静态站点不提供目录索引
|
||||
- 有 \`shell\` 时用 \`ls oa/\`、\`find .\`、\`cat oa/file.csv\`;有 \`tree\` 时用 \`tree oa/\`
|
||||
- 不要说「我没有 shell」——若系统提示已列出 shell,就必须用 shell 在工作区内操作
|
||||
|
||||
## Word 下载页
|
||||
|
||||
- 若用户要求页面里可下载 Word / docx:必须先 \`load_skill\` → \`docx-generate\`
|
||||
- 先生成并确认 \`public/*.docx\` 已存在,再写 \`public/*.html\`
|
||||
- HTML 中只能用同目录相对路径链接该文档,禁止只写下载按钮却没有先把 `.docx` 落盘
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -296,6 +313,7 @@ export function buildSandboxSessionConstraints({ baseConstraints, developerTools
|
||||
'## 生成 / 发布 HTML 页面',
|
||||
'- 你有 write_file/edit_file 工具:**必须由你**写入 `public/xxx.html`(或工作区根目录 `.html`)',
|
||||
'- 开始前执行 load_skill → `static-page-publish`,按技能说明写入 mindspace-cover 元数据',
|
||||
'- 如果用户要求 Word / docx 下载:先 `load_skill` → `docx-generate`,生成并确认 `public/*.docx` 已存在,再写 HTML 用相对路径链接',
|
||||
'- **禁止**用 shell / cat / heredoc / echo / cp 写入 HTML;shell 在容器内执行,文件不会出现在公网 MindSpace 路径',
|
||||
'- **禁止**让用户手动保存到 public 或说无法生成页面(除非 write_file 调用失败)',
|
||||
'- 完成后回复 `[页面标题](公网URL)` 可点击链接;写入 `public/` 时 URL 必须含 `/public/` 路径段',
|
||||
@@ -317,6 +335,7 @@ export function buildPublishConstraints({ slug, username, publicBaseUrl, publish
|
||||
'- **禁止**:访问 `assets/` 内部路径、其它用户目录、主机绝对路径;禁止用公网 URL 列目录或读 CSV',
|
||||
'- **路径规则**:只用相对路径;禁止 `../`;工作区外的路径会被系统拒绝(OS 层强制,非软约束)',
|
||||
'- **生成页面(必须亲自完成)**:先 `load_skill` → `static-page-publish`,再用 `write_file`/`edit_file` 写入 `public/页面.html`',
|
||||
'- **Word 下载页(必须亲自完成)**:若用户要求 Word / docx 下载,必须先 `load_skill` → `docx-generate`,生成并确认 `public/*.docx` 已存在,再在 HTML 中用相对路径链接',
|
||||
'- **用户可见回复**:不要向用户复述 load_skill、技能更新、页脚标记、mindspace-cover 等内部实现;完成后直接给出页面链接或结果',
|
||||
'- **禁止**用 shell 写入 HTML;**禁止**让用户「手动保存到 public 目录」或说「我无法生成页面」——除非 write_file 已失败并报告错误',
|
||||
'- 完成后给出 Markdown 可点击公网链接 `[标题](URL)`;写入 `public/页面.html` 时 URL 为 `.../MindSpace/<用户ID>/public/页面.html`',
|
||||
@@ -335,7 +354,17 @@ export function ensureWorkspaceHintsInstalled(publishDir, context) {
|
||||
return hintsPath;
|
||||
}
|
||||
|
||||
export function ensureDocxSkillInstalled(publishDir) {
|
||||
if (!fs.existsSync(DOCX_SKILL_DIR)) return null;
|
||||
const skillRoot = path.join(publishDir, '.agents', 'skills', DOCX_SKILL_NAME);
|
||||
fs.rmSync(skillRoot, { recursive: true, force: true });
|
||||
fs.mkdirSync(path.dirname(skillRoot), { recursive: true });
|
||||
fs.cpSync(DOCX_SKILL_DIR, skillRoot, { recursive: true });
|
||||
return path.join(skillRoot, 'SKILL.md');
|
||||
}
|
||||
|
||||
export function ensurePublishSkillInstalled(publishDir, context) {
|
||||
ensureDocxSkillInstalled(publishDir);
|
||||
const skillRoot = path.join(publishDir, '.agents', 'skills', PUBLISH_SKILL_NAME);
|
||||
fs.mkdirSync(skillRoot, { recursive: true });
|
||||
const skillPath = path.join(skillRoot, 'SKILL.md');
|
||||
|
||||
Reference in New Issue
Block a user