grok-cli-to-openai-compatible 1.2.5 → 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 (231) hide show
  1. package/.env.example +25 -3
  2. package/README-ZH.md +189 -56
  3. package/README.md +195 -62
  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/key.d.ts +18 -0
  16. package/dist/cli/commands/key.d.ts.map +1 -0
  17. package/dist/cli/commands/key.js +81 -0
  18. package/dist/cli/commands/key.js.map +1 -0
  19. package/dist/cli/commands/logs.d.ts +10 -0
  20. package/dist/cli/commands/logs.d.ts.map +1 -0
  21. package/dist/cli/commands/logs.js +83 -0
  22. package/dist/cli/commands/logs.js.map +1 -0
  23. package/dist/cli/commands/open.d.ts +1 -0
  24. package/dist/cli/commands/open.d.ts.map +1 -1
  25. package/dist/cli/commands/open.js +1 -1
  26. package/dist/cli/commands/open.js.map +1 -1
  27. package/dist/cli/commands/restart.d.ts +1 -0
  28. package/dist/cli/commands/restart.d.ts.map +1 -1
  29. package/dist/cli/commands/restart.js +17 -1
  30. package/dist/cli/commands/restart.js.map +1 -1
  31. package/dist/cli/commands/setup.d.ts.map +1 -1
  32. package/dist/cli/commands/setup.js +12 -0
  33. package/dist/cli/commands/setup.js.map +1 -1
  34. package/dist/cli/commands/start.d.ts +2 -0
  35. package/dist/cli/commands/start.d.ts.map +1 -1
  36. package/dist/cli/commands/start.js +50 -8
  37. package/dist/cli/commands/start.js.map +1 -1
  38. package/dist/cli/commands/status.d.ts +1 -0
  39. package/dist/cli/commands/status.d.ts.map +1 -1
  40. package/dist/cli/commands/status.js +44 -16
  41. package/dist/cli/commands/status.js.map +1 -1
  42. package/dist/cli/commands/stop.d.ts +1 -0
  43. package/dist/cli/commands/stop.d.ts.map +1 -1
  44. package/dist/cli/commands/stop.js +30 -5
  45. package/dist/cli/commands/stop.js.map +1 -1
  46. package/dist/cli/commands/update.d.ts +1 -0
  47. package/dist/cli/commands/update.d.ts.map +1 -1
  48. package/dist/cli/commands/update.js +156 -33
  49. package/dist/cli/commands/update.js.map +1 -1
  50. package/dist/cli/index.js +112 -6
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/cli/lib/db-keys.d.ts +33 -0
  53. package/dist/cli/lib/db-keys.d.ts.map +1 -0
  54. package/dist/cli/lib/db-keys.js +103 -0
  55. package/dist/cli/lib/db-keys.js.map +1 -0
  56. package/dist/cli/lib/env-file.d.ts +7 -0
  57. package/dist/cli/lib/env-file.d.ts.map +1 -1
  58. package/dist/cli/lib/env-file.js +62 -17
  59. package/dist/cli/lib/env-file.js.map +1 -1
  60. package/dist/cli/lib/pm2-runner.d.ts +14 -0
  61. package/dist/cli/lib/pm2-runner.d.ts.map +1 -0
  62. package/dist/cli/lib/pm2-runner.js +179 -0
  63. package/dist/cli/lib/pm2-runner.js.map +1 -0
  64. package/dist/cli/lib/process-mgr.d.ts +15 -0
  65. package/dist/cli/lib/process-mgr.d.ts.map +1 -1
  66. package/dist/cli/lib/process-mgr.js +122 -20
  67. package/dist/cli/lib/process-mgr.js.map +1 -1
  68. package/dist/cli/lib/runner-info.d.ts +20 -0
  69. package/dist/cli/lib/runner-info.d.ts.map +1 -0
  70. package/dist/cli/lib/runner-info.js +120 -0
  71. package/dist/cli/lib/runner-info.js.map +1 -0
  72. package/dist/cli/lib/seed-admin.d.ts.map +1 -1
  73. package/dist/cli/lib/seed-admin.js +2 -1
  74. package/dist/cli/lib/seed-admin.js.map +1 -1
  75. package/dist/cli/lib/spinner.d.ts +20 -0
  76. package/dist/cli/lib/spinner.d.ts.map +1 -0
  77. package/dist/cli/lib/spinner.js +72 -0
  78. package/dist/cli/lib/spinner.js.map +1 -0
  79. package/dist/config/constants.d.ts +31 -0
  80. package/dist/config/constants.d.ts.map +1 -1
  81. package/dist/config/constants.js +103 -2
  82. package/dist/config/constants.js.map +1 -1
  83. package/dist/config/cors.js +1 -1
  84. package/dist/config/cors.js.map +1 -1
  85. package/dist/config/env.d.ts +11 -1
  86. package/dist/config/env.d.ts.map +1 -1
  87. package/dist/config/env.js +43 -3
  88. package/dist/config/env.js.map +1 -1
  89. package/dist/controllers/admin.controller.d.ts +35 -0
  90. package/dist/controllers/admin.controller.d.ts.map +1 -1
  91. package/dist/controllers/admin.controller.js +599 -18
  92. package/dist/controllers/admin.controller.js.map +1 -1
  93. package/dist/controllers/api-key.controller.d.ts.map +1 -1
  94. package/dist/controllers/api-key.controller.js +4 -3
  95. package/dist/controllers/api-key.controller.js.map +1 -1
  96. package/dist/controllers/chat.controller.d.ts.map +1 -1
  97. package/dist/controllers/chat.controller.js +2 -1
  98. package/dist/controllers/chat.controller.js.map +1 -1
  99. package/dist/controllers/document.controller.d.ts.map +1 -1
  100. package/dist/controllers/document.controller.js +3 -2
  101. package/dist/controllers/document.controller.js.map +1 -1
  102. package/dist/dto/admin.dto.d.ts +36 -1
  103. package/dist/dto/admin.dto.d.ts.map +1 -1
  104. package/dist/dto/admin.dto.js +23 -1
  105. package/dist/dto/admin.dto.js.map +1 -1
  106. package/dist/dto/chat.dto.d.ts +73 -0
  107. package/dist/dto/chat.dto.d.ts.map +1 -1
  108. package/dist/dto/chat.dto.js +5 -1
  109. package/dist/dto/chat.dto.js.map +1 -1
  110. package/dist/dto/conversation.dto.d.ts +286 -0
  111. package/dist/dto/conversation.dto.d.ts.map +1 -0
  112. package/dist/dto/conversation.dto.js +62 -0
  113. package/dist/dto/conversation.dto.js.map +1 -0
  114. package/dist/dto/ddos.dto.d.ts +191 -0
  115. package/dist/dto/ddos.dto.d.ts.map +1 -0
  116. package/dist/dto/ddos.dto.js +57 -0
  117. package/dist/dto/ddos.dto.js.map +1 -0
  118. package/dist/entities/api-key.entity.d.ts +2 -0
  119. package/dist/entities/api-key.entity.d.ts.map +1 -1
  120. package/dist/interfaces/auth.interface.d.ts +1 -0
  121. package/dist/interfaces/auth.interface.d.ts.map +1 -1
  122. package/dist/interfaces/express.interface.d.ts +2 -0
  123. package/dist/interfaces/express.interface.d.ts.map +1 -1
  124. package/dist/middlewares/auth.middleware.d.ts.map +1 -1
  125. package/dist/middlewares/auth.middleware.js +30 -3
  126. package/dist/middlewares/auth.middleware.js.map +1 -1
  127. package/dist/middlewares/client-ip.middleware.d.ts +11 -0
  128. package/dist/middlewares/client-ip.middleware.d.ts.map +1 -0
  129. package/dist/middlewares/client-ip.middleware.js +19 -0
  130. package/dist/middlewares/client-ip.middleware.js.map +1 -0
  131. package/dist/middlewares/connection-tracker.d.ts +47 -0
  132. package/dist/middlewares/connection-tracker.d.ts.map +1 -0
  133. package/dist/middlewares/connection-tracker.js +99 -0
  134. package/dist/middlewares/connection-tracker.js.map +1 -0
  135. package/dist/middlewares/rate-limit.middleware.d.ts +9 -2
  136. package/dist/middlewares/rate-limit.middleware.d.ts.map +1 -1
  137. package/dist/middlewares/rate-limit.middleware.js +116 -32
  138. package/dist/middlewares/rate-limit.middleware.js.map +1 -1
  139. package/dist/routes/admin.routes.d.ts.map +1 -1
  140. package/dist/routes/admin.routes.js +38 -0
  141. package/dist/routes/admin.routes.js.map +1 -1
  142. package/dist/routes/v1/chat.routes.d.ts.map +1 -1
  143. package/dist/routes/v1/chat.routes.js +1 -1
  144. package/dist/routes/v1/chat.routes.js.map +1 -1
  145. package/dist/server.js +53 -0
  146. package/dist/server.js.map +1 -1
  147. package/dist/services/abuse-guard.service.d.ts +27 -0
  148. package/dist/services/abuse-guard.service.d.ts.map +1 -0
  149. package/dist/services/abuse-guard.service.js +243 -0
  150. package/dist/services/abuse-guard.service.js.map +1 -0
  151. package/dist/services/api-key.service.d.ts +18 -1
  152. package/dist/services/api-key.service.d.ts.map +1 -1
  153. package/dist/services/api-key.service.js +79 -11
  154. package/dist/services/api-key.service.js.map +1 -1
  155. package/dist/services/chat-admin.service.d.ts +11 -0
  156. package/dist/services/chat-admin.service.d.ts.map +1 -1
  157. package/dist/services/chat-admin.service.js +61 -9
  158. package/dist/services/chat-admin.service.js.map +1 -1
  159. package/dist/services/conversation.service.d.ts +104 -0
  160. package/dist/services/conversation.service.d.ts.map +1 -0
  161. package/dist/services/conversation.service.js +232 -0
  162. package/dist/services/conversation.service.js.map +1 -0
  163. package/dist/services/ddos-policy.service.d.ts +40 -0
  164. package/dist/services/ddos-policy.service.d.ts.map +1 -0
  165. package/dist/services/ddos-policy.service.js +257 -0
  166. package/dist/services/ddos-policy.service.js.map +1 -0
  167. package/dist/services/document.service.d.ts.map +1 -1
  168. package/dist/services/document.service.js +21 -11
  169. package/dist/services/document.service.js.map +1 -1
  170. package/dist/services/ip-blacklist.service.d.ts +40 -0
  171. package/dist/services/ip-blacklist.service.d.ts.map +1 -0
  172. package/dist/services/ip-blacklist.service.js +126 -0
  173. package/dist/services/ip-blacklist.service.js.map +1 -0
  174. package/dist/services/models.service.d.ts +8 -1
  175. package/dist/services/models.service.d.ts.map +1 -1
  176. package/dist/services/models.service.js +18 -3
  177. package/dist/services/models.service.js.map +1 -1
  178. package/dist/services/pm2-config.d.ts +34 -0
  179. package/dist/services/pm2-config.d.ts.map +1 -0
  180. package/dist/services/pm2-config.js +156 -0
  181. package/dist/services/pm2-config.js.map +1 -0
  182. package/dist/services/pm2.service.d.ts +197 -0
  183. package/dist/services/pm2.service.d.ts.map +1 -0
  184. package/dist/services/pm2.service.js +776 -0
  185. package/dist/services/pm2.service.js.map +1 -0
  186. package/dist/services/stats.service.d.ts +36 -0
  187. package/dist/services/stats.service.d.ts.map +1 -1
  188. package/dist/services/stats.service.js +67 -2
  189. package/dist/services/stats.service.js.map +1 -1
  190. package/dist/services/system-health.service.d.ts +30 -0
  191. package/dist/services/system-health.service.d.ts.map +1 -0
  192. package/dist/services/system-health.service.js +234 -0
  193. package/dist/services/system-health.service.js.map +1 -0
  194. package/dist/services/update.service.d.ts +32 -0
  195. package/dist/services/update.service.d.ts.map +1 -1
  196. package/dist/services/update.service.js +176 -41
  197. package/dist/services/update.service.js.map +1 -1
  198. package/dist/services/usage.service.d.ts +43 -0
  199. package/dist/services/usage.service.d.ts.map +1 -0
  200. package/dist/services/usage.service.js +163 -0
  201. package/dist/services/usage.service.js.map +1 -0
  202. package/dist/utils/client-ip.d.ts +41 -0
  203. package/dist/utils/client-ip.d.ts.map +1 -0
  204. package/dist/utils/client-ip.js +172 -0
  205. package/dist/utils/client-ip.js.map +1 -0
  206. package/dist/utils/file-sniff.d.ts +16 -0
  207. package/dist/utils/file-sniff.d.ts.map +1 -0
  208. package/dist/utils/file-sniff.js +151 -0
  209. package/dist/utils/file-sniff.js.map +1 -0
  210. package/dist/utils/ip-match.d.ts +15 -0
  211. package/dist/utils/ip-match.d.ts.map +1 -0
  212. package/dist/utils/ip-match.js +133 -0
  213. package/dist/utils/ip-match.js.map +1 -0
  214. package/dist/utils/stream.d.ts.map +1 -1
  215. package/dist/utils/stream.js +40 -1
  216. package/dist/utils/stream.js.map +1 -1
  217. package/package.json +1 -1
  218. package/prisma/migrations/20260714120000_ip_whitelist_blacklist/migration.sql +19 -0
  219. package/prisma/migrations/20260714220000_chat_conversations/migration.sql +22 -0
  220. package/prisma/migrations/20260714230000_conversation_context/migration.sql +6 -0
  221. package/prisma/schema.prisma +52 -3
  222. package/public/admin/app.js +5696 -375
  223. package/public/admin/assets/logo.svg +37 -0
  224. package/public/admin/disabled.html +131 -0
  225. package/public/admin/i18n.js +1567 -0
  226. package/public/admin/index.html +19 -3
  227. package/public/admin/styles.css +3507 -190
  228. package/public/admin/vendor/marked.min.js +6 -0
  229. package/public/admin/vendor/purify.min.js +3 -0
  230. package/scripts/install.sh +8 -27
  231. 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,18 +61,25 @@ 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
