@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/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ declare class RouteCodexApp {
20
20
  * Stop the RouteCodex server
21
21
  */
22
22
  stop(): Promise<void>;
23
+ private prepareRuntimeExitForensics;
23
24
  /**
24
25
  * Get server status
25
26
  */
package/dist/index.js CHANGED
@@ -13,10 +13,65 @@ import { createRequire } from 'module';
13
13
  import { fileURLToPath } from 'url';
14
14
  import { buildInfo } from './build-info.js';
15
15
  import { isDirectExecution } from './utils/is-direct-execution.js';
16
- import { parseNetstatListeningPids } from './utils/windows-netstat.js';
17
16
  import { reportRouteError } from './error-handling/route-error-hub.js';
17
+ import { flushProcessLifecycleLogQueue, logProcessLifecycle, logProcessLifecycleSync } from './utils/process-lifecycle-logger.js';
18
+ import { getShutdownCallerContext } from './utils/shutdown-caller-context.js';
19
+ import { listManagedServerPidsByPort } from './utils/managed-server-pids.js';
20
+ import { inferUngracefulPreviousExit, resolveRuntimeLifecyclePath, safeMarkRuntimeExit, safeReadRuntimeLifecycle, safeWriteRuntimeLifecycle } from './utils/runtime-exit-forensics.js';
18
21
  import { resolveRouteCodexConfigPath } from './config/config-paths.js';
19
22
  import { loadRouteCodexConfig } from './config/routecodex-config-loader.js';
23
+ let runtimeMinimalLogFilterInstalled = false;
24
+ function resolveBoolFromEnv(value, fallback) {
25
+ if (!value) {
26
+ return fallback;
27
+ }
28
+ const normalized = value.trim().toLowerCase();
29
+ if (normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on') {
30
+ return true;
31
+ }
32
+ if (normalized === '0' || normalized === 'false' || normalized === 'no' || normalized === 'off') {
33
+ return false;
34
+ }
35
+ return fallback;
36
+ }
37
+ function isMinimalRuntimeLogEnabled() {
38
+ return resolveBoolFromEnv(process.env.ROUTECODEX_MINIMAL_RUNTIME_LOGS ?? process.env.RCC_MINIMAL_RUNTIME_LOGS, true);
39
+ }
40
+ function stringifyLogArg(value) {
41
+ if (typeof value === 'string') {
42
+ return value;
43
+ }
44
+ try {
45
+ return JSON.stringify(value);
46
+ }
47
+ catch {
48
+ return String(value);
49
+ }
50
+ }
51
+ function shouldSuppressRuntimeLogLine(text) {
52
+ if (!text) {
53
+ return false;
54
+ }
55
+ return (text.includes('[servertool][') ||
56
+ text.includes('[virtual-router]'));
57
+ }
58
+ function installMinimalRuntimeLogFilter() {
59
+ if (runtimeMinimalLogFilterInstalled || !isMinimalRuntimeLogEnabled()) {
60
+ return;
61
+ }
62
+ runtimeMinimalLogFilterInstalled = true;
63
+ const originalLog = console.log.bind(console);
64
+ const originalInfo = console.info.bind(console);
65
+ const filter = (original) => (...args) => {
66
+ const line = args.map(stringifyLogArg).join(' ');
67
+ if (shouldSuppressRuntimeLogLine(line)) {
68
+ return;
69
+ }
70
+ original(...args);
71
+ };
72
+ console.log = filter(originalLog);
73
+ console.info = filter(originalInfo);
74
+ }
20
75
  // Polyfill CommonJS require for ESM runtime to satisfy dependencies that call require()
21
76
  let moduleRequire = null;
22
77
  try {
@@ -73,7 +128,34 @@ async function reportCliError(code, message, error, severity = 'medium', details
73
128
  }
74
129
  let lastShutdownReason = { kind: 'unknown' };
75
130
  let restartInProgress = false;
131
+ let currentRuntimeLifecyclePath = null;
132
+ function setCurrentRuntimeLifecyclePath(value) {
133
+ currentRuntimeLifecyclePath = typeof value === 'string' && value.trim() ? value.trim() : null;
134
+ }
135
+ function createRuntimeRunId() {
136
+ try {
137
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
138
+ return crypto.randomUUID();
139
+ }
140
+ }
141
+ catch {
142
+ // ignore
143
+ }
144
+ return `run_${Date.now()}_${Math.random().toString(16).slice(2, 10)}`;
145
+ }
76
146
  function recordShutdownReason(reason) {
147
+ if (reason.kind === 'signal' && reason.signal === 'SIGKILL') {
148
+ logProcessLifecycleSync({
149
+ event: 'self_termination',
150
+ source: 'index.recordShutdownReason',
151
+ details: {
152
+ reason: 'self_kill_signal',
153
+ signal: 'SIGKILL',
154
+ pid: process.pid,
155
+ caller: resolveSignalCaller('SIGKILL')
156
+ }
157
+ });
158
+ }
77
159
  if (lastShutdownReason.kind === 'unknown') {
78
160
  lastShutdownReason = reason;
79
161
  }
@@ -86,10 +168,27 @@ process.on('exit', (code) => {
86
168
  };
87
169
  if (reason.kind === 'signal') {
88
170
  payload.signal = reason.signal;
171
+ payload.caller = resolveSignalCaller(reason.signal);
89
172
  }
90
173
  else if (reason.kind === 'uncaughtException' || reason.kind === 'startupError' || reason.kind === 'stopError') {
91
174
  payload.message = reason.message;
92
175
  }
176
+ if (currentRuntimeLifecyclePath) {
177
+ safeMarkRuntimeExit(currentRuntimeLifecyclePath, {
178
+ kind: reason.kind,
179
+ code: typeof code === 'number' ? code : null,
180
+ ...(reason.kind === 'signal' ? { signal: reason.signal } : {}),
181
+ ...(reason.kind === 'uncaughtException' || reason.kind === 'startupError' || reason.kind === 'stopError'
182
+ ? { message: reason.message }
183
+ : {}),
184
+ recordedAt: new Date().toISOString()
185
+ });
186
+ }
187
+ logProcessLifecycleSync({
188
+ event: 'process_exit',
189
+ source: 'index.process.on.exit',
190
+ details: payload
191
+ });
93
192
  // Single-line JSON for easy grep in logs
94
193
  console.log('[routecodex:shutdown]', JSON.stringify(payload));
95
194
  });
@@ -132,6 +231,32 @@ function readRecordBoolean(record, key) {
132
231
  }
133
232
  return readBoolean(record[key]);
134
233
  }
