@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.
- package/configsamples/config.json +19 -0
- package/configsamples/provider/deepseek/config.v1.json +59 -0
- package/dist/build-info.js +2 -2
- package/dist/cli/commands/claude.d.ts +4 -0
- package/dist/cli/commands/claude.js +56 -0
- package/dist/cli/commands/claude.js.map +1 -0
- package/dist/cli/commands/clock-admin.d.ts +20 -0
- package/dist/cli/commands/clock-admin.js +234 -0
- package/dist/cli/commands/clock-admin.js.map +1 -0
- package/dist/cli/commands/code.d.ts +0 -42
- package/dist/cli/commands/code.js +4 -414
- package/dist/cli/commands/code.js.map +1 -1
- package/dist/cli/commands/codex.d.ts +4 -0
- package/dist/cli/commands/codex.js +43 -0
- package/dist/cli/commands/codex.js.map +1 -0
- package/dist/cli/commands/examples.js +13 -16
- package/dist/cli/commands/examples.js.map +1 -1
- package/dist/cli/commands/init/basic.d.ts +40 -0
- package/dist/cli/commands/init/basic.js +482 -0
- package/dist/cli/commands/init/basic.js.map +1 -0
- package/dist/cli/commands/init/camoufox.d.ts +7 -0
- package/dist/cli/commands/init/camoufox.js +59 -0
- package/dist/cli/commands/init/camoufox.js.map +1 -0
- package/dist/cli/commands/init/interactive.d.ts +18 -0
- package/dist/cli/commands/init/interactive.js +223 -0
- package/dist/cli/commands/init/interactive.js.map +1 -0
- package/dist/cli/commands/init/shared.d.ts +66 -0
- package/dist/cli/commands/init/shared.js +9 -0
- package/dist/cli/commands/init/shared.js.map +1 -0
- package/dist/cli/commands/init/workflows.d.ts +29 -0
- package/dist/cli/commands/init/workflows.js +341 -0
- package/dist/cli/commands/init/workflows.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -26
- package/dist/cli/commands/init.js +220 -53
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/launcher-kernel.d.ts +78 -0
- package/dist/cli/commands/launcher-kernel.js +1194 -0
- package/dist/cli/commands/launcher-kernel.js.map +1 -0
- package/dist/cli/commands/start.js +27 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +24 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/stop.d.ts +1 -0
- package/dist/cli/commands/stop.js +201 -4
- package/dist/cli/commands/stop.js.map +1 -1
- package/dist/cli/commands/tmux-inject.d.ts +20 -0
- package/dist/cli/commands/tmux-inject.js +212 -0
- package/dist/cli/commands/tmux-inject.js.map +1 -0
- package/dist/cli/config/init-provider-catalog.js +34 -0
- package/dist/cli/config/init-provider-catalog.js.map +1 -1
- package/dist/cli/register/claude-command.d.ts +3 -0
- package/dist/cli/register/claude-command.js +5 -0
- package/dist/cli/register/claude-command.js.map +1 -0
- package/dist/cli/register/clock-admin-command.d.ts +3 -0
- package/dist/cli/register/clock-admin-command.js +5 -0
- package/dist/cli/register/clock-admin-command.js.map +1 -0
- package/dist/cli/register/codex-command.d.ts +3 -0
- package/dist/cli/register/codex-command.js +5 -0
- package/dist/cli/register/codex-command.js.map +1 -0
- package/dist/cli/register/status-config-commands.d.ts +2 -0
- package/dist/cli/register/status-config-commands.js.map +1 -1
- package/dist/cli/register/tmux-inject-command.d.ts +3 -0
- package/dist/cli/register/tmux-inject-command.js +5 -0
- package/dist/cli/register/tmux-inject-command.js.map +1 -0
- package/dist/cli/server/port-utils.d.ts +3 -2
- package/dist/cli/server/port-utils.js +171 -32
- package/dist/cli/server/port-utils.js.map +1 -1
- package/dist/cli.js +45 -6
- package/dist/cli.js.map +1 -1
- package/dist/client/gemini/gemini-protocol-client.js +56 -5
- package/dist/client/gemini/gemini-protocol-client.js.map +1 -1
- package/dist/commands/token-daemon.js +59 -7
- package/dist/commands/token-daemon.js.map +1 -1
- package/dist/commands/validate.js +87 -15
- package/dist/commands/validate.js.map +1 -1
- package/dist/config/routecodex-config-loader.js +31 -2
- package/dist/config/routecodex-config-loader.js.map +1 -1
- package/dist/docs/daemon-admin-ui.html +948 -74
- package/dist/index.d.ts +1 -0
- package/dist/index.js +325 -37
- package/dist/index.js.map +1 -1
- package/dist/manager/quota/provider-quota-center.js +8 -14
- package/dist/manager/quota/provider-quota-center.js.map +1 -1
- package/dist/modules/llmswitch/bridge.d.ts +39 -0
- package/dist/modules/llmswitch/bridge.js +169 -0
- package/dist/modules/llmswitch/bridge.js.map +1 -1
- package/dist/modules/pipeline/utils/colored-logger.js +1 -1
- package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
- package/dist/providers/auth/deepseek-account-auth.d.ts +39 -0
- package/dist/providers/auth/deepseek-account-auth.js +329 -0
- package/dist/providers/auth/deepseek-account-auth.js.map +1 -0
- package/dist/providers/auth/deepseek-account-token-acquirer.d.ts +15 -0
- package/dist/providers/auth/deepseek-account-token-acquirer.js +644 -0
- package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -0
- package/dist/providers/auth/oauth-lifecycle.js +26 -4
- package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
- package/dist/providers/auth/oauth-repair-cooldown.d.ts +5 -0
- package/dist/providers/auth/oauth-repair-cooldown.js +39 -0
- package/dist/providers/auth/oauth-repair-cooldown.js.map +1 -1
- package/dist/providers/auth/token-scanner/index.d.ts +6 -0
- package/dist/providers/auth/token-scanner/index.js +53 -0
- package/dist/providers/auth/token-scanner/index.js.map +1 -1
- package/dist/providers/core/api/provider-config.d.ts +17 -2
- package/dist/providers/core/api/provider-types.d.ts +6 -0
- package/dist/providers/core/api/provider-types.js.map +1 -1
- package/dist/providers/core/config/camoufox-launcher.d.ts +7 -0
- package/dist/providers/core/config/camoufox-launcher.js +68 -21
- package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
- package/dist/providers/core/config/service-profiles.js +19 -0
- package/dist/providers/core/config/service-profiles.js.map +1 -1
- package/dist/providers/core/contracts/deepseek-provider-contract.d.ts +34 -0
- package/dist/providers/core/contracts/deepseek-provider-contract.js +100 -0
- package/dist/providers/core/contracts/deepseek-provider-contract.js.map +1 -0
- package/dist/providers/core/runtime/anthropic-http-provider.d.ts +0 -5
- package/dist/providers/core/runtime/anthropic-http-provider.js +0 -26
- package/dist/providers/core/runtime/anthropic-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/deepseek-http-provider.d.ts +35 -0
- package/dist/providers/core/runtime/deepseek-http-provider.js +373 -0
- package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -0
- package/dist/providers/core/runtime/deepseek-session-pow.d.ts +55 -0
- package/dist/providers/core/runtime/deepseek-session-pow.js +422 -0
- package/dist/providers/core/runtime/deepseek-session-pow.js.map +1 -0
- package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +0 -3
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +0 -72
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/gemini-http-provider.d.ts +1 -7
- package/dist/providers/core/runtime/gemini-http-provider.js +3 -110
- package/dist/providers/core/runtime/gemini-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.d.ts +1 -0
- package/dist/providers/core/runtime/http-request-executor.js +4 -0
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.d.ts +10 -4
- package/dist/providers/core/runtime/http-transport-provider.js +308 -82
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/providers/core/runtime/iflow-http-provider.d.ts +0 -4
- package/dist/providers/core/runtime/iflow-http-provider.js +0 -28
- package/dist/providers/core/runtime/iflow-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/provider-factory.d.ts +5 -0
- package/dist/providers/core/runtime/provider-factory.js +59 -6
- package/dist/providers/core/runtime/provider-factory.js.map +1 -1
- package/dist/providers/core/runtime/responses-provider.d.ts +0 -2
- package/dist/providers/core/runtime/responses-provider.js +0 -11
- package/dist/providers/core/runtime/responses-provider.js.map +1 -1
- package/dist/providers/core/strategies/oauth-device-flow.js +16 -1
- package/dist/providers/core/strategies/oauth-device-flow.js.map +1 -1
- package/dist/providers/core/utils/provider-type-utils.js +2 -1
- package/dist/providers/core/utils/provider-type-utils.js.map +1 -1
- package/dist/providers/profile/families/anthropic-profile.d.ts +2 -0
- package/dist/providers/profile/families/anthropic-profile.js +32 -0
- package/dist/providers/profile/families/anthropic-profile.js.map +1 -0
- package/dist/providers/profile/families/antigravity-profile.d.ts +2 -0
- package/dist/providers/profile/families/antigravity-profile.js +109 -0
- package/dist/providers/profile/families/antigravity-profile.js.map +1 -0
- package/dist/providers/profile/families/glm-profile.d.ts +2 -0
- package/dist/providers/profile/families/glm-profile.js +48 -0
- package/dist/providers/profile/families/glm-profile.js.map +1 -0
- package/dist/providers/profile/families/iflow-profile.d.ts +2 -0
- package/dist/providers/profile/families/iflow-profile.js +232 -0
- package/dist/providers/profile/families/iflow-profile.js.map +1 -0
- package/dist/providers/profile/families/qwen-profile.d.ts +2 -0
- package/dist/providers/profile/families/qwen-profile.js +14 -0
- package/dist/providers/profile/families/qwen-profile.js.map +1 -0
- package/dist/providers/profile/families/responses-profile.d.ts +2 -0
- package/dist/providers/profile/families/responses-profile.js +28 -0
- package/dist/providers/profile/families/responses-profile.js.map +1 -0
- package/dist/providers/profile/profile-contracts.d.ts +74 -0
- package/dist/providers/profile/profile-contracts.js +2 -0
- package/dist/providers/profile/profile-contracts.js.map +1 -0
- package/dist/providers/profile/profile-registry.d.ts +3 -0
- package/dist/providers/profile/profile-registry.js +40 -0
- package/dist/providers/profile/profile-registry.js.map +1 -0
- package/dist/providers/profile/provider-directory.d.ts +2 -0
- package/dist/providers/profile/provider-directory.js +55 -0
- package/dist/providers/profile/provider-directory.js.map +1 -0
- package/dist/providers/profile/provider-profile-loader.js +43 -3
- package/dist/providers/profile/provider-profile-loader.js.map +1 -1
- package/dist/providers/profile/provider-profile.d.ts +8 -0
- package/dist/scripts/deepseek/pow-solver.mjs +146 -0
- package/dist/scripts/deepseek/sha3_wasm_bg.7b9ca65ddd.wasm +0 -0
- package/dist/server/handlers/config-admin-handler.js +27 -0
- package/dist/server/handlers/config-admin-handler.js.map +1 -1
- package/dist/server/runtime/http-server/clock-client-registry.d.ts +113 -0
- package/dist/server/runtime/http-server/clock-client-registry.js +592 -0
- package/dist/server/runtime/http-server/clock-client-registry.js.map +1 -0
- package/dist/server/runtime/http-server/clock-client-routes.d.ts +2 -0
- package/dist/server/runtime/http-server/clock-client-routes.js +481 -0
- package/dist/server/runtime/http-server/clock-client-routes.js.map +1 -0
- package/dist/server/runtime/http-server/clock-daemon-inject-config.d.ts +1 -0
- package/dist/server/runtime/http-server/clock-daemon-inject-config.js +11 -0
- package/dist/server/runtime/http-server/clock-daemon-inject-config.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +3 -3
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/auth-session.d.ts +1 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-session.js +18 -2
- package/dist/server/runtime/http-server/daemon-admin/auth-session.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/control-handler.js +2 -15
- package/dist/server/runtime/http-server/daemon-admin/control-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +65 -7
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
- package/dist/server/runtime/http-server/executor-metadata.js +37 -1
- package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
- package/dist/server/runtime/http-server/executor-provider.js +55 -0
- package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
- package/dist/server/runtime/http-server/executor-response.js +49 -1
- package/dist/server/runtime/http-server/executor-response.js.map +1 -1
- package/dist/server/runtime/http-server/index.d.ts +10 -0
- package/dist/server/runtime/http-server/index.js +534 -9
- package/dist/server/runtime/http-server/index.js.map +1 -1
- package/dist/server/runtime/http-server/managed-process-probe.d.ts +6 -0
- package/dist/server/runtime/http-server/managed-process-probe.js +294 -0
- package/dist/server/runtime/http-server/managed-process-probe.js.map +1 -0
- package/dist/server/runtime/http-server/middleware.js +16 -1
- package/dist/server/runtime/http-server/middleware.js.map +1 -1
- package/dist/server/runtime/http-server/provider-utils.js +6 -2
- package/dist/server/runtime/http-server/provider-utils.js.map +1 -1
- package/dist/server/runtime/http-server/request-executor.d.ts +1 -0
- package/dist/server/runtime/http-server/request-executor.js +360 -35
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.js +95 -3
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/runtime/http-server/stats-manager.d.ts +10 -0
- package/dist/server/runtime/http-server/stats-manager.js +119 -16
- package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
- package/dist/server/runtime/http-server/tmux-session-probe.d.ts +3 -0
- package/dist/server/runtime/http-server/tmux-session-probe.js +101 -0
- package/dist/server/runtime/http-server/tmux-session-probe.js.map +1 -0
- package/dist/server/utils/stage-logger.js +21 -5
- package/dist/server/utils/stage-logger.js.map +1 -1
- package/dist/token-daemon/index.js +59 -10
- package/dist/token-daemon/index.js.map +1 -1
- package/dist/token-daemon/server-utils.d.ts +1 -0
- package/dist/token-daemon/server-utils.js +4 -1
- package/dist/token-daemon/server-utils.js.map +1 -1
- package/dist/token-daemon/token-daemon.js +38 -4
- package/dist/token-daemon/token-daemon.js.map +1 -1
- package/dist/token-daemon/token-types.d.ts +1 -1
- package/dist/token-daemon/token-types.js +2 -1
- package/dist/token-daemon/token-types.js.map +1 -1
- package/dist/token-daemon/token-utils.js +5 -2
- package/dist/token-daemon/token-utils.js.map +1 -1
- package/dist/utils/clock-client-token.d.ts +3 -0
- package/dist/utils/clock-client-token.js +54 -0
- package/dist/utils/clock-client-token.js.map +1 -0
- package/dist/utils/managed-server-pids.d.ts +25 -0
- package/dist/utils/managed-server-pids.js +176 -0
- package/dist/utils/managed-server-pids.js.map +1 -0
- package/dist/utils/process-lifecycle-logger.d.ts +8 -0
- package/dist/utils/process-lifecycle-logger.js +151 -0
- package/dist/utils/process-lifecycle-logger.js.map +1 -0
- package/dist/utils/runtime-exit-forensics.d.ts +30 -0
- package/dist/utils/runtime-exit-forensics.js +101 -0
- package/dist/utils/runtime-exit-forensics.js.map +1 -0
- package/dist/utils/shutdown-caller-context.d.ts +22 -0
- package/dist/utils/shutdown-caller-context.js +25 -0
- package/dist/utils/shutdown-caller-context.js.map +1 -0
- package/docs/PROVIDERS_BUILTIN.md +8 -0
- package/docs/PROVIDER_TYPES.md +3 -1
- package/docs/SERVERTOOL_PRE_COMMAND_HOOKS.md +85 -0
- package/docs/clock-client-daemon-design.md +343 -0
- package/docs/daemon-admin-ui.html +948 -74
- package/docs/providers/deepseek-web-provider-design.md +192 -0
- package/docs/routing-instructions.md +4 -1
- package/docs/stop-message-auto.md +4 -3
- package/docs/v2-architecture/PROVIDER-V2-CHANGESET-RELEASE-CHECKLIST.md +80 -0
- package/docs/v2-architecture/PROVIDER-V2-LAYERING-ADR-DRAFT.md +225 -0
- package/docs/v2-architecture/PROVIDER-V2-MIGRATION-MATRIX-DRAFT.md +88 -0
- package/docs/v2-architecture/PROVIDER-V2-PHASED-MIGRATION-ROLLBACK-DRAFT.md +164 -0
- package/docs/v2-architecture/PROVIDER-V2-PROFILE-API-REGISTRY-DRAFT.md +201 -0
- package/docs/v2-architecture/PROVIDER-V2-PROFILE-GEMINI-DRAFT.md +56 -0
- package/docs/v2-architecture/PROVIDER-V2-REFACTOR-OVERVIEW-DRAFT.md +102 -0
- package/docs/v2-architecture/PROVIDER-V2-VERIFICATION-MATRIX-DRAFT.md +163 -0
- package/package.json +10 -9
- package/scripts/copy-compat-assets.mjs +18 -0
- package/scripts/copy-modules-config.mjs +1 -0
- package/scripts/deepseek/pow-solver.mjs +146 -0
- package/scripts/deepseek/sha3_wasm_bg.7b9ca65ddd.wasm +0 -0
- package/scripts/ensure-cli-executable.mjs +64 -0
- package/scripts/install-global.sh +5 -2
- package/scripts/install.sh +1 -1
- package/scripts/monitor/daemon-kill-watch.mjs +184 -0
- package/scripts/monitor/port-kill-watch.sh +74 -0
- 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.
|
|
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": "
|
|
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": "
|
|
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.
|
|
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
|
+
});
|
|
Binary file
|
|
@@ -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
|
-
|
|
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
|
package/scripts/install.sh
CHANGED
|
@@ -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
|
+
|