- 開啟 Admin(貼上 `setup` 印出的 **admin API key**,只顯示一次):
70
+ 開啟 Admin(貼上 **admin API key**):
68
71
 
69
72
  ```text
70
73
  http://127.0.0.1:3847/admin/
71
74
  ```
72
75
 
76
+ 若遺失 setup 時的 key:
77
+
78
+ ```bash
79
+ gctoac key create # 明文只顯示一次
80
+ gctoac key list # 只顯示 prefix(明文不會存庫)
81
+ ```
82
+
73
83
  **資料目錄:** `~/.gctoac/`
74
84
  可用 `GCTOAC_HOME` 或 `gctoac --home /path` 覆蓋。
75
85
 
@@ -89,14 +99,20 @@ curl -s http://127.0.0.1:3847/v1/chat/completions \
89
99
 
90
100
  ---
91
101
 
92
- ## 安裝方式
102
+ ## 安裝
93
103
 
94
- ### 全域安裝(建議)
104
+ **支援方式:** 只從 **npm registry** 安裝。
95
105
 
96
106
  ```bash
97
107
  npm install -g grok-cli-to-openai-compatible
98
108
  ```
99
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
+
100
116
  ### 專案依賴
101
117
 
102
118
  ```bash
@@ -105,7 +121,9 @@ npx gctoac setup
105
121
  npx gctoac start --foreground
106
122
  ```
