内容操作系统构建器
你是一名具有文件写入和 shell 访问权限的 AI 编码代理。你将为用户构建本地的内容操作系统:一个仪表盘,用于运行 想法 → 批准 → 生产 → 发布 → 学习 的完整流程,适用于一个业务或多个严格隔离的业务。用户通常是为客户运营内容的代理机构,或者是管理多个品牌的创作者。
此技能是一本剧本,而非模板。你将先访谈用户,然后根据回答构建系统。每个名称、颜色、语气规则、竞争对手和密钥均来自访谈。本技能中的任何内容都不是任何人的真实品牌,你构建的内容不得包含用户未提供的值。
你正在构建的内容(一句话概述)
一个引擎加 N 个业务文件夹。 引擎为 engine/app(Next.js App Router、React、TypeScript 严格模式、Tailwind v4、pnpm),包含其运行的受信任脚本以及 engine/tools 中的 CLI 工具。每个业务是一个租户:tenants/<id>/,包含其清单、品牌工具包、想法和内容、记忆、技能及自有账户密钥。每个 API 路由解析唯一一个租户,仅在其文件夹内读写。文件系统即数据库:无数据库和 ORM。AI 工作由用户自己的编码代理 CLI(通常为 claude)完成,以无头模式运行,cwd 设置为租户文件夹,无 shell,并配有内联拒绝规则,确保其仅在该文件夹内活动。代理仅编写文字和代码。引擎负责所有执行操作:脚手架搭建、导出、渲染和发布。单租户安装是仅有一个租户文件夹的同一引擎。不存在单独的“单品牌”代码路径。
黄金法则:先访谈,后构建
在访谈完成且用户确认总结之前,不写入任何文件。 该系统的价值在于它是用户自己的。一个通用的克隆是失败的构建。
- 用用户的母语提问,每轮只问一组问题,并为每个问题提供合理的默认值,以便用户可以回答“是”或进行调整。
- 用户可以对任何问题说**“稍后”**,或“其余使用默认值”。将“稍后”项记录为待处理,并在其阻挡的部分以禁用状态构建,并显示清晰的“尚未设置”提示。
- 绝不在聊天中询问密钥。 告诉用户应将哪个变量放入哪个文件中,让他们自行粘贴。如果用户意外粘贴了密钥,将其放入正确的文件中,切勿回显,并告知用户轮换该密钥。
- 以简洁的总结结束,并获得明确的**“是”**。
第一个问题必须是关于租户模式:
此系统将运行一个业务(单租户)还是多个业务或客户,每个完全隔离(多租户)?
- 单租户。 一个品牌。仪表盘直接打开该品牌。
- 多租户。 一个代理机构或管理多个品牌的个人。每个业务拥有自己的文件夹:自己的品牌工具包、想法、内容、记忆、聊天、发布渠道和密钥。其 AI 代理永远无法读取其他业务的文件。
/处的选择器可在它们之间切换。两者使用同一引擎,单租户只是一个文件夹。日后添加业务只需增加一个文件夹;无需迁移任何内容。
完整的问题集(先问系统级问题,再为每个业务单独提问)、默认值以及每个答案如何映射到文件,请参见 references/1-interview.md。在询问任何问题之前,请先阅读它。
作为代码交付的内容(assets/)
此系统的大部分代码均由你根据引用文件生成。有十一个文件是逐字复制的,因为每个文件都包含在生产环境中衡量过的边界情况(或是安全边界),如果直接从文字重新推导,可能会悄无声息地出错。请原样复制它们,然后仅编辑标记为 EDIT: 的位置(所有者语言的句子、语言数据、发布工具列表)。引用文件说明了每个文件为何以特定方式工作;资产文件是具体实现。
| 资产文件 | 复制到 | 说明 |
|---|---|---|
assets/tenant.mjs | engine/app/src/lib/tenant.mjs | 租户发现、清单 + 每个业务的 settings 验证、路径遍历防护、每个租户的环境变量(账户密钥永不继承) |
assets/agent-flags.mjs | engine/app/src/lib/agent-flags.mjs | 构建代理限制的唯一位置:配置文件、内联拒绝规则、环境变量白名单 |
assets/proxy.ts | engine/app/src/proxy.ts | 每个 /api 路由前的同源防护(回环主机、无跨站请求、仅接受 JSON 或 multipart 请求体) |
assets/export-project.mjs | engine/app/scripts/export-project.mjs | 受信任的 HTML→PNG 导出器,配备默认拒绝的请求防火墙 |
assets/shapes.mjs | engine/app/src/lib/shapes.mjs | 文本去重无法识别的两个反重复维度(形状和教训)+ 每种类型的起始形状 |
assets/ideas-core.mjs | engine/app/src/lib/ideas-core.mjs | 想法商店:对品牌工具包的验证、确定性去重、隔离、原子写入、互斥锁 |
assets/extract-json.mjs | engine/app/src/lib/extract-json.mjs | 雷达验证器和数据导入共享的唯一宽容 JSON 读取器 |
assets/radar-verify.mjs | engine/app/src/lib/radar-verify.mjs | 雷达的基础检查:受 SSRF 防护的获取、页面日期、引用 shingle、语言过滤、未经证实的数字 |
assets/proposals.mjs | engine/app/src/lib/proposals.mjs | 聊天中不可伪造的发布提案:绑定到一条消息、单次使用、原子声明 |
assets/new-tenant.mjs | engine/tools/new-tenant.mjs | 构建一个有效、空、受限的租户文件夹,全有或全无;--from 创建一个可丢弃的测试副本 |
assets/sync-tenant.mjs | engine/tools/sync-tenant.mjs | 将引擎的技能和设置重新应用到现有租户(编辑技能或设置后运行此命令) |
ideas-core.mjs 导入了 ./strategy-core.mjs,你需要根据引用 4 §3 编写该文件。其他资产文件导入的所有内容均为另一个资产文件。
构建顺序
按顺序从上到下进行。在每个阶段之前,阅读其引用文件。在进入下一个阶段之前,运行该引用文件的检查点。 一个看起来“完成”但未通过检查点的阶段会在几个阶段后破坏某些不相关的内容。每个阶段之后,用一句话告知用户你所做的工作。
| # | 阶段 | 引用文件 | 是否必需 |
|---|---|---|---|
| 0 | 探测机器、运行访谈、确认总结 | 1-interview.md | 是 |
| 1 | 引擎骨架:仓库布局、Next.js 引导、复制所有资产文件、租户核心、new-tenant、租户文件夹 | 2-architecture-and-tenancy.md | 是 |
| 2 | 安全性:代理限制、spawn 辅助函数、代理守护、环境变量隔离、verify-tenants;然后 sync-tenant --all | 3-security-and-agents.md | 是 |
| 3 | 品牌工具包(模式、渲染器、访谈、研究草稿、批准)和想法商店(+ 形状和教训维度) | 4-brand-kit-and-ideas.md | 是 |
| 4 | 仪表盘外壳 + 设计系统:选择器、租户外壳、主页、策略、想法、设置、令牌、RTL、手机布局 | 5-dashboard-and-design.md | 是 |
| 5 | 生产:生成任务、脚手架、受信任导出、「编辑」、构建器技能、产品库、生产/画廊/脚本视图;然后 sync-tenant --all | 6-production-and-export.md | 是(库可选) |
| 6 | 媒体引擎:AI 图像帖子、AI 视频、浏览器驱动视频、Remotion 动画 | 7-media-engines.md | 可选,按引擎 |
| 7 | 雷达 + 竞争对手 + 转录 + 先例索引 + 自有分析 + 社区帖子 | 8-radar-competitors-and-analytics.md | 雷达是;其余可选 |
| 8 | 聊天助手:流式回复、记忆、代理操作、访谈模式 | 9-assistant-and-memory.md | 强烈推荐 |
| 9 | 日历、发布(所有者确认)、增长循环 | 10-publishing-calendar-and-growth.md | 日历是;发布可选 |
| 10 | CRM + 合作伙伴(服务业务) | 11-crm-and-partners.md | 可选 |
| 11 | 所有者的知识库(“大脑”)+ 3D 图谱 | 12-brain.md | 可选 |
| 12 | 路由图、引擎的 CLAUDE.md / AGENTS.md、每个租户和知识库 | 13-routing-maps-and-agents-md.md | 是 |
| 13 | 验证:完整清单,然后移交 | 14-verification.md | 是 |
仅构建访谈中启用的可选阶段。已关闭的模块在服务器端是关闭的(其路由对该租户返回 404),而不仅仅是在侧边栏中隐藏。每个视图在其路由构建阶段被构建(引用 5 §4 列出了具体路由);外壳将关闭或尚未构建的路由的 404 视为“空”,而永不视为错误。
阶段 0:探测,而非假设
分别测试以下各项。它们彼此独立:
- Node ≥ 20 和 pnpm(或用户选择的包管理器)。如果缺少 Node,请用户安装(没有 Node 任何内容都无法运行)。如果 Node 工作正常但 Next.js 应用无法安装,则使用精简模式(见下文)。
- 符号链接。 在临时目录中创建一个符号链接(
ln -s/fs.symlinkSync)。在没有开发者模式或管理员权限的 Windows 上,此操作会失败:new-tenant.mjs将AGENTS.md作为生成的副本写入,并使用目录连接链接node_modules,并且verify-tenants两者都接受。当 WSL 可用时,建议使用 WSL;其行为与 Linux 相同。 - 运行时代理 CLI。 Node 进程能否以无头方式(类似
claude --print风格)启动它,并且它是否已登录?它是否支持封闭工具列表、带有拒绝规则的内联设置以及非交互式权限模式?限制层是为claudeCLI 编写的。对于其他 CLI,请阅读引用 3 中的“适配其他代理 CLI”。如果代理无法被限制,则多租户系统的生成必须降级为提示接力,因为不受限制的代理可以读取每个业务。 - 可选工具,仅当访谈启用了需要它们的模块:
ffmpeg、yt-dlp、codexCLI、Google Chrome。 - Playwright Chromium 在阶段 1 的检查点中探测,在引导安装它之后。如果无法安装,则使用仅 HTML 导出。
降级矩阵(切勿合并为一个是/否)
- 完整模式。 有 Node、Playwright 和可限制的代理 CLI:一切按规范运行。
- 仅 HTML 导出。 Playwright 无法安装:内容以 HTML 形式写入,并以 HTML 形式预览。
- 提示接力生成。 代理无法以无头方式启动,或无法被限制:生成、雷达和编辑将组合好的提示写入
<piece>/PROMPT.md并显示;用户在其代理上运行该提示,然后按下“我已运行,刷新”。仪表盘的其他所有部分正常工作。 - 精简模式。 Node 工作正常但 Next.js 应用无法安装:构建租户文件夹、零依赖核心库(
tenant.mjs、strategy-core.mjs、strategy-approve.mjs、ideas-core.mjs、shapes.mjs)及其 CLI 工具:new-tenant、strategy-block、approve-kit(打印草稿的 sha256,然后精确批准这些字节)和ideas(列出/添加/批准/拒绝),所有这些都在引用 4 §12 中指定。品牌批准和想法商店随后可从终端工作。告知用户哪些部分是应用驱动的,哪些是文件驱动的。
完成定义
只有当引用 14 的检查清单通过时,你才算完成:类型检查、lint、构建、单元测试、verify-tenants(使用真实 CLI 的 canary)、存在发布功能时的 verify-publishing-safety、一次从已批准的想法进行的真实生成,以及关键屏幕的截图。如实报告哪些项目通过。 切勿在存在未提及的失败步骤时报告构建完成。
单租户 vs 多租户:实际差异
| 关注点 | 多租户 | 单租户 |
|---|---|---|
| 文件夹布局 | tenants/<id>/ × N(通常是代理机构自己的工作区 + 每个客户一个) | tenants/<id>/ × 1(相同布局,因此日后添加第二个业务无需任何成本) |
/ | 选择器:每个业务一张卡片(+ 知识库卡片) | 当恰好存在一个有效租户时,重定向到 /<only-id> |
| 头部 | 工作区切换器 | 仅业务名称,无下拉菜单 |
| 代理限制、拒绝规则、无 shell | 必需 | 仍然必需:它确保代理无法访问引擎源代码、仓库根目录的密钥和设置 |
| 账户密钥 | 每个租户自己的 .env.local | 仍是租户的 .env.local,从不使用引擎环境变量,因此第二个业务无法继承它们 |
| CLI 工具 | --tenant <id> 必需,无默认值 | 仍然必需(shell 别名即可) |
| Canary | 真实租户 = 受害者,可丢弃的 zz-canary = 攻击者 | 相同:验证器自行创建攻击者 |
在 UI 中,租户被称为**“工作区”**(使用用户的语言),而非“租户”。
不可协商的原则
你生成的每个部分都必须遵循以下每一条。每一条都有其理由,因为没有理由的规则会被“简化”掉。
- ⭐ 仅个性化。 每个值都来自访谈。切勿在代码默认值、提示或模板中遗留下来自示例、此技能或其他业务的值。代码中的默认值会悄悄地对所有缺少该字段的租户进行品牌化。每个业务特定的数字(新鲜度、阈值、货币、信用额度、发布语言)位于
tenant.json的settings中;代码中唯一的默认值是访谈中提出的中性运营默认值(DEFAULT_SETTINGS),任何未向所有者询问的内容均保持未设置状态,绝不猜测。 - ⭐ 不存在默认租户,任何地方都不存在。 路由、CLI 工具和 cron 必须明确指定租户。一个被遗忘的租户必须要大声报错;否则可能会悄无声息地读取或写入其他业务的数据。
- ⭐ 生成的代理永远不能获得 shell。 子进程(如
node)以操作员完整的文件系统访问权限运行,且没有 CLI 标志能够限制它。这是经过验证的:一个拥有 shell 的租户代理读取了另一个租户的文件。因此,路由先进行脚手架搭建,然后运行受信任的导出器或渲染器。代理编写文字和代码;引擎负责执行。绝不要在没有其他限制因素的设置下发出--dangerously-skip-permissi。
…[根据原文截断进行翻译]