234
+ function resolveSignalCaller(signal) {
235
+ const fromShutdownRoute = getShutdownCallerContext({ maxAgeMs: 10 * 60 * 1000 });
236
+ if (fromShutdownRoute) {
237
+ return {
238
+ callerType: 'shutdown_route_context',
239
+ signal,
240
+ ...fromShutdownRoute
241
+ };
242
+ }
243
+ let parentCommand = '';
244
+ try {
245
+ const ps = spawnSync('ps', ['-o', 'command=', '-p', String(process.ppid)], { encoding: 'utf8' });
246
+ parentCommand = String(ps.stdout || '').trim().slice(0, 1024);
247
+ }
248
+ catch {
249
+ parentCommand = '';
250
+ }
251
+ return {
252
+ callerType: 'unknown_signal_sender',
253
+ signal,
254
+ observedTs: new Date().toISOString(),
255
+ processPid: process.pid,
256
+ processPpid: process.ppid,
257
+ parentCommand
258
+ };
259
+ }
135
260
  if (!process.env.ROUTECODEX_VERSION) {
136
261
  let resolvedVersion = 'dev';
137
262
  try {
@@ -215,6 +340,7 @@ class RouteCodexApp {
215
340
  */
216
341
  async start() {
217
342
  try {
343
+ installMinimalRuntimeLogFilter();
218
344
  console.log('šŸš€ Starting RouteCodex server...');
219
345
  console.log(`šŸ“ Modules configuration file: ${this.modulesConfigPath}`);
220
346
  // ē®€åŒ–ę—„åæ—å·²ē§»é™¤čæč”Œę—¶č‡ŖåŠØåŗ”ē”Øļ¼Œäæē•™ CLI é…ē½®čƒ½åŠ›
@@ -324,6 +450,7 @@ class RouteCodexApp {
324
450
  }
325
451
  return value;
326
452
  };
453
+ this.prepareRuntimeExitForensics(bindPort);
327
454
  process.env.ROUTECODEX_PORT = String(bindPort);
328
455
  process.env.RCC_PORT = String(bindPort);
329
456
  process.env.ROUTECODEX_HTTP_HOST = bindHost;
@@ -360,6 +487,14 @@ class RouteCodexApp {
360
487
  }
361
488
  // 6. åœØęœåŠ”å·²ē›‘å¬ēš„å‰ęäø‹åˆå§‹åŒ–čæč”Œę—¶ļ¼ˆåŒ…ę‹¬ Hub Pipeline 和 Provider OAuth)
362
489
  await this.httpServer.initializeWithUserConfig(userConfig, { providerProfiles });
490
+ try {
491
+ const routeCodexHome = path.join(homedir(), '.routecodex');
492
+ fsSync.mkdirSync(routeCodexHome, { recursive: true });
493
+ fsSync.writeFileSync(path.join(routeCodexHome, `server-${bindPort}.pid`), String(process.pid), 'utf8');
494
+ }
495
+ catch {
496
+ // ignore pid file write failures
497
+ }
363
498
  this._isRunning = true;
364
499
  // 7. č®°å½•å½“å‰čæč”ŒęØ”å¼ļ¼ˆä»… V2)
365
500
  console.log(`${buildInfo.mode === 'dev' ? '🧪 dev' : '🚢 release'} mode Ā· šŸ”µ V2 dynamic pipeline active`);
@@ -424,6 +559,47 @@ class RouteCodexApp {
424
559
  process.exit(1);
425
560
  }
426
561
  }
562
+ prepareRuntimeExitForensics(port) {
563
+ try {
564
+ const lifecyclePath = resolveRuntimeLifecyclePath(port);
565
+ const previous = safeReadRuntimeLifecycle(lifecyclePath);
566
+ const inference = inferUngracefulPreviousExit({
567
+ previous,
568
+ currentPid: process.pid
569
+ });
570
+ if (inference.shouldReport) {
571
+ logProcessLifecycle({
572
+ event: 'previous_ungraceful_exit_detected',
573
+ source: 'index.start',
574
+ details: {
575
+ port,
576
+ markerPath: lifecyclePath,
577
+ reason: inference.reason,
578
+ previousPid: previous?.pid ?? null,
579
+ previousRunId: previous?.runId ?? null,
580
+ previousStartedAt: previous?.startedAt ?? null,
581
+ inference: 'likely_external_kill_or_forced_termination'
582
+ }
583
+ });
584
+ console.warn('[routecodex:forensics] detected previous ungraceful exit on port=' + String(port) +
585
+ ' (pid=' + String(previous?.pid ?? 'unknown') + ', runId=' + String(previous?.runId ?? 'unknown') + ')');
586
+ }
587
+ const currentState = {
588
+ runId: createRuntimeRunId(),
589
+ pid: process.pid,
590
+ port,
591
+ startedAt: new Date().toISOString(),
592
+ buildVersion: buildInfo.version,
593
+ buildMode: buildInfo.mode
594
+ };
595
+ if (safeWriteRuntimeLifecycle(lifecyclePath, currentState)) {
596
+ setCurrentRuntimeLifecyclePath(lifecyclePath);
597
+ }
598
+ }
599
+ catch {
600
+ // forensics path is best-effort and must never block startup
601
+ }
602
+ }
427
603
  /**
428
604
  * Get server status
429
605
  */
@@ -587,11 +763,30 @@ async function ensurePortAvailable(port, opts = {}) {
587
763
  }
588
764
  }
589
765
  }
590
- // Fall back to SIGTERM/SIGKILL processes listening on the port (avoid self-kill by probing first)
591
- const pids = await listPidsOnPort(port);
766
+ // Fall back to SIGTERM/SIGKILL on managed RouteCodex pid files only.
767
+ const pids = listManagedServerPidsByPort(port).map(String);
592
768
  if (!pids.length) {
769
+ const occupied = !(await canBind(port));
770
+ if (occupied) {
771
+ logProcessLifecycle({
772
+ event: 'port_cleanup',
773
+ source: 'index.ensurePortAvailable',
774
+ details: { port, result: 'occupied_unmanaged' }
775
+ });
776
+ throw new Error(`Port ${port} is occupied by unmanaged process; refusing blind kill. Stop process manually or call /shutdown if it is RouteCodex.`);
777
+ }
778
+ logProcessLifecycle({
779
+ event: 'port_cleanup',
780
+ source: 'index.ensurePortAvailable',
781
+ details: { port, result: 'no_managed_pid' }
782
+ });
593
783
  return;
594
784
  }
785
+ logProcessLifecycle({
786
+ event: 'port_cleanup',
787
+ source: 'index.ensurePortAvailable',
788
+ details: { port, result: 'managed_pid_found', pids }
789
+ });
595
790
  for (const pid of pids) {
596
791
  killPidBestEffort(Number(pid), { force: false });
597
792
  }
@@ -601,7 +796,14 @@ async function ensurePortAvailable(port, opts = {}) {
601
796
  return;
602
797
  }
603
798
  }
