grok-cli-to-openai-compatible 1.2.7 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/.env.example +25 -3
  2. package/README-ZH.md +179 -56
  3. package/README.md +186 -63
  4. package/dist/app.d.ts.map +1 -1
  5. package/dist/app.js +199 -12
  6. package/dist/app.js.map +1 -1
  7. package/dist/cli/commands/admin-panel.d.ts +13 -0
  8. package/dist/cli/commands/admin-panel.d.ts.map +1 -0
  9. package/dist/cli/commands/admin-panel.js +98 -0
  10. package/dist/cli/commands/admin-panel.js.map +1 -0
  11. package/dist/cli/commands/doctor.d.ts +1 -0
  12. package/dist/cli/commands/doctor.d.ts.map +1 -1
  13. package/dist/cli/commands/doctor.js +74 -8
  14. package/dist/cli/commands/doctor.js.map +1 -1
  15. package/dist/cli/commands/logs.d.ts +10 -0
  16. package/dist/cli/commands/logs.d.ts.map +1 -0
  17. package/dist/cli/commands/logs.js +83 -0
  18. package/dist/cli/commands/logs.js.map +1 -0
  19. package/dist/cli/commands/open.d.ts +1 -0
  20. package/dist/cli/commands/open.d.ts.map +1 -1
  21. package/dist/cli/commands/open.js +1 -1
  22. package/dist/cli/commands/open.js.map +1 -1
  23. package/dist/cli/commands/restart.d.ts +1 -0
  24. package/dist/cli/commands/restart.d.ts.map +1 -1
  25. package/dist/cli/commands/restart.js +17 -1
  26. package/dist/cli/commands/restart.js.map +1 -1
  27. package/dist/cli/commands/setup.d.ts.map +1 -1
  28. package/dist/cli/commands/setup.js +12 -0
  29. package/dist/cli/commands/setup.js.map +1 -1
  30. package/dist/cli/commands/start.d.ts +2 -0
  31. package/dist/cli/commands/start.d.ts.map +1 -1
  32. package/dist/cli/commands/start.js +50 -8
  33. package/dist/cli/commands/start.js.map +1 -1
  34. package/dist/cli/commands/status.d.ts +1 -0
  35. package/dist/cli/commands/status.d.ts.map +1 -1
  36. package/dist/cli/commands/status.js +39 -14
  37. package/dist/cli/commands/status.js.map +1 -1
  38. package/dist/cli/commands/stop.d.ts +1 -0
  39. package/dist/cli/commands/stop.d.ts.map +1 -1
  40. package/dist/cli/commands/stop.js +30 -5
  41. package/dist/cli/commands/stop.js.map +1 -1
  42. package/dist/cli/commands/update.d.ts +1 -0
  43. package/dist/cli/commands/update.d.ts.map +1 -1
  44. package/dist/cli/commands/update.js +127 -20
  45. package/dist/cli/commands/update.js.map +1 -1
  46. package/dist/cli/index.js +67 -5
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/lib/env-file.d.ts +7 -0
  49. package/dist/cli/lib/env-file.d.ts.map +1 -1
  50. package/dist/cli/lib/env-file.js +62 -17
  51. package/dist/cli/lib/env-file.js.map +1 -1
  52. package/dist/cli/lib/pm2-runner.d.ts +14 -0
  53. package/dist/cli/lib/pm2-runner.d.ts.map +1 -0
  54. package/dist/cli/lib/pm2-runner.js +179 -0
  55. package/dist/cli/lib/pm2-runner.js.map +1 -0
  56. package/dist/cli/lib/process-mgr.d.ts +15 -0
  57. package/dist/cli/lib/process-mgr.d.ts.map +1 -1
  58. package/dist/cli/lib/process-mgr.js +111 -22
  59. package/dist/cli/lib/process-mgr.js.map +1 -1
  60. package/dist/cli/lib/runner-info.d.ts +20 -0
  61. package/dist/cli/lib/runner-info.d.ts.map +1 -0
  62. package/dist/cli/lib/runner-info.js +120 -0
  63. package/dist/cli/lib/runner-info.js.map +1 -0
  64. package/dist/cli/lib/spinner.d.ts +20 -0
  65. package/dist/cli/lib/spinner.d.ts.map +1 -0
  66. package/dist/cli/lib/spinner.js +72 -0
  67. package/dist/cli/lib/spinner.js.map +1 -0
  68. package/dist/config/constants.d.ts +31 -0
  69. package/dist/config/constants.d.ts.map +1 -1
  70. package/dist/config/constants.js +103 -2
  71. package/dist/config/constants.js.map +1 -1
  72. package/dist/config/cors.js +1 -1
  73. package/dist/config/cors.js.map +1 -1
  74. package/dist/config/env.d.ts +11 -1
  75. package/dist/config/env.d.ts.map +1 -1
  76. package/dist/config/env.js +43 -3
  77. package/dist/config/env.js.map +1 -1
  78. package/dist/controllers/admin.controller.d.ts +35 -0
  79. package/dist/controllers/admin.controller.d.ts.map +1 -1
  80. package/dist/controllers/admin.controller.js +599 -18
  81. package/dist/controllers/admin.controller.js.map +1 -1
  82. package/dist/controllers/api-key.controller.d.ts.map +1 -1
  83. package/dist/controllers/api-key.controller.js +4 -3
  84. package/dist/controllers/api-key.controller.js.map +1 -1
  85. package/dist/controllers/chat.controller.d.ts.map +1 -1
  86. package/dist/controllers/chat.controller.js +2 -1
  87. package/dist/controllers/chat.controller.js.map +1 -1
  88. package/dist/controllers/document.controller.d.ts.map +1 -1
  89. package/dist/controllers/document.controller.js +3 -2
  90. package/dist/controllers/document.controller.js.map +1 -1
  91. package/dist/dto/admin.dto.d.ts +36 -1
  92. package/dist/dto/admin.dto.d.ts.map +1 -1
  93. package/dist/dto/admin.dto.js +23 -1
  94. package/dist/dto/admin.dto.js.map +1 -1
  95. package/dist/dto/chat.dto.d.ts +73 -0
  96. package/dist/dto/chat.dto.d.ts.map +1 -1
  97. package/dist/dto/chat.dto.js +5 -1
  98. package/dist/dto/chat.dto.js.map +1 -1
  99. package/dist/dto/conversation.dto.d.ts +286 -0
  100. package/dist/dto/conversation.dto.d.ts.map +1 -0
  101. package/dist/dto/conversation.dto.js +62 -0
  102. package/dist/dto/conversation.dto.js.map +1 -0
  103. package/dist/dto/ddos.dto.d.ts +191 -0
  104. package/dist/dto/ddos.dto.d.ts.map +1 -0
  105. package/dist/dto/ddos.dto.js +57 -0
  106. package/dist/dto/ddos.dto.js.map +1 -0
  107. package/dist/entities/api-key.entity.d.ts +2 -0
  108. package/dist/entities/api-key.entity.d.ts.map +1 -1
  109. package/dist/interfaces/auth.interface.d.ts +1 -0
  110. package/dist/interfaces/auth.interface.d.ts.map +1 -1
  111. package/dist/interfaces/express.interface.d.ts +2 -0
  112. package/dist/interfaces/express.interface.d.ts.map +1 -1
  113. package/dist/middlewares/auth.middleware.d.ts.map +1 -1
  114. package/dist/middlewares/auth.middleware.js +30 -3
  115. package/dist/middlewares/auth.middleware.js.map +1 -1
  116. package/dist/middlewares/client-ip.middleware.d.ts +11 -0
  117. package/dist/middlewares/client-ip.middleware.d.ts.map +1 -0
  118. package/dist/middlewares/client-ip.middleware.js +19 -0
  119. package/dist/middlewares/client-ip.middleware.js.map +1 -0
  120. package/dist/middlewares/connection-tracker.d.ts +47 -0
  121. package/dist/middlewares/connection-tracker.d.ts.map +1 -0
  122. package/dist/middlewares/connection-tracker.js +99 -0
  123. package/dist/middlewares/connection-tracker.js.map +1 -0
  124. package/dist/middlewares/rate-limit.middleware.d.ts +9 -2
  125. package/dist/middlewares/rate-limit.middleware.d.ts.map +1 -1
  126. package/dist/middlewares/rate-limit.middleware.js +116 -32
  127. package/dist/middlewares/rate-limit.middleware.js.map +1 -1
  128. package/dist/routes/admin.routes.d.ts.map +1 -1
  129. package/dist/routes/admin.routes.js +38 -0
  130. package/dist/routes/admin.routes.js.map +1 -1
  131. package/dist/routes/v1/chat.routes.d.ts.map +1 -1
  132. package/dist/routes/v1/chat.routes.js +1 -1
  133. package/dist/routes/v1/chat.routes.js.map +1 -1
  134. package/dist/server.js +53 -0
  135. package/dist/server.js.map +1 -1
  136. package/dist/services/abuse-guard.service.d.ts +27 -0
  137. package/dist/services/abuse-guard.service.d.ts.map +1 -0
  138. package/dist/services/abuse-guard.service.js +243 -0
  139. package/dist/services/abuse-guard.service.js.map +1 -0
  140. package/dist/services/api-key.service.d.ts +18 -1
  141. package/dist/services/api-key.service.d.ts.map +1 -1
  142. package/dist/services/api-key.service.js +79 -11
  143. package/dist/services/api-key.service.js.map +1 -1
  144. package/dist/services/chat-admin.service.d.ts +11 -0
  145. package/dist/services/chat-admin.service.d.ts.map +1 -1
  146. package/dist/services/chat-admin.service.js +61 -9
  147. package/dist/services/chat-admin.service.js.map +1 -1
  148. package/dist/services/conversation.service.d.ts +104 -0
  149. package/dist/services/conversation.service.d.ts.map +1 -0
  150. package/dist/services/conversation.service.js +232 -0
  151. package/dist/services/conversation.service.js.map +1 -0
  152. package/dist/services/ddos-policy.service.d.ts +40 -0
  153. package/dist/services/ddos-policy.service.d.ts.map +1 -0
  154. package/dist/services/ddos-policy.service.js +257 -0
  155. package/dist/services/ddos-policy.service.js.map +1 -0
  156. package/dist/services/document.service.d.ts.map +1 -1
  157. package/dist/services/document.service.js +21 -11
  158. package/dist/services/document.service.js.map +1 -1
  159. package/dist/services/ip-blacklist.service.d.ts +40 -0
  160. package/dist/services/ip-blacklist.service.d.ts.map +1 -0
  161. package/dist/services/ip-blacklist.service.js +126 -0
  162. package/dist/services/ip-blacklist.service.js.map +1 -0
  163. package/dist/services/models.service.d.ts +8 -1
  164. package/dist/services/models.service.d.ts.map +1 -1
  165. package/dist/services/models.service.js +18 -3
  166. package/dist/services/models.service.js.map +1 -1
  167. package/dist/services/pm2-config.d.ts +34 -0
  168. package/dist/services/pm2-config.d.ts.map +1 -0
  169. package/dist/services/pm2-config.js +156 -0
  170. package/dist/services/pm2-config.js.map +1 -0
  171. package/dist/services/pm2.service.d.ts +197 -0
  172. package/dist/services/pm2.service.d.ts.map +1 -0
  173. package/dist/services/pm2.service.js +776 -0
  174. package/dist/services/pm2.service.js.map +1 -0
  175. package/dist/services/stats.service.d.ts +36 -0
  176. package/dist/services/stats.service.d.ts.map +1 -1
  177. package/dist/services/stats.service.js +67 -2
  178. package/dist/services/stats.service.js.map +1 -1
  179. package/dist/services/system-health.service.d.ts +30 -0
  180. package/dist/services/system-health.service.d.ts.map +1 -0
  181. package/dist/services/system-health.service.js +234 -0
  182. package/dist/services/system-health.service.js.map +1 -0
  183. package/dist/services/update.service.d.ts +32 -0
  184. package/dist/services/update.service.d.ts.map +1 -1
  185. package/dist/services/update.service.js +176 -41
  186. package/dist/services/update.service.js.map +1 -1
  187. package/dist/services/usage.service.d.ts +43 -0
  188. package/dist/services/usage.service.d.ts.map +1 -0
  189. package/dist/services/usage.service.js +163 -0
  190. package/dist/services/usage.service.js.map +1 -0
  191. package/dist/utils/client-ip.d.ts +41 -0
  192. package/dist/utils/client-ip.d.ts.map +1 -0
  193. package/dist/utils/client-ip.js +172 -0
  194. package/dist/utils/client-ip.js.map +1 -0
  195. package/dist/utils/file-sniff.d.ts +16 -0
  196. package/dist/utils/file-sniff.d.ts.map +1 -0
  197. package/dist/utils/file-sniff.js +151 -0
  198. package/dist/utils/file-sniff.js.map +1 -0
  199. package/dist/utils/ip-match.d.ts +15 -0
  200. package/dist/utils/ip-match.d.ts.map +1 -0
  201. package/dist/utils/ip-match.js +133 -0
  202. package/dist/utils/ip-match.js.map +1 -0
  203. package/dist/utils/stream.d.ts.map +1 -1
  204. package/dist/utils/stream.js +40 -1
  205. package/dist/utils/stream.js.map +1 -1
  206. package/package.json +1 -1
  207. package/prisma/migrations/20260714120000_ip_whitelist_blacklist/migration.sql +19 -0
  208. package/prisma/migrations/20260714220000_chat_conversations/migration.sql +22 -0
  209. package/prisma/migrations/20260714230000_conversation_context/migration.sql +6 -0
  210. package/prisma/schema.prisma +52 -3
  211. package/public/admin/app.js +5696 -375
  212. package/public/admin/assets/logo.svg +37 -0
  213. package/public/admin/disabled.html +131 -0
  214. package/public/admin/i18n.js +1567 -0
  215. package/public/admin/index.html +19 -3
  216. package/public/admin/styles.css +3507 -190
  217. package/public/admin/vendor/marked.min.js +6 -0
  218. package/public/admin/vendor/purify.min.js +3 -0
  219. package/scripts/install.sh +8 -27
  220. package/scripts/prepare.cjs +11 -8
