@mupt-ai/dari-gateway 0.2.0 → 0.3.0

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 (385) hide show
  1. package/README.md +8 -4
  2. package/dist/bun.d.ts +2 -0
  3. package/dist/bun.js +4 -0
  4. package/dist/context/eval_catalog.d.ts +3 -0
  5. package/dist/context/eval_catalog.js +7 -0
  6. package/dist/context/interaction_fingerprint.d.ts +27 -0
  7. package/dist/context/interaction_fingerprint.js +519 -0
  8. package/dist/context/interaction_fingerprint_format.d.ts +42 -0
  9. package/dist/context/interaction_fingerprint_format.js +113 -0
  10. package/dist/context/interaction_lease_depth.d.ts +2 -0
  11. package/dist/context/interaction_lease_depth.js +110 -0
  12. package/dist/context/lease_history.d.ts +7 -0
  13. package/dist/context/lease_history.js +158 -0
  14. package/dist/context/pricing.d.ts +4 -0
  15. package/dist/context/pricing.js +27 -0
  16. package/dist/context/provider_prompt_accounting.d.ts +14 -0
  17. package/dist/context/provider_prompt_accounting.js +187 -0
  18. package/dist/context/routing_context.d.ts +40 -0
  19. package/dist/context/routing_context.js +211 -0
  20. package/dist/http/auth.d.ts +2 -0
  21. package/dist/http/auth.js +35 -0
  22. package/dist/http/errors.d.ts +19 -0
  23. package/dist/http/errors.js +89 -0
  24. package/dist/http/handler.d.ts +12 -0
  25. package/dist/http/handler.js +88 -0
  26. package/dist/http/http2_server.d.ts +6 -0
  27. package/dist/http/http2_server.js +103 -0
  28. package/dist/http/serve.d.ts +20 -0
  29. package/dist/http/serve.js +78 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.js +9 -0
  32. package/dist/ingress/anthropic_messages.d.ts +3 -0
  33. package/dist/ingress/anthropic_messages.js +122 -0
  34. package/dist/ingress/anthropic_models.d.ts +1 -0
  35. package/dist/ingress/anthropic_models.js +23 -0
  36. package/dist/ingress/chat_completions.d.ts +2 -0
  37. package/dist/ingress/chat_completions.js +44 -0
  38. package/dist/ingress/claude_code/request_context.d.ts +2 -0
  39. package/dist/ingress/claude_code/request_context.js +31 -0
  40. package/dist/ingress/codex.d.ts +3 -0
  41. package/dist/ingress/codex.js +69 -0
  42. package/dist/ingress/codex_models.d.ts +2 -0
  43. package/dist/ingress/codex_models.js +89 -0
  44. package/dist/ingress/json.d.ts +1 -0
  45. package/dist/ingress/json.js +95 -0
  46. package/dist/ingress/models.d.ts +1 -0
  47. package/dist/ingress/models.js +65 -0
  48. package/dist/ingress/muse_code.d.ts +2 -0
  49. package/dist/ingress/muse_code.js +8 -0
  50. package/dist/ingress/muse_models.d.ts +9 -0
  51. package/dist/ingress/muse_models.js +32 -0
  52. package/dist/interaction/capabilities.d.ts +3 -0
  53. package/dist/interaction/capabilities.js +24 -0
  54. package/dist/interaction/image.d.ts +4 -0
  55. package/dist/interaction/image.js +13 -0
  56. package/dist/interaction/portable_reasoning_state.d.ts +4 -0
  57. package/dist/interaction/portable_reasoning_state.js +18 -0
  58. package/dist/interaction/provider_continuation_state.d.ts +6 -0
  59. package/dist/interaction/provider_continuation_state.js +27 -0
  60. package/dist/interaction/tool_identity.d.ts +10 -0
  61. package/dist/interaction/tool_identity.js +41 -0
  62. package/dist/interaction/types.d.ts +204 -0
  63. package/dist/interaction/types.js +5 -0
  64. package/dist/models/catalog.d.ts +35 -0
  65. package/dist/models/catalog.js +232 -0
  66. package/dist/models/context_limits.d.ts +2 -0
  67. package/dist/models/context_limits.js +7 -0
  68. package/dist/models/execution_provider.d.ts +9 -0
  69. package/dist/models/execution_provider.js +17 -0
  70. package/dist/models/gateways.d.ts +11 -0
  71. package/dist/models/gateways.js +45 -0
  72. package/dist/models/ids.d.ts +1 -0
  73. package/dist/models/ids.js +15 -0
  74. package/dist/models/provider_defaults.d.ts +4 -0
  75. package/dist/models/provider_defaults.js +44 -0
  76. package/dist/models/runtime_overrides.d.ts +7 -0
  77. package/dist/models/runtime_overrides.js +226 -0
  78. package/dist/models/subscriptions.d.ts +8 -0
  79. package/dist/models/subscriptions.js +37 -0
  80. package/dist/observability/errors.d.ts +8 -0
  81. package/dist/observability/errors.js +11 -0
  82. package/dist/platform/platform.d.ts +156 -0
  83. package/dist/platform/platform.js +11 -0
  84. package/dist/platform/routing_contract.d.ts +2 -0
  85. package/dist/platform/routing_contract.js +5 -0
  86. package/dist/protocol/input/anthropic_messages.d.ts +2 -0
  87. package/dist/protocol/input/anthropic_messages.js +494 -0
  88. package/dist/protocol/input/chat_completions.d.ts +4 -0
  89. package/dist/protocol/input/chat_completions.js +214 -0
  90. package/dist/protocol/input/chat_completions_validation.d.ts +2 -0
  91. package/dist/protocol/input/chat_completions_validation.js +258 -0
  92. package/dist/protocol/input/openai_responses.d.ts +2 -0
  93. package/dist/protocol/input/openai_responses.js +666 -0
  94. package/dist/protocol/input/router_model.d.ts +7 -0
  95. package/dist/protocol/input/router_model.js +43 -0
  96. package/dist/protocol/output/anthropic_messages.d.ts +10 -0
  97. package/dist/protocol/output/anthropic_messages.js +15 -0
  98. package/dist/protocol/output/anthropic_messages_output.d.ts +10 -0
  99. package/dist/protocol/output/anthropic_messages_output.js +124 -0
  100. package/dist/protocol/output/anthropic_messages_stream.d.ts +16 -0
  101. package/dist/protocol/output/anthropic_messages_stream.js +267 -0
  102. package/dist/protocol/output/chat_completions.d.ts +29 -0
  103. package/dist/protocol/output/chat_completions.js +406 -0
  104. package/dist/protocol/output/chat_reasoning_detail.d.ts +2 -0
  105. package/dist/protocol/output/chat_reasoning_detail.js +13 -0
  106. package/dist/protocol/output/delivered_stream_snapshot.d.ts +10 -0
  107. package/dist/protocol/output/delivered_stream_snapshot.js +31 -0
  108. package/dist/protocol/output/openai_responses.d.ts +10 -0
  109. package/dist/protocol/output/openai_responses.js +14 -0
  110. package/dist/protocol/output/openai_responses_output.d.ts +14 -0
  111. package/dist/protocol/output/openai_responses_output.js +125 -0
  112. package/dist/protocol/output/openai_responses_stream.d.ts +18 -0
  113. package/dist/protocol/output/openai_responses_stream.js +546 -0
  114. package/dist/protocol/output/sse_stream.d.ts +31 -0
  115. package/dist/protocol/output/sse_stream.js +67 -0
  116. package/dist/providers/anthropic_safeguards.d.ts +11 -0
  117. package/dist/providers/anthropic_safeguards.js +81 -0
  118. package/dist/providers/aws_assume_role.d.ts +17 -0
  119. package/dist/providers/aws_assume_role.js +107 -0
  120. package/dist/providers/cancel_estimate.d.ts +43 -0
  121. package/dist/providers/cancel_estimate.js +89 -0
  122. package/dist/providers/execution.d.ts +72 -0
  123. package/dist/providers/execution.js +491 -0
  124. package/dist/providers/model_capabilities.d.ts +11 -0
  125. package/dist/providers/model_capabilities.js +29 -0
  126. package/dist/providers/pi.d.ts +65 -0
  127. package/dist/providers/pi.js +325 -0
  128. package/dist/providers/pi_context.d.ts +7 -0
  129. package/dist/providers/pi_context.js +405 -0
  130. package/dist/providers/pi_options.d.ts +11 -0
  131. package/dist/providers/pi_options.js +410 -0
  132. package/dist/providers/pi_output.d.ts +2 -0
  133. package/dist/providers/pi_output.js +453 -0
  134. package/dist/providers/provider_attempt_runner.d.ts +55 -0
  135. package/dist/providers/provider_attempt_runner.js +90 -0
  136. package/dist/providers/provider_call.d.ts +77 -0
  137. package/dist/providers/provider_call.js +296 -0
  138. package/dist/providers/provider_reported_cost.d.ts +10 -0
  139. package/dist/providers/provider_reported_cost.js +123 -0
  140. package/dist/providers/reasoning.d.ts +12 -0
  141. package/dist/providers/reasoning.js +30 -0
  142. package/dist/providers/response_capture.d.ts +23 -0
  143. package/dist/providers/response_capture.js +47 -0
  144. package/dist/providers/stream_finalization.d.ts +46 -0
  145. package/dist/providers/stream_finalization.js +165 -0
  146. package/dist/providers/subscription_limits.d.ts +33 -0
  147. package/dist/providers/subscription_limits.js +179 -0
  148. package/dist/providers/subscription_usage.d.ts +10 -0
  149. package/dist/providers/subscription_usage.js +79 -0
  150. package/dist/runtime/claude_code/auxiliary_routing.d.ts +3 -0
  151. package/dist/runtime/claude_code/auxiliary_routing.js +60 -0
  152. package/dist/runtime/customer_disconnect.d.ts +20 -0
  153. package/dist/runtime/customer_disconnect.js +49 -0
  154. package/dist/runtime/explicit_model.d.ts +7 -0
  155. package/dist/runtime/explicit_model.js +57 -0
  156. package/dist/runtime/harness_identity/conversation.d.ts +33 -0
  157. package/dist/runtime/harness_identity/conversation.js +39 -0
  158. package/dist/runtime/harness_identity/extract.d.ts +8 -0
  159. package/dist/runtime/harness_identity/extract.js +214 -0
  160. package/dist/runtime/harness_identity/index.d.ts +2 -0
  161. package/dist/runtime/harness_identity/index.js +2 -0
  162. package/dist/runtime/prepare_routed_completion.d.ts +33 -0
  163. package/dist/runtime/prepare_routed_completion.js +186 -0
  164. package/dist/runtime/provider_stream_lifecycle.d.ts +31 -0
  165. package/dist/runtime/provider_stream_lifecycle.js +88 -0
  166. package/dist/runtime/provider_stream_outcome.d.ts +23 -0
  167. package/dist/runtime/provider_stream_outcome.js +55 -0
  168. package/dist/runtime/request_tags.d.ts +7 -0
  169. package/dist/runtime/request_tags.js +33 -0
  170. package/dist/runtime/routed_completion.d.ts +17 -0
  171. package/dist/runtime/routed_completion.js +80 -0
  172. package/dist/runtime/routed_protocol.d.ts +30 -0
  173. package/dist/runtime/routed_protocol.js +1 -0
  174. package/dist/runtime/routed_runtime.d.ts +40 -0
  175. package/dist/runtime/routed_runtime.js +535 -0
  176. package/dist/runtime/routing_lease.d.ts +26 -0
  177. package/dist/runtime/routing_lease.js +210 -0
  178. package/dist/runtime/runtime_reporter.d.ts +71 -0
  179. package/dist/runtime/runtime_reporter.js +35 -0
  180. package/dist/runtime/strict_provider_access.d.ts +6 -0
  181. package/dist/runtime/strict_provider_access.js +40 -0
  182. package/dist/self_host/config.d.ts +46 -0
  183. package/dist/self_host/config.js +105 -0
  184. package/dist/self_host/main.d.ts +16 -0
  185. package/dist/self_host/main.js +95 -0
  186. package/dist/self_host/platform.d.ts +13 -0
  187. package/dist/self_host/platform.js +50 -0
  188. package/dist/self_host/prefix_store.d.ts +46 -0
  189. package/dist/self_host/prefix_store.js +261 -0
  190. package/dist/self_host/resolve.d.ts +28 -0
  191. package/dist/self_host/resolve.js +167 -0
  192. package/dist/self_host/subscriptions/access.d.ts +10 -0
  193. package/dist/self_host/subscriptions/access.js +37 -0
  194. package/dist/self_host/subscriptions/http.d.ts +15 -0
  195. package/dist/self_host/subscriptions/http.js +187 -0
  196. package/dist/self_host/subscriptions/index.d.ts +24 -0
  197. package/dist/self_host/subscriptions/index.js +24 -0
  198. package/dist/self_host/subscriptions/oauth.d.ts +59 -0
  199. package/dist/self_host/subscriptions/oauth.js +376 -0
  200. package/dist/self_host/subscriptions/store.d.ts +78 -0
  201. package/dist/self_host/subscriptions/store.js +236 -0
  202. package/dist/strategies/auto_routing_selector.d.ts +12 -0
  203. package/dist/strategies/auto_routing_selector.js +61 -0
  204. package/dist/strategies/eval_relevance.d.ts +17 -0
  205. package/dist/strategies/eval_relevance.js +32 -0
  206. package/dist/strategies/fallback_decision.d.ts +8 -0
  207. package/dist/strategies/fallback_decision.js +17 -0
  208. package/dist/strategies/priority_selector.d.ts +7 -0
  209. package/dist/strategies/priority_selector.js +37 -0
  210. package/dist/strategies/route_decision.d.ts +22 -0
  211. package/dist/strategies/route_decision.js +65 -0
  212. package/dist/strategies/routing.d.ts +74 -0
  213. package/dist/strategies/routing.js +280 -0
  214. package/dist/strategies/selector_projection.d.ts +15 -0
  215. package/dist/strategies/selector_projection.js +161 -0
  216. package/dist/telemetry/background.d.ts +7 -0
  217. package/dist/telemetry/background.js +33 -0
  218. package/dist/telemetry/benchmark_replay.d.ts +37 -0
  219. package/dist/telemetry/benchmark_replay.js +108 -0
  220. package/dist/telemetry/billing_finalization.d.ts +64 -0
  221. package/dist/telemetry/billing_finalization.js +96 -0
  222. package/dist/telemetry/ingest_values.d.ts +4 -0
  223. package/dist/telemetry/ingest_values.js +12 -0
  224. package/dist/telemetry/model_cost.d.ts +3 -0
  225. package/dist/telemetry/model_cost.js +15 -0
  226. package/dist/telemetry/prefix_state.d.ts +47 -0
  227. package/dist/telemetry/prefix_state.js +116 -0
  228. package/dist/telemetry/report.d.ts +88 -0
  229. package/dist/telemetry/report.js +621 -0
  230. package/dist/telemetry/requests/interaction_observability.d.ts +45 -0
  231. package/dist/telemetry/requests/interaction_observability.js +180 -0
  232. package/dist/telemetry/requests/retained_interaction_request.d.ts +8 -0
  233. package/dist/telemetry/requests/retained_interaction_request.js +10 -0
  234. package/dist/telemetry/scrub.d.ts +2 -0
  235. package/dist/telemetry/scrub.js +31 -0
  236. package/dist/telemetry/skills/claude/catalog.d.ts +6 -0
  237. package/dist/telemetry/skills/claude/catalog.js +99 -0
  238. package/dist/telemetry/skills/claude/file_reads.d.ts +4 -0
  239. package/dist/telemetry/skills/claude/file_reads.js +110 -0
  240. package/dist/telemetry/skills/claude/observations.d.ts +3 -0
  241. package/dist/telemetry/skills/claude/observations.js +366 -0
  242. package/dist/telemetry/skills/codex/catalog.d.ts +11 -0
  243. package/dist/telemetry/skills/codex/catalog.js +138 -0
  244. package/dist/telemetry/skills/codex/exec_file_reads.d.ts +9 -0
  245. package/dist/telemetry/skills/codex/exec_file_reads.js +36 -0
  246. package/dist/telemetry/skills/codex/explicit.d.ts +3 -0
  247. package/dist/telemetry/skills/codex/explicit.js +90 -0
  248. package/dist/telemetry/skills/codex/file_reads.d.ts +4 -0
  249. package/dist/telemetry/skills/codex/file_reads.js +37 -0
  250. package/dist/telemetry/skills/codex/identity.d.ts +2 -0
  251. package/dist/telemetry/skills/codex/identity.js +20 -0
  252. package/dist/telemetry/skills/observations.d.ts +21 -0
  253. package/dist/telemetry/skills/observations.js +41 -0
  254. package/dist/telemetry/skills/paths.d.ts +11 -0
  255. package/dist/telemetry/skills/paths.js +61 -0
  256. package/dist/telemetry/skills/pi.d.ts +6 -0
  257. package/dist/telemetry/skills/pi.js +223 -0
  258. package/dist/telemetry/skills/shell_file_reads.d.ts +7 -0
  259. package/dist/telemetry/skills/shell_file_reads.js +226 -0
  260. package/dist/telemetry/skills/shell_words.d.ts +13 -0
  261. package/dist/telemetry/skills/shell_words.js +189 -0
  262. package/dist/telemetry/tools/input.d.ts +2 -0
  263. package/dist/telemetry/tools/input.js +14 -0
  264. package/dist/telemetry/tools/observations.d.ts +29 -0
  265. package/dist/telemetry/tools/observations.js +247 -0
  266. package/dist/telemetry/usage.d.ts +57 -0
  267. package/dist/telemetry/usage.js +136 -0
  268. package/dist/types.d.ts +97 -0
  269. package/dist/types.js +1 -0
  270. package/package.json +22 -7
  271. package/src/bun.ts +2 -2
  272. package/src/context/eval_catalog.ts +1 -1
  273. package/src/context/interaction_fingerprint.ts +9 -9
  274. package/src/context/interaction_fingerprint_format.ts +1 -1
  275. package/src/context/interaction_lease_depth.ts +1 -1
  276. package/src/context/pricing.ts +6 -3
  277. package/src/context/provider_prompt_accounting.ts +5 -5
  278. package/src/context/routing_context.ts +16 -16
  279. package/src/http/auth.ts +1 -1
  280. package/src/http/handler.ts +15 -8
  281. package/src/http/serve.ts +3 -3
  282. package/src/index.ts +14 -6
  283. package/src/ingress/anthropic_messages.ts +12 -12
  284. package/src/ingress/anthropic_models.ts +1 -1
  285. package/src/ingress/chat_completions.ts +17 -10
  286. package/src/ingress/claude_code/request_context.ts +2 -2
  287. package/src/ingress/codex.ts +14 -10
  288. package/src/ingress/codex_models.ts +4 -4
  289. package/src/ingress/json.ts +1 -1
  290. package/src/ingress/models.ts +22 -10
  291. package/src/ingress/muse_code.ts +9 -0
  292. package/src/ingress/muse_models.ts +36 -0
  293. package/src/interaction/capabilities.ts +1 -1
  294. package/src/interaction/portable_reasoning_state.ts +1 -1
  295. package/src/interaction/provider_continuation_state.ts +1 -1
  296. package/src/interaction/tool_identity.ts +2 -2
  297. package/src/interaction/types.ts +2 -0
  298. package/src/models/catalog.ts +310 -0
  299. package/src/models/context_limits.ts +1 -1
  300. package/src/models/execution_provider.ts +5 -2
  301. package/src/models/ids.ts +1 -1
  302. package/src/models/provider_defaults.ts +4 -1
  303. package/src/models/runtime_overrides.ts +23 -1
  304. package/src/models/subscriptions.ts +54 -0
  305. package/src/observability/errors.ts +2 -2
  306. package/src/platform/platform.ts +9 -5
  307. package/src/protocol/input/anthropic_messages.ts +7 -7
  308. package/src/protocol/input/chat_completions.ts +8 -6
  309. package/src/protocol/input/chat_completions_validation.ts +6 -5
  310. package/src/protocol/input/openai_responses.ts +6 -6
  311. package/src/protocol/output/anthropic_messages.ts +3 -3
  312. package/src/protocol/output/anthropic_messages_output.ts +6 -4
  313. package/src/protocol/output/anthropic_messages_stream.ts +7 -7
  314. package/src/protocol/output/chat_completions.ts +13 -13
  315. package/src/protocol/output/chat_reasoning_detail.ts +1 -1
  316. package/src/protocol/output/openai_responses.ts +3 -3
  317. package/src/protocol/output/openai_responses_output.ts +4 -2
  318. package/src/protocol/output/openai_responses_stream.ts +6 -6
  319. package/src/protocol/output/sse_stream.ts +3 -3
  320. package/src/providers/anthropic_safeguards.ts +2 -2
  321. package/src/providers/aws_assume_role.ts +2 -2
  322. package/src/providers/cancel_estimate.ts +1 -1
  323. package/src/providers/execution.ts +17 -17
  324. package/src/providers/pi.ts +34 -19
  325. package/src/providers/pi_context.ts +6 -6
  326. package/src/providers/pi_options.ts +27 -11
  327. package/src/providers/pi_output.ts +5 -5
  328. package/src/providers/provider_attempt_runner.ts +1 -1
  329. package/src/providers/provider_call.ts +21 -17
  330. package/src/providers/provider_reported_cost.ts +3 -3
  331. package/src/providers/reasoning.ts +2 -2
  332. package/src/providers/stream_finalization.ts +9 -9
  333. package/src/providers/subscription_limits.ts +24 -7
  334. package/src/runtime/claude_code/auxiliary_routing.ts +5 -5
  335. package/src/runtime/customer_disconnect.ts +1 -1
  336. package/src/runtime/explicit_model.ts +19 -20
  337. package/src/runtime/harness_identity/conversation.ts +1 -1
  338. package/src/runtime/harness_identity/extract.ts +3 -3
  339. package/src/runtime/harness_identity/index.ts +2 -2
  340. package/src/runtime/prepare_routed_completion.ts +35 -16
  341. package/src/runtime/provider_stream_lifecycle.ts +1 -1
  342. package/src/runtime/provider_stream_outcome.ts +2 -2
  343. package/src/runtime/request_tags.ts +2 -2
  344. package/src/runtime/routed_completion.ts +11 -11
  345. package/src/runtime/routed_protocol.ts +2 -2
  346. package/src/runtime/routed_runtime.ts +20 -19
  347. package/src/runtime/routing_lease.ts +7 -7
  348. package/src/runtime/runtime_reporter.ts +3 -3
  349. package/src/runtime/strict_provider_access.ts +42 -0
  350. package/src/self_host/main.ts +12 -12
  351. package/src/self_host/platform.ts +5 -5
  352. package/src/self_host/prefix_store.ts +2 -2
  353. package/src/self_host/resolve.ts +17 -31
  354. package/src/self_host/subscriptions/access.ts +2 -2
  355. package/src/self_host/subscriptions/http.ts +2 -2
  356. package/src/self_host/subscriptions/index.ts +4 -4
  357. package/src/self_host/subscriptions/oauth.ts +139 -8
  358. package/src/self_host/subscriptions/store.ts +2 -1
  359. package/src/strategies/auto_routing_selector.ts +2 -2
  360. package/src/strategies/eval_relevance.ts +3 -3
  361. package/src/strategies/priority_selector.ts +1 -1
  362. package/src/strategies/route_decision.ts +7 -7
  363. package/src/strategies/routing.ts +10 -10
  364. package/src/strategies/selector_projection.ts +2 -2
  365. package/src/telemetry/billing_finalization.ts +3 -3
  366. package/src/telemetry/model_cost.ts +1 -1
  367. package/src/telemetry/prefix_state.ts +4 -4
  368. package/src/telemetry/report.ts +21 -21
  369. package/src/telemetry/requests/interaction_observability.ts +1 -1
  370. package/src/telemetry/requests/retained_interaction_request.ts +1 -1
  371. package/src/telemetry/skills/claude/catalog.ts +1 -1
  372. package/src/telemetry/skills/claude/file_reads.ts +6 -6
  373. package/src/telemetry/skills/claude/observations.ts +3 -3
  374. package/src/telemetry/skills/codex/catalog.ts +3 -3
  375. package/src/telemetry/skills/codex/exec_file_reads.ts +4 -4
  376. package/src/telemetry/skills/codex/explicit.ts +3 -3
  377. package/src/telemetry/skills/codex/file_reads.ts +5 -5
  378. package/src/telemetry/skills/observations.ts +7 -7
  379. package/src/telemetry/skills/pi.ts +3 -3
  380. package/src/telemetry/skills/shell_file_reads.ts +2 -2
  381. package/src/telemetry/skills/shell_words.ts +1 -1
  382. package/src/telemetry/tools/input.ts +1 -1
  383. package/src/telemetry/tools/observations.ts +9 -9
  384. package/src/telemetry/usage.ts +5 -5
  385. package/src/types.ts +20 -3