604
- const remain = await listPidsOnPort(port);
799
+ const remain = listManagedServerPidsByPort(port).map(String);
800
+ if (remain.length) {
801
+ logProcessLifecycle({
802
+ event: 'port_cleanup',
803
+ source: 'index.ensurePortAvailable',
804
+ details: { port, result: 'force_kill', pids: remain }
805
+ });
806
+ }
605
807
  for (const pid of remain) {
606
808
  killPidBestEffort(Number(pid), { force: true });
607
809
  }
@@ -611,24 +813,67 @@ function killPidBestEffort(pid, opts) {
611
813
  if (!Number.isFinite(pid) || pid <= 0) {
612
814
  return;
613
815
  }
816
+ if (pid === process.pid) {
817
+ logProcessLifecycle({
818
+ event: 'kill_attempt',
819
+ source: 'index.ensurePortAvailable',
820
+ details: {
821
+ targetPid: pid,
822
+ signal: 'SKIP_SELF',
823
+ result: 'skipped',
824
+ reason: 'self_kill_guard',
825
+ caller: resolveSignalCaller('SELF_GUARD')
826
+ }
827
+ });
828
+ return;
829
+ }
830
+ const signal = opts.force ? 'SIGKILL' : 'SIGTERM';
614
831
  if (process.platform === 'win32') {
615
832
  const args = ['/PID', String(pid), '/T'];
616
833
  if (opts.force) {
617
834
  args.push('/F');
618
835
  }
836
+ logProcessLifecycle({
837
+ event: 'kill_attempt',
838
+ source: 'index.ensurePortAvailable',
839
+ details: { targetPid: pid, signal: opts.force ? 'TASKKILL_F' : 'TASKKILL', result: 'attempt' }
840
+ });
619
841
  try {
620
842
  spawnSync('taskkill', args, { stdio: 'ignore', encoding: 'utf8' });
843
+ logProcessLifecycle({
844
+ event: 'kill_attempt',
845
+ source: 'index.ensurePortAvailable',
846
+ details: { targetPid: pid, signal: opts.force ? 'TASKKILL_F' : 'TASKKILL', result: 'success' }
847
+ });
621
848
  }
622
- catch {
623
- // best-effort
849
+ catch (error) {
850
+ logProcessLifecycle({
851
+ event: 'kill_attempt',
852
+ source: 'index.ensurePortAvailable',
853
+ details: { targetPid: pid, signal: opts.force ? 'TASKKILL_F' : 'TASKKILL', result: 'failed', error }
854
+ });
624
855
  }
625
856
  return;
626
857
  }
858
+ logProcessLifecycle({
859
+ event: 'kill_attempt',
860
+ source: 'index.ensurePortAvailable',
861
+ details: { targetPid: pid, signal, result: 'attempt' }
862
+ });
627
863
  try {
628
- process.kill(pid, opts.force ? 'SIGKILL' : 'SIGTERM');
864
+ process.kill(pid, signal);
865
+ logProcessLifecycle({
866
+ event: 'kill_attempt',
867
+ source: 'index.ensurePortAvailable',
868
+ details: { targetPid: pid, signal, result: 'success' }
869
+ });
629
870
  }
630
- catch {
631
- // best-effort
871
+ catch (error) {
872
+ logProcessLifecycle({
873
+ event: 'kill_attempt',
874
+ source: 'index.ensurePortAvailable',
875
+ details: { targetPid: pid, signal, result: 'failed', error }
876
+ });
632
877
  }
633
878
  }
634
879
  async function canBind(port) {
@@ -645,32 +890,6 @@ async function canBind(port) {
645
890
  }
646
891
  });
647
892
  }
