@jsonstudio/rcc 0.89.1803 → 0.89.1959

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 (283) hide show
  1. package/configsamples/config.json +19 -0
  2. package/configsamples/provider/deepseek/config.v1.json +59 -0
  3. package/dist/build-info.js +2 -2
  4. package/dist/cli/commands/claude.d.ts +4 -0
  5. package/dist/cli/commands/claude.js +56 -0
  6. package/dist/cli/commands/claude.js.map +1 -0
  7. package/dist/cli/commands/clock-admin.d.ts +20 -0
  8. package/dist/cli/commands/clock-admin.js +234 -0
  9. package/dist/cli/commands/clock-admin.js.map +1 -0
  10. package/dist/cli/commands/code.d.ts +0 -42
  11. package/dist/cli/commands/code.js +4 -414
  12. package/dist/cli/commands/code.js.map +1 -1
  13. package/dist/cli/commands/codex.d.ts +4 -0
  14. package/dist/cli/commands/codex.js +43 -0
  15. package/dist/cli/commands/codex.js.map +1 -0
  16. package/dist/cli/commands/examples.js +13 -16
  17. package/dist/cli/commands/examples.js.map +1 -1
  18. package/dist/cli/commands/init/basic.d.ts +40 -0
  19. package/dist/cli/commands/init/basic.js +482 -0
  20. package/dist/cli/commands/init/basic.js.map +1 -0
  21. package/dist/cli/commands/init/camoufox.d.ts +7 -0
  22. package/dist/cli/commands/init/camoufox.js +59 -0
  23. package/dist/cli/commands/init/camoufox.js.map +1 -0
  24. package/dist/cli/commands/init/interactive.d.ts +18 -0
  25. package/dist/cli/commands/init/interactive.js +223 -0
  26. package/dist/cli/commands/init/interactive.js.map +1 -0
  27. package/dist/cli/commands/init/shared.d.ts +66 -0
  28. package/dist/cli/commands/init/shared.js +9 -0
  29. package/dist/cli/commands/init/shared.js.map +1 -0
  30. package/dist/cli/commands/init/workflows.d.ts +29 -0
  31. package/dist/cli/commands/init/workflows.js +341 -0
  32. package/dist/cli/commands/init/workflows.js.map +1 -0
  33. package/dist/cli/commands/init.d.ts +2 -26
  34. package/dist/cli/commands/init.js +220 -53
  35. package/dist/cli/commands/init.js.map +1 -1
  36. package/dist/cli/commands/launcher-kernel.d.ts +78 -0
  37. package/dist/cli/commands/launcher-kernel.js +1194 -0
  38. package/dist/cli/commands/launcher-kernel.js.map +1 -0
  39. package/dist/cli/commands/start.js +27 -1
  40. package/dist/cli/commands/start.js.map +1 -1
  41. package/dist/cli/commands/status.d.ts +2 -0
  42. package/dist/cli/commands/status.js +24 -1
  43. package/dist/cli/commands/status.js.map +1 -1
  44. package/dist/cli/commands/stop.d.ts +1 -0
  45. package/dist/cli/commands/stop.js +201 -4
  46. package/dist/cli/commands/stop.js.map +1 -1
  47. package/dist/cli/commands/tmux-inject.d.ts +20 -0
  48. package/dist/cli/commands/tmux-inject.js +212 -0
  49. package/dist/cli/commands/tmux-inject.js.map +1 -0
  50. package/dist/cli/config/init-provider-catalog.js +34 -0
  51. package/dist/cli/config/init-provider-catalog.js.map +1 -1
  52. package/dist/cli/register/claude-command.d.ts +3 -0
  53. package/dist/cli/register/claude-command.js +5 -0
  54. package/dist/cli/register/claude-command.js.map +1 -0
  55. package/dist/cli/register/clock-admin-command.d.ts +3 -0
  56. package/dist/cli/register/clock-admin-command.js +5 -0
  57. package/dist/cli/register/clock-admin-command.js.map +1 -0
  58. package/dist/cli/register/codex-command.d.ts +3 -0
  59. package/dist/cli/register/codex-command.js +5 -0
  60. package/dist/cli/register/codex-command.js.map +1 -0
  61. package/dist/cli/register/status-config-commands.d.ts +2 -0
  62. package/dist/cli/register/status-config-commands.js.map +1 -1
  63. package/dist/cli/register/tmux-inject-command.d.ts +3 -0
  64. package/dist/cli/register/tmux-inject-command.js +5 -0
  65. package/dist/cli/register/tmux-inject-command.js.map +1 -0
  66. package/dist/cli/server/port-utils.d.ts +3 -2
  67. package/dist/cli/server/port-utils.js +171 -32
  68. package/dist/cli/server/port-utils.js.map +1 -1
  69. package/dist/cli.js +45 -6
  70. package/dist/cli.js.map +1 -1
  71. package/dist/client/gemini/gemini-protocol-client.js +56 -5
  72. package/dist/client/gemini/gemini-protocol-client.js.map +1 -1
  73. package/dist/commands/token-daemon.js +59 -7
  74. package/dist/commands/token-daemon.js.map +1 -1
  75. package/dist/commands/validate.js +87 -15
  76. package/dist/commands/validate.js.map +1 -1
  77. package/dist/config/routecodex-config-loader.js +31 -2
  78. package/dist/config/routecodex-config-loader.js.map +1 -1
  79. package/dist/docs/daemon-admin-ui.html +948 -74
  80. package/dist/index.d.ts +1 -0
  81. package/dist/index.js +325 -37
  82. package/dist/index.js.map +1 -1
  83. package/dist/manager/quota/provider-quota-center.js +8 -14
  84. package/dist/manager/quota/provider-quota-center.js.map +1 -1
  85. package/dist/modules/llmswitch/bridge.d.ts +39 -0
  86. package/dist/modules/llmswitch/bridge.js +169 -0
  87. package/dist/modules/llmswitch/bridge.js.map +1 -1
  88. package/dist/modules/pipeline/utils/colored-logger.js +1 -1
  89. package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
  90. package/dist/providers/auth/deepseek-account-auth.d.ts +39 -0
  91. package/dist/providers/auth/deepseek-account-auth.js +329 -0
  92. package/dist/providers/auth/deepseek-account-auth.js.map +1 -0
  93. package/dist/providers/auth/deepseek-account-token-acquirer.d.ts +15 -0
  94. package/dist/providers/auth/deepseek-account-token-acquirer.js +644 -0
  95. package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -0
  96. package/dist/providers/auth/oauth-lifecycle.js +26 -4
  97. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  98. package/dist/providers/auth/oauth-repair-cooldown.d.ts +5 -0
  99. package/dist/providers/auth/oauth-repair-cooldown.js +39 -0
  100. package/dist/providers/auth/oauth-repair-cooldown.js.map +1 -1
  101. package/dist/providers/auth/token-scanner/index.d.ts +6 -0
  102. package/dist/providers/auth/token-scanner/index.js +53 -0
  103. package/dist/providers/auth/token-scanner/index.js.map +1 -1
  104. package/dist/providers/core/api/provider-config.d.ts +17 -2
  105. package/dist/providers/core/api/provider-types.d.ts +6 -0
  106. package/dist/providers/core/api/provider-types.js.map +1 -1
  107. package/dist/providers/core/config/camoufox-launcher.d.ts +7 -0
  108. package/dist/providers/core/config/camoufox-launcher.js +68 -21
  109. package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
  110. package/dist/providers/core/config/service-profiles.js +19 -0
  111. package/dist/providers/core/config/service-profiles.js.map +1 -1
  112. package/dist/providers/core/contracts/deepseek-provider-contract.d.ts +34 -0
  113. package/dist/providers/core/contracts/deepseek-provider-contract.js +100 -0
  114. package/dist/providers/core/contracts/deepseek-provider-contract.js.map +1 -0
  115. package/dist/providers/core/runtime/anthropic-http-provider.d.ts +0 -5
  116. package/dist/providers/core/runtime/anthropic-http-provider.js +0 -26
  117. package/dist/providers/core/runtime/anthropic-http-provider.js.map +1 -1
  118. package/dist/providers/core/runtime/deepseek-http-provider.d.ts +35 -0
  119. package/dist/providers/core/runtime/deepseek-http-provider.js +373 -0
  120. package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -0
  121. package/dist/providers/core/runtime/deepseek-session-pow.d.ts +55 -0
  122. package/dist/providers/core/runtime/deepseek-session-pow.js +422 -0
  123. package/dist/providers/core/runtime/deepseek-session-pow.js.map +1 -0
  124. package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +0 -3
  125. package/dist/providers/core/runtime/gemini-cli-http-provider.js +0 -72
  126. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  127. package/dist/providers/core/runtime/gemini-http-provider.d.ts +1 -7
  128. package/dist/providers/core/runtime/gemini-http-provider.js +3 -110
  129. package/dist/providers/core/runtime/gemini-http-provider.js.map +1 -1
  130. package/dist/providers/core/runtime/http-request-executor.d.ts +1 -0
  131. package/dist/providers/core/runtime/http-request-executor.js +4 -0
  132. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  133. package/dist/providers/core/runtime/http-transport-provider.d.ts +10 -4
  134. package/dist/providers/core/runtime/http-transport-provider.js +308 -82
  135. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  136. package/dist/providers/core/runtime/iflow-http-provider.d.ts +0 -4
  137. package/dist/providers/core/runtime/iflow-http-provider.js +0 -28
  138. package/dist/providers/core/runtime/iflow-http-provider.js.map +1 -1
  139. package/dist/providers/core/runtime/provider-factory.d.ts +5 -0
  140. package/dist/providers/core/runtime/provider-factory.js +59 -6
  141. package/dist/providers/core/runtime/provider-factory.js.map +1 -1
  142. package/dist/providers/core/runtime/responses-provider.d.ts +0 -2
  143. package/dist/providers/core/runtime/responses-provider.js +0 -11
  144. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  145. package/dist/providers/core/strategies/oauth-device-flow.js +16 -1
  146. package/dist/providers/core/strategies/oauth-device-flow.js.map +1 -1
  147. package/dist/providers/core/utils/provider-type-utils.js +2 -1
  148. package/dist/providers/core/utils/provider-type-utils.js.map +1 -1
  149. package/dist/providers/profile/families/anthropic-profile.d.ts +2 -0
  150. package/dist/providers/profile/families/anthropic-profile.js +32 -0
  151. package/dist/providers/profile/families/anthropic-profile.js.map +1 -0
  152. package/dist/providers/profile/families/antigravity-profile.d.ts +2 -0
  153. package/dist/providers/profile/families/antigravity-profile.js +109 -0
  154. package/dist/providers/profile/families/antigravity-profile.js.map +1 -0
  155. package/dist/providers/profile/families/glm-profile.d.ts +2 -0
  156. package/dist/providers/profile/families/glm-profile.js +48 -0
  157. package/dist/providers/profile/families/glm-profile.js.map +1 -0
  158. package/dist/providers/profile/families/iflow-profile.d.ts +2 -0
  159. package/dist/providers/profile/families/iflow-profile.js +232 -0
  160. package/dist/providers/profile/families/iflow-profile.js.map +1 -0
  161. package/dist/providers/profile/families/qwen-profile.d.ts +2 -0
  162. package/dist/providers/profile/families/qwen-profile.js +14 -0
  163. package/dist/providers/profile/families/qwen-profile.js.map +1 -0
  164. package/dist/providers/profile/families/responses-profile.d.ts +2 -0
  165. package/dist/providers/profile/families/responses-profile.js +28 -0
  166. package/dist/providers/profile/families/responses-profile.js.map +1 -0
  167. package/dist/providers/profile/profile-contracts.d.ts +74 -0
  168. package/dist/providers/profile/profile-contracts.js +2 -0
  169. package/dist/providers/profile/profile-contracts.js.map +1 -0
  170. package/dist/providers/profile/profile-registry.d.ts +3 -0
  171. package/dist/providers/profile/profile-registry.js +40 -0
  172. package/dist/providers/profile/profile-registry.js.map +1 -0
  173. package/dist/providers/profile/provider-directory.d.ts +2 -0
  174. package/dist/providers/profile/provider-directory.js +55 -0
  175. package/dist/providers/profile/provider-directory.js.map +1 -0
  176. package/dist/providers/profile/provider-profile-loader.js +43 -3
  177. package/dist/providers/profile/provider-profile-loader.js.map +1 -1
  178. package/dist/providers/profile/provider-profile.d.ts +8 -0
  179. package/dist/scripts/deepseek/pow-solver.mjs +146 -0
  180. package/dist/scripts/deepseek/sha3_wasm_bg.7b9ca65ddd.wasm +0 -0
  181. package/dist/server/handlers/config-admin-handler.js +27 -0
  182. package/dist/server/handlers/config-admin-handler.js.map +1 -1
  183. package/dist/server/runtime/http-server/clock-client-registry.d.ts +113 -0
  184. package/dist/server/runtime/http-server/clock-client-registry.js +592 -0
  185. package/dist/server/runtime/http-server/clock-client-registry.js.map +1 -0
  186. package/dist/server/runtime/http-server/clock-client-routes.d.ts +2 -0
  187. package/dist/server/runtime/http-server/clock-client-routes.js +481 -0
  188. package/dist/server/runtime/http-server/clock-client-routes.js.map +1 -0
  189. package/dist/server/runtime/http-server/clock-daemon-inject-config.d.ts +1 -0
  190. package/dist/server/runtime/http-server/clock-daemon-inject-config.js +11 -0
  191. package/dist/server/runtime/http-server/clock-daemon-inject-config.js.map +1 -0
  192. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +3 -3
  193. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
  194. package/dist/server/runtime/http-server/daemon-admin/auth-session.d.ts +1 -0
  195. package/dist/server/runtime/http-server/daemon-admin/auth-session.js +18 -2
  196. package/dist/server/runtime/http-server/daemon-admin/auth-session.js.map +1 -1
  197. package/dist/server/runtime/http-server/daemon-admin/control-handler.js +2 -15
  198. package/dist/server/runtime/http-server/daemon-admin/control-handler.js.map +1 -1
  199. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +65 -7
  200. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
  201. package/dist/server/runtime/http-server/executor-metadata.js +37 -1
  202. package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
  203. package/dist/server/runtime/http-server/executor-provider.js +55 -0
  204. package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
  205. package/dist/server/runtime/http-server/executor-response.js +49 -1
  206. package/dist/server/runtime/http-server/executor-response.js.map +1 -1
  207. package/dist/server/runtime/http-server/index.d.ts +10 -0
  208. package/dist/server/runtime/http-server/index.js +534 -9
  209. package/dist/server/runtime/http-server/index.js.map +1 -1
  210. package/dist/server/runtime/http-server/managed-process-probe.d.ts +6 -0
  211. package/dist/server/runtime/http-server/managed-process-probe.js +294 -0
  212. package/dist/server/runtime/http-server/managed-process-probe.js.map +1 -0
  213. package/dist/server/runtime/http-server/middleware.js +16 -1
  214. package/dist/server/runtime/http-server/middleware.js.map +1 -1
  215. package/dist/server/runtime/http-server/provider-utils.js +6 -2
  216. package/dist/server/runtime/http-server/provider-utils.js.map +1 -1
  217. package/dist/server/runtime/http-server/request-executor.d.ts +1 -0
  218. package/dist/server/runtime/http-server/request-executor.js +360 -35
  219. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  220. package/dist/server/runtime/http-server/routes.js +95 -3
  221. package/dist/server/runtime/http-server/routes.js.map +1 -1
  222. package/dist/server/runtime/http-server/stats-manager.d.ts +10 -0
  223. package/dist/server/runtime/http-server/stats-manager.js +119 -16
  224. package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
  225. package/dist/server/runtime/http-server/tmux-session-probe.d.ts +3 -0
  226. package/dist/server/runtime/http-server/tmux-session-probe.js +101 -0
  227. package/dist/server/runtime/http-server/tmux-session-probe.js.map +1 -0
  228. package/dist/server/utils/stage-logger.js +21 -5
  229. package/dist/server/utils/stage-logger.js.map +1 -1
  230. package/dist/token-daemon/index.js +59 -10
  231. package/dist/token-daemon/index.js.map +1 -1
  232. package/dist/token-daemon/server-utils.d.ts +1 -0
  233. package/dist/token-daemon/server-utils.js +4 -1
  234. package/dist/token-daemon/server-utils.js.map +1 -1
  235. package/dist/token-daemon/token-daemon.js +38 -4
  236. package/dist/token-daemon/token-daemon.js.map +1 -1
  237. package/dist/token-daemon/token-types.d.ts +1 -1
  238. package/dist/token-daemon/token-types.js +2 -1
  239. package/dist/token-daemon/token-types.js.map +1 -1
  240. package/dist/token-daemon/token-utils.js +5 -2
  241. package/dist/token-daemon/token-utils.js.map +1 -1
  242. package/dist/utils/clock-client-token.d.ts +3 -0
  243. package/dist/utils/clock-client-token.js +54 -0
  244. package/dist/utils/clock-client-token.js.map +1 -0
  245. package/dist/utils/managed-server-pids.d.ts +25 -0
  246. package/dist/utils/managed-server-pids.js +176 -0
  247. package/dist/utils/managed-server-pids.js.map +1 -0
  248. package/dist/utils/process-lifecycle-logger.d.ts +8 -0
  249. package/dist/utils/process-lifecycle-logger.js +151 -0
  250. package/dist/utils/process-lifecycle-logger.js.map +1 -0
  251. package/dist/utils/runtime-exit-forensics.d.ts +30 -0
  252. package/dist/utils/runtime-exit-forensics.js +101 -0
  253. package/dist/utils/runtime-exit-forensics.js.map +1 -0
  254. package/dist/utils/shutdown-caller-context.d.ts +22 -0
  255. package/dist/utils/shutdown-caller-context.js +25 -0
  256. package/dist/utils/shutdown-caller-context.js.map +1 -0
  257. package/docs/PROVIDERS_BUILTIN.md +8 -0
  258. package/docs/PROVIDER_TYPES.md +3 -1
  259. package/docs/SERVERTOOL_PRE_COMMAND_HOOKS.md +85 -0
  260. package/docs/clock-client-daemon-design.md +343 -0
  261. package/docs/daemon-admin-ui.html +948 -74
  262. package/docs/providers/deepseek-web-provider-design.md +192 -0
  263. package/docs/routing-instructions.md +4 -1
  264. package/docs/stop-message-auto.md +4 -3
  265. package/docs/v2-architecture/PROVIDER-V2-CHANGESET-RELEASE-CHECKLIST.md +80 -0
  266. package/docs/v2-architecture/PROVIDER-V2-LAYERING-ADR-DRAFT.md +225 -0
  267. package/docs/v2-architecture/PROVIDER-V2-MIGRATION-MATRIX-DRAFT.md +88 -0
  268. package/docs/v2-architecture/PROVIDER-V2-PHASED-MIGRATION-ROLLBACK-DRAFT.md +164 -0
  269. package/docs/v2-architecture/PROVIDER-V2-PROFILE-API-REGISTRY-DRAFT.md +201 -0
  270. package/docs/v2-architecture/PROVIDER-V2-PROFILE-GEMINI-DRAFT.md +56 -0
  271. package/docs/v2-architecture/PROVIDER-V2-REFACTOR-OVERVIEW-DRAFT.md +102 -0
  272. package/docs/v2-architecture/PROVIDER-V2-VERIFICATION-MATRIX-DRAFT.md +163 -0
  273. package/package.json +10 -9
  274. package/scripts/copy-compat-assets.mjs +18 -0
  275. package/scripts/copy-modules-config.mjs +1 -0
  276. package/scripts/deepseek/pow-solver.mjs +146 -0
  277. package/scripts/deepseek/sha3_wasm_bg.7b9ca65ddd.wasm +0 -0
  278. package/scripts/ensure-cli-executable.mjs +64 -0
  279. package/scripts/install-global.sh +5 -2
  280. package/scripts/install.sh +1 -1
  281. package/scripts/monitor/daemon-kill-watch.mjs +184 -0
  282. package/scripts/monitor/port-kill-watch.sh +74 -0
  283. package/scripts/quick-install.sh +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonstudio/rcc",