@@ -0,0 +1,113 @@
1
+ import { createHash } from "node:crypto";
2
+ import { stableStringify } from "@mupt-ai/dari-router/policy-engine";
3
+ // Bump when canonical fingerprint semantics change so persisted hashes from
4
+ // incompatible contracts remain disjoint.
5
+ const INTERACTION_FINGERPRINT_VERSION = "interaction-v3";
6
+ const OPTION_FINGERPRINT_VERSION = "interaction-options-v1";
7
+ export function interactionFingerprintHeadHash(routerId, request) {
8
+ const systemItems = [];
9
+ for (const item of request.items) {
10
+ if (item.type !== "message"
11
+ || (item.role !== "system" && item.role !== "developer")) {
12
+ break;
13
+ }
14
+ systemItems.push({
15
+ actor: item.role,
16
+ content: systemFingerprintContent(item.content, item.contentShape),
17
+ });
18
+ }
19
+ return sha256(stableStringify({
20
+ version: INTERACTION_FINGERPRINT_VERSION,
21
+ routerId,
22
+ ...(request.agentContext === undefined ? {} : { agentContext: {
23
+ requestClass: request.agentContext.requestClass,
24
+ agentId: request.agentContext.agentId ?? null,
25
+ } }),
26
+ instructions: request.instructions ?? null,
27
+ systemItems,
28
+ tools: request.tools,
29
+ }));
30
+ }
31
+ function systemFingerprintContent(content, shape) {
32
+ const normalized = interactionFingerprintContent(content, shape);
33
+ // Anthropic defines a string system value and one plain text block as
34
+ // equivalent. Preserve that established head identity without flattening
35
+ // structured system content such as images or multiple blocks.
36
+ if (Array.isArray(normalized)
37
+ && normalized.length === 1
38
+ && normalized[0]?.type === "text") {
39
+ return normalized[0].text;
40
+ }
41
+ return normalized;
42
+ }
43
+ export function interactionOptionsFingerprints(request) {
44
+ return {
45
+ tool_choice_fp: optionFingerprint("tool-choice", request.toolChoice ?? null),
46
+ response_format_fp: optionFingerprint("response-format", request.responseFormat ?? null),
47
+ };
48
+ }
49
+ export function canonicalInteractionFingerprintStep(step) {
50
+ return stableStringify({
51
+ actor: step.actor,
52
+ content: step.content,
53
+ calls: step.calls.length > 0 ? step.calls : null,
54
+ resultCallId: step.resultCallId,
55
+ ...(step.itemId ? { itemId: step.itemId } : {}),
56
+ ...(step.phase ? { phase: step.phase } : {}),
57
+ ...(step.reasoning ? { reasoning: step.reasoning } : {}),
58
+ });
59
+ }
60
+ export function interactionFingerprintContent(content, shape) {
61
+ // Preserve the established identity rule that absent and explicit null
62
+ // content are equivalent. Structured parts remain distinct from strings.
63
+ if (shape === "absent" || shape === "null")
64
+ return null;
65
+ if (shape === "string") {
66
+ if (typeof content === "string")
67
+ return content;
68
+ if (!Array.isArray(content))
69
+ return "";
70
+ return content
71
+ .filter((part) => part.type === "text")
72
+ .map((part) => part.text)
73
+ .join("");
74
+ }
75
+ if (!Array.isArray(content))
76
+ return [];
77
+ return content.map((part) => {
78
+ if (part.type === "text")
79
+ return { type: "text", text: part.text };
80
+ if (part.type === "tool_reference") {
81
+ return {
82
+ type: "tool_reference",
83
+ toolName: part.toolName,
84
+ };
85
+ }
86
+ return {
87
+ type: "image",
88
+ url: part.url,
89
+ ...(part.detail !== undefined ? { detail: part.detail } : {}),
90
+ };
91
+ });
92
+ }
93
+ export function normalizedAssistantFingerprintContent(content, shape) {
94
+ const normalized = interactionFingerprintContent(content, shape);
95
+ return typeof normalized === "string" && normalized.trim() === ""
96
+ ? null
97
+ : normalized;
98
+ }
99
+ export function appendFingerprintContentText(content, text) {
100
+ if (!text)
101
+ return content;
102
+ if (typeof content === "string")
103
+ return content ? `${content}\n${text}` : text;
104
+ if (Array.isArray(content))
105
+ return [...content, { type: "text", text }];
106
+ return text;
107
+ }
108
+ function optionFingerprint(kind, value) {
109
+ return sha256(`${OPTION_FINGERPRINT_VERSION}\u0000${kind}\u0000${stableStringify(value)}`);
110
+ }
111
+ function sha256(text) {
112
+ return createHash("sha256").update(text, "utf8").digest("hex");
113
+ }
@@ -0,0 +1,2 @@
1
+ import type { InteractionRequest } from "../interaction/types.js";
2
+ export declare function interactionLeaseFenceDepth(request: InteractionRequest): number;
@@ -0,0 +1,110 @@
1
+ // Monotonic, target-independent position used only to fence asynchronous
2
+ // lease writes. It follows canonical Interaction grouping and deliberately
3
+ // does not serialize selector messages or approximate provider cache blocks.
4
+ export function interactionLeaseFenceDepth(request) {
5
+ const state = {
6
+ depth: 0,
7
+ last: null,
8
+ };
9
+ const startAssistant = (args) => {
10
+ const assistant = {
11
+ kind: "assistant",
12
+ rawBlocks: args.rawBlocks,
13
+ hasContent: args.hasContent ?? false,
14
+ hasReasoning: args.hasReasoning ?? false,
15
+ hasToolCalls: args.hasToolCalls ?? false,
16
+ hostedToolCarrier: args.hostedToolCarrier ?? false,
17
+ };
18
+ state.depth += groupBlockCount(assistant.rawBlocks);
19
+ state.last = assistant;
20
+ return assistant;
21
+ };
22
+ const addAssistantBlock = (assistant) => {
23
+ const before = groupBlockCount(assistant.rawBlocks);
24
+ assistant.rawBlocks += 1;
25
+ state.depth += groupBlockCount(assistant.rawBlocks) - before;
26
+ };
27
+ const addOther = (blocks) => {
28
+ state.depth += groupBlockCount(blocks);
29
+ state.last = { kind: "other" };
30
+ };
31
+ for (const item of request.items) {
32
+ if (item.type === "reasoning") {
33
+ if (state.last?.kind === "assistant"
34
+ && !state.last.hasContent
35
+ && !state.last.hostedToolCarrier) {
36
+ state.last.hasReasoning = true;
37
+ }
38
+ else {
39
+ startAssistant({ rawBlocks: 0, hasReasoning: true });
40
+ }
41
+ continue;
42
+ }
43
+ if (item.type === "reasoning_configuration") {
44
+ continue;
45
+ }
46
+ if (item.type === "tool_result") {
47
+ addOther(1);
48
+ continue;
49
+ }
50
+ if (item.type === "tool_call" || item.type === "hosted_tool_call") {
51
+ const assistant = state.last?.kind === "assistant"
52
+ ? state.last
53
+ : startAssistant({ rawBlocks: 0 });
54
+ addAssistantBlock(assistant);
55
+ assistant.hasToolCalls = true;
56
+ if (item.type === "hosted_tool_call") {
57
+ assistant.hostedToolCarrier = true;
58
+ }
59
+ continue;
60
+ }
61
+ if (item.role === "system" || item.role === "developer") {
62
+ state.last = { kind: "other" };
63
+ continue;
64
+ }
65
+ const blocks = messageContentBlocks(item);
66
+ const hasContent = blocks > 0;
67
+ if (item.role === "assistant"
68
+ && state.last?.kind === "assistant"
69
+ && state.last.hasReasoning
70
+ && !state.last.hasContent
71
+ && !state.last.hasToolCalls) {
72
+ const before = groupBlockCount(state.last.rawBlocks);
73
+ state.last.rawBlocks = blocks;
74
+ state.last.hasContent = hasContent;
75
+ state.depth += groupBlockCount(state.last.rawBlocks) - before;
76
+ continue;
77
+ }
78
+ if (item.role === "assistant") {
79
+ startAssistant({ rawBlocks: blocks, hasContent });
80
+ }
81
+ else {
82
+ addOther(blocks);
83
+ }
84
+ }
85
+ return state.depth;
86
+ }
87
+ function messageContentBlocks(message) {
88
+ if (message.contentShape === "absent" || message.contentShape === "null") {
89
+ return 0;
90
+ }
91
+ if (message.contentShape === "string") {
92
+ return stringContent(message.content).length > 0 ? 1 : 0;
93
+ }
94
+ if (Array.isArray(message.content))
95
+ return message.content.length;
96
+ return message.content === null ? 0 : 1;
97
+ }
98
+ function stringContent(content) {
99
+ if (typeof content === "string")
100
+ return content;
101
+ if (!Array.isArray(content))
102
+ return "";
103
+ return content
104
+ .filter((part) => part.type === "text")
105
+ .map((part) => part.text)
106
+ .join("");
107
+ }
108
+ function groupBlockCount(rawBlocks) {
109
+ return Math.max(1, rawBlocks);
110
+ }
@@ -0,0 +1,7 @@
1
+ import { type ChatMessage, type RouterPrefixHit, type RoutingCandidate, type SelectorLeaseHistoryEntry } from "@mupt-ai/dari-router/policy-engine";
2
+ export declare function leaseHistoryFromPrefixHits(args: {
3
+ prefixHits: readonly RouterPrefixHit[];
4
+ conversationId: string;
5
+ candidates: readonly RoutingCandidate[];
6
+ messages: readonly ChatMessage[];
7
+ }): SelectorLeaseHistoryEntry[];
@@ -0,0 +1,158 @@
1
+ import { isReasoningEffort, isRecord, routingCandidateKey, } from "@mupt-ai/dari-router/policy-engine";
2
+ const MAX_HISTORY_LEASES = 3;
3
+ const MAX_OBSERVATION_CHARS = 3_000;
4
+ const TEST_COMMAND = /(?:^|\s)(?:bun|npm|pnpm|yarn|uv|pytest|cargo|go|make|npx|bash)\b[^\n]*(?:test|check|lint|typecheck|vet|build)/i;
5
+ export function leaseHistoryFromPrefixHits(args) {
6
+ const candidateKeys = new Set(args.candidates.map(routingCandidateKey));
7
+ const hits = deduplicatedHits(args.prefixHits)
8
+ .filter((hit) => hit.conversation_id === args.conversationId)
9
+ .sort((left, right) => left.message_depth - right.message_depth);
10
+ const segments = [];
11
+ for (const hit of hits) {
12
+ const remaining = hit.lease_turns_remaining;
13
+ const effort = hit.next_reasoning_effort;
14
+ if (typeof remaining !== "number" ||
15
+ !Number.isInteger(remaining) ||
16
+ remaining < 0 ||
17
+ !hit.next_model ||
18
+ !isReasoningEffort(effort)) {
19
+ continue;
20
+ }
21
+ const candidate = { model: hit.next_model, reasoningEffort: effort };
22
+ if (!candidateKeys.has(routingCandidateKey(candidate)))
23
+ continue;
24
+ const current = segments.at(-1);
25
+ if (current !== undefined &&
26
+ routingCandidateKey(current.candidate) === routingCandidateKey(candidate) &&
27
+ remaining < current.lastRemaining) {
28
+ current.lastRemaining = remaining;
29
+ continue;
30
+ }
31
+ segments.push({
32
+ candidate,
33
+ requestedTurns: remaining + 1,
34
+ lastRemaining: remaining,
35
+ rationale: hit.reason ?? "",
36
+ });
37
+ }
38
+ const recent = segments.slice(-MAX_HISTORY_LEASES);
39
+ const turns = conversationTurns(args.messages);
40
+ let turnCursor = turns.length;
41
+ const history = [...recent].reverse().map((segment) => {
42
+ const completedTurns = Math.max(0, Math.min(segment.requestedTurns, segment.requestedTurns - segment.lastRemaining));
43
+ const start = Math.max(0, turnCursor - completedTurns);
44
+ const observation = turns.slice(start, turnCursor);
45
+ turnCursor = start;
46
+ return observationForSegment(segment, completedTurns, observation);
47
+ });
48
+ return history.reverse();
49
+ }
50
+ function observationForSegment(segment, completedTurns, turns) {
51
+ const calls = turns.flatMap((turn) => turn.assistant.tool_calls ?? []);
52
+ const results = turns.flatMap((turn) => turn.toolResults);
53
+ const lastCall = calls.at(-1);
54
+ const callId = typeof lastCall?.["id"] === "string" ? lastCall["id"] : null;
55
+ const lastResult = callId === null
56
+ ? undefined
57
+ : [...results].reverse().find((result) => result.tool_call_id === callId);
58
+ const testCall = [...calls].reverse().find((call) => {
59
+ const parsed = toolCall(call);
60
+ return parsed?.name === "bash" && TEST_COMMAND.test(command(parsed.arguments));
61
+ });
62
+ const parsedLastCall = lastCall === undefined ? null : toolCall(lastCall);
63
+ const parsedTestCall = testCall === undefined ? null : toolCall(testCall);
64
+ const testCallId = typeof testCall?.["id"] === "string" ? testCall["id"] : null;
65
+ const testResult = testCallId === null
66
+ ? undefined
67
+ : [...results].reverse().find((result) => result.tool_call_id === testCallId);
68
+ const lastAssistant = turns.at(-1)?.assistant;
69
+ const thought = lastAssistant?.reasoning_content
70
+ ?? lastAssistant?.reasoning_text
71
+ ?? lastAssistant?.reasoning
72
+ ?? null;
73
+ return {
74
+ candidate: {
75
+ model: segment.candidate.model,
76
+ thinking_level: segment.candidate.reasoningEffort,
77
+ },
78
+ requested_turns: segment.requestedTurns,
79
+ completed_turns: completedTurns,
80
+ rationale: truncate(segment.rationale),
81
+ last_agent_thought: thought === null ? null : truncate(thought),
82
+ last_tool_call: parsedLastCall === null
83
+ ? null
84
+ : { name: parsedLastCall.name, arguments: compactJson(parsedLastCall.arguments) },
85
+ last_tool_result: lastResult === undefined ? null : compactJson(lastResult.content ?? null),
86
+ // Generic Chat Completions tool results do not carry a portable error bit
87
+ // or a trustworthy changed-file count.
88
+ tool_errors: null,
89
+ files_changed: null,
90
+ tests: parsedTestCall === null
91
+ ? null
92
+ : {
93
+ command: truncate(command(parsedTestCall.arguments)),
94
+ status: "unknown",
95
+ result: testResult === undefined ? null : compactJson(testResult.content ?? null),
96
+ },
97
+ };
98
+ }
99
+ function deduplicatedHits(hits) {
100
+ const byState = new Map();
101
+ for (const hit of hits) {
102
+ const key = [
103
+ hit.conversation_id,
104
+ hit.message_depth,
105
+ hit.next_model ?? "",
106
+ hit.next_reasoning_effort ?? "",
107
+ hit.lease_turns_remaining ?? "",
108
+ ].join("\u0000");
109
+ const existing = byState.get(key);
110
+ if (existing === undefined || existing.updated_at < hit.updated_at)
111
+ byState.set(key, hit);
112
+ }
113
+ return [...byState.values()];
114
+ }
115
+ function conversationTurns(messages) {
116
+ const turns = [];
117
+ let current;
118
+ for (const message of messages) {
119
+ if (message.role === "assistant") {
120
+ current = { assistant: message, toolResults: [] };
121
+ turns.push(current);
122
+ }
123
+ else if (message.role === "tool" && current !== undefined) {
124
+ current.toolResults.push(message);
125
+ }
126
+ }
127
+ return turns;
128
+ }
129
+ function toolCall(value) {
130
+ const fn = value["function"];
131
+ if (!isRecord(fn) || typeof fn.name !== "string")
132
+ return null;
133
+ const rawArguments = fn.arguments ?? {};
134
+ if (typeof rawArguments !== "string") {
135
+ return { name: fn.name, arguments: compactJson(rawArguments) };
136
+ }
137
+ try {
138
+ return { name: fn.name, arguments: JSON.parse(rawArguments) };
139
+ }
140
+ catch {
141
+ return { name: fn.name, arguments: rawArguments };
142
+ }
143
+ }
144
+ function command(value) {
145
+ return isRecord(value) && typeof value.command === "string" ? value.command : "";
146
+ }
147
+ function compactJson(value) {
148
+ const serialized = JSON.stringify(value) ?? "null";
149
+ if (serialized.length <= MAX_OBSERVATION_CHARS) {
150
+ return JSON.parse(serialized);
151
+ }
152
+ return `${serialized.slice(0, MAX_OBSERVATION_CHARS)}…`;
153
+ }
154
+ function truncate(value) {
155
+ return value.length <= MAX_OBSERVATION_CHARS
156
+ ? value
157
+ : `${value.slice(0, MAX_OBSERVATION_CHARS)}…`;
158
+ }
@@ -0,0 +1,4 @@
1
+ import type { ModelPricing, PricingLookup } from "@mupt-ai/dari-router/policy-engine";
2
+ import type { ResolvedRouter } from "../types.js";
3
+ export declare function pricingLookupForRouter(credentials: ResolvedRouter): PricingLookup;
4
+ export declare function modelPricingForRouter(credentials: ResolvedRouter, model: string): ModelPricing | null;
@@ -0,0 +1,27 @@
1
+ import { registeredModelPrice } from "../providers/pi.js";
2
+ export function pricingLookupForRouter(credentials) {
3
+ return (model) => modelPricingForRouter(credentials, model);
4
+ }
5
+ export function modelPricingForRouter(credentials, model) {
6
+ // A model the platform neither prices nor configures is served from Pi's
7
+ // catalog (see buildModel), so its catalog price is the one it is billed at.
8
+ const price = credentials.model_prices?.[model]
9
+ ?? (credentials.model_configs?.[model] === undefined ? registeredModelPrice(model) : null);
10
+ if (!price || typeof price.input !== "number" || typeof price.output !== "number")
11
+ return null;
12
+ // Null cached rates mean the provider publishes none: bill cached prompt
13
+ // buckets at the input rate, never for free.
14
+ return {
15
+ input: price.input,
16
+ output: price.output,
17
+ cacheRead: price.cached_input ?? price.input,
18
+ cacheWrite: price.cache_write ?? price.input,
19
+ ...(price.tiers?.length ? { tiers: price.tiers.map((tier) => ({
20
+ inputTokensAbove: tier.input_tokens_above,
21
+ input: tier.input,
22
+ output: tier.output,
23
+ cacheRead: tier.cached_input ?? tier.input,
24
+ cacheWrite: tier.cache_write ?? tier.input,
25
+ })) } : {}),
26
+ };
27
+ }
@@ -0,0 +1,14 @@
1
+ import { type CandidatePromptAccounting } from "@mupt-ai/dari-router/policy-engine";
2
+ import type { InteractionRequest, ProviderIdentity } from "../interaction/types.js";
3
+ import type { InteractionPrefixContext } from "./interaction_fingerprint.js";
4
+ type PromptMetrics = {
5
+ blockDepth: number;
6
+ serializedChars: number;
7
+ };
8
+ export declare function providerPromptAccounting(args: {
9
+ request: InteractionRequest;
10
+ prefix: InteractionPrefixContext;
11
+ targetsByModel: ReadonlyMap<string, ProviderIdentity>;
12
+ }): CandidatePromptAccounting;
13
+ export declare function promptMetrics(request: InteractionRequest, target: ProviderIdentity): PromptMetrics;
14
+ export {};
@@ -0,0 +1,187 @@
1
+ import { isRecord, stableStringify, } from "@mupt-ai/dari-router/policy-engine";
2
+ import { toolsByWireName } from "../interaction/tool_identity.js";
3
+ import { buildContext } from "../providers/pi_context.js";
4
+ import { isOpenAIResponsesApi } from "../providers/model_capabilities.js";
5
+ const ACCOUNTING_IMAGE_URL = "data:image/png;base64,AA==";
6
+ const IMAGE_ESTIMATED_TOKENS = {
7
+ low: 512,
8
+ auto: 1024,
9
+ high: 2048,
10
+ original: 2048,
11
+ };
12
+ const CHARS_PER_ESTIMATED_TOKEN = 4;
13
+ // Cost and cache-lookback estimates are candidate-specific because compatible
14
+ // continuation state and provider serialization can change what each model
15
+ // sees.
16
+ export function providerPromptAccounting(args) {
17
+ const fullByModel = new Map();
18
+ const prefixCharsByModelAndItem = new Map();
19
+ const targetFor = (model) => {
20
+ const target = args.targetsByModel.get(model);
21
+ if (!target) {
22
+ throw new Error(`missing provider target for ${model}`);
23
+ }
24
+ return target;
25
+ };
26
+ const fullMetrics = (model) => {
27
+ const cached = fullByModel.get(model);
28
+ if (cached)
29
+ return cached;
30
+ const target = targetFor(model);
31
+ const metrics = promptMetrics(args.request, target);
32
+ fullByModel.set(model, metrics);
33
+ return metrics;
34
+ };
35
+ return {
36
+ anchorSemantics: "stored_input",
37
+ providerBlockDepthFor: (model) => fullMetrics(model).blockDepth,
38
+ promptEstimateFor: (model, anchor) => {
39
+ const full = fullMetrics(model);
40
+ if (!anchor) {
41
+ return {
42
+ chars: full.serializedChars,
43
+ reusesStoredPromptTokens: false,
44
+ };
45
+ }
46
+ const itemIndex = args.prefix.itemIndexByHashByModel
47
+ .get(model)
48
+ ?.get(anchor.hash);
49
+ if (itemIndex === undefined) {
50
+ return {
51
+ chars: full.serializedChars,
52
+ reusesStoredPromptTokens: false,
53
+ };
54
+ }
55
+ const key = `${model}\u0000${itemIndex}`;
56
+ let prefixChars = prefixCharsByModelAndItem.get(key);
57
+ if (prefixChars === undefined) {
58
+ prefixChars = promptMetrics({
59
+ ...args.request,
60
+ items: args.request.items.slice(0, itemIndex + 1),
61
+ }, targetFor(model)).serializedChars;
62
+ prefixCharsByModelAndItem.set(key, prefixChars);
63
+ }
64
+ return {
65
+ chars: Math.max(0, full.serializedChars - prefixChars),
66
+ reusesStoredPromptTokens: true,
67
+ };
68
+ },
69
+ };
70
+ }
71
+ export function promptMetrics(request, target) {
72
+ const accountingInput = promptAccountingInput(request);
73
+ const context = buildContext(accountingInput.request, target);
74
+ const messages = context.messages.flatMap((message) => {
75
+ const visible = providerVisibleMessage(message);
76
+ return visible ? [visible] : [];
77
+ });
78
+ const tools = providerVisibleTools(request, context.tools, target);
79
+ const prompt = {
80
+ ...(context.systemPrompt !== undefined
81
+ ? { systemPrompt: context.systemPrompt }
82
+ : {}),
83
+ ...(tools.length ? { tools } : {}),
84
+ messages,
85
+ ...(request.responseFormat !== undefined
86
+ ? { responseFormat: request.responseFormat }
87
+ : {}),
88
+ ...(request.toolChoice !== undefined
89
+ ? { toolChoice: request.toolChoice }
90
+ : {}),
91
+ ...(request.parallelToolCalls !== undefined
92
+ ? { parallelToolCalls: request.parallelToolCalls }
93
+ : {}),
94
+ };
95
+ return {
96
+ blockDepth: messages.reduce((total, message) => total + providerVisibleBlockCount(message), 0),
97
+ serializedChars: stableStringify(prompt).length + accountingInput.imageEstimatedChars,
98
+ };
99
+ }
100
+ function providerVisibleMessage(value) {
101
+ if (!isRecord(value) || typeof value.role !== "string")
102
+ return null;
103
+ if (value.role === "assistant") {
104
+ return {
105
+ role: value.role,
106
+ content: sanitizeProviderContent(Array.isArray(value.content) ? value.content : []),
107
+ };
108
+ }
109
+ if (value.role === "toolResult") {
110
+ return {
111
+ role: value.role,
112
+ toolCallId: value.toolCallId ?? null,
113
+ toolName: value.toolName ?? null,
114
+ content: sanitizeProviderContent(Array.isArray(value.content) ? value.content : []),
115
+ isError: value.isError === true,
116
+ };
117
+ }
118
+ return {
119
+ role: value.role,
120
+ content: sanitizeProviderContent(value.content ?? ""),
121
+ };
122
+ }
123
+ function sanitizeProviderContent(value) {
124
+ if (!Array.isArray(value))
125
+ return value;
126
+ return value.map((part) => {
127
+ if (!isRecord(part))
128
+ return part;
129
+ if (part.type === "providerItem" && isRecord(part.item)) {
130
+ return part.item;
131
+ }
132
+ if (part.type === "image"
133
+ && typeof part.mimeType === "string"
134
+ && typeof part.data === "string") {
135
+ return { ...part, data: "<image-data>" };
136
+ }
137
+ return part;
138
+ });
139
+ }
140
+ function providerVisibleBlockCount(message) {
141
+ if (message.role === "toolResult")
142
+ return 1;
143
+ const content = message.content;
144
+ return Math.max(1, Array.isArray(content) ? content.length : 1);
145
+ }
146
+ function providerVisibleTools(request, contextTools, target) {
147
+ const definitions = toolsByWireName(request.tools);
148
+ const tools = (contextTools ?? []).map((tool) => {
149
+ if (typeof tool.name !== "string")
150
+ return tool;
151
+ const definition = definitions.get(tool.name);
152
+ return definition?.kind !== "function"
153
+ || definition.strict === undefined
154
+ ? tool
155
+ : { ...tool, strict: definition.strict };
156
+ });
157
+ if (!isOpenAIResponsesApi(target.api))
158
+ return tools;
159
+ return [
160
+ ...tools,
161
+ ...request.tools.flatMap((tool) => tool.kind === "hosted" ? [tool.config] : []),
162
+ ];
163
+ }
164
+ function promptAccountingInput(request) {
165
+ let imageEstimatedChars = 0;
166
+ const sanitizeContent = (parts) => parts.map((part) => {
167
+ if (part.type !== "image")
168
+ return part;
169
+ const detail = part.detail ?? "auto";
170
+ imageEstimatedChars +=
171
+ IMAGE_ESTIMATED_TOKENS[detail] * CHARS_PER_ESTIMATED_TOKEN;
172
+ return { ...part, url: ACCOUNTING_IMAGE_URL };
173
+ });
174
+ const items = request.items.map((item) => {
175
+ if (item.type === "message") {
176
+ return { ...item, content: sanitizeContent(item.content) };
177
+ }
178
+ if (item.type === "tool_result" && Array.isArray(item.output)) {
179
+ return { ...item, output: sanitizeContent(item.output) };
180
+ }
181
+ return item;
182
+ });
183
+ return {
184
+ request: { ...request, items },
185
+ imageEstimatedChars,
186
+ };
187
+ }
@@ -0,0 +1,40 @@
1
+ import { type ActiveLease, type PendingLease, type CandidateCostEstimate, type ChainHits, type PrefixHit, type ChatMessage, type PreviousDecision, type PricingLookup, type SelectorLeaseHistoryEntry, type StrategyCandidateResolution } from "@mupt-ai/dari-router/policy-engine";
2
+ import { type InteractionRequest, type ProviderIdentity } from "../interaction/types.js";
3
+ import { type SelectorImage } from "../strategies/selector_projection.js";
4
+ import type { ResolvedRouter } from "../types.js";
5
+ import { type InteractionPrefixContext } from "./interaction_fingerprint.js";
6
+ export type ImageCapabilityPrunedModel = {
7
+ model: string;
8
+ reason: "image_input_unsupported";
9
+ };
10
+ export type RoutingContext = {
11
+ leaseDepth: number;
12
+ hits: ChainHits;
13
+ reportingCostEstimates: CandidateCostEstimate[];
14
+ previousDecision?: PreviousDecision;
15
+ activeLease?: ActiveLease;
16
+ pendingLease?: PendingLease;
17
+ pricing: PricingLookup;
18
+ conversationId: string;
19
+ isNewConversation: boolean;
20
+ identityMatchDepth: number | null;
21
+ identityHit?: PrefixHit;
22
+ zdr: boolean;
23
+ candidateResolution: StrategyCandidateResolution;
24
+ imageCapabilityPrunedModels?: ImageCapabilityPrunedModel[];
25
+ prefix: InteractionPrefixContext;
26
+ targetsByModel: ReadonlyMap<string, ProviderIdentity>;
27
+ selectorMessages: ChatMessage[];
28
+ selectorImages: SelectorImage[];
29
+ leaseHistory?: SelectorLeaseHistoryEntry[];
30
+ providerBlockDepthFor: (model: string) => number;
31
+ };
32
+ export declare function derivePrefixLookupHashes(routerId: string, interaction: InteractionRequest): string[];
33
+ export declare function buildRoutingContext(args: {
34
+ routerId: string;
35
+ interaction: InteractionRequest;
36
+ credentials: ResolvedRouter;
37
+ previousDecision?: PreviousDecision;
38
+ explicitConversationId?: string;
39
+ receivedAt?: Date;
40
+ }): Promise<RoutingContext>;