648
- async function listPidsOnPort(port) {
649
- if (process.platform === 'win32') {
650
- try {
651
- const result = spawnSync('netstat', ['-ano', '-p', 'tcp'], { encoding: 'utf8' });
652
- if (result.error) {
653
- return [];
654
- }
655
- return parseNetstatListeningPids(result.stdout || '', port).map(String);
656
- }
657
- catch {
658
- return [];
659
- }
660
- }
661
- return await new Promise(resolve => {
662
- try {
663
- const ps = spawn('lsof', ['-ti', `:${port}`]);
664
- let out = '';
665
- ps.stdout.on('data', d => (out += String(d)));
666
- ps.on('close', () => resolve(out.split(/\s+/).map(s => s.trim()).filter(Boolean)));
667
- ps.on('error', () => resolve([]));
668
- }
669
- catch {
670
- resolve([]);
671
- }
672
- });
673
- }
674
893
  async function attemptHttpShutdown(port) {
675
894
  try {
676
895
  const controller = new AbortController();
@@ -685,9 +904,20 @@ async function attemptHttpShutdown(port) {
685
904
  signal: controller.signal
686
905
  }).catch(() => null);
687
906
  clearTimeout(timeout);
688
- return !!(res && res.ok);
907
+ const ok = !!(res && res.ok);
908
+ logProcessLifecycle({
909
+ event: 'http_shutdown_probe',
910
+ source: 'index.attemptHttpShutdown',
911
+ details: { port, result: ok ? 'ok' : 'not_ready', status: res?.status }
912
+ });
913
+ return ok;
689
914
  }
