From 5732925f64fab2e99a63da81ae775cf2e231120d Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 14 Aug 2026 12:44:59 +0800 Subject: [PATCH] =?UTF-8?q?docs(README):=20=E8=A3=9C=E4=B8=8A=20pnpm/turbo?= =?UTF-8?q?=20=E9=96=8B=E7=99=BC=E6=B5=81=E7=A8=8B=E3=80=81=E7=92=B0?= =?UTF-8?q?=E5=A2=83=E8=AE=8A=E6=95=B8=E8=A1=A8=E8=88=87=E6=AD=A3=E5=BC=8F?= =?UTF-8?q?=E7=92=B0=E5=A2=83=E9=83=A8=E7=BD=B2=E8=B7=AF=E5=BE=91=E8=AA=AA?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 11 +++++++++ README.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 689a834..23468fc 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,14 @@ # 複製為 .env 後依需要調整。 # R-2 階段會改為 postgresql 連線字串(例如 postgresql://user:password@localhost:5432/kokorone)。 DATABASE_URL="file:./prisma/dev.db" + +# R-2:情緒狀態即時讀寫/session 快取的加速層;連不到時自動退回原本行為(DB/行程記憶體),不是必要依賴。 +REDIS_URL=redis://127.0.0.1:6379 + +# R-3:LLM_PROVIDER=mock(預設,冒煙測試固定用這個)|claude(真的呼叫 API) +LLM_PROVIDER=mock +# 這個部署走 CLIProxy(OpenAI 相容的分散式派工代理)而不是直連 api.anthropic.com, +# 底層仍是 Claude;若改直連官方 API,把 CLAUDE_BASE_URL 換成 https://api.anthropic.com/v1 即可。 +CLAUDE_BASE_URL=http://localhost:3000/api/v1 +CLAUDE_API_KEY= +CLAUDE_MODEL=claude-sonnet-4-5 diff --git a/README.md b/README.md index 5a7cdbe..a2270e2 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,68 @@ 以人腦「記憶/情緒/關係」架構為引擎基礎的戀愛陪伴系統。 -> 目前使用 npm workspaces 開發(本機無 pnpm),待 R-1 階段會遷移至 pnpm + Turborepo,對外指令介面(`npm run restart` / `npm run smoke`)保持不變。 +## 開發環境 + +Monorepo 採 pnpm workspace + Turborepo(`pnpm-workspace.yaml` / `turbo.json`)。 + +```bash +pnpm install # 安裝所有 workspace 套件 +pnpm run build # turbo run build(依相依順序建置 shared/db/api,並建置 web 的 production bundle) +pnpm run restart # 停止舊的 api/web 行程、重建 TypeScript(tsc -b)、重新啟動並等待健康檢查 +pnpm run smoke A # 執行 A 群組冒煙測試;all 表示依序執行 A~R 全部群組 +``` + +對外指令介面(`restart` / `smoke`)維持與遷移前相同的腳本名稱;唯一差異是 +**pnpm 不會像 npm 一樣吃掉 `--` 分隔符**,`pnpm run smoke -- A` 會把字面上的 +`--` 一起傳給腳本而找不到群組,要執行子指令請直接接在腳本名稱後面 +(`pnpm run smoke A`),不要加 `--`。 + +## 環境變數 + +複製 `.env.example` 為 `.env` 後依需要調整;`apps/web/.env.local` 另外可設定 +`NEXT_PUBLIC_API_URL`(瀏覽器端呼叫 api 用,預設 `http://localhost:3001`)。 + +| 變數 | 預設值 | 說明 | +| --- | --- | --- | +| `DATABASE_URL` | `file:./prisma/dev.db` | Prisma 連線字串。R-5 若遷移到 PostgreSQL,改為 `postgresql://user:password@host:5432/db` 並將 `prisma/schema.prisma` 的 `provider` 由 `sqlite` 換成 `postgresql`。 | +| `PORT` | `3001` | api(NestJS)監聽埠。 | +| `PORT_API` / `PORT_WEB` | `3001` / `3100` | `pnpm run restart`(`scripts/dev-restart.mjs`)啟動 api/web 時使用的埠號。 | +| `WEB_ORIGIN` | `http://localhost:3100` | api 的 CORS 允許來源之一;`http://localhost:8081`(Expo web 開發伺服器)已固定加入,不受此變數影響。 | +| `NEXT_PUBLIC_API_URL` | `http://localhost:3001` | web(Next.js)呼叫 api 的位址,build time 注入,正式環境需在建置時設定。 | +| `LLM_PROVIDER` | `mock` | `mock`(模板庫,冒煙測試固定用這個)/`claude`(呼叫真實 API,見下)。 | +| `CLAUDE_BASE_URL` | `http://localhost:3000/api/v1` | OpenAI 相容的 chat completions 端點基底路徑。本專案的部署方式是透過 [CLIProxy](https://gitea.jsc.idv.tw/jiantw83/CLIProxy)(分散式派工代理,本機 3000 埠)轉發到真實 Claude,而非直連 `api.anthropic.com`;若要直連官方 API,把這個值換成 `https://api.anthropic.com/v1` 並確認金鑰/請求格式相容即可,`ClaudeProvider` 的呼叫端程式碼不需要改動。 | +| `CLAUDE_API_KEY` | (無) | 呼叫 `CLAUDE_BASE_URL` 用的金鑰,`LLM_PROVIDER=claude` 時必填。 | +| `CLAUDE_MODEL` | `claude-sonnet-4-5` | 要求 Provider 使用的模型名稱;CLIProxy 端需要有對應的 Worker 已註冊、能接這個模型的派工,否則會回報「沒有任何可用的 {模型}-{執行者}-{工具} 組合」。 | +| `TTS_PROVIDER` | `mock` | `mock`/`real`(P-4 空殼,尚未接上真實供應商,人工確認後才實作)。 | +| `PUSH_PROVIDER` | `mock` | `mock`/`expo`(Q-3,`expo` 直接可用,不需金鑰)。 | + +## 部署路徑 + +開發環境:以上服務直接用 `node`/`next dev`/`expo start` 跑在同一台 Linux 主機上 +(`pnpm run restart` 一鍵重啟 api/web),**不使用 Docker**——這是本專案的實際 +部署選擇,取代原先技術選型草案中「Docker Compose(開發)」的規劃。 + +正式環境建議路徑: + +1. **建置**:`pnpm install --frozen-lockfile && pnpm run build`(turbo 依序建置 + `packages/shared`/`packages/db`/`apps/api`,並產出 `apps/web` 的 production + bundle)。 +2. **資料庫遷移**:`npx prisma migrate deploy`(依 `DATABASE_URL` 指向的資料庫套用 + 遷移;R-5 遷移到 PostgreSQL 後流程相同,只是連線字串換成 postgresql)。 +3. **啟動**: + - api:`node apps/api/dist/main.js`(讀取上表環境變數)。 + - web:`apps/web` 下 `npx next start -p `(讀取建置時注入的 + `NEXT_PUBLIC_API_URL`)。 + - mobile:`apps/mobile` 透過 `eas build` 產出實際的 App Store/Google Play + 安裝檔,不隨 api/web 一起常駐部署。 +4. **程序常駐與重啟**:用 systemd unit(或 pm2)分別管理 api/web 兩個 + Node 行程,設定 `Restart=on-failure`;健康檢查沿用 `GET /health` + (api)與首頁 200(web),與 `scripts/dev-restart.mjs` 開發環境用的 + 檢查邏輯一致。 +5. **反向代理/TLS**:nginx 或雲端負載平衡器終止 TLS 後轉發到 api/web + 對應埠號,對外只曝露 443。 + +這個路徑刻意不假設 K8s 或容器化,只依賴「Node.js 行程 + systemd + nginx」, +因為這台開發主機本身就是照這個模式跑(`pnpm run restart` 正是這個模式的 +開發期簡化版),移植到正式主機時只是把「用 node 直接跑」換成「用 systemd +管理同一組 node 指令」,中間不需要引入額外的容器化工具鏈。