@jsonstudio/llms 0.6.2979 → 0.6.3238

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 (246) hide show
  1. package/dist/conversion/args-mapping.js +8 -0
  2. package/dist/conversion/{shared/bridge-actions.js → bridge-actions.js} +2 -1
  3. package/dist/conversion/{shared/bridge-id-utils.js → bridge-id-utils.js} +1 -1
  4. package/dist/conversion/{shared/bridge-instructions.js → bridge-instructions.js} +1 -1
  5. package/dist/conversion/{shared/bridge-message-utils.d.ts → bridge-message-utils.d.ts} +1 -1
  6. package/dist/conversion/{shared/bridge-message-utils.js → bridge-message-utils.js} +5 -149
  7. package/dist/conversion/{shared/bridge-metadata.js → bridge-metadata.js} +1 -1
  8. package/dist/conversion/{shared/bridge-policies.js → bridge-policies.js} +1 -1
  9. package/dist/conversion/codecs/gemini-openai-codec.js +27 -8
  10. package/dist/conversion/codecs/responses-openai-codec.js +1 -1
  11. package/dist/conversion/{shared/compaction-detect.d.ts → compaction-detect.d.ts} +1 -1
  12. package/dist/conversion/compaction-detect.js +4 -0
  13. package/dist/conversion/compat/actions/apply-patch-fixer.js +2 -2
  14. package/dist/conversion/compat/actions/deepseek-web-response.d.ts +0 -1
  15. package/dist/conversion/compat/actions/deepseek-web-response.js +15 -405
  16. package/dist/conversion/compat/actions/harvest-tool-calls-from-text.js +1 -1
  17. package/dist/conversion/compat/actions/lmstudio-responses-fc-ids.js +1 -1
  18. package/dist/conversion/compat/actions/qwen-transform.js +74 -2
  19. package/dist/conversion/compat/actions/snapshot.js +1 -1
  20. package/dist/conversion/compat/antigravity-session-signature.js +36 -0
  21. package/dist/conversion/compat/profiles/chat-deepseek-web.json +0 -22
  22. package/dist/conversion/compat/profiles/chat-glm.json +251 -72
  23. package/dist/conversion/compat/profiles/chat-iflow.json +174 -39
  24. package/dist/conversion/compat/profiles/chat-lmstudio.json +43 -14
  25. package/dist/conversion/hub/operation-table/operation-table-runner.js +2 -2
  26. package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +1 -1
  27. package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.d.ts +8 -0
  28. package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +404 -0
  29. package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +5 -381
  30. package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +2 -2
  31. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +2 -8
  32. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +1 -0
  33. package/dist/conversion/hub/pipeline/hub-pipeline.js +50 -3
  34. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +1 -1
  35. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +62 -0
  36. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +3 -1
  37. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.js +1 -1
  38. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/chat-process-semantics-bridge.d.ts +1 -1
  39. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +42 -29
  40. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.js +12 -0
  41. package/dist/conversion/hub/policy/protocol-spec.js +1 -1
  42. package/dist/conversion/hub/process/chat-process-clock-reminders.js +1 -1
  43. package/dist/conversion/hub/process/chat-process-clock-tools.js +1 -1
  44. package/dist/conversion/hub/process/chat-process-continue-execution.js +1 -1
  45. package/dist/conversion/hub/process/chat-process-servertool-orchestration.js +1 -1
  46. package/dist/conversion/hub/process/chat-process-web-search.js +1 -1
  47. package/dist/conversion/hub/response/provider-response.js +14 -5
  48. package/dist/conversion/hub/response/response-mappers.js +23 -1
  49. package/dist/conversion/hub/response/response-runtime.js +28 -5
  50. package/dist/conversion/hub/snapshot-recorder.js +3 -92
  51. package/dist/conversion/hub/tool-governance/engine.d.ts +8 -0
  52. package/dist/conversion/hub/tool-governance/engine.js +40 -193
  53. package/dist/conversion/hub/tool-governance/rules.js +73 -69
  54. package/dist/conversion/hub/tool-surface/tool-surface-engine.js +1 -1
  55. package/dist/conversion/index.d.ts +1 -2
  56. package/dist/conversion/index.js +1 -2
  57. package/dist/conversion/{shared/jsonish.js → jsonish.js} +1 -1
  58. package/dist/conversion/{shared/mcp-injection.js → mcp-injection.js} +1 -1
  59. package/dist/conversion/media.js +4 -0
  60. package/dist/conversion/{shared/metadata-passthrough.d.ts → metadata-passthrough.d.ts} +1 -1
  61. package/dist/conversion/{shared/metadata-passthrough.js → metadata-passthrough.js} +2 -2
  62. package/dist/conversion/payload-budget.js +47 -0
  63. package/dist/conversion/protocol-field-allowlists.d.ts +7 -0
  64. package/dist/conversion/protocol-field-allowlists.js +9 -0
  65. package/dist/conversion/{shared/protocol-state.d.ts → protocol-state.d.ts} +2 -2
  66. package/dist/conversion/{shared/protocol-state.js → protocol-state.js} +2 -2
  67. package/dist/conversion/{shared/errors.d.ts → provider-protocol-error.d.ts} +0 -3
  68. package/dist/conversion/provider-protocol-error.js +25 -0
  69. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +8 -5
  70. package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -1
  71. package/dist/conversion/responses/responses-openai-bridge.d.ts +1 -1
  72. package/dist/conversion/responses/responses-openai-bridge.js +43 -10
  73. package/dist/conversion/{shared/runtime-metadata.d.ts → runtime-metadata.d.ts} +1 -1
  74. package/dist/conversion/{shared/runtime-metadata.js → runtime-metadata.js} +2 -2
  75. package/dist/conversion/shared/anthropic-message-utils.js +19 -8
  76. package/dist/conversion/shared/chat-request-filters.d.ts +3 -4
  77. package/dist/conversion/shared/chat-request-filters.js +22 -78
  78. package/dist/conversion/shared/gemini-tool-utils.d.ts +1 -1
  79. package/dist/conversion/shared/openai-finalizer.js +1 -0
  80. package/dist/conversion/shared/openai-message-normalize.js +2 -2
  81. package/dist/conversion/shared/reasoning-normalizer.js +6 -0
  82. package/dist/conversion/shared/reasoning-utils.js +5 -2
  83. package/dist/conversion/shared/responses-conversation-store.js +1 -1
  84. package/dist/conversion/shared/responses-output-builder.js +55 -11
  85. package/dist/conversion/shared/responses-reasoning-registry.d.ts +14 -2
  86. package/dist/conversion/shared/responses-reasoning-registry.js +34 -6
  87. package/dist/conversion/shared/responses-response-utils.js +99 -9
  88. package/dist/conversion/shared/responses-tool-utils.js +1 -1
  89. package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +1 -1
  90. package/dist/conversion/shared/text-markup-normalizer.d.ts +2 -2
  91. package/dist/conversion/shared/text-markup-normalizer.js +1 -1
  92. package/dist/conversion/shared/tool-filter-pipeline.js +1 -1
  93. package/dist/conversion/shared/tool-governor.js +3 -3
  94. package/dist/conversion/shared/tool-mapping.d.ts +1 -1
  95. package/dist/conversion/{shared/snapshot-utils.d.ts → snapshot-utils.d.ts} +11 -0
  96. package/dist/conversion/{shared/snapshot-utils.js → snapshot-utils.js} +14 -23
  97. package/dist/conversion/types/text-markup-normalizer.d.ts +13 -0
  98. package/dist/conversion/types/text-markup-normalizer.js +1 -0
  99. package/dist/filters/special/request-tools-normalize.js +1 -1
  100. package/dist/filters/special/response-tool-text-canonicalize.js +2 -2
  101. package/dist/native/router_hotpath_napi.node +0 -0
  102. package/dist/quota/quota-manager.js +31 -59
  103. package/dist/quota/quota-state.js +14 -7
  104. package/dist/router/virtual-router/bootstrap/profile-builder.d.ts +1 -0
  105. package/dist/router/virtual-router/bootstrap/profile-builder.js +13 -0
  106. package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +2 -0
  107. package/dist/router/virtual-router/bootstrap/provider-normalization.js +4 -1
  108. package/dist/router/virtual-router/bootstrap/streaming-helpers.d.ts +7 -0
  109. package/dist/router/virtual-router/bootstrap/streaming-helpers.js +44 -0
  110. package/dist/router/virtual-router/bootstrap.js +2 -0
  111. package/dist/router/virtual-router/engine/routing-state/store.d.ts +1 -2
  112. package/dist/router/virtual-router/engine/routing-state/store.js +2 -2
  113. package/dist/router/virtual-router/engine-legacy/config.d.ts +11 -0
  114. package/dist/router/virtual-router/engine-legacy/config.js +108 -0
  115. package/dist/router/virtual-router/engine-legacy/direct-model.d.ts +10 -0
  116. package/dist/router/virtual-router/engine-legacy/direct-model.js +38 -0
  117. package/dist/router/virtual-router/engine-legacy/health.d.ts +13 -0
  118. package/dist/router/virtual-router/engine-legacy/health.js +104 -0
  119. package/dist/router/virtual-router/engine-legacy/helpers.d.ts +16 -0
  120. package/dist/router/virtual-router/engine-legacy/helpers.js +226 -0
  121. package/dist/router/virtual-router/engine-legacy/route-finalize.d.ts +9 -0
  122. package/dist/router/virtual-router/engine-legacy/route-finalize.js +84 -0
  123. package/dist/router/virtual-router/engine-legacy/route-selection.d.ts +17 -0
  124. package/dist/router/virtual-router/engine-legacy/route-selection.js +205 -0
  125. package/dist/router/virtual-router/engine-legacy/route-state-allowlist.d.ts +3 -0
  126. package/dist/router/virtual-router/engine-legacy/route-state-allowlist.js +36 -0
  127. package/dist/router/virtual-router/engine-legacy/route-state.d.ts +12 -0
  128. package/dist/router/virtual-router/engine-legacy/route-state.js +386 -0
  129. package/dist/router/virtual-router/engine-legacy/route-utils.d.ts +19 -0
  130. package/dist/router/virtual-router/engine-legacy/route-utils.js +212 -0
  131. package/dist/router/virtual-router/engine-legacy/routing.d.ts +8 -0
  132. package/dist/router/virtual-router/engine-legacy/routing.js +8 -0
  133. package/dist/router/virtual-router/engine-legacy/selection-core.d.ts +28 -0
  134. package/dist/router/virtual-router/engine-legacy/selection-core.js +112 -0
  135. package/dist/router/virtual-router/engine-legacy/selection-state.d.ts +16 -0
  136. package/dist/router/virtual-router/engine-legacy/selection-state.js +187 -0
  137. package/dist/router/virtual-router/engine-legacy/state-accessors.d.ts +21 -0
  138. package/dist/router/virtual-router/engine-legacy/state-accessors.js +118 -0
  139. package/dist/router/virtual-router/engine-legacy.d.ts +123 -0
  140. package/dist/router/virtual-router/engine-legacy.js +194 -0
  141. package/dist/router/virtual-router/engine-logging.d.ts +2 -0
  142. package/dist/router/virtual-router/engine-logging.js +7 -2
  143. package/dist/router/virtual-router/engine-selection/key-parsing.js +0 -3
  144. package/dist/router/virtual-router/engine-selection/native-chat-request-filter-semantics.d.ts +1 -0
  145. package/dist/router/virtual-router/engine-selection/native-chat-request-filter-semantics.js +54 -0
  146. package/dist/router/virtual-router/engine-selection/native-hub-bridge-policy-semantics.d.ts +10 -0
  147. package/dist/router/virtual-router/engine-selection/native-hub-bridge-policy-semantics.js +67 -0
  148. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.d.ts +30 -0
  149. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.js +202 -0
  150. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.d.ts +2 -0
  151. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.js +83 -0
  152. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +43 -2
  153. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +75 -0
  154. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +205 -0
  155. package/dist/router/virtual-router/engine-selection/native-snapshot-hooks.d.ts +3 -0
  156. package/dist/router/virtual-router/engine-selection/native-snapshot-hooks.js +109 -0
  157. package/dist/router/virtual-router/engine-selection/native-virtual-router-engine-proxy.d.ts +16 -0
  158. package/dist/router/virtual-router/engine-selection/native-virtual-router-engine-proxy.js +14 -0
  159. package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.d.ts +2 -0
  160. package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js +86 -0
  161. package/dist/router/virtual-router/engine-selection/tier-selection-quota-integration.js +100 -0
  162. package/dist/router/virtual-router/engine-selection/tier-selection-select.js +99 -0
  163. package/dist/router/virtual-router/engine.d.ts +22 -105
  164. package/dist/router/virtual-router/engine.js +274 -1641
  165. package/dist/router/virtual-router/load-balancer.d.ts +8 -0
  166. package/dist/router/virtual-router/load-balancer.js +65 -2
  167. package/dist/router/virtual-router/provider-registry.js +2 -0
  168. package/dist/router/virtual-router/routing-instructions/clean.d.ts +3 -0
  169. package/dist/router/virtual-router/routing-instructions/clean.js +34 -0
  170. package/dist/router/virtual-router/routing-instructions/parse.d.ts +18 -0
  171. package/dist/router/virtual-router/routing-instructions/parse.js +377 -0
  172. package/dist/router/virtual-router/routing-instructions/state.d.ts +4 -0
  173. package/dist/router/virtual-router/routing-instructions/state.js +245 -0
  174. package/dist/router/virtual-router/routing-instructions/types.d.ts +70 -0
  175. package/dist/router/virtual-router/routing-instructions/types.js +2 -0
  176. package/dist/router/virtual-router/routing-instructions.d.ts +5 -89
  177. package/dist/router/virtual-router/routing-instructions.js +4 -655
  178. package/dist/router/virtual-router/sticky-session-store.d.ts +4 -0
  179. package/dist/router/virtual-router/sticky-session-store.js +19 -81
  180. package/dist/router/virtual-router/tool-signals.js +21 -3
  181. package/dist/router/virtual-router/types.d.ts +4 -0
  182. package/dist/servertool/clock/session-scope.js +32 -1
  183. package/dist/servertool/engine.js +79 -8
  184. package/dist/servertool/handlers/antigravity-thought-signature-bootstrap.js +1 -1
  185. package/dist/servertool/handlers/clock-auto.js +1 -1
  186. package/dist/servertool/handlers/clock.js +1 -1
  187. package/dist/servertool/handlers/compaction-detect.d.ts +1 -1
  188. package/dist/servertool/handlers/compaction-detect.js +1 -1
  189. package/dist/servertool/handlers/gemini-empty-reply-continue.js +1 -1
  190. package/dist/servertool/handlers/iflow-model-error-retry.js +1 -1
  191. package/dist/servertool/handlers/recursive-detection-guard.js +1 -1
  192. package/dist/servertool/handlers/review.js +1 -1
  193. package/dist/servertool/handlers/stop-message-auto/iflow-followup.js +1 -1
  194. package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +1 -1
  195. package/dist/servertool/handlers/stop-message-auto.js +1 -1
  196. package/dist/servertool/handlers/vision.js +1 -1
  197. package/dist/servertool/handlers/web-search.js +1 -1
  198. package/dist/servertool/reenter-backend.js +1 -1
  199. package/dist/servertool/server-side-tools.js +2 -2
  200. package/dist/servertool/stop-gateway-context.js +1 -1
  201. package/dist/servertool/stop-message-compare-context.js +1 -1
  202. package/dist/sse/json-to-sse/event-generators/responses.d.ts +4 -0
  203. package/dist/sse/json-to-sse/event-generators/responses.js +95 -1
  204. package/dist/sse/json-to-sse/sequencers/responses-sequencer.js +6 -4
  205. package/dist/sse/sse-to-json/builders/response-builder.d.ts +8 -0
  206. package/dist/sse/sse-to-json/builders/response-builder.js +162 -4
  207. package/dist/sse/sse-to-json/responses-sse-to-json-converter.js +2 -0
  208. package/dist/sse/types/responses-types.d.ts +6 -2
  209. package/dist/tools/apply-patch/structured/coercion.js +5 -0
  210. package/dist/tools/args-json.js +29 -0
  211. package/package.json +8 -5
  212. package/dist/conversion/shared/args-mapping.js +0 -77
  213. package/dist/conversion/shared/compaction-detect.js +0 -4
  214. package/dist/conversion/shared/errors.js +0 -31
  215. package/dist/conversion/shared/media.js +0 -4
  216. package/dist/conversion/shared/payload-budget.js +0 -165
  217. package/dist/conversion/shared/protocol-field-allowlists.d.ts +0 -7
  218. package/dist/conversion/shared/protocol-field-allowlists.js +0 -149
  219. package/dist/conversion/shared/snapshot-hooks.d.ts +0 -11
  220. package/dist/conversion/shared/snapshot-hooks.js +0 -503
  221. package/dist/conversion/shared/text-markup-normalizer/extractors-apply-patch.d.ts +0 -2
  222. package/dist/conversion/shared/text-markup-normalizer/extractors-apply-patch.js +0 -129
  223. package/dist/conversion/shared/text-markup-normalizer/extractors-json.d.ts +0 -4
  224. package/dist/conversion/shared/text-markup-normalizer/extractors-json.js +0 -637
  225. package/dist/conversion/shared/text-markup-normalizer/extractors-shared.d.ts +0 -21
  226. package/dist/conversion/shared/text-markup-normalizer/extractors-shared.js +0 -177
  227. package/dist/conversion/shared/text-markup-normalizer/extractors-transcript.d.ts +0 -5
  228. package/dist/conversion/shared/text-markup-normalizer/extractors-transcript.js +0 -385
  229. package/dist/conversion/shared/text-markup-normalizer/extractors-xml.d.ts +0 -10
  230. package/dist/conversion/shared/text-markup-normalizer/extractors-xml.js +0 -602
  231. package/dist/conversion/shared/text-markup-normalizer/extractors.d.ts +0 -5
  232. package/dist/conversion/shared/text-markup-normalizer/extractors.js +0 -4
  233. package/dist/conversion/shared/tool-canonicalizer.d.ts +0 -2
  234. package/dist/conversion/shared/tool-canonicalizer.js +0 -38
  235. /package/dist/conversion/{shared/args-mapping.d.ts → args-mapping.d.ts} +0 -0
  236. /package/dist/conversion/{shared/bridge-actions.d.ts → bridge-actions.d.ts} +0 -0
  237. /package/dist/conversion/{shared/bridge-id-utils.d.ts → bridge-id-utils.d.ts} +0 -0
  238. /package/dist/conversion/{shared/bridge-instructions.d.ts → bridge-instructions.d.ts} +0 -0
  239. /package/dist/conversion/{shared/bridge-metadata.d.ts → bridge-metadata.d.ts} +0 -0
  240. /package/dist/conversion/{shared/bridge-policies.d.ts → bridge-policies.d.ts} +0 -0
  241. /package/dist/conversion/{shared/jsonish.d.ts → jsonish.d.ts} +0 -0
  242. /package/dist/conversion/{shared/mcp-injection.d.ts → mcp-injection.d.ts} +0 -0
  243. /package/dist/conversion/{shared/media.d.ts → media.d.ts} +0 -0
  244. /package/dist/conversion/{shared/payload-budget.d.ts → payload-budget.d.ts} +0 -0
  245. /package/dist/conversion/{shared → types}/bridge-message-types.d.ts +0 -0
  246. /package/dist/conversion/{shared → types}/bridge-message-types.js +0 -0