690
- catch {
915
+ catch (error) {
916
+ logProcessLifecycle({
917
+ event: 'http_shutdown_probe',
918
+ source: 'index.attemptHttpShutdown',
919
+ details: { port, result: 'failed', error }
920
+ });
691
921
  return false;
692
922
  }
693
923
  }
@@ -706,13 +936,34 @@ async function gracefulShutdown(app) {
706
936
  ? 'reason=stopError'
707
937
  : 'reason=unknown';
708
938
  console.log(`\nšŸ›‘ Stopping RouteCodex server gracefully... (${reasonLabel})`);
939
+ logProcessLifecycle({
940
+ event: 'graceful_shutdown',
941
+ source: 'index.gracefulShutdown',
942
+ details: {
943
+ reason: reasonLabel,
944
+ result: 'start',
945
+ caller: reason.kind === 'signal' ? resolveSignalCaller(reason.signal) : getShutdownCallerContext({ maxAgeMs: 10 * 60 * 1000 })
946
+ }
947
+ });
709
948
  try {
710
949
  await app.stop();
950
+ logProcessLifecycle({
951
+ event: 'graceful_shutdown',
952
+ source: 'index.gracefulShutdown',
953
+ details: { reason: reasonLabel, result: 'success' }
954
+ });
955
+ await flushProcessLifecycleLogQueue();
711
956
  process.exit(0);
712
957
  }
713
958
  catch (error) {
714
959
  await reportCliError('GRACEFUL_SHUTDOWN_FAILED', 'Error during graceful shutdown', error, 'high');
715
960
  console.error('āŒ Error during graceful shutdown:', error);
961
+ logProcessLifecycle({
962
+ event: 'graceful_shutdown',
963
+ source: 'index.gracefulShutdown',
964
+ details: { reason: reasonLabel, result: 'failed', error }
965
+ });
966
+ await flushProcessLifecycleLogQueue();
716
967
  process.exit(1);
717
968
  }
718
969
  }
@@ -762,6 +1013,11 @@ async function restartSelf(app, signal) {
762
1013
  }