107
123
 
108
- ### 由原始碼安裝
124
+ ### 由原始碼開發(貢獻者)
125
+
126
+ `dist/` **不會** commit 到 git。clone 後請自行 build:
109
127
 
110
128
  ```bash
111
129
  git clone https://github.com/yanshekki/Grok-Cli-to-OpenAI-compatible.git
@@ -113,25 +131,18 @@ cd Grok-Cli-to-OpenAI-compatible
113
131
  npm install
114
132
  npm run build
115
133
  npm link # 可選:把 gctoac 掛到 PATH
116
- gctoac setup
117
- gctoac start
118
- ```
119
-
120
- 一鍵腳本(clone 到 `~/.gctoac/src` 再 `npm link`):
121
-
122
- ```bash
123
- curl -fsSL https://raw.githubusercontent.com/yanshekki/Grok-Cli-to-OpenAI-compatible/main/scripts/install.sh | bash
124
134
  ```
125
135
 
126
- > 請優先使用 **`npm install -g grok-cli-to-openai-compatible`**。
127
- > 不建議 `npm install -g github:yanshekki/...`(部分 npm 版本會失敗)。
136
+ > **不要** 使用 `npm install -g github:…`(不支援)。
128
137
 
129
138
  ### 更新
130
139
 
131
140
  ```bash
132
- gctoac update # 更新套件並重啟
133
- gctoac update --check # 只檢查是否有新版本
134
- 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
135
146
  ```