3
- "version": "0.89.1803",
3
+ "version": "0.89.1959",
4
4
  "description": "Multi-provider OpenAI proxy server with anthropic/responses/chat support (release)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,11 +29,11 @@
29
29
  "node": ">=20 <26"
30
30
  },
31
31
  "scripts": {
32
- "build": "npm run llmswitch:ensure && node scripts/build-core.mjs && node scripts/vendor-core.mjs && npm run clean && node scripts/gen-build-info.mjs && tsc && node scripts/copy-compat-assets.mjs && node scripts/copy-modules-config.mjs",
33
- "build:dev": "bash -lc 'export BUILD_MODE=dev; npm run build && npm run test:unified-hub-shadow && npm run verify:e2e-toolcall && npm run verify:apply-patch && npm run verify:apply-patch-regressions && npm run verify:exec-command && npm run test:routing-instructions && npm run test:cli && npm run install:global && npm run mock:regressions && npm run test:blackbox-antigravity-parity && npm run verify:errorsamples && npm run verify:e2e-gemini-followup-sample'",
34
- "build:min": "npm run llmswitch:ensure && node scripts/build-core.mjs && node scripts/vendor-core.mjs && npm run clean && node scripts/gen-build-info.mjs && tsc && node scripts/copy-compat-assets.mjs && node scripts/copy-modules-config.mjs",
32
+ "build": "npm run llmswitch:ensure && node scripts/build-core.mjs && node scripts/vendor-core.mjs && npm run clean && node scripts/gen-build-info.mjs && tsc && node scripts/copy-compat-assets.mjs && node scripts/copy-modules-config.mjs && npm run fix:cli-permission",
33
+ "build:dev": "bash -lc 'export BUILD_MODE=dev; npm run build && npm run fix:cli-permission && npm run test:unified-hub-shadow && npm run verify:e2e-toolcall && npm run verify:apply-patch && npm run verify:apply-patch-regressions && npm run verify:exec-command && npm run test:routing-instructions && npm run test:cli && npm run install:global && npm run mock:regressions && npm run test:blackbox-antigravity-parity && npm run verify:errorsamples && npm run verify:e2e-gemini-followup-sample'",
34
+ "build:min": "npm run llmswitch:ensure && node scripts/build-core.mjs && node scripts/vendor-core.mjs && npm run clean && node scripts/gen-build-info.mjs && tsc && node scripts/copy-compat-assets.mjs && node scripts/copy-modules-config.mjs && npm run fix:cli-permission",
35
35
  "prepack": "echo skip-prepack",
36
- "postbuild": "chmod +x dist/cli.js || true",
36
+ "postbuild": "node scripts/ensure-cli-executable.mjs",
37
37
  "build:watch": "tsc --watch",
38
38
  "start": "npm run -s start:bg",
39
39
  "dev": "tsx watch src/index.ts",
@@ -46,7 +46,7 @@
46
46
  "test:ci:coverage": "npm run test:ci:jest:coverage",
47
47
  "verify:repo-sanity": "node scripts/ci/repo-sanity.mjs",
48
48
  "vr:dryrun": "node scripts/virtual-router-dryrun.mjs",
49
- "test:routing-instructions": "npm run jest:run -- --runTestsByPath tests/token-daemon/token-daemon.auto-refresh-noninteractive.spec.ts tests/token-daemon/token-daemon.refresh-ahead.spec.ts tests/commands/oauth-command.qwen-auto.spec.ts tests/token-daemon/interactive-refresh.spec.ts tests/server/runtime/request-executor.single-attempt.spec.ts tests/server/runtime/executor-provider.retryable.spec.ts tests/providers/auth/tokenfile-auth.iflow.spec.ts tests/providers/auth/antigravity-user-agent.unit.test.ts tests/providers/auth/antigravity-fingerprint.unit.test.ts tests/providers/auth/antigravity-warmup.unit.test.ts tests/providers/core/runtime/gemini-cli-http-provider.unit.test.ts tests/providers/core/runtime/antigravity-quota-client.unit.test.ts tests/manager/quota/provider-quota-center.spec.ts tests/manager/quota/provider-quota-store.spec.ts tests/manager/quota/quota-manager-refresh.spec.ts tests/manager/quota/provider-quota-daemon-module.spec.ts tests/manager/quota/provider-key-normalization.spec.ts tests/server/http-server/daemon-admin.e2e.spec.ts tests/server/http-server/quota-view-injection.spec.ts tests/server/http-server/quota-refresh-triggers.e2e.spec.ts tests/server/http-server/hub-policy-injection.spec.ts tests/server/http-server/session-header-injection.spec.ts tests/server/http-server/session-dir.spec.ts tests/server/handlers/sse-timeout.spec.ts tests/utils/is-direct-execution.test.ts tests/utils/windows-netstat.test.ts tests/servertool/virtual-router-context-fallback.spec.ts tests/servertool/virtual-router-longcontext-fallback.spec.ts tests/servertool/virtual-router-series-cooldown.spec.ts tests/servertool/recursive-detection-guard.spec.ts tests/servertool/routing-instructions.spec.ts tests/servertool/stop-message-auto.spec.ts tests/servertool/stopmessage-session-scope.spec.ts tests/servertool/stopmessage-anthropic-stop-sequence.spec.ts tests/servertool/stopmessage-compaction-false-positive.spec.ts tests/servertool/servertool-progress-logging.spec.ts tests/servertool/servertool-clock.spec.ts tests/servertool/antigravity-thought-signature-bootstrap.spec.ts tests/compat/tabglm-claude-code-profile.spec.ts tests/compat/antigravity-thought-signature.spec.ts tests/sharedmodule/mcp-tool-descriptions.spec.ts tests/sharedmodule/virtual-router-routing-model-validation.spec.ts tests/unified-hub/hub-v1-single-path-imports.spec.ts",
49
+ "test:routing-instructions": "npm run jest:run -- --runTestsByPath tests/token-daemon/token-daemon.auto-refresh-noninteractive.spec.ts tests/token-daemon/token-daemon.refresh-ahead.spec.ts tests/commands/oauth-command.qwen-auto.spec.ts tests/token-daemon/interactive-refresh.spec.ts tests/server/runtime/request-executor.single-attempt.spec.ts tests/server/runtime/executor-provider.retryable.spec.ts tests/providers/auth/tokenfile-auth.iflow.spec.ts tests/providers/auth/antigravity-user-agent.unit.test.ts tests/providers/auth/antigravity-fingerprint.unit.test.ts tests/providers/auth/antigravity-warmup.unit.test.ts tests/providers/core/runtime/gemini-cli-http-provider.unit.test.ts tests/providers/core/runtime/antigravity-quota-client.unit.test.ts tests/manager/quota/provider-quota-center.spec.ts tests/manager/quota/provider-quota-store.spec.ts tests/manager/quota/quota-manager-refresh.spec.ts tests/manager/quota/provider-quota-daemon-module.spec.ts tests/manager/quota/provider-key-normalization.spec.ts tests/server/http-server/daemon-admin.e2e.spec.ts tests/server/http-server/clock-client-routes.spec.ts tests/server/http-server/quota-view-injection.spec.ts tests/server/http-server/quota-refresh-triggers.e2e.spec.ts tests/server/http-server/hub-policy-injection.spec.ts tests/server/http-server/session-header-injection.spec.ts tests/server/http-server/session-dir.spec.ts tests/server/handlers/sse-timeout.spec.ts tests/utils/is-direct-execution.test.ts tests/utils/windows-netstat.test.ts tests/servertool/virtual-router-context-fallback.spec.ts tests/servertool/virtual-router-longcontext-fallback.spec.ts tests/servertool/virtual-router-series-cooldown.spec.ts tests/servertool/recursive-detection-guard.spec.ts tests/servertool/routing-instructions.spec.ts tests/servertool/stop-message-auto.spec.ts tests/servertool/stopmessage-session-scope.spec.ts tests/servertool/stopmessage-anthropic-stop-sequence.spec.ts tests/servertool/stopmessage-compaction-false-positive.spec.ts tests/servertool/servertool-progress-logging.spec.ts tests/servertool/servertool-clock.spec.ts tests/servertool/antigravity-thought-signature-bootstrap.spec.ts tests/compat/tabglm-claude-code-profile.spec.ts tests/compat/antigravity-thought-signature.spec.ts tests/sharedmodule/mcp-tool-descriptions.spec.ts tests/sharedmodule/virtual-router-routing-model-validation.spec.ts tests/unified-hub/hub-v1-single-path-imports.spec.ts",
50
50
  "test:cli": "npm run jest:run -- --runTestsByPath tests/cli/camoufox-command.spec.ts tests/cli/clean-command.spec.ts tests/cli/code-command.spec.ts tests/cli/config-command.spec.ts tests/cli/env-command.spec.ts tests/cli/env-output.spec.ts tests/cli/examples-command.spec.ts tests/cli/port-command.spec.ts tests/cli/port-utils.spec.ts tests/cli/restart-command.spec.ts tests/cli/smoke.spec.ts tests/cli/start-command.spec.ts tests/cli/status-command.spec.ts tests/cli/stop-command.spec.ts",
51
51
  "test:watch": "npm run jest:run -- --watch",
52
52
  "test:coverage": "npm run jest:run -- --coverage",
@@ -64,7 +64,7 @@
64
64
  "clean": "rm -rf dist coverage",
65
65
  "prebuild": "npm run verify:repo-sanity && echo skip-lint",
66
66
  "prepare": "",
67
- "postinstall": "chmod +x dist/cli.js || true",
67
+ "postinstall": "node scripts/ensure-cli-executable.mjs",
68
68
  "verify:apply-patch": "node scripts/verify-apply-patch.mjs",
69
69
  "verify:apply-patch-regressions": "node scripts/verify-apply-patch-regressions.mjs",
70
70
  "verify:exec-command": "node scripts/tests/exec-command-loop.mjs",
@@ -144,11 +144,12 @@
144
144
  "publish:rcc": "node scripts/publish-rcc.mjs",
145
145
  "pack:rcc": "node scripts/pack-rcc.mjs",
146
146
  "build:rccx": "npm run build:min && node scripts/pack-mode.mjs --name @jsonstudio/rccx --bin rccx",
147
- "compare:codex:rccx": "node scripts/compare-codex-rccx.mjs"
147
+ "compare:codex:rccx": "node scripts/compare-codex-rccx.mjs",
148
+ "fix:cli-permission": "node scripts/ensure-cli-executable.mjs"
148
149
  },
