@jsonstudio/rcc 0.90.814 → 0.90.872

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 (217) hide show
  1. package/README.md +8 -0
  2. package/configsamples/provider-default/ali-coding-plan/config.v2.json +76 -0
  3. package/configsamples/provider-default/antigravity/config.v2.json +142 -0
  4. package/configsamples/provider-default/ark-coding-plan/config.v2.json +64 -0
  5. package/configsamples/provider-default/crs/config.v2.json +54 -0
  6. package/configsamples/provider-default/deepseek-web/config.v2.json +56 -0
  7. package/configsamples/provider-default/gemini/config.v2.json +43 -0
  8. package/configsamples/provider-default/gemini-cli/config.v2.json +45 -0
  9. package/configsamples/provider-default/gemini-native/config.v2.json +208 -0
  10. package/configsamples/provider-default/glm/config.v2.json +33 -0
  11. package/configsamples/provider-default/glm-anthropic/config.v2.json +29 -0
  12. package/configsamples/provider-default/kimi/config.v2.json +25 -0
  13. package/configsamples/provider-default/lmstudio/config.v2.json +79 -0
  14. package/configsamples/provider-default/lmstudio-proxy/config.v2.json +78 -0
  15. package/configsamples/provider-default/manifest.json +31 -0
  16. package/configsamples/provider-default/meituan/config.v2.json +20 -0
  17. package/configsamples/provider-default/mimo/config.v2.json +26 -0
  18. package/configsamples/provider-default/modelscope/config.v2.json +81 -0
  19. package/configsamples/provider-default/my-openai/config.v2.json +20 -0
  20. package/configsamples/provider-default/nvidia/config.v2.json +32 -0
  21. package/configsamples/provider-default/opencode-zen-free/config.v2.json +56 -0
  22. package/configsamples/provider-default/openrouter/config.v2.json +210 -0
  23. package/configsamples/provider-default/qwen/config.v2.json +38 -0
  24. package/configsamples/provider-default/qwenchat/config.v2.json +53 -0
  25. package/configsamples/provider-default/tab/config.v2.json +26 -0
  26. package/configsamples/provider-default/tabglm/config.v2.json +77 -0
  27. package/dist/build-info.js +2 -2
  28. package/dist/cli/commands/config.d.ts +5 -0
  29. package/dist/cli/commands/config.js +369 -1
  30. package/dist/cli/commands/config.js.map +1 -1
  31. package/dist/cli/commands/examples.js +3 -0
  32. package/dist/cli/commands/examples.js.map +1 -1
  33. package/dist/cli/commands/init.js +25 -1
  34. package/dist/cli/commands/init.js.map +1 -1
  35. package/dist/cli/commands/launcher-kernel.js +122 -46
  36. package/dist/cli/commands/launcher-kernel.js.map +1 -1
  37. package/dist/cli/commands/start.js +60 -3
  38. package/dist/cli/commands/start.js.map +1 -1
  39. package/dist/cli/config/bundled-provider-pack.d.ts +20 -0
  40. package/dist/cli/config/bundled-provider-pack.js +146 -0
  41. package/dist/cli/config/bundled-provider-pack.js.map +1 -0
  42. package/dist/cli/register/status-config-commands.d.ts +2 -0
  43. package/dist/cli/register/status-config-commands.js.map +1 -1
  44. package/dist/cli.js +81 -28
  45. package/dist/cli.js.map +1 -1
  46. package/dist/debug/snapshot-store.js +2 -1
  47. package/dist/debug/snapshot-store.js.map +1 -1
  48. package/dist/index.js +23 -14
  49. package/dist/index.js.map +1 -1
  50. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +1 -1
  51. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -1
  52. package/dist/manager/quota/provider-quota-center.js +1 -1
  53. package/dist/manager/quota/provider-quota-center.js.map +1 -1
  54. package/dist/manager/storage/file-store.js +10 -0
  55. package/dist/manager/storage/file-store.js.map +1 -1
  56. package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js +18 -1
  57. package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js.map +1 -1
  58. package/dist/modules/llmswitch/bridge/snapshot-recorder.js +132 -51
  59. package/dist/modules/llmswitch/bridge/snapshot-recorder.js.map +1 -1
  60. package/dist/provider-sdk/provider-runtime-inference.js +2 -2
  61. package/dist/provider-sdk/provider-runtime-inference.js.map +1 -1
  62. package/dist/providers/auth/deepseek-account-token-acquirer.js +32 -3
  63. package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -1
  64. package/dist/providers/core/api/provider-types.d.ts +11 -0
  65. package/dist/providers/core/config/service-profiles.js +1 -1
  66. package/dist/providers/core/runtime/deepseek-http-provider.d.ts +2 -0
  67. package/dist/providers/core/runtime/deepseek-http-provider.js +31 -1
  68. package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -1
  69. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.d.ts +3 -2
  70. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js +513 -96
  71. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js.map +1 -1
  72. package/dist/providers/core/runtime/standard-tool-text-harvest.d.ts +8 -0
  73. package/dist/providers/core/runtime/standard-tool-text-harvest.js +16 -0
  74. package/dist/providers/core/runtime/standard-tool-text-harvest.js.map +1 -0
  75. package/dist/providers/core/runtime/standard-tool-text-request-transform.d.ts +4 -1
  76. package/dist/providers/core/runtime/standard-tool-text-request-transform.js +121 -3
  77. package/dist/providers/core/runtime/standard-tool-text-request-transform.js.map +1 -1
  78. package/dist/providers/core/utils/snapshot-writer.js +5 -2
  79. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  80. package/dist/providers/profile/provider-profile-loader.js +52 -1
  81. package/dist/providers/profile/provider-profile-loader.js.map +1 -1
  82. package/dist/providers/profile/provider-profile.d.ts +3 -0
  83. package/dist/server/handlers/handler-response-utils.js +1 -0
  84. package/dist/server/handlers/handler-response-utils.js.map +1 -1
  85. package/dist/server/handlers/images-handler.d.ts +9 -0
  86. package/dist/server/handlers/images-handler.js +258 -0
  87. package/dist/server/handlers/images-handler.js.map +1 -0
  88. package/dist/server/handlers/types.d.ts +7 -0
  89. package/dist/server/runtime/http-server/antigravity-startup-tasks.d.ts +3 -0
  90. package/dist/server/runtime/http-server/antigravity-startup-tasks.js +16 -0
  91. package/dist/server/runtime/http-server/antigravity-startup-tasks.js.map +1 -1
  92. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +3 -18
  93. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
  94. package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.d.ts +7 -0
  95. package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.js +17 -0
  96. package/dist/server/runtime/http-server/daemon-admin/providers-handler-utils.js.map +1 -1
  97. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +50 -17
  98. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
  99. package/dist/server/runtime/http-server/daemon-admin-routes.js +32 -2
  100. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
  101. package/dist/server/runtime/http-server/executor/provider-response-converter.js +42 -13
  102. package/dist/server/runtime/http-server/executor/provider-response-converter.js.map +1 -1
  103. package/dist/server/runtime/http-server/executor/provider-response-utils.js +41 -3
  104. package/dist/server/runtime/http-server/executor/provider-response-utils.js.map +1 -1
  105. package/dist/server/runtime/http-server/executor/usage-aggregator.js +7 -7
  106. package/dist/server/runtime/http-server/executor/usage-aggregator.js.map +1 -1
  107. package/dist/server/runtime/http-server/executor/usage-logger.d.ts +9 -0
  108. package/dist/server/runtime/http-server/executor/usage-logger.js +35 -2
  109. package/dist/server/runtime/http-server/executor/usage-logger.js.map +1 -1
  110. package/dist/server/runtime/http-server/executor-metadata.js +12 -4
  111. package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
  112. package/dist/server/runtime/http-server/executor-pipeline.js +24 -15
  113. package/dist/server/runtime/http-server/executor-pipeline.js.map +1 -1
  114. package/dist/server/runtime/http-server/executor-provider.d.ts +6 -1
  115. package/dist/server/runtime/http-server/executor-provider.js +137 -5
  116. package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
  117. package/dist/server/runtime/http-server/http-server-bootstrap.js +6 -0
  118. package/dist/server/runtime/http-server/http-server-bootstrap.js.map +1 -1
  119. package/dist/server/runtime/http-server/http-server-lifecycle.js +23 -15
  120. package/dist/server/runtime/http-server/http-server-lifecycle.js.map +1 -1
  121. package/dist/server/runtime/http-server/http-server-runtime-providers.js +14 -4
  122. package/dist/server/runtime/http-server/http-server-runtime-providers.js.map +1 -1
  123. package/dist/server/runtime/http-server/http-server-runtime-setup.js +83 -1
  124. package/dist/server/runtime/http-server/http-server-runtime-setup.js.map +1 -1
  125. package/dist/server/runtime/http-server/hub-shadow-compare.js +2 -41
  126. package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
  127. package/dist/server/runtime/http-server/provider-routing-scope.d.ts +9 -0
  128. package/dist/server/runtime/http-server/provider-routing-scope.js +20 -0
  129. package/dist/server/runtime/http-server/provider-routing-scope.js.map +1 -0
  130. package/dist/server/runtime/http-server/provider-traffic-governor.d.ts +67 -0
  131. package/dist/server/runtime/http-server/provider-traffic-governor.js +467 -0
  132. package/dist/server/runtime/http-server/provider-traffic-governor.js.map +1 -0
  133. package/dist/server/runtime/http-server/request-executor.d.ts +8 -0
  134. package/dist/server/runtime/http-server/request-executor.js +446 -21
  135. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  136. package/dist/server/runtime/http-server/routes.js +13 -0
  137. package/dist/server/runtime/http-server/routes.js.map +1 -1
  138. package/dist/server/runtime/http-server/session-client-registry.js +30 -4
  139. package/dist/server/runtime/http-server/session-client-registry.js.map +1 -1
  140. package/dist/server/runtime/http-server/session-client-route-utils.d.ts +7 -0
  141. package/dist/server/runtime/http-server/session-client-route-utils.js +38 -0
  142. package/dist/server/runtime/http-server/session-client-route-utils.js.map +1 -1
  143. package/dist/server/runtime/http-server/session-client-routes.js +12 -2
  144. package/dist/server/runtime/http-server/session-client-routes.js.map +1 -1
  145. package/dist/server/utils/request-id-manager.js +42 -5
  146. package/dist/server/utils/request-id-manager.js.map +1 -1
  147. package/dist/server/utils/stage-logger.d.ts +1 -0
  148. package/dist/server/utils/stage-logger.js +27 -0
  149. package/dist/server/utils/stage-logger.js.map +1 -1
  150. package/dist/utils/errorsamples.js +3 -1
  151. package/dist/utils/errorsamples.js.map +1 -1
  152. package/dist/utils/sensitive-redaction.d.ts +1 -0
  153. package/dist/utils/sensitive-redaction.js +122 -0
  154. package/dist/utils/sensitive-redaction.js.map +1 -0
  155. package/docs/INSTALLATION_AND_QUICKSTART.md +14 -1
  156. package/docs/PORTS.md +12 -0
  157. package/docs/lmstudio-tool-calling.md +25 -0
  158. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.d.ts +3 -0
  159. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.js +62 -0
  160. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwenchat-web.json +47 -0
  161. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/operation-table-runner.js +68 -7
  162. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper-from-chat.js +138 -3
  163. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-chat-process-request-utils.js +24 -0
  164. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-chat-process-entry.js +7 -1
  165. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage.js +7 -0
  166. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.d.ts +24 -0
  167. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.js +203 -0
  168. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-route-and-outbound.js +17 -12
  169. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +11 -0
  170. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-stage-timing.js +82 -1
  171. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +47 -14
  172. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +43 -0
  173. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/client-remap-protocol-switch.js +222 -19
  174. package/node_modules/@jsonstudio/llms/dist/conversion/hub/policy/policy-engine.js +2 -2
  175. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-pending-tool-sync.js +24 -7
  176. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.js +90 -1
  177. package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.d.ts +1 -0
  178. package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.js +252 -1
  179. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge/utils.js +5 -3
  180. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge.js +44 -4
  181. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.d.ts +3 -1
  182. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.js +20 -23
  183. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-governor.js +68 -30
  184. package/node_modules/@jsonstudio/llms/dist/conversion/snapshot-utils.js +48 -8
  185. package/node_modules/@jsonstudio/llms/dist/native/router_hotpath_napi.node +0 -0
  186. package/node_modules/@jsonstudio/llms/dist/quota/quota-state.js +2 -2
  187. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-state/store.js +35 -2
  188. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.js +9 -9
  189. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/sticky-session-store.js +104 -18
  190. package/node_modules/@jsonstudio/llms/dist/servertool/engine.js +79 -32
  191. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.js +49 -0
  192. package/node_modules/@jsonstudio/llms/dist/servertool/pending-session.js +48 -2
  193. package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.js +14 -1
  194. package/node_modules/@jsonstudio/llms/dist/servertool/types.d.ts +1 -0
  195. package/node_modules/@jsonstudio/llms/package.json +1 -1
  196. package/node_modules/ajv/dist/compile/jtd/serialize.js +9 -2
  197. package/node_modules/ajv/dist/compile/jtd/serialize.js.map +1 -1
  198. package/node_modules/ajv/dist/core.d.ts +1 -0
  199. package/node_modules/ajv/dist/core.js.map +1 -1
  200. package/node_modules/ajv/dist/vocabularies/validation/pattern.js +13 -4
  201. package/node_modules/ajv/dist/vocabularies/validation/pattern.js.map +1 -1
  202. package/node_modules/ajv/lib/compile/jtd/serialize.ts +13 -2
  203. package/node_modules/ajv/lib/core.ts +1 -0
  204. package/node_modules/ajv/lib/vocabularies/validation/pattern.ts +15 -4
  205. package/node_modules/ajv/package.json +2 -1
  206. package/package.json +15 -10
  207. package/scripts/ci/repo-sanity.mjs +23 -2
  208. package/scripts/ci/secrets-check.mjs +48 -0
  209. package/scripts/ci/silent-failure-audit.mjs +192 -0
  210. package/scripts/mock-provider/run-regressions.mjs +1 -0
  211. package/scripts/pack-mode.mjs +32 -36
  212. package/scripts/publish-rcc.mjs +38 -60
  213. package/scripts/tests/apply-patch-loop.mjs +1 -0
  214. package/scripts/tests/blackbox-rcc-vs-routecodex-antigravity.mjs +2 -0
  215. package/scripts/tools-dev/responses-debug-client/src/index.ts +8 -3
  216. package/scripts/verify-e2e-toolcall.mjs +1 -0
  217. package/scripts/verify-install-e2e.mjs +2 -1