136
147
 
137
148
  亦可在 Admin → **系統狀態** → 一鍵更新。
@@ -146,27 +157,45 @@ gctoac update --no-restart # 更新但不重啟
146
157
  | `http://127.0.0.1:3847/admin/` | Admin 控制台 |
147
158
  | `http://127.0.0.1:3847/health` | 健康檢查 |
148
159
 
149
- 覆蓋方式:`.env` `PORT=`,或:
160
+ 更改監聽連接埠(會寫入 `.env`;Admin 儲存時會重啟 runner):
150
161
 
151
162
  ```bash
152
- 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
153
169
  ```
154
170
 
171
+ **Admin → PM2 → 監聽連接埠** — 預設 **3847**,儲存並重啟。改完請用**新 port** 開啟 Admin(例如 `http://127.0.0.1:4000/admin/`)。
172
+
155
173
  ---
156
174
 
157
175
  ## CLI(`gctoac` / `gcoa`)
158
176
 
177
+ 全域選項:`--home <path>`、`--port <n>`(預設 **3847**)。
178
+
159
179
  | 指令 | 說明 |
160
180
  |------|------|
161
- | `gctoac setup` | 建目錄、`.env`、migrate、seed admin key |
162
- | `gctoac start` | 背景啟動 gateway |
181
+ | `gctoac setup` | 建目錄、`.env`、migrate、seed admin key,盡量安裝 pm2 |
182
+ | `gctoac start` | 背景啟動 gateway(detached gctoac) |
163
183
  | `gctoac start -f` | 前景啟動 |
