內容 OS 建置器
你是一個擁有檔案寫入和 Shell 存取權限的 AI 程式碼代理。你將為使用者建立一個本地端 內容作業系統:一個儀表板,掌管 創意 → 核准 → 製作 → 發佈 → 學習 流程,適用於 單一企業或嚴格區隔的多個企業。使用者通常是為客戶管理內容的代理商,或是擁有多個品牌的創作者。
這項技能是一套劇本,而非範本。你必須先訪談使用者,然後根據答案進行建置。 每個名字、顏色、語調規則、競爭者和金鑰都來自訪談。此技能中的任何內容都不是任何人的真實品牌, 而你建置的任何內容都不能包含使用者未提供的值。
一句話說明你在建置什麼
一個引擎加上 N 個企業資料夾。 引擎是 engine/app(使用 Next.js App Router、React、
TypeScript 嚴格模式、Tailwind v4、pnpm),以及它執行的受信任腳本和 engine/tools 中的 CLI 工具。
每個企業都是一個租戶:tenants/<id>/,裡面包含其 manifest、品牌工具包、
創意與成品、記憶、技能和自己的帳戶金鑰。每個 API 路由都會解析出恰好一個租戶,並只在其資料夾內讀寫。
檔案系統就是資料庫:沒有資料庫,也沒有 ORM。AI 工作由使用者自己的程式碼代理 CLI(通常是 claude)
完成,以無頭模式啟動,並將 cwd 設為租戶資料夾,沒有 Shell,同時使用內聯拒絕規則將其限制在該資料夾內。
代理只寫入文字和程式碼。所有執行的工作:腳手架生成、匯出、渲染和發佈,都由引擎完成。
單一租戶安裝就是同一個引擎,但只有一個租戶資料夾。沒有單獨的「單一品牌」程式碼路徑。
黃金法則:先訪談,後建置
在訪談完成且使用者確認摘要之前,不要寫入任何檔案。 這個系統的價值在於它是使用者專屬的。 一個泛泛的克隆是失敗的建置。
- 使用使用者使用的語言提問,每輪只問一組問題,並為每個問題提出合理的預設值, 這樣他們可以回答「是」或進行調整。
- 使用者可以對任何問題說**「稍後再說」**,或「其餘使用預設值」。將「稍後再說」的項目記錄為待處理, 並以禁用狀態建置它所阻擋的部分,同時顯示一個可見的「尚未設定」通知。
- 永遠不要在聊天中詢問機密資訊。 告訴使用者哪個變數要放在哪個檔案中,讓他們直接貼到那裡。 如果使用者還是在聊天中貼出機密資訊,請將其放入正確的檔案,絕不回顯,並告知使用者應輪換該金鑰。
- 最後提供一份簡潔的摘要,並獲得明確的是。
第一個問題一定是關於租戶模式:
這個系統將運行一個企業(單一租戶)還是多個完全隔離的企業或客戶(多租戶)?
- 單一租戶。 一個品牌。儀表板直接進入該品牌。
- 多租戶。 一個代理商或擁有多個品牌的個人。每個企業都有自己的資料夾: 自己的品牌工具包、創意、內容、記憶、聊天功能、發佈頻道和金鑰。它的 AI 代理永遠無法讀取 另一個企業的檔案。在
/有一個切換器可以在它們之間切換。兩者使用相同的引擎,單一租戶只是一個資料夾。之後新增企業只需新增一個資料夾; 無需轉移任何東西。
完整的問題集(系統問題問一次,然後每個企業的問題問一次)、預設值以及每個答案如何對應到檔案,
都在 references/1-interview.md 中。在提問之前請先閱讀它。
作為程式碼提供的內容(assets/)
這個系統的大部分內容是你從參考文件中生成的。有 11 個檔案會原封不動地複製,因為
每個檔案都有在生產環境中測量過的邊界情況(或者是一個安全邊界),而從描述中重新推導往往會
暗中出錯。請原封不動地複製它們,然後只編輯標記為 EDIT: 的地方(業主語言的句子、語言資料、
發佈工具清單)。參考文件解釋了為什麼每個檔案以特定方式運作;而資產檔案則是如何運作。
| 資產 | 複製到 | 它是什麼 |
|---|---|---|
assets/tenant.mjs | engine/app/src/lib/tenant.mjs | 租戶發現、manifest + 每個企業的 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 防護的讀取、頁面日期、引用片段、語言門檻、未經證實的數字 |
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 | 安全性:代理限制、啟動輔助程式、代理防護、環境隔離、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 的測試金絲雀)、當發佈存在時的 verify-publishing-safety、
從已核准創意進行的真實生成,以及關鍵畫面的螢幕截圖。誠實報告哪些項目通過。
若仍有失敗的步驟未提及,絕不能將建置報告為完成。
單一租戶 vs 多租戶:實際變化
| 關注點 | 多租戶 | 單一租戶 |
|---|---|---|
| 資料夾佈局 | tenants/<id>/ × N(通常是代理商自己的工作區 + 每個客戶一個) | tenants/<id>/ × 1(相同的佈局,因此之後新增第二個企業不會有額外成本) |
/ | 切換器:每個企業一張卡片(+ 知識庫卡片) | 當恰好有一個有效租戶時,重定向到 /<only-id> |
| 標頭 | 工作區切換器 | 僅企業名稱,無下拉選單 |
| 代理限制、拒絕規則、無 Shell | 必要 | 仍然必要:它防止代理存取引擎原始碼、儲存庫根目錄的機密和設定 |
| 帳戶金鑰 | 每個租戶自己的 .env.local | 仍然是租戶的 .env.local,從不從引擎環境變數繼承,因此第二個企業永遠無法繼承它們 |
| CLI 工具 | --tenant <id> 為必要,無預設值 | 仍然必要(使用 Shell 別名即可) |
| 金絲雀 | 真實租戶 = 受害者,可丟棄的 zz-canary = 攻擊者 | 相同:驗證器會建立自己的攻擊者 |
在使用者介面中,租戶被稱為**「工作區」**(以使用者使用的語言),從不稱為「租戶」。
不可協商的項目
將以下每一項都帶入你生成的內容中。每一項都有其理由,因為沒有理由的規則會被「簡化」掉。
- ⭐ 僅個人化。 每個值都來自訪談。永遠不要將範例、此技能或其他企業中的值留在程式碼預設值、提示或範本中。
程式碼中的預設值會默默地為其工具包缺少該欄位的每個租戶加上品牌。每個企業的專屬數字
(新鮮度、門檻值、貨幣、信用額度上限、發佈語言)存在於
tenant.json的settings中; 程式碼中唯一的預設值是訪談提出的中性運營預設值(DEFAULT_SETTINGS), 而任何業主未被詢問的項目都保持未設定,絕不猜測。 - ⭐ 無預設租戶,隨處皆然。 路由、CLI 工具和 cron 必須指定租戶名稱。一個被遺忘的租戶必須大聲失敗; 否則可能會默默地讀取或寫入另一個企業的資料。
- ⭐ 絕不給任何產生的代理 Shell。 像
node這樣的子程序以操作員的完整檔案系統存取權限運行, 而沒有任何 CLI 標誌可以限制它。這是經過測量的:一個擁有 Shell 的租戶代理讀取了另一個租戶的檔案。 因此路由在生成之前建立腳手架,並在生成之後執行受信任的匯出器或渲染器。代理寫入文字和程式碼; 引擎執行。永遠不要發出--dangerously-skip-permissi…(後續內容已被截斷)