@@ -107,6 +107,7 @@ export interface CurrentOptions {
107
107
  timestamp?: "string" | "date" // JTD only
108
108
  parseDate?: boolean // JTD only
109
109
  allowDate?: boolean // JTD only
110
+ specialNumbers?: "fast" | "null" // JTD only
110
111
  $comment?:
111
112
  | true
112
113
  | ((comment: string, schemaPath?: string, rootSchema?: AnySchemaObject) => unknown)
@@ -1,6 +1,7 @@
1
1
  import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"
2
2
  import type {KeywordCxt} from "../../compile/validate"
3
3
  import {usePattern} from "../code"
4
+ import {useFunc} from "../../compile/util"
4
5
  import {_, str} from "../../compile/codegen"
5
6
 
6
7
  export type PatternError = ErrorObject<"pattern", {pattern: string}, string | {$data: string}>
@@ -17,11 +18,21 @@ const def: CodeKeywordDefinition = {
17
18
  $data: true,
18
19
  error,
19
20
  code(cxt: KeywordCxt) {
20
- const {data, $data, schema, schemaCode, it} = cxt
21
- // TODO regexp should be wrapped in try/catchs
21
+ const {gen, data, $data, schema, schemaCode, it} = cxt
22
22
  const u = it.opts.unicodeRegExp ? "u" : ""
23
- const regExp = $data ? _`(new RegExp(${schemaCode}, ${u}))` : usePattern(cxt, schema)
24
- cxt.fail$data(_`!${regExp}.test(${data})`)
23
+ if ($data) {
24
+ const {regExp} = it.opts.code
25
+ const regExpCode = regExp.code === "new RegExp" ? _`new RegExp` : useFunc(gen, regExp)
26
+ const valid = gen.let("valid")
27
+ gen.try(
28
+ () => gen.assign(valid, _`${regExpCode}(${schemaCode}, ${u}).test(${data})`),
29
+ () => gen.assign(valid, false)
30
+ )
31
+ cxt.fail$data(_`!${valid}`)
32
+ } else {
33
+ const regExp = usePattern(cxt, schema)
34
+ cxt.fail$data(_`!${regExp}.test(${data})`)
35
+ }
25
36
  },
26
37
  }
27
38
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ajv",
3
- "version": "8.17.1",
3
+ "version": "8.18.0",
4
4
  "description": "Another JSON Schema Validator",
5
5
  "main": "dist/ajv.js",
6
6
  "types": "dist/ajv.d.ts",
@@ -9,6 +9,7 @@
9
9
  "dist/",
10
10
  ".runkit_example.js"
11
11
  ],