164
- | `gctoac stop` | 停止背景進程 |
165
- | `gctoac restart` | 重啟 |
166
- | `gctoac status` | 顯示 PID + health |
167
- | `gctoac migrate` | Prisma migration |
168
- | `gctoac seed` | 產生 admin API key |
169
- | `gctoac doctor` | 檢查環境 |
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 |
195
+ | `gctoac seed` | 產生 admin API key(若未有) |
196
+ | `gctoac key` / `key create` | 建立 API key(明文只顯示一次) |
197
+ | `gctoac key list` | 列出 keys(只有 prefix) |
198
+ | `gctoac key revoke <id>` | 撤銷 key |
170
199
  | `gctoac update` | 自我更新後重啟 |
171
200
  | `gctoac update --check` | 只檢查有無新版本 |
172
201
  | `gctoac update --no-restart` | 更新但不重啟 |
@@ -176,6 +205,8 @@ gctoac --port 3847 start
176
205
  ```bash
177
206
  gctoac --home ~/.gctoac-alt setup
178
207
  gctoac --port 3847 start
208
+ gctoac status
209
+ gctoac logs clear
179
210
  ```
180
211
 
181
212
  ---
@@ -186,12 +217,15 @@ gctoac --port 3847 start
186
217
  |------|------|
187
218
  | OpenAI API | `POST /v1/chat/completions`(stream / 非 stream)、`GET /v1/models` |
