@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,82 +1,4 @@
1
- import { isJsonObject, jsonClone } from '../../types/json.js';
2
- import { normalizeChatMessageContentWithNative } from '../../../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
3
- import { ensureProtocolState } from '../../../shared/protocol-state.js';
4
- import { mapReqInboundBridgeToolsToChatWithNative } from '../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
5
- const CHAT_PARAMETER_KEYS = [
6
- 'model',
7
- 'temperature',
8
- 'top_p',
9
- 'top_k',
10
- 'max_tokens',
11
- 'frequency_penalty',
12
- 'presence_penalty',
13
- 'logit_bias',
14
- 'response_format',
15
- 'parallel_tool_calls',
16
- 'tool_choice',
17
- 'seed',
18
- 'user',
19
- 'metadata',
20
- 'stop',
21
- 'stop_sequences',
22
- 'stream'
23
- ];
24
- const KNOWN_TOP_LEVEL_FIELDS = new Set([
25
- 'messages',
26
- 'tools',
27
- 'tool_outputs',
28
- ...CHAT_PARAMETER_KEYS,
29
- 'stageExpectations',
30
- 'stages'
31
- ]);
32
- function flattenSystemContent(content) {
33
- if (typeof content === 'string')
34
- return content;
35
- if (Array.isArray(content)) {
36
- return content.map(flattenSystemContent).filter(Boolean).join('\n');
37
- }
38
- if (content && typeof content === 'object') {
39
- const obj = content;
40
- if (typeof obj.text === 'string')
41
- return obj.text;
42
- if (typeof obj.content === 'string')
43
- return obj.content;
44
- if (Array.isArray(obj.content))
45
- return obj.content.map(flattenSystemContent).join('\n');
46
- }
47
- return '';
48
- }
49
- function normalizeToolContent(content) {
50
- if (typeof content === 'string')
51
- return content;
52
- if (content === null || content === undefined)
53
- return '';
54
- try {
55
- return JSON.stringify(content);
56
- }
57
- catch {
58
- return String(content ?? '');
59
- }
60
- }
61
- function maybeAugmentRouteCodexApplyPatchPrecheck(content) {
62
- if (!content || typeof content !== 'string') {
63
- return content;
64
- }
65
- if (content.includes('[RouteCodex precheck]')) {
66
- return content;
67
- }
68
- const lower = content.toLowerCase();
69
- if (!lower.includes('failed to parse function arguments')) {
70
- return content;
71
- }
72
- if (content.includes('missing field `input`')) {
73
- return `${content}\n\n[RouteCodex precheck] apply_patch 参数解析失败:缺少字段 "input"。当前 RouteCodex 期望 { input, patch } 形态,并且两个字段都应包含完整统一 diff 文本。`;
74
- }
75
- if (content.includes('invalid type: map, expected a string')) {
76
- return `${content}\n\n[RouteCodex precheck] apply_patch 参数类型错误:检测到 JSON 对象(map),但客户端期望字符串。请先对参数做 JSON.stringify 再写入 arguments,或直接提供 { patch: "<统一 diff>" } 形式。`;
77
- }
78
- return content;
79
- }
1
+ import { mapOpenaiChatFromChatWithNative, mapOpenaiChatToChatWithNative } from '../../../../router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.js';
80
2
  export function maybeAugmentApplyPatchErrorContent(content, toolName) {
81
3
  if (!content)
82
4
  return content;
@@ -86,316 +8,18 @@ export function maybeAugmentApplyPatchErrorContent(content, toolName) {
86
8
  if (!isApplyPatch) {
87
9
  return content;
88
10
  }
89
- // 避免重复追加提示。
11
+ // Avoid duplicate hints.
90
12
  if (content.includes('[apply_patch hint]')) {
91
13
  return content;
92
14
  }
93
- const hint = '\n\n[apply_patch hint] 在使用 apply_patch 之前,请先读取目标文件的最新内容,并基于该内容生成补丁;同时确保补丁格式符合工具规范(统一补丁格式或结构化参数),避免上下文不匹配或语法错误。';
15
+ const hint = '\n\n[apply_patch hint] \u5728\u4f7f\u7528 apply_patch \u4e4b\u524d\uff0c\u8bf7\u5148\u8bfb\u53d6\u76ee\u6807\u6587\u4ef6\u7684\u6700\u65b0\u5185\u5bb9\uff0c\u5e76\u57fa\u4e8e\u8be5\u5185\u5bb9\u751f\u6210\u8865\u4e01\uff1b\u540c\u65f6\u786e\u4fdd\u8865\u4e01\u683c\u5f0f\u7b26\u5408\u5de5\u5177\u89c4\u8303\uff08\u7edf\u4e00\u8865\u4e01\u683c\u5f0f\u6216\u7ed3\u6784\u5316\u53c2\u6570\uff09\uff0c\u907f\u514d\u4e0a\u4e0b\u6587\u4e0d\u5339\u914d\u6216\u8bed\u6cd5\u9519\u8bef\u3002';
94
16
  return content + hint;
95
17
  }
96
- function recordToolCallIssues(message, messageIndex, missing) {
97
- const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : undefined;
98
- if (!toolCalls?.length)
99
- return;
100
- toolCalls.forEach((entry, callIndex) => {
101
- if (!isJsonObject(entry)) {
102
- missing.push({
103
- path: `messages[${messageIndex}].tool_calls[${callIndex}]`,
104
- reason: 'invalid_tool_call_entry',
105
- originalValue: jsonClone(entry)
106
- });
107
- return;
108
- }
109
- const fnBlock = entry.function;
110
- if (!isJsonObject(fnBlock)) {
111
- missing.push({
112
- path: `messages[${messageIndex}].tool_calls[${callIndex}].function`,
113
- reason: 'missing_tool_function',
114
- originalValue: jsonClone(fnBlock)
115
- });
116
- return;
117
- }
118
- const fnName = fnBlock.name;
119
- if (typeof fnName !== 'string' || !fnName.trim().length) {
120
- missing.push({
121
- path: `messages[${messageIndex}].tool_calls[${callIndex}].function.name`,
122
- reason: 'missing_tool_name'
123
- });
124
- }
125
- });
126
- }
127
- function collectSystemRawBlocks(raw) {
128
- if (!Array.isArray(raw))
129
- return undefined;
130
- const blocks = [];
131
- raw.forEach((entry) => {
132
- if (!isJsonObject(entry))
133
- return;
134
- if (String(entry.role ?? '').toLowerCase() !== 'system')
135
- return;
136
- blocks.push(jsonClone(entry));
137
- });
138
- return blocks.length ? blocks : undefined;
139
- }
140
- function normalizeChatMessages(raw) {
141
- const norm = {
142
- messages: [],
143
- systemSegments: [],
144
- toolOutputs: [],
145
- missingFields: []
146
- };
147
- if (raw === undefined) {
148
- norm.missingFields.push({ path: 'messages', reason: 'absent' });
149
- return norm;
150
- }
151
- if (!Array.isArray(raw)) {
152
- norm.missingFields.push({ path: 'messages', reason: 'invalid_type', originalValue: jsonClone(raw) });
153
- return norm;
154
- }
155
- raw.forEach((value, index) => {
156
- if (!isJsonObject(value)) {
157
- norm.missingFields.push({ path: `messages[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(value) });
158
- return;
159
- }
160
- const roleValue = value.role;
161
- if (typeof roleValue !== 'string') {
162
- norm.missingFields.push({ path: `messages[${index}].role`, reason: 'missing_role' });
163
- return;
164
- }
165
- const chatMessage = value;
166
- if (roleValue !== 'system' && roleValue !== 'tool') {
167
- const normalizedContent = normalizeChatMessageContentWithNative(chatMessage.content);
168
- const shouldOverwriteContent = !Array.isArray(chatMessage.content);
169
- if (shouldOverwriteContent && normalizedContent.contentText !== undefined) {
170
- chatMessage.content = normalizedContent.contentText;
171
- }
172
- if (typeof normalizedContent.reasoningText === 'string' && normalizedContent.reasoningText.trim().length) {
173
- chatMessage.reasoning_content = normalizedContent.reasoningText.trim();
174
- }
175
- }
176
- norm.messages.push(chatMessage);
177
- const toolCallCandidate = value.tool_calls;
178
- if (Array.isArray(toolCallCandidate) && toolCallCandidate.length) {
179
- recordToolCallIssues(value, index, norm.missingFields);
180
- }
181
- if (roleValue === 'system') {
182
- const segment = flattenSystemContent(chatMessage.content);
183
- if (segment.trim().length) {
184
- norm.systemSegments.push(segment);
185
- }
186
- return;
187
- }
188
- if (roleValue === 'tool') {
189
- const rawCallId = (value.tool_call_id ?? value.call_id ?? value.id);
190
- const toolCallId = typeof rawCallId === 'string' && rawCallId.trim().length ? rawCallId.trim() : undefined;
191
- if (!toolCallId) {
192
- norm.missingFields.push({ path: `messages[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
193
- return;
194
- }
195
- const nameValue = typeof value.name === 'string' && value.name.trim().length ? value.name : undefined;
196
- const normalizedToolOutput = normalizeToolContent(value.content ?? value.output);
197
- const routeCodexPrechecked = maybeAugmentRouteCodexApplyPatchPrecheck(normalizedToolOutput);
198
- if (routeCodexPrechecked !== normalizedToolOutput) {
199
- // Keep tool role message content aligned with outbound provider requests (e.g. Chat→Responses),
200
- // while avoiding double-injection.
201
- if (typeof chatMessage.content === 'string' || chatMessage.content === undefined || chatMessage.content === null) {
202
- chatMessage.content = routeCodexPrechecked;
203
- }
204
- else if (typeof chatMessage.output === 'string') {
205
- chatMessage.output = routeCodexPrechecked;
206
- }
207
- }
208
- const outputEntry = {
209
- tool_call_id: toolCallId,
210
- content: routeCodexPrechecked,
211
- name: nameValue
212
- };
213
- outputEntry.content = maybeAugmentApplyPatchErrorContent(outputEntry.content, outputEntry.name);
214
- norm.toolOutputs.push(outputEntry);
215
- }
216
- });
217
- return norm;
218
- }
219
- function normalizeStandaloneToolOutputs(raw, missing) {
220
- if (!Array.isArray(raw) || raw.length === 0)
221
- return [];
222
- const outputs = [];
223
- raw.forEach((entry, index) => {
224
- if (!isJsonObject(entry)) {
225
- missing.push({ path: `tool_outputs[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
226
- return;
227
- }
228
- const rawCallId = entry.tool_call_id ?? entry.call_id ?? entry.id;
229
- const toolCallId = typeof rawCallId === 'string' && rawCallId.trim().length ? rawCallId.trim() : undefined;
230
- if (!toolCallId) {
231
- missing.push({ path: `tool_outputs[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
232
- return;
233
- }
234
- const nameValue = typeof entry.name === 'string' && entry.name.trim().length ? entry.name : undefined;
235
- const rawContent = normalizeToolContent(entry.content ?? entry.output);
236
- const content = maybeAugmentApplyPatchErrorContent(rawContent, nameValue);
237
- outputs.push({
238
- tool_call_id: toolCallId,
239
- content,
240
- name: nameValue
241
- });
242
- });
243
- return outputs;
244
- }
245
- function normalizeTools(raw, missing) {
246
- if (!Array.isArray(raw) || raw.length === 0) {
247
- return undefined;
248
- }
249
- const tools = mapReqInboundBridgeToolsToChatWithNative(raw);
250
- if (tools.length === 0) {
251
- raw.forEach((entry, index) => {
252
- missing.push({ path: `tools[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
253
- });
254
- }
255
- return tools.length ? tools : undefined;
256
- }
257
- function extractParameters(body) {
258
- const params = {};
259
- for (const key of CHAT_PARAMETER_KEYS) {
260
- if (body[key] !== undefined) {
261
- params[key] = body[key];
262
- }
263
- }
264
- return Object.keys(params).length ? params : undefined;
265
- }
266
- function collectExtraFields(body) {
267
- const extras = {};
268
- for (const [key, value] of Object.entries(body)) {
269
- if (KNOWN_TOP_LEVEL_FIELDS.has(key)) {
270
- continue;
271
- }
272
- if (value !== undefined) {
273
- extras[key] = jsonClone(value);
274
- }
275
- }
276
- return Object.keys(extras).length ? extras : undefined;
277
- }
278
- function extractOpenAIExtraFieldsFromSemantics(semantics) {
279
- if (!semantics || !semantics.providerExtras || !isJsonObject(semantics.providerExtras)) {
280
- return undefined;
281
- }
282
- const openaiExtras = semantics.providerExtras.openaiChat;
283
- if (!openaiExtras || !isJsonObject(openaiExtras)) {
284
- return undefined;
285
- }
286
- const stored = openaiExtras.extraFields;
287
- if (!stored || !isJsonObject(stored)) {
288
- return undefined;
289
- }
290
- return stored;
291
- }
292
- function hasExplicitEmptyToolsSemantics(semantics) {
293
- if (!semantics || !semantics.tools || !isJsonObject(semantics.tools)) {
294
- return false;
295
- }
296
- const flag = semantics.tools.explicitEmpty;
297
- return flag === true;
298
- }
299
- function buildOpenAISemantics(options) {
300
- const semantics = {};
301
- if (options.systemSegments && options.systemSegments.length) {
302
- semantics.system = {
303
- textBlocks: options.systemSegments.map((segment) => segment)
304
- };
305
- }
306
- if (options.extraFields && Object.keys(options.extraFields).length) {
307
- semantics.providerExtras = {
308
- openaiChat: {
309
- extraFields: jsonClone(options.extraFields)
310
- }
311
- };
312
- }
313
- if (options.explicitEmptyTools) {
314
- semantics.tools = {
315
- explicitEmpty: true
316
- };
317
- }
318
- return Object.keys(semantics).length ? semantics : undefined;
319
- }
320
- function applyExtraFields(body, metadata, semantics) {
321
- const sources = [];
322
- const semanticsExtras = extractOpenAIExtraFieldsFromSemantics(semantics);
323
- if (semanticsExtras) {
324
- sources.push(semanticsExtras);
325
- }
326
- if (!sources.length) {
327
- return;
328
- }
329
- for (const source of sources) {
330
- for (const [key, value] of Object.entries(source)) {
331
- if (body[key] !== undefined) {
332
- continue;
333
- }
334
- body[key] = jsonClone(value);
335
- }
336
- }
337
- }
338
18
  export class ChatSemanticMapper {
339
19
  async toChat(format, ctx) {
340
- const payload = (format.payload ?? {});
341
- const normalized = normalizeChatMessages(payload.messages);
342
- const topLevelOutputs = normalizeStandaloneToolOutputs(payload.tool_outputs, normalized.missingFields);
343
- const toolOutputs = [...normalized.toolOutputs];
344
- for (const entry of topLevelOutputs) {
345
- if (!toolOutputs.find(item => item.tool_call_id === entry.tool_call_id)) {
346
- toolOutputs.push(entry);
347
- }
348
- }
349
- const metadata = { context: ctx };
350
- const rawSystemBlocks = collectSystemRawBlocks(payload.messages);
351
- if (rawSystemBlocks) {
352
- const protocolState = ensureProtocolState(metadata, 'openai');
353
- protocolState.systemMessages = jsonClone(rawSystemBlocks);
354
- }
355
- if (normalized.missingFields.length) {
356
- metadata.missingFields = normalized.missingFields;
357
- }
358
- const extraFields = collectExtraFields(payload);
359
- const explicitEmptyTools = Array.isArray(payload.tools) && payload.tools.length === 0;
360
- const semantics = buildOpenAISemantics({
361
- systemSegments: normalized.systemSegments,
362
- extraFields,
363
- explicitEmptyTools
364
- });
365
- return {
366
- messages: normalized.messages,
367
- tools: normalizeTools(payload.tools, normalized.missingFields),
368
- toolOutputs: toolOutputs.length ? toolOutputs : undefined,
369
- parameters: extractParameters(payload),
370
- semantics,
371
- metadata
372
- };
20
+ return mapOpenaiChatToChatWithNative((format.payload ?? {}), ctx);
373
21
  }
374
22
  async fromChat(chat, ctx) {
375
- const shouldEmitEmptyTools = hasExplicitEmptyToolsSemantics(chat.semantics);
376
- const payload = {
377
- messages: chat.messages,
378
- tools: chat.tools ?? (shouldEmitEmptyTools ? [] : undefined),
379
- ...(chat.parameters || {})
380
- };
381
- applyExtraFields(payload, chat.metadata, chat.semantics);
382
- // Do not forward tool_outputs to provider wire formats. OpenAI Chat
383
- // endpoints expect tool results to appear as tool role messages, and
384
- // sending the legacy top-level field causes upstream HTTP 400 responses.
385
- // Concrete translation happens earlier when responses input is unfolded
386
- // into ChatEnvelope.messages, so the provider request only needs the
387
- // canonical message list.
388
- if (payload.max_tokens === undefined && typeof payload.max_output_tokens === 'number') {
389
- payload.max_tokens = payload.max_output_tokens;
390
- delete payload.max_output_tokens;
391
- }
392
- return {
393
- protocol: 'openai-chat',
394
- direction: 'response',
395
- payload,
396
- meta: {
397
- context: ctx
398
- }
399
- };
23
+ return mapOpenaiChatFromChatWithNative(chat, ctx);
400
24
  }
401
25
  }
@@ -1,9 +1,9 @@
1
1
  import { isJsonObject, jsonClone } from '../../types/json.js';
2
2
  import { buildOpenAIChatFromGeminiRequest } from '../../../codecs/gemini-openai-codec.js';
3
- import { encodeMetadataPassthrough, extractMetadataPassthrough } from '../../../shared/metadata-passthrough.js';
3
+ import { encodeMetadataPassthrough, extractMetadataPassthrough } from '../../../metadata-passthrough.js';
4
4
  import { mapBridgeToolsToChat, mapChatToolsToBridge } from '../../../shared/tool-mapping.js';
5
5
  import { prepareGeminiToolsForBridge, buildGeminiToolsFromBridge } from '../../../shared/gemini-tool-utils.js';
6
- import { ensureProtocolState, getProtocolState } from '../../../shared/protocol-state.js';
6
+ import { ensureProtocolState, getProtocolState } from '../../../protocol-state.js';
7
7
  import { sanitizeReasoningTaggedText } from '../../../shared/reasoning-utils.js';
8
8
  import { applyClaudeThinkingToolSchemaCompatWithNative } from '../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.js';
9
9
  import { extractAntigravityGeminiSessionIdWithNative } from '../../../../router/virtual-router/engine-selection/native-router-hotpath.js';
@@ -471,14 +471,8 @@ export class ResponsesSemanticMapper {
471
471
  context: ctx
472
472
  }
473
473
  };
474
- // Some responses providers (e.g. TAB) reject sampling knobs with HTTP 400.
475
- // Filter these at mapper outbound so they never reach openai-responses providers.
476
- const unsupportedParams = ['temperature', 'top_p', 'seed', 'logit_bias'];
477
- for (const key of unsupportedParams) {
478
- if (key in result.payload) {
479
- delete result.payload[key];
480
- }
481
- }
474
+ // Sampling knobs should remain intact for OpenAI Responses protocol.
475
+ // Provider-specific removal belongs in compatibility profiles, not here.
482
476
  return result;
483
477
  }
484
478
  }
@@ -95,6 +95,7 @@ export declare class HubPipeline {
95
95
  private resolveAliasMapFromSources;
96
96
  private resolveProtocolHooks;
97
97
  private buildAdapterContext;
98
+ private applyMaxTokensPolicy;
98
99
  private maybeCreateStageRecorder;
99
100
  private asJsonObject;
100
101
  private normalizeRequest;
@@ -13,7 +13,7 @@ import { GeminiSemanticMapper } from '../semantic-mappers/gemini-mapper.js';
13
13
  import { ChatFormatAdapter } from '../format-adapters/chat-format-adapter.js';
14
14
  import { ChatSemanticMapper } from '../semantic-mappers/chat-mapper.js';
15
15
  import { createSnapshotRecorder } from '../snapshot-recorder.js';
16
- import { shouldRecordSnapshots } from '../../shared/snapshot-utils.js';
16
+ import { shouldRecordSnapshots } from '../../snapshot-utils.js';
17
17
  import { runReqInboundStage1FormatParse } from './stages/req_inbound/req_inbound_stage1_format_parse/index.js';
18
18
  import { runReqInboundStage2SemanticMap } from './stages/req_inbound/req_inbound_stage2_semantic_map/index.js';
19
19
  import { runChatContextCapture, captureResponsesContextSnapshot } from './stages/req_inbound/req_inbound_stage3_context_capture/index.js';
@@ -28,10 +28,10 @@ import { extractSessionIdentifiersFromMetadata } from './session-identifiers.js'
28
28
  import { computeRequestTokens } from '../../../router/virtual-router/token-estimator.js';
29
29
  import { annotatePassthroughGovernanceSkipWithNative, attachPassthroughProviderInputAuditWithNative, buildPassthroughAuditWithNative, applyOutboundStreamPreferenceWithNative, normalizeHubEndpointWithNative, extractAdapterContextMetadataFieldsWithNative, resolveApplyPatchToolModeFromToolsWithNative, resolveHubClientProtocolWithNative, resolveHubPolicyOverrideFromMetadataWithNative, resolveHubProviderProtocolWithNative, resolveOutboundStreamIntentWithNative, resolveHubShadowCompareConfigWithNative, resolveActiveProcessModeWithNative, findMappableSemanticsKeysWithNative, resolveHubSseProtocolFromMetadataWithNative, resolveStopMessageRouterMetadataWithNative, runHubPipelineOrchestrationWithNative } from '../../../router/virtual-router/engine-selection/native-hub-pipeline-orchestration-semantics.js';
30
30
  import { normalizeAliasMapWithNative, resolveAliasMapFromRespSemanticsWithNative } from '../../../router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js';
31
- import { isCompactionRequest } from '../../shared/compaction-detect.js';
31
+ import { isCompactionRequest } from '../../compaction-detect.js';
32
32
  import { applyHubProviderOutboundPolicy, recordHubPolicyObservation, setHubPolicyRuntimePolicy } from '../policy/policy-engine.js';
33
33
  import { applyProviderOutboundToolSurface } from '../tool-surface/tool-surface-engine.js';
34
- import { cloneRuntimeMetadata, ensureRuntimeMetadata, readRuntimeMetadata } from '../../shared/runtime-metadata.js';
34
+ import { cloneRuntimeMetadata, ensureRuntimeMetadata, readRuntimeMetadata } from '../../runtime-metadata.js';
35
35
  function isTruthyEnv(value) {
36
36
  const v = typeof value === 'string' ? value.trim().toLowerCase() : '';
37
37
  return v === '1' || v === 'true' || v === 'yes' || v === 'on';
@@ -392,6 +392,10 @@ export class HubPipeline {
392
392
  }
393
393
  const disableStickyRoutes = readRuntimeMetadata(normalized.metadata)?.disableStickyRoutes === true;
394
394
  const stopMessageRouterMetadata = resolveStopMessageRouterMetadata(normalized.metadata);
395
+ const estimatedInputTokens = (() => {
396
+ const value = normalized.metadata?.estimatedInputTokens;
397
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
398
+ })();
395
399
  const metadataInput = {
396
400
  requestId: normalized.id,
397
401
  entryEndpoint: normalized.entryEndpoint,
@@ -402,6 +406,7 @@ export class HubPipeline {
402
406
  routeHint: normalized.routeHint,
403
407
  stage: normalized.stage,
404
408
  responsesResume: responsesResume,
409
+ ...(estimatedInputTokens !== undefined ? { estimatedInputTokens } : {}),
405
410
  ...(disableStickyRoutes ? { disableStickyRoutes: true } : {}),
406
411
  ...(serverToolRequired ? { serverToolRequired: true } : {}),
407
412
  ...(sessionIdentifiers.sessionId ? { sessionId: sessionIdentifiers.sessionId } : {}),
@@ -441,6 +446,7 @@ export class HubPipeline {
441
446
  }
442
447
  const outboundStream = this.resolveOutboundStreamIntent(routing.target?.streaming);
443
448
  workingRequest = this.applyOutboundStreamPreference(workingRequest, outboundStream, activeProcessMode);
449
+ this.applyMaxTokensPolicy(workingRequest, routing.target);
444
450
  const outboundAdapterContext = this.buildAdapterContext(normalized, routing.target);
445
451
  if (routing.target?.compatibilityProfile) {
446
452
  outboundAdapterContext.compatibilityProfile = routing.target.compatibilityProfile;
@@ -1278,6 +1284,47 @@ export class HubPipeline {
1278
1284
  }
1279
1285
  return adapterContext;
1280
1286
  }
1287
+ applyMaxTokensPolicy(request, target) {
1288
+ if (!target) {
1289
+ return;
1290
+ }
1291
+ const params = request.parameters || (request.parameters = {});
1292
+ const direct = typeof params.max_tokens === 'number' && Number.isFinite(params.max_tokens)
1293
+ ? Math.floor(params.max_tokens)
1294
+ : undefined;
1295
+ const maxOutputRaw = typeof params.max_output_tokens === 'number' &&
1296
+ Number.isFinite(params.max_output_tokens)
1297
+ ? Math.floor(params.max_output_tokens)
1298
+ : undefined;
1299
+ let desired = direct ?? maxOutputRaw;
1300
+ // Default max tokens = 8k when client does not set.
1301
+ if (!desired || desired <= 0) {
1302
+ desired = 8192;
1303
+ }
1304
+ let providerCap = typeof target.maxOutputTokens === 'number' && Number.isFinite(target.maxOutputTokens)
1305
+ ? Math.floor(target.maxOutputTokens)
1306
+ : undefined;
1307
+ if (!providerCap) {
1308
+ const registry = this.routerEngine
1309
+ .providerRegistry;
1310
+ const profile = registry?.get?.(target.providerKey);
1311
+ const candidate = typeof profile?.maxOutputTokens === 'number' && Number.isFinite(profile.maxOutputTokens)
1312
+ ? Math.floor(profile.maxOutputTokens)
1313
+ : undefined;
1314
+ if (candidate && candidate > 0) {
1315
+ providerCap = candidate;
1316
+ }
1317
+ }
1318
+ if (providerCap && providerCap > 0) {
1319
+ desired = Math.min(desired, providerCap);
1320
+ }
1321
+ if (desired && desired > 0) {
1322
+ params.max_tokens = desired;
1323
+ if (params.max_output_tokens !== undefined) {
1324
+ params.max_output_tokens = desired;
1325
+ }
1326
+ }
1327
+ }
1281
1328
  maybeCreateStageRecorder(context, endpoint, options) {
1282
1329
  if (options?.disableSnapshots === true) {
1283
1330
  return undefined;
@@ -1,6 +1,6 @@
1
1
  import type { AdapterContext, ChatEnvelope } from '../../../../types/chat-envelope.js';
2
2
  import type { FormatEnvelope } from '../../../../types/format-envelope.js';
3
- import type { JsonObject } from '../../../../types/json.js';
3
+ import { type JsonObject } from '../../../../types/json.js';
4
4
  import type { SemanticMapper, StageRecorder } from '../../../../format-adapters/index.js';
5
5
  import type { StandardizedRequest } from '../../../../types/standardized.js';
6
6
  export interface ReqInboundStage2SemanticMapOptions {
@@ -1,3 +1,4 @@
1
+ import { isJsonObject, jsonClone } from '../../../../types/json.js';
1
2
  import { applyHubOperationTableInbound } from '../../../../operation-table/operation-table-runner.js';
2
3
  import { recordStage } from '../../../stages/utils.js';
3
4
  import { liftReqInboundSemantics } from './semantic-lift.js';
@@ -5,6 +6,19 @@ import { validateChatEnvelopeWithNative } from '../../../../../../router/virtual
5
6
  import { chatEnvelopeToStandardizedWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
6
7
  export async function runReqInboundStage2SemanticMap(options) {
7
8
  const chatEnvelope = await options.semanticMapper.toChat(options.formatEnvelope, options.adapterContext);
9
+ const preservedResponsesContext = (() => {
10
+ if (!chatEnvelope.semantics || typeof chatEnvelope.semantics !== 'object') {
11
+ return undefined;
12
+ }
13
+ const semantics = chatEnvelope.semantics;
14
+ const responsesNode = isJsonObject(semantics.responses)
15
+ ? semantics.responses
16
+ : undefined;
17
+ const contextNode = responsesNode && isJsonObject(responsesNode.context)
18
+ ? responsesNode.context
19
+ : undefined;
20
+ return contextNode ? jsonClone(contextNode) : undefined;
21
+ })();
8
22
  applyHubOperationTableInbound({
9
23
  formatEnvelope: options.formatEnvelope,
10
24
  chatEnvelope,
@@ -18,6 +32,27 @@ export async function runReqInboundStage2SemanticMap(options) {
18
32
  adapterContext: options.adapterContext,
19
33
  responsesResume: options.responsesResume
20
34
  });
35
+ if (preservedResponsesContext) {
36
+ const currentSemantics = chatEnvelope.semantics;
37
+ if (!currentSemantics || typeof currentSemantics !== 'object') {
38
+ chatEnvelope.semantics = { responses: { context: jsonClone(preservedResponsesContext) } };
39
+ }
40
+ else {
41
+ const semantics = currentSemantics;
42
+ const responsesNode = isJsonObject(semantics.responses)
43
+ ? semantics.responses
44
+ : {};
45
+ if (!isJsonObject(responsesNode.context)) {
46
+ chatEnvelope.semantics = {
47
+ ...semantics,
48
+ responses: {
49
+ ...responsesNode,
50
+ context: jsonClone(preservedResponsesContext)
51
+ }
52
+ };
53
+ }
54
+ }
55
+ }
21
56
  validateChatEnvelopeWithNative(chatEnvelope, {
22
57
  stage: 'req_inbound',
23
58
  direction: 'request'
@@ -29,5 +64,32 @@ export async function runReqInboundStage2SemanticMap(options) {
29
64
  endpoint: options.adapterContext.entryEndpoint,
30
65
  requestId: options.adapterContext.requestId
31
66
  });
67
+ // Ensure responses semantics (context) survive into standardized request for VirtualRouter parsing.
68
+ if (chatEnvelope.semantics && typeof chatEnvelope.semantics === 'object') {
69
+ const envelopeSemantics = chatEnvelope.semantics;
70
+ const existing = standardizedRequest.semantics;
71
+ if (!existing || typeof existing !== 'object') {
72
+ standardizedRequest.semantics = jsonClone(envelopeSemantics);
73
+ }
74
+ else {
75
+ const existingObj = existing;
76
+ const envelopeResponses = isJsonObject(envelopeSemantics.responses)
77
+ ? envelopeSemantics.responses
78
+ : undefined;
79
+ const envelopeContext = envelopeResponses && isJsonObject(envelopeResponses.context)
80
+ ? envelopeResponses.context
81
+ : undefined;
82
+ if (envelopeContext) {
83
+ const nextResponses = {
84
+ ...(isJsonObject(existingObj.responses) ? existingObj.responses : {}),
85
+ context: jsonClone(envelopeContext)
86
+ };
87
+ standardizedRequest.semantics = {
88
+ ...existingObj,
89
+ responses: nextResponses
90
+ };
91
+ }
92
+ }
93
+ }
32
94
  return { chatEnvelope, standardizedRequest };
33
95
  }
@@ -1,5 +1,6 @@
1
1
  import { recordStage } from '../../../stages/utils.js';
2
2
  import { applyReqProcessRouteSelectionWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.js';
3
+ import { cleanRoutingInstructionMarkersWithNative } from '../../../../../../router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js';
3
4
  function replaceRecordInPlace(target, source) {
4
5
  for (const key of Object.keys(target)) {
5
6
  if (!Object.prototype.hasOwnProperty.call(source, key)) {
@@ -18,7 +19,8 @@ export function runReqProcessStage2RouteSelect(options) {
18
19
  routeName: result.decision.routeName,
19
20
  originalModel: previousModel
20
21
  });
21
- replaceRecordInPlace(options.request, nativeApplied.request);
22
+ const cleanedRequest = cleanRoutingInstructionMarkersWithNative(nativeApplied.request);
23
+ replaceRecordInPlace(options.request, cleanedRequest);
22
24
  replaceRecordInPlace(options.normalizedMetadata, nativeApplied.normalizedMetadata);
23
25
  recordStage(options.stageRecorder, 'chat_process.req.stage5.route_select', {
24
26
  target: result.target,
@@ -1,6 +1,6 @@
1
1
  import { defaultSseCodecRegistry } from '../../../../../../sse/index.js';
2
2
  import { recordStage } from '../../../stages/utils.js';
3
- import { ProviderProtocolError } from '../../../../../shared/errors.js';
3
+ import { ProviderProtocolError } from '../../../../../provider-protocol-error.js';
4
4
  import { extractContextLengthDiagnosticsWithNative, extractSseWrapperErrorWithNative, isContextLengthExceededSignalWithNative, parseJsonObjectCandidateWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js';
5
5
  import { tryDecodeJsonBodyFromStream } from './stream-json-sniffer.js';
6
6
  function resolveProviderType(protocol) {
@@ -1,5 +1,5 @@
1
1
  import type { JsonObject } from '../../../../types/json.js';
2
- import type { BridgeToolDefinition } from '../../../../../shared/bridge-message-types.js';
2
+ import type { BridgeToolDefinition } from '../../../../../types/bridge-message-types.js';
3
3
  export declare function resolveAliasMapFromSemantics(semantics?: JsonObject): Record<string, string> | undefined;
4
4
  export declare function normalizeAliasMap(candidate: unknown): Record<string, string> | undefined;
5
5
  export declare function resolveClientToolsRawFromSemantics(semantics?: JsonObject): BridgeToolDefinition[] | undefined;