12
+ "sideEffects": false,
12
13
  "scripts": {
13
14
  "eslint": "eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite",
14
15
  "prettier:write": "prettier --write \"./**/*.{json,yaml,js,ts}\"",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonstudio/rcc",
3
- "version": "0.90.814",
3
+ "version": "0.90.872",
4
4
  "description": "Multi-provider OpenAI proxy server with anthropic/responses/chat support (release)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -52,8 +52,9 @@
52
52
  "verify:repo-sanity": "node scripts/ci/repo-sanity.mjs",
53
53
  "verify:llmswitch-rustification-audit": "node scripts/ci/llmswitch-rustification-audit.mjs",
54
54
  "verify:file-line-limit": "node scripts/ci/check-file-line-limit.mjs",
55
+ "audit:silent-failure": "node scripts/ci/silent-failure-audit.mjs",
55
56
  "vr:dryrun": "node scripts/virtual-router-dryrun.mjs",
56
- "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/server/runtime/http-server/executor/usage-aggregator.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/deepseek-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/session-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-sample-replay.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-hit-log.spec.ts tests/sharedmodule/virtual-router-routing-model-validation.spec.ts tests/unified-hub/hub-v1-single-path-imports.spec.ts",
57
+ "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/server/runtime/http-server/executor/usage-aggregator.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/deepseek-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/session-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-sample-replay.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-hit-log.spec.ts tests/sharedmodule/virtual-router-routing-model-validation.spec.ts tests/unified-hub/hub-v1-single-path-imports.spec.ts tests/sharedmodule/tool-governor-exec-command-guard.spec.ts",
57
58
  "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",
58
59
  "test:watch": "npm run jest:run -- --watch",
59
60
  "test:coverage": "npm run jest:run -- --coverage",
@@ -129,7 +130,7 @@
129
130
  "duplication:fix": "node scripts/duplicate-code-handler.mjs --threshold 5 --auto-fix true",
130
131
  "dup:scan": "node scripts/duplicate-code-handler.mjs --threshold 5 --output reports",
131
132
  "dup:auto-fix": "node scripts/duplicate-code-handler.mjs --threshold 5 --output reports --auto-fix true",
132
- "secrets:check": "echo 'Secrets check temporarily disabled'",
133
+ "secrets:check": "node scripts/ci/secrets-check.mjs",
133
134
  "format:check": "prettier --check src/**/*.{ts,js,json}",
134
135
  "format:fix": "prettier --write src/**/*.{ts,js,json}",
135
136
  "verify:split-args": "node scripts/verify-toolcall-arg-splitting.mjs",
@@ -155,22 +156,21 @@
155
156
  "mock:clean": "node scripts/mock-provider/clean.mjs",
156
157
  "publish:rcc": "node scripts/publish-rcc.mjs",
157
158
  "pack:rcc": "node scripts/pack-rcc.mjs",
158
- "build:rccx": "npm run build:min && node scripts/pack-mode.mjs --name @jsonstudio/rccx --bin rccx",
159
- "compare:codex:rccx": "node scripts/compare-codex-rccx.mjs",
160
159
  "fix:cli-permission": "node scripts/ensure-cli-executable.mjs",
161
- "fix:cli-shim": "node scripts/ensure-cli-command-shim.mjs"
160
+ "fix:cli-shim": "node scripts/ensure-cli-command-shim.mjs",
161
+ "public:rcc": "npm run publish:rcc --"
162
162
  },