@@ -1,503 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
- const DEFAULT_SNAPSHOT_ROOT = path.join(os.homedir(), '.routecodex', 'codex-samples');
5
- const DEFAULT_ERRORSAMPLES_ROOT = path.join(os.homedir(), '.routecodex', 'errorsamples');
6
- const PENDING_PROVIDER_DIR = '__pending__';
7
- const POLICY_VIOLATIONS_DIR = '__policy_violations__';
8
- function resolveSnapshotRoot() {
9
- const envOverride = process.env.RCC_SNAPSHOT_DIR ||
10
- process.env.ROUTECODEX_SNAPSHOT_DIR;
11
- if (envOverride && envOverride.trim()) {
12
- return path.resolve(envOverride.trim());
13
- }
14
- return DEFAULT_SNAPSHOT_ROOT;
15
- }
16
- function resolveErrorsamplesRoot() {
17
- const envOverride = process.env.ROUTECODEX_ERRORSAMPLES_DIR ||
18
- process.env.ROUTECODEX_ERROR_SAMPLES_DIR;
19
- if (envOverride && String(envOverride).trim()) {
20
- return path.resolve(String(envOverride).trim());
21
- }
22
- return DEFAULT_ERRORSAMPLES_ROOT;
23
- }
24
- function safeErrorsampleName(name) {
25
- return String(name || 'sample').replace(/[^\w.-]/g, '_');
26
- }
27
- async function cleanupZeroByteJsonFiles(dir) {
28
- let entries = [];
29
- try {
30
- entries = await fs.readdir(dir);
31
- }
32
- catch {
33
- return;
34
- }
35
- const candidates = entries.filter((name) => name.endsWith('.json'));
36
- if (candidates.length === 0) {
37
- return;
38
- }
39
- await Promise.allSettled(candidates.map(async (name) => {
40
- const full = path.join(dir, name);
41
- try {
42
- const st = await fs.stat(full);
43
- if (!st.isFile() || st.size > 0) {
44
- return;
45
- }
46
- await fs.unlink(full);
47
- }
48
- catch {
49
- // ignore cleanup failures
50
- }
51
- }));
52
- }
53
- async function writeUniqueErrorsampleFile(dir, baseName, contents) {
54
- const parsed = path.parse(baseName);
55
- const ext = parsed.ext || '.json';
56
- const stem = parsed.name || 'sample';
57
- const tmpDir = path.join(dir, '_tmp');
58
- try {
59
- await fs.mkdir(tmpDir, { recursive: true });
60
- }
61
- catch {
62
- // ignore; fallback to direct writes
63
- }
64
- for (let i = 0; i < 32; i += 1) {
65
- const suffix = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
66
- const fileName = `${stem}_${suffix}${ext}`;
67
- try {
68
- const dest = path.join(dir, fileName);
69
- const tmp = path.join(tmpDir, `${fileName}.tmp`);
70
- await fs.writeFile(tmp, contents, { encoding: 'utf-8', flag: 'wx' });
71
- await fs.rename(tmp, dest);
72
- return;
73
- }
74
- catch (error) {
75
- if (toErrorCode(error) === 'EEXIST') {
76
- continue;
77
- }
78
- throw error;
79
- }
80
- }
81
- // last resort (best-effort overwrite into a timestamped file)
82
- const fallback = `${stem}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}${ext}`;
83
- await fs.writeFile(path.join(dir, fallback), contents, { encoding: 'utf-8' });
84
- }
85
- function resolveSnapshotFolder(endpoint) {
86
- const lowered = (endpoint || '').trim().toLowerCase();
87
- if (lowered.includes('/v1/responses') || lowered.includes('/responses.submit')) {
88
- return 'openai-responses';
89
- }
90
- if (lowered.includes('/v1/messages')) {
91
- return 'anthropic-messages';
92
- }
93
- return 'openai-chat';
94
- }
95
- function sanitizeToken(value, fallback) {
96
- if (typeof value !== 'string') {
97
- return fallback;
98
- }
99
- const trimmed = value.trim();
100
- if (!trimmed) {
101
- return fallback;
102
- }
103
- return trimmed.replace(/[^A-Za-z0-9_.-]/g, '_') || fallback;
104
- }
105
- function channelSuffix(channel) {
106
- if (!channel) {
107
- return '';
108
- }
109
- const token = sanitizeToken(channel, '');
110
- return token ? `_${token}` : '';
111
- }
112
- function readStringField(value) {
113
- return typeof value === 'string' && value.trim().length ? value.trim() : undefined;
114
- }
115
- function extractNestedProviderKey(value) {
116
- if (!value || typeof value !== 'object') {
117
- return undefined;
118
- }
119
- const obj = value;
120
- const direct = readStringField(obj.providerKey) ||
121
- readStringField(obj.providerId) ||
122
- readStringField(obj.profileId);
123
- if (direct) {
124
- return direct;
125
- }
126
- const target = obj.target;
127
- if (target && typeof target === 'object') {
128
- const tk = readStringField(target.providerKey);
129
- if (tk) {
130
- return tk;
131
- }
132
- }
133
- const meta = obj.meta;
134
- if (meta && typeof meta === 'object') {
135
- const m = meta;
136
- const fromMeta = readStringField(m.providerKey) ||
137
- readStringField(m.providerId);
138
- if (fromMeta) {
139
- return fromMeta;
140
- }
141
- const ctx = m.context;
142
- if (ctx && typeof ctx === 'object') {
143
- const c = ctx;
144
- const fromCtx = readStringField(c.providerKey) ||
145
- readStringField(c.providerId) ||
146
- readStringField(c.profileId);
147
- if (fromCtx) {
148
- return fromCtx;
149
- }
150
- }
151
- }
152
- return undefined;
153
- }
154
- function extractNestedGroupRequestId(value) {
155
- if (!value || typeof value !== 'object') {
156
- return undefined;
157
- }
158
- const obj = value;
159
- const direct = readStringField(obj.clientRequestId) ||
160
- readStringField(obj.groupRequestId);
161
- if (direct) {
162
- return direct;
163
- }
164
- const meta = obj.meta;
165
- if (meta && typeof meta === 'object') {
166
- const m = meta;
167
- const fromMeta = readStringField(m.clientRequestId) ||
168
- readStringField(m.groupRequestId);
169
- if (fromMeta) {
170
- return fromMeta;
171
- }
172
- const ctx = m.context;
173
- if (ctx && typeof ctx === 'object') {
174
- const c = ctx;
175
- const fromCtx = readStringField(c.clientRequestId) ||
176
- readStringField(c.groupRequestId);
177
- if (fromCtx) {
178
- return fromCtx;
179
- }
180
- }
181
- }
182
- return undefined;
183
- }
184
- function extractNestedEntryEndpoint(value) {
185
- if (!value || typeof value !== 'object') {
186
- return undefined;
187
- }
188
- const obj = value;
189
- const direct = readStringField(obj.entryEndpoint) ||
190
- readStringField(obj.entry_endpoint);
191
- if (direct) {
192
- return direct;
193
- }
194
- const meta = obj.meta;
195
- if (meta && typeof meta === 'object') {
196
- const m = meta;
197
- const fromMeta = readStringField(m.entryEndpoint) ||
198
- readStringField(m.entry_endpoint);
199
- if (fromMeta) {
200
- return fromMeta;
201
- }
202
- const ctx = m.context;
203
- if (ctx && typeof ctx === 'object') {
204
- const c = ctx;
205
- const fromCtx = readStringField(c.entryEndpoint) ||
206
- readStringField(c.entry_endpoint);
207
- if (fromCtx) {
208
- return fromCtx;
209
- }
210
- }
211
- }
212
- const metadata = obj.metadata;
213
- if (metadata && typeof metadata === 'object') {
214
- const md = metadata;
215
- const fromMetadata = readStringField(md.entryEndpoint) ||
216
- readStringField(md.entry_endpoint);
217
- if (fromMetadata) {
218
- return fromMetadata;
219
- }
220
- }
221
- const runtime = obj.runtime;
222
- if (runtime && typeof runtime === 'object') {
223
- const r = runtime;
224
- const fromRuntime = readStringField(r.entryEndpoint) ||
225
- readStringField(r.entry_endpoint);
226
- if (fromRuntime) {
227
- return fromRuntime;
228
- }
229
- }
230
- return undefined;
231
- }
232
- function toErrorCode(error) {
233
- if (!error || typeof error !== 'object') {
234
- return undefined;
235
- }
236
- const code = error.code;
237
- return typeof code === 'string' && code.trim() ? code : undefined;
238
- }
239
- function readNumberField(value) {
240
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
241
- }
242
- function isHubPolicyStage(stage) {
243
- return typeof stage === 'string' && stage.startsWith('hub_policy.');
244
- }
245
- function isHubToolSurfaceStage(stage) {
246
- return typeof stage === 'string' && stage.startsWith('hub_toolsurface.');
247
- }
248
- function hasPolicyViolations(value) {
249
- if (!value || typeof value !== 'object') {
250
- return false;
251
- }
252
- const obj = value;
253
- const violations = obj.violations;
254
- if (Array.isArray(violations) && violations.length > 0) {
255
- return true;
256
- }
257
- const summary = obj.summary;
258
- if (summary && typeof summary === 'object') {
259
- const total = readNumberField(summary.totalViolations);
260
- if (typeof total === 'number' && total > 0) {
261
- return true;
262
- }
263
- }
264
- return false;
265
- }
266
- function hasToolSurfaceDiff(value) {
267
- if (!value || typeof value !== 'object') {
268
- return false;
269
- }
270
- const obj = value;
271
- const diffCount = readNumberField(obj.diffCount);
272
- if (typeof diffCount === 'number' && diffCount > 0) {
273
- return true;
274
- }
275
- // Response-side tool surface mismatch detection records expected/detected protocol
276
- // without a numeric diffCount; treat any protocol mismatch as a diff.
277
- const expected = readStringField(obj.expectedProtocol);
278
- const detected = readStringField(obj.detectedProtocol);
279
- if (expected && detected && expected !== detected) {
280
- return true;
281
- }
282
- return false;
283
- }
284
- function hasPolicyEnforcementChanges(value) {
285
- if (!value || typeof value !== 'object') {
286
- return false;
287
- }
288
- const obj = value;
289
- const removed = obj.removedTopLevelKeys;
290
- if (Array.isArray(removed) && removed.length > 0) {
291
- return true;
292
- }
293
- const flattened = obj.flattenedWrappers;
294
- if (Array.isArray(flattened) && flattened.length > 0) {
295
- return true;
296
- }
297
- return false;
298
- }
299
- async function writeUniqueFile(dir, baseName, contents) {
300
- const parsed = path.parse(baseName);
301
- const ext = parsed.ext || '.json';
302
- const stem = parsed.name || 'snapshot';
303
- const tmpPrefix = `.__tmp_${stem}_${process.pid}_${Date.now()}`;
304
- for (let i = 0; i < 64; i += 1) {
305
- const name = i === 0 ? `${stem}${ext}` : `${stem}_${i}${ext}`;
306
- try {
307
- const dest = path.join(dir, name);
308
- const tmp = path.join(dir, `${tmpPrefix}_${Math.random().toString(36).slice(2, 8)}${ext}`);
309
- await fs.writeFile(tmp, contents, { encoding: 'utf-8', flag: 'wx' });
310
- try {
311
- await fs.link(tmp, dest);
312
- await fs.unlink(tmp).catch(() => { });
313
- return;
314
- }
315
- catch (error) {
316
- await fs.unlink(tmp).catch(() => { });
317
- if (toErrorCode(error) === 'EEXIST') {
318
- continue;
319
- }
320
- throw error;
321
- }
322
- }
323
- catch (error) {
324
- if (toErrorCode(error) === 'EEXIST') {
325
- continue;
326
- }
327
- throw error;
328
- }
329
- }
330
- const fallback = `${stem}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}${ext}`;
331
- const dest = path.join(dir, fallback);
332
- const tmp = path.join(dir, `${tmpPrefix}_${Math.random().toString(36).slice(2, 8)}${ext}`);
333
- await fs.writeFile(tmp, contents, { encoding: 'utf-8', flag: 'wx' });
334
- try {
335
- await fs.link(tmp, dest);
336
- }
337
- finally {
338
- await fs.unlink(tmp).catch(() => { });
339
- }
340
- }
341
- const requestProviderIndex = globalThis
342
- .__routecodexSnapshotProviderIndex ||
343
- new Map();
344
- globalThis
345
- .__routecodexSnapshotProviderIndex = requestProviderIndex;
346
- async function mergeDirs(src, dest) {
347
- await fs.mkdir(dest, { recursive: true });
348
- let entries = [];
349
- try {
350
- entries = await fs.readdir(src);
351
- }
352
- catch {
353
- return;
354
- }
355
- for (const name of entries) {
356
- const from = path.join(src, name);
357
- const to = path.join(dest, name);
358
- try {
359
- await fs.rename(from, to);
360
- }
361
- catch (error) {
362
- if (toErrorCode(error) === 'EEXIST') {
363
- // avoid overwriting; keep both
364
- const parsed = path.parse(name);
365
- const ext = parsed.ext || '';
366
- const stem = parsed.name || 'snapshot';
367
- const suffix = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
368
- try {
369
- await fs.rename(from, path.join(dest, `${stem}_${suffix}${ext}`));
370
- }
371
- catch {
372
- // ignore move failure
373
- }
374
- continue;
375
- }
376
- // ignore other move failures
377
- }
378
- }
379
- try {
380
- await fs.rmdir(src);
381
- }
382
- catch {
383
- // ignore
384
- }
385
- }
386
- async function promotePendingDir(options) {
387
- if (!options.groupRequestToken || options.providerToken === PENDING_PROVIDER_DIR) {
388
- return;
389
- }
390
- const pending = path.join(options.root, options.folder, PENDING_PROVIDER_DIR, options.groupRequestToken);
391
- const dest = path.join(options.root, options.folder, options.providerToken, options.groupRequestToken);
392
- try {
393
- await fs.access(pending);
394
- }
395
- catch {
396
- return;
397
- }
398
- await fs.mkdir(path.dirname(dest), { recursive: true });
399
- try {
400
- await fs.rename(pending, dest);
401
- }
402
- catch {
403
- // if rename fails (already exists / cross-device), merge
404
- await mergeDirs(pending, dest);
405
- }
406
- }
407
- async function writeSnapshotFile(options, rootOverride) {
408
- const root = rootOverride || resolveSnapshotRoot();
409
- const folder = resolveSnapshotFolder(extractNestedEntryEndpoint(options.data) || options.endpoint);
410
- const stageToken = sanitizeToken(options.stage, 'snapshot');
411
- const groupRequestToken = sanitizeToken(options.groupRequestId ||
412
- extractNestedGroupRequestId(options.data) ||
413
- options.requestId, `req_${Date.now()}`);
414
- const providerFromOptions = readStringField(options.providerKey);
415
- const providerFromData = extractNestedProviderKey(options.data);
416
- const knownProvider = requestProviderIndex.get(groupRequestToken);
417
- const providerToken = sanitizeToken(providerFromOptions || providerFromData || knownProvider || PENDING_PROVIDER_DIR, PENDING_PROVIDER_DIR);
418
- if (!knownProvider && providerToken !== PENDING_PROVIDER_DIR) {
419
- requestProviderIndex.set(groupRequestToken, providerToken);
420
- await promotePendingDir({ root, folder, groupRequestToken, providerToken });
421
- }
422
- const dir = path.join(root, folder, providerToken, groupRequestToken);
423
- await fs.mkdir(dir, { recursive: true });
424
- // Write a stable runtime marker for this request folder (best-effort).
425
- try {
426
- const metaPath = path.join(dir, '__runtime.json');
427
- const payload = JSON.stringify({
428
- timestamp: new Date().toISOString(),
429
- versions: {
430
- routecodex: process.env.ROUTECODEX_VERSION,
431
- routecodexBuildTime: process.env.ROUTECODEX_BUILD_TIME,
432
- llmswitchCore: process.env.ROUTECODEX_LLMSWITCH_CORE_VERSION,
433
- node: process.version
434
- }
435
- }, null, 2);
436
- await fs.writeFile(metaPath, payload, { encoding: 'utf-8', flag: 'wx' }).catch(() => { });
437
- }
438
- catch {
439
- // ignore
440
- }
441
- const spacing = options.verbosity === 'minimal' ? undefined : 2;
442
- const payload = spacing !== undefined
443
- ? JSON.stringify(options.data, null, spacing)
444
- : JSON.stringify(options.data);
445
- const fileName = `${stageToken}${channelSuffix(options.channel)}.json`;
446
- await writeUniqueFile(dir, fileName, payload);
447
- }
448
- export async function writeSnapshotViaHooks(options) {
449
- const stage = sanitizeToken(options.stage, 'snapshot');
450
- // 1) Normal snapshots (always).
451
- try {
452
- await writeSnapshotFile({ ...options, stage });
453
- }
454
- catch {
455
- // snapshot writes must never block callers
456
- }
457
- // 2) Policy violations snapshots (copy-on-violation only).
458
- // This allows leaving observe mode always on without drowning normal codex-samples traffic.
459
- try {
460
- if (isHubPolicyStage(stage) &&
461
- (hasPolicyViolations(options.data) || hasPolicyEnforcementChanges(options.data))) {
462
- const base = resolveSnapshotRoot();
463
- const policyRoot = path.join(base, POLICY_VIOLATIONS_DIR);
464
- await writeSnapshotFile({ ...options, stage }, policyRoot);
465
- }
466
- }
467
- catch {
468
- // never block callers
469
- }
470
- // 3) Tool surface diffs (copy-on-diff only) → ~/.routecodex/errorsamples/tool-surface/
471
- try {
472
- if (isHubToolSurfaceStage(stage) && hasToolSurfaceDiff(options.data)) {
473
- const root = resolveErrorsamplesRoot();
474
- const dir = path.join(root, safeErrorsampleName('tool-surface'));
475
- await fs.mkdir(dir, { recursive: true });
476
- // Best-effort cleanup: when the process exits abruptly, an in-flight async
477
- // write can leave behind 0-byte placeholder files. Keep the observable
478
- // directory clean so operators can tail it.
479
- await cleanupZeroByteJsonFiles(dir);
480
- const stamp = new Date().toISOString();
481
- const payload = {
482
- kind: 'hub_toolsurface_diff',
483
- timestamp: stamp,
484
- endpoint: options.endpoint,
485
- stage,
486
- requestId: options.requestId,
487
- providerKey: options.providerKey,
488
- groupRequestId: options.groupRequestId,
489
- runtime: {
490
- routecodexVersion: process.env.ROUTECODEX_VERSION,
491
- routecodexBuildTime: process.env.ROUTECODEX_BUILD_TIME,
492
- llmswitchCore: process.env.ROUTECODEX_LLMSWITCH_CORE_VERSION,
493
- node: process.version
494
- },
495
- observation: options.data
496
- };
497
- await writeUniqueErrorsampleFile(dir, `${safeErrorsampleName(stage)}.json`, JSON.stringify(payload, null, 2));
498
- }
499
- }
500
- catch {
501
- // never block callers
502
- }
503
- }
@@ -1,2 +0,0 @@
1
- import { type ToolCallLite } from './extractors-shared.js';
2
- export declare function extractApplyPatchCallsFromText(text: string): ToolCallLite[] | null;
@@ -1,129 +0,0 @@
1
- import { isStructuredApplyPatchPayload } from '../../../tools/apply-patch-structured.js';
2
- import { genToolCallId } from './extractors-shared.js';
3
- function extractStructuredApplyPatchPayloads(text) {
4
- const payloads = [];
5
- try {
6
- const fenceRe = /```(?:json|apply_patch|toon)?\s*([\s\S]*?)\s*```/gi;
7
- let fm;
8
- while ((fm = fenceRe.exec(text)) !== null) {
9
- const body = fm[1] || '';
10
- try {
11
- const parsed = JSON.parse(body);
12
- if (isStructuredApplyPatchPayload(parsed)) {
13
- payloads.push(parsed);
14
- }
15
- }
16
- catch {
17
- /* ignore invalid JSON */
18
- }
19
- }
20
- if (!payloads.length && typeof text === 'string' && text.includes('"changes"')) {
21
- try {
22
- const parsed = JSON.parse(text);
23
- if (isStructuredApplyPatchPayload(parsed)) {
24
- payloads.push(parsed);
25
- }
26
- }
27
- catch {
28
- /* ignore */
29
- }
30
- }
31
- }
32
- catch {
33
- /* ignore */
34
- }
35
- return payloads;
36
- }
37
- function normalizeRawApplyPatchBlock(raw) {
38
- try {
39
- const lines = String(raw || '')
40
- .split(/\r?\n/)
41
- .map((line) => line.replace(/\r/g, ''));
42
- while (lines.length > 0 && !lines[0].trim()) {
43
- lines.shift();
44
- }
45
- while (lines.length > 0 && !lines[lines.length - 1].trim()) {
46
- lines.pop();
47
- }
48
- if (!lines.length)
49
- return '';
50
- const indents = lines
51
- .filter((line) => line.trim().length > 0)
52
- .map((line) => {
53
- const m = line.match(/^[ \t]*/);
54
- return m ? m[0].length : 0;
55
- });
56
- const minIndent = indents.length ? Math.min(...indents) : 0;
57
- if (minIndent <= 0) {
58
- return lines.join('\n').trim();
59
- }
60
- return lines
61
- .map((line) => line.replace(new RegExp(`^[ \\t]{0,${minIndent}}`), ''))
62
- .join('\n')
63
- .trim();
64
- }
65
- catch {
66
- return String(raw || '').trim();
67
- }
68
- }
69
- function extractRawApplyPatchBlocks(text) {
70
- const out = [];
71
- try {
72
- if (typeof text !== 'string' || !text)
73
- return out;
74
- const seen = new Set();
75
- const blockRe = /\*\*\*\s*Begin Patch(?:\s*\*\*\*)?[\s\S]*?\*\*\*\s*End Patch(?:\s*\*\*\*)?/gi;
76
- let m;
77
- while ((m = blockRe.exec(text)) !== null) {
78
- const normalized = normalizeRawApplyPatchBlock(String(m[0] || ''));
79
- if (!normalized)
80
- continue;
81
- // Avoid turning incidental prose into apply_patch.
82
- if (!/\*\*\*\s*(?:Add|Update|Delete)\s+File:/i.test(normalized))
83
- continue;
84
- if (seen.has(normalized))
85
- continue;
86
- seen.add(normalized);
87
- out.push(normalized);
88
- }
89
- }
90
- catch {
91
- /* ignore */
92
- }
93
- return out;
94
- }
95
- export function extractApplyPatchCallsFromText(text) {
96
- try {
97
- if (typeof text !== 'string' || !text)
98
- return null;
99
- const payloads = extractStructuredApplyPatchPayloads(text);
100
- const patchBlocks = extractRawApplyPatchBlocks(text);
101
- if (!payloads.length && !patchBlocks.length)
102
- return null;
103
- const out = [];
104
- for (const payload of payloads) {
105
- let argsStr = '{}';
106
- try {
107
- argsStr = JSON.stringify(payload);
108
- }
109
- catch {
110
- argsStr = '{"changes":[]}';
111
- }
112
- out.push({ id: genToolCallId(), name: 'apply_patch', args: argsStr });
113
- }
114
- for (const patch of patchBlocks) {
115
- let argsStr = '{}';
116
- try {
117
- argsStr = JSON.stringify({ patch, input: patch });
118
- }
119
- catch {
120
- argsStr = '{"patch":""}';
121
- }
122
- out.push({ id: genToolCallId(), name: 'apply_patch', args: argsStr });
123
- }
124
- return out;
125
- }
126
- catch {
127
- return null;
128
- }
129
- }
@@ -1,4 +0,0 @@
1
- import { type TextMarkupNormalizeOptions, type ToolCallLite } from './extractors-shared.js';
2
- export declare function tryParseJsonWithModelRepairs(raw: string): unknown | null;
3
- export declare function salvageToolArgsFromRawText(toolName: string, rawArgs: string): Record<string, unknown> | null;
4
- export declare function extractJsonToolCallsFromText(text: string, options?: TextMarkupNormalizeOptions): ToolCallLite[] | null;