package/.env.example CHANGED
@@ -1,5 +1,6 @@
1
- NODE_ENV=development
2
- # Unique default port for this project (override anytime)
1
+ # development = pretty logs; production recommended for long-running service
2
+ NODE_ENV=production
3
+ # Unique default port for this project (override anytime; Admin PM2 page can change it)
3
4
  PORT=3847
4
5
  HOST=0.0.0.0
5
6
 
@@ -28,14 +29,35 @@ GROK_SAFE_MODE=false
28
29
  GROK_SAFE_MAX_TURNS=4
29
30
  GROK_SAFE_TIMEOUT_MS=120000
30
31
  ADMIN_PANEL_ENABLED=true
32
+ # Allow Admin UI to control PM2 (start/stop/restart for grok-openai-gateway only)
33
+ PM2_ADMIN_ENABLED=true
31
34
 
32
35
  CORS_ORIGINS=http://localhost:3847,http://127.0.0.1:3847
36
+ # --- DDoS / rate limits: initial defaults only ---
37
+ # After first boot, Admin → DDoS Center policy is authoritative (stored in DB).
38
+ # Reset to these env values via Admin → DDoS → "Reset to env defaults".
33
39
  RATE_LIMIT_WINDOW_MS=60000
34
40
  RATE_LIMIT_MAX=120