163
163
  "dependencies": {
164
164
  "@ai-sdk/anthropic": "^3.0.58",
165
165
  "@ai-sdk/openai": "^3.0.41",
166
166
  "@anthropic-ai/sdk": "^0.65.0",
167
- "@jsonstudio/llms": "0.6.4299",
167
+ "@jsonstudio/llms": "0.6.4305",
168
168
  "@lmstudio/sdk": "^1.5.0",
169
169
  "@radix-ui/react-switch": "^1.2.6",
170
170
  "@types/socket.io": "^3.0.1",
171
171
  "ai": "^6.0.116",
172
- "ajv": "^8.17.1",
173
- "axios": "^1.12.2",
172
+ "ajv": "^8.18.0",
173
+ "axios": "^1.14.0",
174
174
  "chalk": "^5.6.2",
175
175
  "commander": "^14.0.1",
176
176
  "cors": "^2.8.5",
@@ -238,5 +238,10 @@
238
238
  },
239
239
  "bundleDependencies": [
240
240
  "@jsonstudio/llms"
241
- ]
241
+ ],
242
+ "overrides": {
243
+ "path-to-regexp": "0.1.13",
244
+ "qs": "6.15.0",
245
+ "socket.io-parser": "4.2.6"
246
+ }
242
247
  }
@@ -61,6 +61,7 @@ function isForbiddenTrackedPath(p) {
61
61
  if (p.startsWith('.iflow/')) return true;
62
62
  if (p === '.secrets.baseline') return true;
63
63
  if (p.endsWith('/.DS_Store') || p === '.DS_Store') return true;
64
+ if (/(^|\/)[^/]+\.bak\d*$/i.test(p)) return true;
64
65
  return false;
65
66
  }
66
67
 