188
219
  | Thinking | `reasoning_content` + Grok `thought` + `grok.*` |
189
- | 文件 | 加密上傳;可用 `document_ids` 注入 chat |
220
+ | 文件 | 類型嗅探上傳、加密儲存(DB 或檔案系統)、下載 |
190
221
  | Safe / Agent | 每 key 政策;可全域強制 safe |
191
222
  | 加密 | AES-256-GCM 加密 prompt、response、檔案 |
192
- | Admin Panel | 儀表板、完整解密 chat、keys、文件、audit、設定、一鍵更新 |
193
- | CLI | 生命週期控制 + 自我更新 |
194
- | 運維 | 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 |
195
229
 
196
230
  ---
197
231
 
@@ -274,6 +308,7 @@ console.log(res.choices[0].message.content);
274
308
  | POST | `/v1/documents` | 上傳(欄位 `file`) |
275
309
  | GET/DELETE | `/v1/documents`… | 列表 / 軟刪除 |
276
310
  | POST/GET/DELETE | `/v1/api-keys`… | Admin 管理 key |
311
+ | * | `/admin/api/*` | Admin JSON API(需 `role=admin`) |
277
312
 
278
313
  ---
279
314
 
@@ -284,7 +319,7 @@ console.log(res.choices[0].message.content);
284
319
  | **`safe`**(client 預設) | 對外應用 | Sandbox cwd、不 always-approve、限制 tools、較短 timeout |
285
320
  | **`agent`** | 受信 / 內網 | 完整 CLI tools(可 always-approve);cwd 仍受 allowlist 限制 |
286
321
 
287
- - 全域強制 safe:`GROK_SAFE_MODE=true` 或 Admin → 安全設定
322
+ - 全域強制 safe:`GROK_SAFE_MODE=true` 或 Admin → **安全設定**
288
323
  - Client **無法** 靠 request body 提權
289
324
  - **不要** 將 `agent` key 暴露於公網
290
325
 
@@ -298,25 +333,67 @@ http://127.0.0.1:3847/admin/
298
333
 
299
334
  | 頁面 | 功能 |
300
335
  |------|------|
301
- | 儀表板 | 統計、最近 chat、併發 |
302
- | Chat 記錄 | **完整解密** prompt / reasoning / response |
303
- | API Keys | 建立、改 mode/role/限流、撤銷 |
304
- | 文件 | 列表、解密預覽、刪除 |
305
- | Audit Logs | 操作紀錄 |
306
- | 安全設定 | 全域 safe、tools、timeout |
307
- | 系統狀態 | 健康、版本、**一鍵更新並重啟** |
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
+ | **系統狀態** | 健康、軟體檢查、一鍵更新並重啟 |
308
347
 
309
348
  Admin API 前綴:`/admin/api/*`(需要 `role=admin`)。
310
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
+
311
387
  ---
312
388
 
313
389
  ## 環境變數
314
390
 
315
- 詳見 [`.env.example`](./.env.example)
391
+ 詳見 [`.env.example`](./.env.example)。`gctoac setup` 新建時預設 **`NODE_ENV=production`**。
316
392
 