149
150
  "dependencies": {
150
151
  "@anthropic-ai/sdk": "^0.65.0",
151
- "@jsonstudio/llms": "0.6.1739",
152
+ "@jsonstudio/llms": "^0.6.1892",
152
153
  "@lmstudio/sdk": "^1.5.0",
153
154
  "@radix-ui/react-switch": "^1.2.6",
154
155
  "@types/socket.io": "^3.0.1",
@@ -19,8 +19,11 @@ async function main() {
19
19
  const PROMPT_DIST = path.resolve(process.cwd(), 'dist/config/system-prompts');
20
20
  const CAMOUFOX_SRC = path.resolve(process.cwd(), 'scripts/camoufox');
21
21
  const CAMOUFOX_DIST = path.resolve(process.cwd(), 'dist/scripts/camoufox');
22
+ const DEEPSEEK_SRC = path.resolve(process.cwd(), 'scripts/deepseek');
23
+ const DEEPSEEK_DIST = path.resolve(process.cwd(), 'dist/scripts/deepseek');
22
24
  const promptCopied = [];
23
25
  const camoufoxCopied = [];
26
+ const deepseekCopied = [];
24
27
  try {
25
28
  // copy system prompt artifacts only; provider compat assets are owned by llmswitch-core
26
29
  try {
@@ -52,8 +55,23 @@ async function main() {
52
55
  } catch (camoufoxErr) {
53
56
  if (camoufoxErr && camoufoxErr.code !== 'ENOENT') throw camoufoxErr;
54
57
  }
58
+ try {
59
+ for await (const file of walk(DEEPSEEK_SRC)) {
60
+ const stats = await fs.stat(file);
61
+ if (stats.isFile()) {
62
+ const rel = path.relative(DEEPSEEK_SRC, file);
63
+ const dest = path.join(DEEPSEEK_DIST, rel);
64
+ await ensureDir(path.dirname(dest));
65
+ await fs.copyFile(file, dest);
66
+ deepseekCopied.push(rel);
67
+ }
68
+ }
69
+ } catch (deepseekErr) {
70
+ if (deepseekErr && deepseekErr.code !== 'ENOENT') throw deepseekErr;
71
+ }
55
72
  console.log(`[copy-compat-assets] prompts copied: ${promptCopied.length}`);
56
73
  console.log(`[copy-compat-assets] camoufox assets copied: ${camoufoxCopied.length}`);
74
+ console.log(`[copy-compat-assets] deepseek assets copied: ${deepseekCopied.length}`);
57
75
  } catch (err) {
58
76
  console.error('[copy-compat-assets] failed:', err?.message || String(err));
59
77
  process.exit(1);
@@ -26,6 +26,7 @@ async function copyModulesConfig() {
26
26
  await fs.mkdir(path.dirname(distDaemonAdminUi), { recursive: true });
27
27
  await fs.copyFile(srcDaemonAdminUi, distDaemonAdminUi);
28
28
  console.log('[copy-modules-config] copied daemon-admin-ui.html to dist/docs/daemon-admin-ui.html');
29
+
29
30
  } catch (error) {
30
31
  if (error.code === 'ENOENT') {
31
32
  console.warn('[copy-modules-config] docs/daemon-admin-ui.html not found, skipping');
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from 'node:fs/promises';
3
+ import { resolve, dirname } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+
8
+ function readStdin() {
9
+ return new Promise((resolveInput, rejectInput) => {
10
+ let data = '';
11
+ process.stdin.setEncoding('utf8');
12
+ process.stdin.on('data', (chunk) => {
13
+ data += chunk;
14
+ });
15
+ process.stdin.on('end', () => resolveInput(data));
16
+ process.stdin.on('error', rejectInput);
17
+ });
18
+ }
19
+
20
+ class DeepSeekHash {
21
+ constructor() {
22
+ this.wasmInstance = null;
23
+ this.offset = 0;
24
+ this.cachedUint8Memory = null;
25
+ this.cachedTextEncoder = new TextEncoder();
26
+ }
27
+
28
+ getCachedUint8Memory() {
29
+ if (this.cachedUint8Memory === null || this.cachedUint8Memory.byteLength === 0) {
30
+ this.cachedUint8Memory = new Uint8Array(this.wasmInstance.memory.buffer);
31
+ }
32
+ return this.cachedUint8Memory;
33
+ }
34
+
35
+ encodeString(text, allocate, reallocate) {
36
+ if (!reallocate) {
37
+ const encoded = this.cachedTextEncoder.encode(text);
38
+ const ptr = allocate(encoded.length, 1) >>> 0;
39
+ const memory = this.getCachedUint8Memory();
40
+ memory.subarray(ptr, ptr + encoded.length).set(encoded);
41
+ this.offset = encoded.length;
42
+ return ptr;
43
+ }
44
+
45
+ const strLength = text.length;
46
+ let ptr = allocate(strLength, 1) >>> 0;
47
+ const memory = this.getCachedUint8Memory();
48
+ let asciiLength = 0;
49
+
50
+ for (; asciiLength < strLength; asciiLength += 1) {
51
+ const charCode = text.charCodeAt(asciiLength);
52
+ if (charCode > 127) {
53
+ break;
54
+ }
55
+ memory[ptr + asciiLength] = charCode;
56
+ }
57
+
58
+ if (asciiLength !== strLength) {
59
+ if (asciiLength > 0) {
60
+ text = text.slice(asciiLength);
61
+ }
62
+ ptr = reallocate(ptr, strLength, asciiLength + text.length * 3, 1) >>> 0;
63
+ const result = this.cachedTextEncoder.encodeInto(
64
+ text,
65
+ this.getCachedUint8Memory().subarray(ptr + asciiLength, ptr + asciiLength + text.length * 3)
66
+ );
67
+ asciiLength += result.written;
68
+ ptr = reallocate(ptr, asciiLength + text.length * 3, asciiLength, 1) >>> 0;
69
+ }
70
+
71
+ this.offset = asciiLength;
72
+ return ptr;
73
+ }
74
+
75
+ async init(wasmPath) {
76
+ const wasmBuffer = await readFile(wasmPath);
77
+ const { instance } = await WebAssembly.instantiate(wasmBuffer, { wbg: {} });
78
+ this.wasmInstance = instance.exports;
79
+ }
80
+
81
+ solve(algorithm, challenge, salt, difficulty, expireAt) {
82
+ if (algorithm !== 'DeepSeekHashV1') {
83
+ throw new Error(`Unsupported algorithm: ${algorithm}`);
84
+ }
85
+
86
+ const prefix = `${salt}_${expireAt}_`;
87
+ const retptr = this.wasmInstance.__wbindgen_add_to_stack_pointer(-16);
88
+
89
+ try {
90
+ const ptr0 = this.encodeString(
91
+ challenge,
92
+ this.wasmInstance.__wbindgen_export_0,
93
+ this.wasmInstance.__wbindgen_export_1
94
+ );
95
+ const len0 = this.offset;
96
+
97
+ const ptr1 = this.encodeString(
98
+ prefix,
99
+ this.wasmInstance.__wbindgen_export_0,
100
+ this.wasmInstance.__wbindgen_export_1
101
+ );
102
+ const len1 = this.offset;
103
+
104
+ this.wasmInstance.wasm_solve(retptr, ptr0, len0, ptr1, len1, Number(difficulty));
105
+
106
+ const dataView = new DataView(this.wasmInstance.memory.buffer);
107
+ const status = dataView.getInt32(retptr + 0, true);
108
+ const value = dataView.getFloat64(retptr + 8, true);
109
+ if (status === 0 || !Number.isFinite(value)) {
110
+ return null;
111
+ }
112
+ return Math.trunc(value);
113
+ } finally {
114
+ this.wasmInstance.__wbindgen_add_to_stack_pointer(16);
115
+ }
116
+ }
117
+ }
118
+
119
+ async function main() {
120
+ const raw = await readStdin();
121
+ if (!raw || !raw.trim()) {
122
+ throw new Error('Missing stdin JSON payload');
123
+ }
124
+
125
+ const payload = JSON.parse(raw);
126
+ const wasmPath = payload.wasmPath
127
+ ? resolve(String(payload.wasmPath))
128
+ : resolve(__dirname, 'sha3_wasm_bg.7b9ca65ddd.wasm');
129
+
130
+ const solver = new DeepSeekHash();
131
+ await solver.init(wasmPath);
132
+ const answer = solver.solve(
133
+ payload.algorithm,
134
+ payload.challenge,
135
+ payload.salt,
136
+ payload.difficulty,
137
+ payload.expireAt
138
+ );
139
+
140
+ process.stdout.write(JSON.stringify({ ok: answer !== null, answer }) + '\n');
141
+ }
142
+
143
+ main().catch((error) => {
144
+ process.stderr.write((error && error.stack) ? String(error.stack) : String(error) + '\n');
145
+ process.exit(1);
146
+ });
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { execSync } from 'node:child_process';
5
+
6
+ if (process.platform === 'win32') {
7
+ process.exit(0);
8
+ }
9
+
10
+ function ensureExecutable(filePath) {
11
+ if (!filePath || !fs.existsSync(filePath)) {
12
+ return;
13
+ }
14
+ try {
15
+ const stat = fs.statSync(filePath);
16
+ const nextMode = stat.mode | 0o111;
17
+ fs.chmodSync(filePath, nextMode);
18
+ } catch {
19
+ // ignore best-effort chmod failures
20
+ }
21
+ }
22
+
23
+ function getCommandOutput(command) {
24
+ try {
25
+ return execSync(command, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
26
+ } catch {
27
+ return '';
28
+ }
29
+ }
30
+
31
+ function ensureLocalCli() {
32
+ const cliPath = path.join(process.cwd(), 'dist', 'cli.js');
33
+ ensureExecutable(cliPath);
34
+ }
35
+
36
+ function ensureGlobalBinTarget(binName) {
37
+ const prefix = getCommandOutput('npm config get prefix');
38
+ if (!prefix) {
39
+ return;
40
+ }
41
+
42
+ const binPath = path.join(prefix, 'bin', binName);
43
+ if (fs.existsSync(binPath)) {
44
+ try {
45
+ const realTarget = fs.realpathSync(binPath);
46
+ ensureExecutable(realTarget);
47
+ } catch {
48
+ ensureExecutable(binPath);
49
+ }
50
+ }
51
+
52
+ const globalRoot = getCommandOutput('npm root -g');
53
+ if (!globalRoot) {
54
+ return;
55
+ }
56
+
57
+ const packageName = binName === 'rcc' ? '@jsonstudio/rcc' : 'routecodex';
58
+ const globalCliPath = path.join(globalRoot, packageName, 'dist', 'cli.js');
59
+ ensureExecutable(globalCliPath);
60
+ }
61
+
62
+ ensureLocalCli();
63
+ ensureGlobalBinTarget('routecodex');
64
+ ensureGlobalBinTarget('rcc');
@@ -87,8 +87,8 @@ build_project() {
87
87
  echo "💡 尝试手动构建:npm run build"
88
88
  exit 1
89
89
  }
90
- # 确保CLI可执行
91
- chmod +x dist/cli.js
90
+ # 确保CLI可执行(本地 + 全局目标自愈)
91
+ node scripts/ensure-cli-executable.mjs || true
92
92
 
93
93
  # 检查构建结果
94
94
  if [ ! -f "dist/cli.js" ]; then
@@ -127,6 +127,9 @@ global_install() {
127
127
  # 执行安装(跳过可选依赖,减少体积;允许脚本执行以生成可执行文件)
128
128
  npm install -g . --no-audit --no-fund --omit=optional
129
129
 
130
+ # 全局安装后再次修复可执行位(解决偶发 permission denied)
131
+ node scripts/ensure-cli-executable.mjs || true
132
+
130
133
  if [ $? -eq 0 ]; then
131
134
  echo "✅ 全局安装成功"
132
135
  else
@@ -51,7 +51,7 @@ build_project() {
51
51
  # 设置执行权限
52
52
  set_permissions() {
53
53
  echo "🔑 设置执行权限..."
54
- chmod +x dist/cli.js || true
54
+ node scripts/ensure-cli-executable.mjs || true
55
55
  }
56
56
 
57
57
  # 验证安装
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Monitor routecodex processes and record termination events with context.
4
+ * Usage:
5
+ * node scripts/monitor/daemon-kill-watch.mjs [--port <port>] [--label <label>]
6
+ */
7
+
8
+ import { spawn, execSync } from 'node:child_process';
9
+ import fs from 'node:fs';
10
+ import path from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ const args = process.argv.slice(2);
17
+ let port = null;
18
+ let label = '';
19
+
20
+ for (let i = 0; i < args.length; i++) {
21
+ if (args[i] === '--port' && i + 1 < args.length) {
22
+ port = args[++i];
23
+ } else if (args[i] === '--label' && i + 1 < args.length) {
24
+ label = args[++i];
25
+ }
26
+ }
27
+
28
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
29
+ const logFile = path.join('/tmp', `routecodex-daemon-watch-${timestamp}.log`);
30
+
31
+ function log(line) {
32
+ const ts = new Date().toISOString();
33
+ const out = `[${ts}] ${line}`;
34
+ console.log(out);
35
+ fs.appendFileSync(logFile, out + '\n');
36
+ }
37
+
38
+ function getPidsForPort(p) {
39
+ try {
40
+ const out = execSync(`lsof -t -nP -iTCP:${p} -sTCP:LISTEN`, { encoding: 'utf8', timeout: 5000 });
41
+ return out.trim().split('\n').filter(Boolean);
42
+ } catch {
43
+ return [];
44
+ }
45
+ }
46
+
47
+ function getRoutecodexPids() {
48
+ try {
49
+ const out = execSync(`pgrep -fa "routecodex|dist/index.js"`, { encoding: 'utf8' });
50
+ const lines = out.trim().split('\n').filter(Boolean);
51
+ return lines.map(line => {
52
+ const m = line.match(/^(\d+)\s+(.*)$/);
53
+ if (m) return { pid: m[1], cmd: m[2] };
54
+ return null;
55
+ }).filter(Boolean);
56
+ } catch {
57
+ return [];
58
+ }
59
+ }
60
+
61
+ function isPidAlive(pid) {
62
+ try {
63
+ process.kill(Number(pid), 0);
64
+ return true;
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ function captureSystemLogs(minutes = 2) {
71
+ try {
72
+ const out = execSync(`log show --last ${minutes}m --style syslog 2>&1 | grep -iE "routecodex|node.*index|killed|sigkill|sigterm|jetsam|memorystatus" | tail -n 100`, { encoding: 'utf8', shell: true, timeout: 10000 });
73
+ return out.trim();
74
+ } catch (e) {
75
+ return `Failed to capture logs: ${e.message}`;
76
+ }
77
+ }
78
+
79
+ function captureProcessSnapshot() {
80
+ try {
81
+ const out = execSync('ps -Ao pid,ppid,pcpu,rss,etime,comm,args | grep -E "(routecodex|node|dist/index.js)"', { encoding: 'utf8', shell: true });
82
+ return out.trim();
83
+ } catch (e) {
84
+ return `No matching processes: ${e.message}`;
85
+ }
86
+ }
87
+
88
+ async function main() {
89
+ log('monitor start');
90
+ log(`label=${label || 'none'}`);
91
+ log(`logFile=${logFile}`);
92
+
93
+ const watchedPids = new Map();
94
+
95
+ // Initial scan
96
+ if (port) {
97
+ const pids = getPidsForPort(port);
98
+ for (const pid of pids) {
99
+ watchedPids.set(pid, { type: 'port', port, cmd: 'listener' });
100
+ log(`watching pid=${pid} (port=${port})`);
101
+ }
102
+ }
103
+
104
+ const rcPids = getRoutecodexPids();
105
+ for (const p of rcPids) {
106
+ if (!watchedPids.has(p.pid)) {
107
+ watchedPids.set(p.pid, { type: 'cmd', cmd: p.cmd });
108
+ log(`watching pid=${p.pid} (cmd=${p.cmd})`);
109
+ }
110
+ }
111
+
112
+ if (watchedPids.size === 0) {
113
+ log('no routecodex processes found to watch');
114
+ process.exit(1);
115
+ }
116
+
117
+ log(`watching ${watchedPids.size} process(es)`);
118
+
119
+ // Watch loop
120
+ while (true) {
121
+ await new Promise(r => setTimeout(r, 500));
122
+
123
+ const vanished = [];
124
+ for (const [pid, info] of watchedPids) {
125
+ if (!isPidAlive(pid)) {
126
+ vanished.push({ pid, ...info });
127
+ }
128
+ }
129
+
130
+ if (vanished.length > 0) {
131
+ for (const v of vanished) {
132
+ log(`PROCESS VANISHED: pid=${v.pid} type=${v.type} cmd=${v.cmd || v.port || 'unknown'}`);
133
+ watchedPids.delete(v.pid);
134
+ }
135
+
136
+ log('--- SYSTEM LOGS (last 2m) ---');
137
+ const logs = captureSystemLogs(2);
138
+ for (const line of logs.split('\n')) {
139
+ log(`SYSLOG: ${line}`);
140
+ }
141
+
142
+ log('--- PROCESS SNAPSHOT ---');
143
+ const snapshot = captureProcessSnapshot();
144
+ for (const line of snapshot.split('\n')) {
145
+ log(`PS: ${line}`);
146
+ }
147
+
148
+ // Rescan for new processes
149
+ const newPids = getRoutecodexPids();
150
+ for (const p of newPids) {
151
+ if (!watchedPids.has(p.pid)) {
152
+ watchedPids.set(p.pid, { type: 'cmd', cmd: p.cmd });
153
+ log(`new process detected: pid=${p.pid} cmd=${p.cmd}`);
154
+ }
155
+ }
156
+ }
157
+
158
+ // Check for port change if port specified
159
+ if (port) {
160
+ const currentPids = getPidsForPort(port);
161
+ for (const pid of currentPids) {
162
+ if (!watchedPids.has(pid)) {
163
+ watchedPids.set(pid, { type: 'port', port, cmd: 'listener' });
164
+ log(`new listener on port ${port}: pid=${pid}`);
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ process.on('SIGINT', () => {
172
+ log('monitor interrupted by SIGINT');
173
+ process.exit(0);
174
+ });
175
+
176
+ process.on('SIGTERM', () => {
177
+ log('monitor interrupted by SIGTERM');
178
+ process.exit(0);
179
+ });
180
+
181
+ main().catch(e => {
182
+ log(`ERROR: ${e.message}`);
183
+ process.exit(1);
184
+ });
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env bash
2
+ # Monitor a TCP port's listener PID and record when it disappears.
3
+ # Usage:
4
+ # bash scripts/monitor/port-kill-watch.sh <port> [label]
5
+ # Output log:
6
+ # /tmp/routecodex-port-watch-<port>-<timestamp>.log
7
+
8
+ set -euo pipefail
9
+
10
+ PORT=${1:-}
11
+ LABEL=${2:-}
12
+
13
+ if [[ -z "$PORT" ]]; then
14
+ echo "Usage: $0 <port> [label]" >&2
15
+ exit 2
16
+ fi
17
+
18
+ if ! [[ "$PORT" =~ ^[0-9]+$ ]]; then
19
+ echo "Invalid port: $PORT" >&2
20
+ exit 2
21
+ fi
22
+
23
+ TS=$(date +%Y%m%d-%H%M%S)
24
+ LOG_FILE="/tmp/routecodex-port-watch-${PORT}-${TS}.log"
25
+ INTERVAL_MS=500
26
+
27
+ log() {
28
+ echo "[$(date +%Y-%m-%dT%H:%M:%S%z)] $*" | tee -a "$LOG_FILE" >/dev/null
29
+ }
30
+
31
+ resolve_pid() {
32
+ lsof -t -nP -iTCP:"$PORT" -sTCP:LISTEN 2>/dev/null | head -n 1 || true
33
+ }
34
+
35
+ log "watch start port=${PORT} label=${LABEL:-none} log=${LOG_FILE}"
36
+
37
+ PID=$(resolve_pid)
38
+ if [[ -z "$PID" ]]; then
39
+ log "no listener detected on port ${PORT}"
40
+ exit 1
41
+ fi
42
+
43
+ log "listener pid=${PID}"
44
+
45
+ while true; do
46
+ if ! kill -0 "$PID" 2>/dev/null; then
47
+ log "listener pid ${PID} exited"
48
+ break
49
+ fi
50
+ CURRENT=$(resolve_pid)
51
+ if [[ -z "$CURRENT" ]]; then
52
+ log "listener on port ${PORT} vanished (pid=${PID})"
53
+ break
54
+ fi
55
+ if [[ "$CURRENT" != "$PID" ]]; then
56
+ log "listener pid changed ${PID} -> ${CURRENT}"
57
+ PID="$CURRENT"
58
+ fi
59
+ sleep 0.5
60
+ done
61
+
62
+ log "capturing recent logs (last 2m, syslog style)"
63
+ log "--- log show (filtered) ---"
64
+ /usr/bin/log show --last 2m --style syslog 2>/dev/null \
65
+ | grep -i -E "killed|kill|SIGKILL|SIGTERM|routecodex|node|memorystatus|jetsam" \
66
+ | tail -n 200 \
67
+ | tee -a "$LOG_FILE" >/dev/null || true
68
+ log "--- end ---"
69
+
70
+ log "capturing process snapshot"
71
+ ps -Ao pid,ppid,state,etime,comm,args | grep -E "(routecodex|node|dist/index.js)" | tee -a "$LOG_FILE" >/dev/null || true
72
+
73
+ log "done"
74
+
@@ -43,7 +43,7 @@ if [ ! -f "dist/cli.js" ]; then
43
43
  exit 1
44
44
  fi
45
45
 
46
- chmod +x dist/cli.js
46
+ node scripts/ensure-cli-executable.mjs || true
47
47
 
48
48
  # 全局安装
49
49
  echo "🌍 全局安装..."