41
+ # Unauthenticated / IP-only cap (stricter than RATE_LIMIT_MAX)
42
+ RATE_LIMIT_IP_MAX=60
43
+ # Short burst window for chat (10s) — window also editable in Admin policy
44
+ CHAT_BURST_MAX=20
45
+ # Temporary IP block after repeated failed auth (auto-auth rule defaults)
46
+ BLOCK_FAILED_AUTH_THRESHOLD=20
47
+ BLOCK_FAILED_AUTH_WINDOW_MS=300000
48
+ BLOCK_DURATION_MS=600000
35
49
  BODY_LIMIT=1mb
50
+ # Max single upload size (bytes). Larger uploads are rejected before processing.
36
51
  UPLOAD_MAX_BYTES=10485760
52
+ # Below this size → encrypted in SQLite; above → encrypted file under STORAGE_DIR
37
53
  DOCUMENT_DB_MAX_BYTES=1048576
54
+ # Absolute or relative path for encrypted large documents (*.enc)
38
55
  STORAGE_DIR=./storage
39
56
 
40
57
  LOG_LEVEL=info
41
- TRUST_PROXY=true
58
+ # Reverse proxy / CDN client IP (nginx, Cloudflare, load balancer)
59
+ # TRUST_PROXY hops: 0=off (socket only), 1=nginx or CF→app (default), 2=CF→nginx→app
60
+ # Legacy: true→1, false→0. Can also be set in Admin → DDoS → Reverse proxy (runtime).
61
+ TRUST_PROXY=1
62
+ # auto | cloudflare | nginx | x-forwarded-for | socket
63
+ PROXY_IP_SOURCE=auto
package/README-ZH.md CHANGED
@@ -15,15 +15,17 @@
15
15
  | **npm** | [`grok-cli-to-openai-compatible`](https://www.npmjs.com/package/grok-cli-to-openai-compatible) |
16
16
  | **CLI** | `gctoac` · 短名 `gcoa` |
17
17
  | **預設 port** | **`3847`** |
18
+ | **NODE_ENV 預設** | **`production`**(本機開發才設 `development`) |
18
19
 
19
20
  **主要能力**
20
21
 
21
22
  - OpenAI 相容 `POST /v1/chat/completions`(stream / 非 stream)
22
23
  - Thinking / `reasoning_content`(DeepSeek 風格 + Grok `thought`)
23
- - 每把 key 的 **safe** / **agent** 政策
24
+ - 每把 key 的 **safe** / **agent** 政策 + 全域安全覆寫
24
25
  - AES-256-GCM 加密 + 完整 chat 稽核
25
- - Admin Panel:`/admin`(解密 prompt 輸入輸出、金鑰、一鍵更新)
26
- - 控制 CLI:`gctoac setup | start | stop | status | update`
26
+ - **Admin Panel** 儀表板、對話、金鑰、文件、稽核、用量、**DDoS 中心**、PM2、系統更新
27
+ - **DDoS/防濫用** 可配置限流、多規則自動封鎖、反向代理真實客戶端 IP(nginx / Cloudflare)
28
+ - 控制 CLI:setup、start/stop/restart、status、doctor、logs、update、keys、admin on/off
27
29
 
28
30
  ```text
29
31
  Client (OpenAI SDK / curl / Open WebUI)
@@ -31,6 +33,7 @@ Client (OpenAI SDK / curl / Open WebUI)
31
33
 
32
34
  Express Gateway :3847
33
35
  · 認證 · 限流 · safe/agent
36
+ · 代理感知 Client IP · 自動封鎖
34
37
  · 加密稽核 · Admin /admin
35
38
  · gctoac start | stop | status | update
36
39
 
@@ -58,10 +61,10 @@ grok --version
58
61
  ```bash
59
62
  npm install -g grok-cli-to-openai-compatible
60
63
 
61
- gctoac doctor # 檢查 Node / Grok / 環境
62
- gctoac setup # 建立 ~/.gctoac、.env、資料庫、admin API key
64
+ gctoac doctor # 檢查 Node / Grok / 環境 / runner / 代理
65
+ gctoac setup # 資料目錄、.env(NODE_ENV=production)、資料庫、admin API key
63
66
  gctoac start # http://127.0.0.1:3847
64
- gctoac status
67
+ gctoac status # runner、port、proxy、health
65
68
  ```
66
69
 
67
70
  開啟 Admin(貼上 **admin API key**):
@@ -70,7 +73,7 @@ gctoac status
70
73
  http://127.0.0.1:3847/admin/
71
74
  ```
72
75
 
73
- 若遺失 setup 時的 key,可隨時建立新的:
76
+ 若遺失 setup 時的 key
74
77
 
75
78
  ```bash
76
79
  gctoac key create # 明文只顯示一次
@@ -96,14 +99,20 @@ curl -s http://127.0.0.1:3847/v1/chat/completions \
96
99
 
97
100
  ---
98
101
 
99
- ## 安裝方式
102
+ ## 安裝
100
103
 
101
- ### 全域安裝(建議)
104
+ **支援方式:** 只從 **npm registry** 安裝。
102
105
 
103
106
  ```bash
104
107
  npm install -g grok-cli-to-openai-compatible
105
108
  ```
106
109
 
110
+ 可選輔助腳本(等同上面指令):
111
+
112
+ ```bash
113
+ curl -fsSL https://raw.githubusercontent.com/yanshekki/Grok-Cli-to-OpenAI-compatible/main/scripts/install.sh | bash
114
+ ```
115
+
107
116
  ### 專案依賴
108
117
 
109
118
  ```bash
@@ -112,7 +121,9 @@ npx gctoac setup
112
121
  npx gctoac start --foreground
113
122
  ```
114
123
 
115
- ### 由原始碼安裝
124
+ ### 由原始碼開發(貢獻者)
125
+
126
+ `dist/` **不會** commit 到 git。clone 後請自行 build:
116
127
 
117
128
  ```bash
118
129
  git clone https://github.com/yanshekki/Grok-Cli-to-OpenAI-compatible.git
@@ -120,25 +131,18 @@ cd Grok-Cli-to-OpenAI-compatible
120
131
  npm install
121
132
  npm run build
122
133
  npm link # 可選:把 gctoac 掛到 PATH
123
- gctoac setup
124
- gctoac start
125
134
  ```
126
135
 
127
- 一鍵腳本(clone `~/.gctoac/src` `npm link`):
128
-
129
- ```bash
130
- curl -fsSL https://raw.githubusercontent.com/yanshekki/Grok-Cli-to-OpenAI-compatible/main/scripts/install.sh | bash
131
- ```
132
-
133
- > 請優先使用 **`npm install -g grok-cli-to-openai-compatible`**。
134
- > 不建議 `npm install -g github:yanshekki/...`(部分 npm 版本會失敗)。
136
+ > **不要** 使用 `npm install -g github:…`(不支援)。
135
137
 
136
138
  ### 更新
137
139
 
138
140
  ```bash
139
- gctoac update # 更新套件並重啟
140
- gctoac update --check # 只檢查是否有新版本
141
- gctoac update --no-restart # 更新但不重啟
141
+ npm install -g grok-cli-to-openai-compatible@latest
142
+ #
143
+ gctoac update # 自我更新並排程重啟
144
+ gctoac update --check # 只檢查
145
+ gctoac update --no-restart
142
146
  ```
143
147
 
144
148
  亦可在 Admin → **系統狀態** → 一鍵更新。
@@ -153,30 +157,45 @@ gctoac update --no-restart # 更新但不重啟
153
157
  | `http://127.0.0.1:3847/admin/` | Admin 控制台 |
154
158
  | `http://127.0.0.1:3847/health` | 健康檢查 |
155
159
 
156
- 覆蓋方式:`.env` `PORT=`,或:
160
+ 更改監聽連接埠(會寫入 `.env`;Admin 儲存時會重啟 runner):
157
161
 
158
162
  ```bash
159
- gctoac --port 3847 start
163
+ # CLI 寫入 PORT 到 .env 並啟動
164
+ gctoac --port 4000 start
165
+ gctoac --port 4000 start --pm2
166
+
167
+ # 或編輯 .env
168
+ PORT=4000
160
169
  ```
161
170
 
171
+ **Admin → PM2 → 監聽連接埠** — 預設 **3847**,儲存並重啟。改完請用**新 port** 開啟 Admin(例如 `http://127.0.0.1:4000/admin/`)。
172
+
162
173
  ---
163
174
 
164
175
  ## CLI(`gctoac` / `gcoa`)
165
176
 
177
+ 全域選項:`--home <path>`、`--port <n>`(預設 **3847**)。
178
+
166
179
  | 指令 | 說明 |
167
180
  |------|------|
168
- | `gctoac setup` | 建目錄、`.env`、migrate、seed admin key |
169
- | `gctoac start` | 背景啟動 gateway |
181
+ | `gctoac setup` | 建目錄、`.env`、migrate、seed admin key,盡量安裝 pm2 |
182
+ | `gctoac start` | 背景啟動 gateway(detached gctoac) |
170
183
  | `gctoac start -f` | 前景啟動 |
171
- | `gctoac stop` | 停止背景進程 |
172
- | `gctoac restart` | 重啟 |
173
- | `gctoac status` | 顯示 PID + health |
174
- | `gctoac migrate` | Prisma migration |
184
+ | `gctoac start --pm2` | PM2 啟動 |
185
+ | `gctoac stop` | 停止 gctoac + PM2 app + 清 port 佔用 |
186
+ | `gctoac restart` | 重啟;跟從 **preferred runner**(上次用 PM2 則用 PM2) |
187
+ | `gctoac restart --pm2` | 強制用 PM2 重啟 |
188
+ | `gctoac status` | Runner、NODE_ENV、port、trust proxy/IP 來源、health |
189
+ | `gctoac doctor` | 全面檢查(代理、雙 runner、port 衝突、log 大小) |
190
+ | `gctoac logs` / `logs show` | 查看 pm2 + gctoac 日誌 |
191
+ | `gctoac logs clear` | 清空日誌(與 Admin 清除一致) |
192
+ | `gctoac admin status` | Admin 面板開關狀態 |
193
+ | `gctoac admin on` / `off` | 開關 Admin(DB;**只能用 CLI `on` 重開**) |
194
+ | `gctoac migrate` | Prisma migrate deploy |
175
195
  | `gctoac seed` | 產生 admin API key(若未有) |
176
- | `gctoac key` / `gctoac key create` | **建立 API key**(明文只顯示一次) |
196
+ | `gctoac key` / `key create` | 建立 API key(明文只顯示一次) |
177
197
  | `gctoac key list` | 列出 keys(只有 prefix) |
178
198
  | `gctoac key revoke <id>` | 撤銷 key |
179
- | `gctoac doctor` | 檢查環境 |
180
199
  | `gctoac update` | 自我更新後重啟 |
181
200
  | `gctoac update --check` | 只檢查有無新版本 |
182
201
  | `gctoac update --no-restart` | 更新但不重啟 |
@@ -186,6 +205,8 @@ gctoac --port 3847 start
186
205
  ```bash
187
206
  gctoac --home ~/.gctoac-alt setup
188
207
  gctoac --port 3847 start
208
+ gctoac status
209
+ gctoac logs clear
189
210
  ```
190
211
 
191
212
  ---
@@ -196,12 +217,15 @@ gctoac --port 3847 start
196
217
  |------|------|
197
218
  | OpenAI API | `POST /v1/chat/completions`(stream / 非 stream)、`GET /v1/models` |
198
219
  | Thinking | `reasoning_content` + Grok `thought` + `grok.*` |
199
- | 文件 | 加密上傳;可用 `document_ids` 注入 chat |
220
+ | 文件 | 類型嗅探上傳、加密儲存(DB 或檔案系統)、下載 |
200
221
  | Safe / Agent | 每 key 政策;可全域強制 safe |
201
222
  | 加密 | AES-256-GCM 加密 prompt、response、檔案 |
202
- | Admin Panel | 儀表板、完整解密 chat、keys、文件、audit、設定、一鍵更新 |
203
- | CLI | 生命週期控制 + 自我更新 |
204
- | 運維 | SQLite、PM2、GitHub Actions CI |
223
+ | 對話歷史 | 多輪對話、上下文模式(full / summary / recent) |
224
+ | Admin Panel | 儀表板、對話、金鑰、文件、稽核、用量、DDoS、PM2、系統 |
225
+ | DDoS 中心 | 即時連線、黑名單、自動封鎖、可配置策略與預設檔 |
226
+ | 反向代理 | 信任層數 + CF / nginx / X-Forwarded-For 真實 IP |
227
+ | CLI | 生命週期、preferred runner、日誌、自我更新 |
228
+ | 運維 | SQLite、PM2、日誌自動裁剪(>5 MB)、GitHub Actions CI |
205
229
 
206
230
  ---
207
231
 
@@ -284,6 +308,7 @@ console.log(res.choices[0].message.content);
284
308
  | POST | `/v1/documents` | 上傳(欄位 `file`) |
285
309
  | GET/DELETE | `/v1/documents`… | 列表 / 軟刪除 |
286
310
  | POST/GET/DELETE | `/v1/api-keys`… | Admin 管理 key |
311
+ | * | `/admin/api/*` | Admin JSON API(需 `role=admin`) |
287
312
 
288
313
  ---
289
314
 
@@ -294,7 +319,7 @@ console.log(res.choices[0].message.content);
294
319
  | **`safe`**(client 預設) | 對外應用 | Sandbox cwd、不 always-approve、限制 tools、較短 timeout |
295
320
  | **`agent`** | 受信 / 內網 | 完整 CLI tools(可 always-approve);cwd 仍受 allowlist 限制 |
296
321
 
297
- - 全域強制 safe:`GROK_SAFE_MODE=true` 或 Admin → 安全設定
322
+ - 全域強制 safe:`GROK_SAFE_MODE=true` 或 Admin → **安全設定**
298
323
  - Client **無法** 靠 request body 提權
299
324
  - **不要** 將 `agent` key 暴露於公網
300
325
 
@@ -308,25 +333,67 @@ http://127.0.0.1:3847/admin/
308
333
 
309
334
  | 頁面 | 功能 |
310
335
  |------|------|
311
- | 儀表板 | 統計、最近 chat、併發 |
312
- | Chat 記錄 | **完整解密** prompt / reasoning / response |
313
- | API Keys | 建立、改 mode/role/限流、撤銷 |
314
- | 文件 | 列表、解密預覽、刪除 |
315
- | Audit Logs | 操作紀錄 |
316
- | 安全設定 | 全域 safe、tools、timeout |
317
- | 系統狀態 | 健康、版本、**一鍵更新並重啟** |
336
+ | **儀表板** | 24h KPI、成功率、防護摘要、模型用量、運行狀態(port/加密) |
337
+ | **對話** | 多輪 playground、歷史、上下文模式、附件 |
338
+ | **對話記錄** | 搜尋/篩選/分頁;**完整解密** prompt/reasoning/response |
339
+ | **API 金鑰** | 建立/編輯 mode/role/限流/IP 白名單;撤銷 |
340
+ | **文件** | 搜尋/篩選/分頁;預覽、下載、刪除;DB 與檔案系統儲存 |
341
+ | **稽核日誌** | 搜尋/篩選/分頁;可讀動作標籤 |
342
+ | **用量與防護** | 24h 統計、按模型/按金鑰分 tab、限流摘要 |
343
+ | **DDoS 中心** | 即時連線、黑名單、自動封鎖事件、**可配置防護策略**(寬鬆/均衡/嚴格/自訂)、反向代理 IP |
344
+ | **安全設定** | 全域 safe、tools、timeout |
345
+ | **PM2** | Runner 切換(gctoac ↔ PM2)、**監聽連接埠**(預設 3847)、設定、**清除日誌** + 自動裁剪 |
346
+ | **系統狀態** | 健康、軟體檢查、一鍵更新並重啟 |
318
347
 
319
348
  Admin API 前綴:`/admin/api/*`(需要 `role=admin`)。
320
349
 
350
+ ### DDoS/防濫用(運行時)
351
+
352
+ 策略存於資料庫(Admin → DDoS)。環境變數只是**初始預設**;儲存後以 Admin 為準。可用「重設為環境預設」還原。
353
+
354
+ | 能力 | 說明 |
355
+ |------|------|
356
+ | 限流 | 視窗、每 key 上限、每 IP 上限、chat burst |
357
+ | 自動封鎖 | 失敗認證、重複 429、並發洪水、請求速率、累犯升級 |
358
+ | 預設檔 | 寬鬆/均衡/嚴格/自訂(自動判定) |
359
+ | 白名單 | 永不被自動封鎖(例如 `127.0.0.1`) |
360
+ | 手動封鎖 | TTL 或永久 |
361
+
362
+ ### 反向代理/CDN(客戶端 IP)
363
+
364
+ 經 **nginx** 或 **Cloudflare** 時,請設定信任層數,令封鎖、限流、稽核使用**真實用戶 IP**:
365
+
366
+ | 設定 | 常見值 |
367
+ |------|--------|
368
+ | 信任代理層數 | `1` = nginx 或 CF→應用;`2` = CF→nginx→應用;`0` = 僅直連 |
369
+ | IP 來源 | `auto`(建議)、`cloudflare`、`nginx`、`x-forwarded-for`、`socket` |
370
+
371
+ 在 **Admin → DDoS → 反向代理** 設定,或 env:
372
+
373
+ ```env
374
+ TRUST_PROXY=1
375
+ PROXY_IP_SOURCE=auto
376
+ ```
377
+
378
+ nginx 示例:
379
+
380
+ ```nginx
381
+ proxy_set_header Host $host;
382
+ proxy_set_header X-Real-IP $remote_addr;
383
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
384
+ proxy_set_header X-Forwarded-Proto $scheme;
385
+ ```
386
+
321
387
  ---
322
388
 
323
389
  ## 環境變數
324
390
 
325
- 詳見 [`.env.example`](./.env.example)
391
+ 詳見 [`.env.example`](./.env.example)。`gctoac setup` 新建時預設 **`NODE_ENV=production`**。
326
392
 
327
393
  | 變數 | 說明 |
328
394
  |------|------|
329
- | `PORT` | 預設 **`3847`** |
395
+ | `NODE_ENV` | 預設 **`production`**。本機開發才設 `development`(美化日誌) |
396
+ | `PORT` | 預設 **`3847`**(亦可在 Admin → PM2 修改) |
330
397
  | `DATABASE_URL` | SQLite,例如 `file:../data/gateway.db`(相對 `prisma/`) |
331
398
  | `ENCRYPTION_KEY` | 32-byte key:`openssl rand -base64 32` |
332
399
  | `GROK_BIN` | 預設 `grok` |
@@ -335,16 +402,35 @@ Admin API 前綴:`/admin/api/*`(需要 `role=admin`)。
335
402
  | `GROK_ALWAYS_APPROVE` | 只對 agent;safe 一律關閉 |
336
403
  | `GROK_SAFE_MODE` | 強制全部 key 用 safe |
337
404
  | `GROK_MAX_CONCURRENT` | 最多並行 Grok 進程 |
338
- | `ADMIN_PANEL_ENABLED` | 開關 `/admin` |
339
- | `CORS_ORIGINS` | 逗號分隔 origins |
405
+ | `ADMIN_PANEL_ENABLED` | 硬關 `/admin`(env,需重啟)。運行時:`gctoac admin on\|off` |
406
+ | `PM2_ADMIN_ENABLED` | 允許 Admin 控制 PM2 |
407
+ | `CORS_ORIGINS` | 逗號分隔 origins(改 `PORT` 時請一併更新) |
408
+ | `RATE_LIMIT_*` / `CHAT_BURST_MAX` / `BLOCK_*` | 限流/自動認證初始值(DDoS 策略儲存後會覆寫) |
409
+ | `TRUST_PROXY` | 代理層數:`0`/`1`/`2`…(`true`→1,`false`→0) |
410
+ | `PROXY_IP_SOURCE` | `auto` \| `cloudflare` \| `nginx` \| `x-forwarded-for` \| `socket` |
340
411
  | `GCTOAC_HOME` | CLI 資料目錄(預設 `~/.gctoac`) |
341
- | `STORAGE_DIR` | 加密檔案 + sandbox |
412
+ | `STORAGE_DIR` | 加密大檔 + sandbox |
413
+ | `UPLOAD_MAX_BYTES` / `DOCUMENT_DB_MAX_BYTES` | 上傳上限/DB 與檔案系統分界 |
342
414
 
343
415
  **請備份 `ENCRYPTION_KEY`。** 遺失後歷史資料無法解密。
344
416
 
345
417
  ---
346
418
 
347
- ## 生產環境(PM2)
419
+ ## 生產環境
420
+
421
+ ### 建議:CLI
422
+
423
+ ```bash
424
+ gctoac setup
425
+ gctoac start # detached gctoac
426
+ # 或
427
+ gctoac start --pm2 # 使用 PM2
428
+ gctoac status
429
+ ```
430
+
431
+ `gctoac restart` 會跟從上次的 **preferred runner**(gctoac 或 PM2)。
432
+
433
+ ### PM2 ecosystem
348
434
 
349
435
  ```bash
350
436
  npm run build
@@ -352,7 +438,21 @@ pm2 start ecosystem.config.cjs
352
438
  pm2 logs grok-openai-gateway
353
439
  ```
354
440
 
355
- 或直接:`gctoac start`(背景執行,pid 寫入資料目錄)。
441
+ ### 日誌
442
+
443
+ - 檔案位於 `logs/`(或資料目錄):`pm2-error.log`、`pm2-out.log`、`gctoac.*.log`
444
+ - **Admin → PM2 → 清除日誌**,或 `gctoac logs clear`
445
+ - **自動裁剪:** 每次讀取日誌時,單檔 **> 5 MB** 只保留最後約 512 KB
446
+
447
+ ### 避免 EADDRINUSE
448
+
449
+ 同一 port 只應有一個 runner。若 gctoac 與 PM2 搶 port:
450
+
451
+ ```bash
452
+ gctoac stop
453
+ gctoac start # 或:gctoac start --pm2
454
+ gctoac doctor # 會標示 mixed runners
455
+ ```
356
456
 
357
457
  ---
358
458
 
@@ -362,7 +462,7 @@ pm2 logs grok-openai-gateway
362
462
  src/ TypeScript 原始碼(app、routes、services、cli)
363
463
  public/admin/ Admin SPA
364
464
  prisma/ Schema、migrations、seed
365
- dist/ 編譯後 JS(隨 npm 發佈)
465
+ dist/ 編譯後 JS(gitignore;npm run build / prepublishOnly 產生)
366
466
  scripts/ prepare、install.sh
367
467
  tests/ Vitest
368
468
  ```
@@ -373,18 +473,19 @@ tests/ Vitest
373
473
 
374
474
  ```bash
375
475
  npm run dev # 開發
376
- npm run build # 編譯 + prisma generate
476
+ npm run build # prisma generate + tsc
377
477
  npm start # node dist/server.js
378
478
  npm test # 單元 + 整合測試
379
479
  npm run db:setup # migrate + seed
380
- gctoac setup|start|status|stop|doctor|update
480
+ gctoac setup|start|status|stop|doctor|logs|update
381
481
  ```
382
482
 
383
483
  ### 發佈到 npm(維護者)
384
484
 
485
+ `prepublishOnly` 會跑 `npm run build`,tarball 一定包含 `dist/`。
486
+
385
487
  ```bash
386
488
  npm login
387
- npm run build
388
489
  npm publish --access public --otp=<2FA六位碼>
389
490
  ```
390
491
 
@@ -395,7 +496,29 @@ npm publish --access public --otp=<2FA六位碼>
395
496
  - API key 只存 **SHA-256 hash**
396
497
  - Chat prompt/response 與文件以 **AES-256-GCM** 靜態加密
397
498
  - 對外 client 請用 **`safe`** mode
499
+ - **客戶端 IP:** 只有 **可信代理列表** 內的 TCP peer(預設 `127.0.0.1`)先會採信 `CF-Connecting-IP`/`X-Real-IP`/`XFF`。直連客戶**無法偽造 header** 繞過限流或 ban 他人。遠端 nginx 請把其 IP 加進 Admin → DDoS → 可信代理。
500
+ - Admin 只應開喺本機/VPN;admin key 存 `sessionStorage`(XSS = 完全接管)
398
501
  - 不要 commit `.env`,不要外洩 admin key
502
+ - 可完全關閉 Admin:`gctoac admin off`(只能用 `gctoac admin on` 重開)
503
+ - 一鍵更新/PM2/改 port 需 admin(視 admin key 為 root)
504
+
505
+ ---
506
+
507
+ ## 👤 作者
508
+
509
+ **Ki (yanshekki)** — 全端工程師、量化交易者,[YSK Limited](https://ysk.hk/) 創辦人。
510
+
511
+ 🌐 [linktr.ee/yanshekki](https://linktr.ee/yanshekki) · 🏢 [ysk.hk](https://ysk.hk/)
512
+
513
+ ### ☕ 支持 / 打賞
514
+
515
+ 如果呢個 Grok → OpenAI Gateway 對你有幫助,歡迎請我飲杯咖啡!
516
+
517
+ | 網路 | 地址 |
518
+ | --- | --- |
519
+ | **EVM** (ETH/BSC/AVAX) | `yanshekki.eth` |
520
+ | **NEAR** | `yanshekki.near` |
521
+ | **ADA** (Cardano) | `$yanshekki` |
399
522
 
400
523
  ---
401
524