763
1014
  restartInProgress = true;
764
1015
  recordShutdownReason({ kind: 'signal', signal });
1016
+ logProcessLifecycle({
1017
+ event: 'restart_signal_received',
1018
+ source: 'index.restartSelf',
1019
+ details: { signal }
1020
+ });
765
1021
  console.log(`\nšŸ”„ Restart signal received (${signal}). Restarting RouteCodex server process...`);
766
1022
  const argv = process.argv.slice(1);
767
1023
  const env = { ...process.env };
@@ -790,13 +1046,20 @@ async function restartSelf(app, signal) {
790
1046
  }
791
1047
  try {
792
1048
  const child = spawn(process.execPath, argv, { stdio: 'inherit', env });
1049
+ logProcessLifecycle({
1050
+ event: 'restart_spawn_child',
1051
+ source: 'index.restartSelf',
1052
+ details: { signal, childPid: child.pid ?? null, argv }
1053
+ });
793
1054
  console.log(`[routecodex:restart] spawned pid=${child.pid ?? 'unknown'}`);
794
1055
  }
795
1056
  catch (error) {
796
1057
  await reportCliError('SERVER_RESTART_SPAWN_FAILED', 'Failed to spawn restarted server', error, 'critical').catch(() => { });
797
1058
  console.error('āŒ Failed to spawn restarted server:', error);
1059
+ await flushProcessLifecycleLogQueue();
798
1060
  process.exit(1);
799
1061
  }
1062
+ await flushProcessLifecycleLogQueue();
800
1063
  process.exit(0);
801
1064
  }
802
1065
  /**
@@ -807,10 +1070,20 @@ async function main() {
807
1070
  const app = new RouteCodexApp(modulesConfigPath);
808
1071
  // Setup signal handlers for graceful shutdown
809
1072
  process.on('SIGTERM', () => {
1073
+ logProcessLifecycleSync({
1074
+ event: 'signal_received',
1075
+ source: 'index.main',
1076
+ details: { signal: 'SIGTERM', caller: resolveSignalCaller('SIGTERM') }
1077
+ });
810
1078
  recordShutdownReason({ kind: 'signal', signal: 'SIGTERM' });
811
1079
  void gracefulShutdown(app);
812
1080
  });
813
1081
  process.on('SIGINT', () => {
1082
+ logProcessLifecycleSync({
1083
+ event: 'signal_received',
1084
+ source: 'index.main',
1085
+ details: { signal: 'SIGINT', caller: resolveSignalCaller('SIGINT') }
1086
+ });
814
1087
  recordShutdownReason({ kind: 'signal', signal: 'SIGINT' });
815
1088
  void gracefulShutdown(app);
816
1089
  });
@@ -819,15 +1092,30 @@ async function main() {
819
1092
  // - The server respawns itself (same argv), then exits.
820
1093
  if (process.platform !== 'win32') {
821
1094
  process.on('SIGUSR2', () => {
1095
+ logProcessLifecycle({
1096
+ event: 'signal_received',
1097
+ source: 'index.main',
1098
+ details: { signal: 'SIGUSR2' }
1099
+ });
822
1100
  void restartSelf(app, 'SIGUSR2');
823
1101
  });
824
1102
  process.on('SIGHUP', () => {
1103
+ logProcessLifecycle({
1104
+ event: 'signal_received',
1105
+ source: 'index.main',
1106
+ details: { signal: 'SIGHUP' }
1107
+ });
825
1108
  void restartSelf(app, 'SIGHUP');
826
1109
  });
827
1110
  }
828
1111
  // Handle uncaught exceptions
829
1112
  process.on('uncaughtException', (error) => {
830
1113
  const message = error instanceof Error ? error.message : String(error ?? '');
1114
+ logProcessLifecycle({
1115
+ event: 'uncaught_exception',
1116
+ source: 'index.main',
1117
+ details: { message, error }
1118
+ });
831
1119
  recordShutdownReason({ kind: 'uncaughtException', message });
832
1120
  void reportCliError('UNCAUGHT_EXCEPTION', 'Uncaught Exception', error, 'critical');
833
1121
  console.error('āŒ Uncaught Exception:', error);