317
393
  | 變數 | 說明 |
318
394
  |------|------|
319
- | `PORT` | 預設 **`3847`** |
395
+ | `NODE_ENV` | 預設 **`production`**。本機開發才設 `development`(美化日誌) |
396
+ | `PORT` | 預設 **`3847`**(亦可在 Admin → PM2 修改) |
320
397
  | `DATABASE_URL` | SQLite,例如 `file:../data/gateway.db`(相對 `prisma/`) |
321
398
  | `ENCRYPTION_KEY` | 32-byte key:`openssl rand -base64 32` |
322
399
  | `GROK_BIN` | 預設 `grok` |
@@ -325,16 +402,35 @@ Admin API 前綴:`/admin/api/*`(需要 `role=admin`)。
325
402
  | `GROK_ALWAYS_APPROVE` | 只對 agent;safe 一律關閉 |
326
403
  | `GROK_SAFE_MODE` | 強制全部 key 用 safe |
327
404
  | `GROK_MAX_CONCURRENT` | 最多並行 Grok 進程 |
328
- | `ADMIN_PANEL_ENABLED` | 開關 `/admin` |
329
- | `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` |
330
411
  | `GCTOAC_HOME` | CLI 資料目錄(預設 `~/.gctoac`) |
331
- | `STORAGE_DIR` | 加密檔案 + sandbox |
412
+ | `STORAGE_DIR` | 加密大檔 + sandbox |
413
+ | `UPLOAD_MAX_BYTES` / `DOCUMENT_DB_MAX_BYTES` | 上傳上限/DB 與檔案系統分界 |
332
414
 
333
415
  **請備份 `ENCRYPTION_KEY`。** 遺失後歷史資料無法解密。
334
416
 
335
417
  ---
336
418
 
337
- ## 生產環境(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
338
434
 
339
435
  ```bash
340
436
  npm run build
@@ -342,7 +438,21 @@ pm2 start ecosystem.config.cjs
342
438
  pm2 logs grok-openai-gateway
343
439
  ```
344
440
 
345
- 或直接:`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
+ ```
346
456
 
347
457
  ---
348
458
 
@@ -352,7 +462,7 @@ pm2 logs grok-openai-gateway
352
462
  src/ TypeScript 原始碼(app、routes、services、cli)
353
463
  public/admin/ Admin SPA
354
464
  prisma/ Schema、migrations、seed
355
- dist/ 編譯後 JS(隨 npm 發佈)
465
+ dist/ 編譯後 JS(gitignore;npm run build / prepublishOnly 產生)
356
466
  scripts/ prepare、install.sh
357
467
  tests/ Vitest
358
468
  ```
@@ -363,18 +473,19 @@ tests/ Vitest
363
473
 
364
474
  ```bash
365
475
  npm run dev # 開發
366
- npm run build # 編譯 + prisma generate
476
+ npm run build # prisma generate + tsc
367
477
  npm start # node dist/server.js
368
478
  npm test # 單元 + 整合測試
369
479
  npm run db:setup # migrate + seed
370
- gctoac setup|start|status|stop|doctor|update
480
+ gctoac setup|start|status|stop|doctor|logs|update
371
481
  ```
372
482
 
373
483
  ### 發佈到 npm(維護者)
374
484
 
485
+ `prepublishOnly` 會跑 `npm run build`,tarball 一定包含 `dist/`。
486
+
375
487
  ```bash
376
488
  npm login
377
- npm run build
378
489
  npm publish --access public --otp=<2FA六位碼>
379
490
  ```
380
491
 
@@ -385,7 +496,29 @@ npm publish --access public --otp=<2FA六位碼>
385
496
  - API key 只存 **SHA-256 hash**
386
497
  - Chat prompt/response 與文件以 **AES-256-GCM** 靜態加密
387
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 = 完全接管)
388
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` |
389
522
 
390
523
  ---
391
524