@@ -134,6 +135,8 @@ function checkTrackedSecrets() {
134
135
  const patterns = [
135
136
  // OpenAI-style API keys.
136
137
  { label: 'openai_sk', mode: 'E', pattern: String.raw`sk-[A-Za-z0-9]{20,}` },
138
+ // OpenRouter API keys.
139
+ { label: 'openrouter_sk', mode: 'E', pattern: String.raw`sk-or-v1-[A-Za-z0-9]{32,}` },
137
140
  // Google API keys.
138
141
  { label: 'google_api_key', mode: 'E', pattern: String.raw`AIza[0-9A-Za-z\-_]{20,}` },
139
142
  // GitHub classic personal access tokens.
@@ -149,8 +152,26 @@ function checkTrackedSecrets() {
149
152
  const out = spawnSync(
150
153
  'git',
151
154
  entry.mode === 'F'
152
- ? ['grep', '-nF', '-e', entry.pattern, '--', '.', ':(exclude)scripts/ci/repo-sanity.mjs']
153
- : ['grep', '-nE', '-e', entry.pattern, '--', '.', ':(exclude)scripts/ci/repo-sanity.mjs'],
155
+ ? [
156
+ 'grep',
157
+ '-nF',
158
+ '-e',
159
+ entry.pattern,
160
+ '--',
161
+ '.',
162
+ ':(exclude)scripts/ci/repo-sanity.mjs',
163
+ ':(exclude)scripts/ci/secrets-check.mjs'
164
+ ]
165
+ : [
166
+ 'grep',
167
+ '-nE',
168
+ '-e',
169
+ entry.pattern,
170
+ '--',
171
+ '.',
172
+ ':(exclude)scripts/ci/repo-sanity.mjs',
173
+ ':(exclude)scripts/ci/secrets-check.mjs'
174
+ ],
154
175
  { encoding: 'utf8' }
155
176
  );
156
177
  // git grep exits with 1 when no matches; 0 when matches; >1 for errors.
@@ -0,0 +1,48 @@
1
+ import { spawnSync } from 'node:child_process';
2
+
3
+ const patterns = [
4
+ { label: 'openai_sk', mode: 'E', pattern: String.raw`sk-[A-Za-z0-9]{20,}` },
5
+ { label: 'openrouter_sk', mode: 'E', pattern: String.raw`sk-or-v1-[A-Za-z0-9]{32,}` },
6
+ { label: 'google_api_key', mode: 'E', pattern: String.raw`AIza[0-9A-Za-z\-_]{20,}` },
7
+ { label: 'github_pat', mode: 'E', pattern: String.raw`ghp_[A-Za-z0-9]{30,}` },
8
+ { label: 'private_key', mode: 'F', pattern: '-----BEGIN PRIVATE KEY-----' },
9
+ { label: 'rsa_private_key', mode: 'F', pattern: '-----BEGIN RSA PRIVATE KEY-----' },
10
+ { label: 'ec_private_key', mode: 'F', pattern: '-----BEGIN EC PRIVATE KEY-----' }
11
+ ];
12
+
13
+ function runGitGrep(entry) {
14
+ const args =
15
+ entry.mode === 'F'
16
+ ? ['grep', '-nF', '-e', entry.pattern, '--', '.', ':(exclude)scripts/ci/repo-sanity.mjs', ':(exclude)scripts/ci/secrets-check.mjs']
17
+ : ['grep', '-nE', '-e', entry.pattern, '--', '.', ':(exclude)scripts/ci/repo-sanity.mjs', ':(exclude)scripts/ci/secrets-check.mjs'];
18
+ const out = spawnSync('git', args, { encoding: 'utf8' });
19
+ if ((out.status ?? 0) > 1) {
20
+ throw new Error(`git grep failed for ${entry.label}: ${out.stderr || out.stdout}`);
21
+ }
22
+ if (out.status !== 0) {
23
+ return [];
24
+ }
25
+ return String(out.stdout || '')
26
+ .split('\n')
27
+ .map((line) => line.trim())
28
+ .filter(Boolean)
29
+ .map((line) => `[${entry.label}] ${line}`);
30
+ }
31
+
32
+ const hits = [];
33
+ for (const entry of patterns) {
34
+ hits.push(...runGitGrep(entry));
35
+ }
36
+
37
+ if (hits.length) {
38
+ console.error('[secrets-check] potential secrets detected in tracked files:');
39
+ for (const line of hits.slice(0, 200)) {
40
+ console.error(`- ${line}`);
41
+ }
42
+ if (hits.length > 200) {
43
+ console.error(`- ... (${hits.length - 200} more)`);
44
+ }
45
+ process.exit(2);
46
+ }
47
+
48
+ console.log('[secrets-check] ok');
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const roots = ['src', 'sharedmodule/llmswitch-core/src'];
6
+ const includeExt = /\.(ts|tsx|js|mjs|cjs|rs)$/;
7
+ const args = new Set(process.argv.slice(2));
8
+ const failOnRisk = args.has('--fail-on-risk');
9
+ const jsonOutput = args.has('--json');
10
+
11
+ const NOISE_HINT_RE = /\b(ignore|best[- ]effort|non-blocking|swallow|fallback)\b/i;
12
+ const HAS_HANDLED_RE =
13
+ /\b(throw|console\.(warn|error|info)|logger\.(warn|warning|error|info)|report\w*Error|logProcessLifecycle|log\w*NonBlocking|emit\w*|record\w*Error)\b/;
14
+
15
+ function walk(dir, out) {
16
+ if (!fs.existsSync(dir)) return;
17
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
18
+ if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name.startsWith('.')) continue;
19
+ const full = path.join(dir, entry.name);
20
+ if (entry.isDirectory()) {
21
+ walk(full, out);
22
+ continue;
23
+ }
24
+ if (includeExt.test(entry.name)) out.push(full);
25
+ }
26
+ }
27
+
28
+ function lineOf(source, index) {
29
+ let line = 1;
30
+ for (let i = 0; i < index; i++) {
31
+ if (source.charCodeAt(i) === 10) line += 1;
32
+ }
33
+ return line;
34
+ }
35
+
36
+ function findBlockEnd(source, openBraceIndex) {
37
+ let depth = 0;
38
+ let inS = false;
39
+ let inD = false;
40
+ let inT = false;
41
+ let escaped = false;
42
+ let inLineComment = false;
43
+ let inBlockComment = false;
44
+ for (let i = openBraceIndex; i < source.length; i += 1) {
45
+ const ch = source[i];
46
+ const nx = source[i + 1];
47
+ if (inLineComment) {
48
+ if (ch === '\n') inLineComment = false;
49
+ continue;
50
+ }
51
+ if (inBlockComment) {
52
+ if (ch === '*' && nx === '/') {
53
+ inBlockComment = false;
54
+ i += 1;
55
+ }
56
+ continue;
57
+ }
58
+ if (inS) {
59
+ if (!escaped && ch === '\\') {
60
+ escaped = true;
61
+ continue;
62
+ }
63
+ if (!escaped && ch === "'") inS = false;
64
+ escaped = false;
65
+ continue;
66
+ }
67
+ if (inD) {
68
+ if (!escaped && ch === '\\') {
69
+ escaped = true;
70
+ continue;
71
+ }
72
+ if (!escaped && ch === '"') inD = false;
73
+ escaped = false;
74
+ continue;
75
+ }
76
+ if (inT) {
77
+ if (!escaped && ch === '\\') {
78
+ escaped = true;
79
+ continue;
80
+ }
81
+ if (!escaped && ch === '`') inT = false;
82
+ escaped = false;
83
+ continue;
84
+ }
85
+ if (ch === '/' && nx === '/') {
86
+ inLineComment = true;
87
+ i += 1;
88
+ continue;
89
+ }
90
+ if (ch === '/' && nx === '*') {
91
+ inBlockComment = true;
92
+ i += 1;
93
+ continue;
94
+ }
95
+ if (ch === "'") {
96
+ inS = true;
97
+ continue;
98
+ }
99
+ if (ch === '"') {
100
+ inD = true;
101
+ continue;
102
+ }
103
+ if (ch === '`') {
104
+ inT = true;
105
+ continue;
106
+ }
107
+ if (ch === '{') {
108
+ depth += 1;
109
+ continue;
110
+ }
111
+ if (ch === '}') {
112
+ depth -= 1;
113
+ if (depth === 0) return i;
114
+ }
115
+ }
116
+ return -1;
117
+ }
118
+
119
+ const files = [];
120
+ for (const root of roots) walk(root, files);
121
+
122
+ const catchRisk = [];
123
+ const promiseCatchRisk = [];
124
+ const catchRe = /catch\s*(\([^)]*\))?\s*\{/g;
125
+ const promiseCatchRe = /\.catch\(\s*(\([^)]*\)\s*=>\s*)?(\{\s*\}|undefined|null)?\s*\)/g;
126
+
127
+ for (const file of files) {
128
+ const source = fs.readFileSync(file, 'utf8');
129
+
130
+ let m;
131
+ while ((m = catchRe.exec(source)) !== null) {
132
+ const open = source.indexOf('{', m.index);
133
+ if (open < 0) continue;
134
+ const end = findBlockEnd(source, open);
135
+ if (end < 0) continue;
136
+ const body = source.slice(open + 1, end).trim();
137
+ const hasHandled = HAS_HANDLED_RE.test(body);
138
+ const noopOnly = /^(?:\/\*[\s\S]*?\*\/|\/\/.*|\s|;|return\s*;)*$/.test(body);
139
+ const looksSwallow = !hasHandled && (noopOnly || NOISE_HINT_RE.test(body));
140
+ if (looksSwallow) {
141
+ catchRisk.push({
142
+ file,
143
+ line: lineOf(source, m.index),
144
+ snippet: body.split('\n').slice(0, 3).join(' ').slice(0, 180)
145
+ });
146
+ }
147
+ catchRe.lastIndex = end + 1;
148
+ }
149
+
150
+ while ((m = promiseCatchRe.exec(source)) !== null) {
151
+ promiseCatchRisk.push({ file, line: lineOf(source, m.index), snippet: m[0] });
152
+ }
153
+ }
154
+
155
+ const byFile = new Map();
156
+ for (const row of catchRisk) {
157
+ byFile.set(row.file, (byFile.get(row.file) || 0) + 1);
158
+ }
159
+ const topFiles = [...byFile.entries()]
160
+ .sort((a, b) => b[1] - a[1])
161
+ .slice(0, 40)
162
+ .map(([file, count]) => ({ file, count }));
163
+
164
+ const report = {
165
+ roots,
166
+ scannedFiles: files.length,
167
+ catchRiskCount: catchRisk.length,
168
+ promiseCatchRiskCount: promiseCatchRisk.length,
169
+ topFiles,
170
+ sample: catchRisk.slice(0, 120)
171
+ };
172
+
173
+ if (jsonOutput) {
174
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
175
+ } else {
176
+ console.log(`[silent-failure-audit] scanned files=${report.scannedFiles}`);
177
+ console.log(
178
+ `[silent-failure-audit] risky catch blocks=${report.catchRiskCount}, risky promise.catch=${report.promiseCatchRiskCount}`
179
+ );
180
+ console.log('[silent-failure-audit] top files:');
181
+ for (const row of topFiles) {
182
+ console.log(` - ${row.count} ${row.file}`);
183
+ }
184
+ console.log('[silent-failure-audit] sample:');
185
+ for (const row of report.sample.slice(0, 30)) {
186
+ console.log(` - ${row.file}:${row.line} ${row.snippet}`);
187
+ }
188
+ }
189
+
190
+ if (failOnRisk && (report.catchRiskCount > 0 || report.promiseCatchRiskCount > 0)) {
191
+ process.exit(2);
192
+ }
@@ -198,6 +198,7 @@ async function createServer(configPath, port, snapshotRoot) {
198
198
  HOME: isolatedHome,
199
199
  USERPROFILE: isolatedHome,
200
200
  ROUTECODEX_USE_MOCK: '1',
201
+ ROUTECODEX_ALLOW_MOCK_RUNTIME: '1',
201
202
  ROUTECODEX_MOCK_CONFIG_PATH: configPath,
202
203
  ROUTECODEX_MOCK_SAMPLES_DIR: MOCK_SAMPLES_DIR,
203
204
  ROUTECODEX_MOCK_VALIDATE_NAMES: '1',
@@ -62,18 +62,36 @@ function installLocalLlmsFromTarball() {
62
62
  if ((pack.status ?? 0) !== 0) {
63
63
  throw new Error(`npm pack ${localLlmsDir} failed`);
64
64
  }
65
- const lines = String(pack.stdout || '')
66
- .split('\n')
67
- .map((line) => line.trim())
68
- .filter(Boolean);
69
- const tarballName = lines[lines.length - 1];
70
- if (!tarballName) {
71
- throw new Error('npm pack local llms produced empty tarball name');
72
- }
73
- const tarballPath = path.join(tmpDir, tarballName);
74
- if (!exists(tarballPath)) {
75
- throw new Error(`local llms tarball missing: ${tarballPath}`);
65
+
66
+ const streamText = `${String(pack.stdout || '')}\n${String(pack.stderr || '')}`;
67
+ const candidates = Array.from(
68
+ new Set(
69
+ streamText
70
+ .split(/\s+/)
71
+ .map((token) => token.trim())
72
+ .filter((token) => token.endsWith('.tgz'))
73
+ )
74
+ );
75
+
76
+ const tarballsInTmp = (() => {
77
+ try {
78
+ return fs.readdirSync(tmpDir)
79
+ .filter((name) => name.endsWith('.tgz'))
80
+ .map((name) => path.join(tmpDir, name));
81
+ } catch {
82
+ return [];
83
+ }
84
+ })();
85
+
86
+ const resolvedCandidates = candidates
87
+ .map((token) => (path.isAbsolute(token) ? token : path.join(tmpDir, token)))
88
+ .filter((candidatePath) => exists(candidatePath));
89
+
90
+ const tarballPath = resolvedCandidates[0] || tarballsInTmp[0] || '';
91
+ if (!tarballPath) {
92
+ throw new Error(`local llms tarball missing (stdout=${JSON.stringify(String(pack.stdout || '').trim())})`);
76
93
  }
94
+
77
95
  runNpm(['install', '--no-audit', '--no-fund', '--no-save', tarballPath]);
78
96
  } finally {
79
97
  fs.rmSync(tmpDir, { recursive: true, force: true });
@@ -108,13 +126,10 @@ function readLocalLlmsVersion() {
108
126
 
109
127
  const isDevPkg = args.name === 'routecodex';
110
128
  const isRcc = args.name === 'rcc' || args.name === '@jsonstudio/rcc';
111
- const isRccx = args.name === '@jsonstudio/rccx';
112
129
 
113
130
  let hadDevLink = false;
114
- if (!isRccx) {
115
- hadDevLink = isSymlink(llmsPath);
116
- runEnsureMode('release');
117
- }
131
+ hadDevLink = isSymlink(llmsPath);
132
+ runEnsureMode('release');
118
133
 
119
134
  const original = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
120
135
  fs.writeFileSync(backupPath, JSON.stringify(original, null, 2));
@@ -138,7 +153,7 @@ try {
138
153
  mutated.name = args.name;
139
154
  mutated.bin = { [args.bin]: 'dist/cli.js' };
140
155
  // Ensure description mentions mode
141
- const suffix = (isRcc || isRccx) ? ' (release)' : ' (dev)';
156
+ const suffix = isRcc ? ' (release)' : ' (dev)';
142
157
  mutated.description = String(original.description || 'RouteCodex')
143
158
  .replace(/\s*\((dev|release)\)$/, '')
144
159
  .concat(suffix);
@@ -189,25 +204,6 @@ try {
189
204
  }
190
205
  mutated.files = baseFiles;
191
206
  }
192
- } else if (isRccx) {
193
- // rccx: wasm-backed llms 核心,通过 npm alias 将 @jsonstudio/llms 指向 wasm 引擎包。
194
- mutated.bundledDependencies = [];
195
- mutated.bundleDependencies = [];
196
-
197
- const deps = { ...(original.dependencies || {}) };
198
- // 移除原有 TS 版 llms 直连依赖
199
- if (deps['@jsonstudio/llms']) {
200
- delete deps['@jsonstudio/llms'];
201
- }
202
- // 推断 wasm 引擎版本,若未声明则使用本地 llms-engine 缺省版本
203
- const engineVersion = deps['@jsonstudio/llms-engine'] || '^0.3.0';
204
- deps['@jsonstudio/llms-engine'] = engineVersion;
205
- // 通过 npm alias 保持 import 形状不变
206
- deps['@jsonstudio/llms'] = `npm:@jsonstudio/llms-engine@${engineVersion}`;
207
- deps.ajv = deps.ajv || '^8.17.1';
208
- deps.zod = deps.zod || '^3.23.8';
209
-
210
- mutated.dependencies = deps;
211
207
  }
212
208
  fs.writeFileSync(pkgPath, JSON.stringify(mutated, null, 2));
213
209
 
@@ -6,98 +6,76 @@ import { fileURLToPath } from 'node:url';
6
6
 
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
  const PROJECT_ROOT = path.resolve(__dirname, '..');
9
- const PACK_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'pack-mode.mjs');
10
9
  const pkgPath = path.join(PROJECT_ROOT, 'package.json');
11
- const llmsPath = path.join(PROJECT_ROOT, 'node_modules', '@jsonstudio', 'llms');
12
- const localLlmsPkgPath = path.join(PROJECT_ROOT, 'sharedmodule', 'llmswitch-core', 'package.json');
13
10
 
14
11
  function parseArgs(argv) {
15
- const out = {};
12
+ const out = { passthrough: [] };
16
13
  for (let i = 2; i < argv.length; i++) {
17
14
  const a = argv[i];
18
15
  if (a === '--llms-tgz') { out.llmsTgz = argv[++i]; continue; }
19
16
  if (a === '--llms-version') { out.llmsVersion = argv[++i]; continue; }
17
+ if (a === '--tag') { out.tag = argv[++i]; continue; }
18
+ if (a === '--dry-run') { out.dryRun = true; continue; }
19
+ out.passthrough.push(a);
20
20
  }
21
21
  return out;
22
22
  }
23
23
 
24
- function exists(p) {
25
- try {
26
- fs.accessSync(p);
27
- return true;
28
- } catch {
29
- return false;
30
- }
31
- }
32
-
33
24
  function run(command, args, options = {}) {
34
- const res = spawnSync(command, args, { stdio: 'inherit', ...options });
25
+ const res = spawnSync(command, args, { stdio: 'inherit', cwd: PROJECT_ROOT, ...options });
35
26
  if ((res.status ?? 0) !== 0) {
36
27
  throw new Error(`${command} ${args.join(' ')} failed`);
37
28
  }
38
29
  }
39
30
 
31
+ function readPkgVersion() {
32
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
33
+ return String(pkg.version || '').trim();
34
+ }
35
+
40
36
  try {
41
37
  const args = parseArgs(process.argv);
42
- const llmsTgz = String(args.llmsTgz || process.env.RCC_LLMS_TGZ || '').trim();
43
- const llmsVersion = String(
44
- args.llmsVersion ||
45
- process.env.RCC_LLMS_VERSION ||
46
- (exists(localLlmsPkgPath) ? JSON.parse(fs.readFileSync(localLlmsPkgPath, 'utf-8')).version : '')
47
- ).trim();
48
38
 
49
- const hadDevLink = (() => {
50
- try {
51
- return fs.lstatSync(llmsPath).isSymbolicLink();
52
- } catch {
53
- return false;
54
- }
55
- })();
39
+ // 始终内联本地 llms,避免发布流程改动全局 llms link。
40
+ const env = {
41
+ ...process.env,
42
+ RCC_LLMS_INLINE_LOCAL: process.env.RCC_LLMS_INLINE_LOCAL ?? '1'
43
+ };
56
44
 
57
- if (llmsTgz) {
58
- if (!exists(llmsTgz)) {
59
- throw new Error(`--llms-tgz not found: ${llmsTgz}`);
60
- }
61
- if (hadDevLink) {
62
- run(process.execPath, [path.join(PROJECT_ROOT, 'scripts', 'link-llmswitch.mjs'), 'unlink'], { cwd: PROJECT_ROOT });
63
- }
64
- run('npm', ['install', '--no-audit', '--no-fund', '--no-save', llmsTgz], { cwd: PROJECT_ROOT });
45
+ const packArgs = ['run', 'pack:rcc', '--'];
46
+ if (args.llmsTgz) {
47
+ packArgs.push('--llms-tgz', String(args.llmsTgz));
48
+ }
49
+ if (args.llmsVersion) {
50
+ packArgs.push('--llms-version', String(args.llmsVersion));
65
51
  }
66
52
 
67
- // 1) 使用 release 模式构建 dist。若存在本地 sharedmodule/llmswitch-core,则 release 也以其为唯一真源。
68
- run('npm', ['run', 'build:min'], {
69
- cwd: PROJECT_ROOT,
70
- env: { ...process.env, BUILD_MODE: 'release', ...(llmsVersion ? { RCC_LLMS_VERSION: llmsVersion } : {}) }
71
- });
53
+ run('npm', packArgs, { env });
72
54
 
73
- // 2) 通过 pack-mode 生成 rcc tarball(内部会临时切换 package.json.name/bin,并同步 llms 版本声明)
74
- run(
75
- process.execPath,
76
- [PACK_SCRIPT, '--name', '@jsonstudio/rcc', '--bin', 'rcc'],
77
- { cwd: PROJECT_ROOT, env: { ...process.env, ...(llmsVersion ? { RCC_LLMS_VERSION: llmsVersion } : {}) } }
78
- );
55
+ const version = readPkgVersion();
56
+ if (!version) {
57
+ throw new Error('failed to read version from package.json after pack:rcc');
58
+ }
79
59
 
80
- // 构建过程中版本号可能被 bump(gen-build-info 会 auto-bump),因此需要在 pack 之后重新读取版本号
81
- const updatedPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
82
- const version = updatedPkg.version;
83
60
  const tarballName = `jsonstudio-rcc-${version}.tgz`;
84
61
  const tarballPath = path.join(PROJECT_ROOT, tarballName);
85
-
86
62
  if (!fs.existsSync(tarballPath)) {
87
63
  throw new Error(`tarball not found: ${tarballPath}`);
88
64
  }
89
65
 
90
- // 3) 发布 npm
91
- run('npm', ['publish', tarballName], { cwd: PROJECT_ROOT });
92
-
93
- // 4) 发布结束后恢复 dev 模式(routecodex 约定始终为 dev CLI;rcc 发布时才切 release)。
94
- if (hadDevLink) {
95
- run('npm', ['run', 'llmswitch:ensure'], {
96
- cwd: PROJECT_ROOT,
97
- env: { ...process.env, BUILD_MODE: 'dev' }
98
- });
66
+ const publishArgs = ['publish', tarballName];
67
+ if (args.tag) {
68
+ publishArgs.push('--tag', String(args.tag));
99
69
  }
70
+ if (args.dryRun) {
71
+ publishArgs.push('--dry-run');
72
+ }
73
+ if (args.passthrough.length > 0) {
74
+ publishArgs.push(...args.passthrough);
75
+ }
76
+
77
+ run('npm', publishArgs);
100
78
  } catch (err) {
101
- console.error('[publish-rcc] failed:', err.message);
79
+ console.error('[publish-rcc] failed:', err instanceof Error ? err.message : String(err));
102
80
  process.exit(1);
103
81
  }