@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
@@ -2,17 +2,20 @@
2
2
  Codex reads the Codex catalog; Anthropic-SDK clients (Claude Desktop /
3
3
  Cowork gateway probes, Claude Code) read the Anthropic list shape. The
4
4
  handler detects the caller, authenticates in that protocol's auth shape,
5
- and selects the matching catalog adapter. */
5
+ and selects the matching catalog adapter. `?detail=1` instead returns the
6
+ model catalog (models/catalog.ts), optionally narrowed with
7
+ `provider=<id>[,<id>...]`. */
6
8
 
7
- import { anthropicToken, bearerToken } from "../http/auth";
8
- import { errorResponse } from "../http/errors";
9
- import { captureRequestError } from "../observability/errors";
10
- import { anthropicErrorResponse } from "./anthropic_messages";
11
- import { modelSupportsImageInput } from "../providers/model_capabilities";
12
- import { modelMetadataLookup } from "../providers/pi";
13
- import { resolveRouter } from "../strategies/routing";
14
- import { anthropicModelsResponse } from "./anthropic_models";
15
- import { codexModelsResponse } from "./codex_models";
9
+ import { anthropicToken, bearerToken } from "../http/auth.js";
10
+ import { errorResponse } from "../http/errors.js";
11
+ import { captureRequestError } from "../observability/errors.js";
12
+ import { anthropicErrorResponse } from "./anthropic_messages.js";
13
+ import { listModelCatalog } from "../models/catalog.js";
14
+ import { modelSupportsImageInput } from "../providers/model_capabilities.js";
15
+ import { modelMetadataLookup } from "../providers/pi.js";
16
+ import { resolveRouter } from "../strategies/routing.js";
17
+ import { anthropicModelsResponse } from "./anthropic_models.js";
18
+ import { codexModelsResponse } from "./codex_models.js";
16
19
 
17
20
  export async function handleModels(request: Request, routerId: string): Promise<Response> {
18
21
  // Anthropic SDK clients always send anthropic-version, and API-key probes
@@ -26,6 +29,15 @@ export async function handleModels(request: Request, routerId: string): Promise<
26
29
  // Resolution authenticates the key and confirms the router exists even
27
30
  // when the response body (Anthropic shape) does not depend on it.
28
31
  const router = await resolveRouter({ routerId, apiKey });
32
+ const query = new URL(request.url).searchParams;
33
+ if (query.get("detail") === "1") {
34
+ const providers = query.get("provider")?.split(",").map((id) => id.trim()).filter(Boolean);
35
+ const data = await listModelCatalog({
36
+ ...(providers?.length ? { providers } : {}),
37
+ signal: request.signal,
38
+ });
39
+ return Response.json({ object: "list", data }, { headers: { "Cache-Control": "no-store" } });
40
+ }
29
41
  if (anthropicClient) {
30
42
  return Response.json(anthropicModelsResponse(), {
31
43
  headers: {
@@ -0,0 +1,9 @@
1
+ // Muse Code names its surface (TUI, `muse exec`, desktop, `muse serve`) in
2
+ // x-client-id on every model request.
3
+ const MUSE_CODE_CLIENT_IDS = new Set(["tbh:tui", "tbh:exec", "tbh:desktop", "tbh:serve"]);
4
+
5
+ /** Muse Code's x-client-id when the request comes from Muse Code. */
6
+ export function museCodeClientId(headers: Headers): string | undefined {
7
+ const clientId = headers.get("x-client-id")?.trim().toLowerCase();
8
+ return clientId !== undefined && MUSE_CODE_CLIENT_IDS.has(clientId) ? clientId : undefined;
9
+ }
@@ -0,0 +1,36 @@
1
+ import { bearerToken } from "../http/auth.js";
2
+ import { errorResponse } from "../http/errors.js";
3
+ import { resolveRouter } from "../strategies/routing.js";
4
+ import type { ResolvedRouter } from "../types.js";
5
+
6
+ /**
7
+ * Muse Code fetches its model list from its base URL's origin
8
+ * (`/muse-code/models`) before its first request. A list of only the router's
9
+ * models lets Muse Code pick from them and start on the first; `dari/routing`
10
+ * leads it only on the Autorouting plan.
11
+ */
12
+ export function museCodeModelsResponse(
13
+ router: Pick<ResolvedRouter, "enabled_models" | "autorouting_enabled">,
14
+ ): Record<string, unknown> {
15
+ const ids = [
16
+ ...(router.autorouting_enabled === false ? [] : ["dari/routing"]),
17
+ ...router.enabled_models.map((model) => `dari/model/${model}`),
18
+ ];
19
+ return {
20
+ data: ids.map((id, index) => ({
21
+ id,
22
+ display_label: id === "dari/routing" ? "Dari Routing" : id.slice("dari/model/".length),
23
+ is_default: index === 0,
24
+ })),
25
+ };
26
+ }
27
+
28
+ export async function handleMuseCodeModels(request: Request, routerId: string): Promise<Response> {
29
+ try {
30
+ // Only Muse Code fetches this list, so its plans apply even without a Meta key.
31
+ const router = await resolveRouter({ routerId, apiKey: bearerToken(request.headers), clientHarness: "muse_code" });
32
+ return Response.json(museCodeModelsResponse(router), { headers: { "Cache-Control": "no-store" } });
33
+ } catch (error) {
34
+ return errorResponse(error);
35
+ }
36
+ }
@@ -1,5 +1,5 @@
1
1
  import type { HardCapability } from "@mupt-ai/dari-router/policy-engine";
2
- import type { InteractionItem, InteractionRequest } from "./types";
2
+ import type { InteractionItem, InteractionRequest } from "./types.js";
3
3
 
4
4
  export function requiredCapabilitiesFor(
5
5
  request: Pick<InteractionRequest, "items" | "responseFormat" | "toolChoice" | "tools">
@@ -4,7 +4,7 @@ import {
4
4
  type PortableReasoningState,
5
5
  } from "@mupt-ai/dari-router/protocols";
6
6
 
7
- import { rethrowFrameworkErrorAsHttp } from "../http/errors";
7
+ import { rethrowFrameworkErrorAsHttp } from "../http/errors.js";
8
8
 
9
9
  export type { PortableReasoningState } from "@mupt-ai/dari-router/protocols";
10
10
 
@@ -6,7 +6,7 @@ import {
6
6
  type ProviderIdentity,
7
7
  } from "@mupt-ai/dari-router/protocols";
8
8
 
9
- import { rethrowFrameworkErrorAsHttp } from "../http/errors";
9
+ import { rethrowFrameworkErrorAsHttp } from "../http/errors.js";
10
10
 
11
11
  export type { ProviderContinuationState, ProviderIdentity } from "@mupt-ai/dari-router/protocols";
12
12
  export { compatibleProviderContinuation, isAnthropicEffort, sameProviderIdentity } from "@mupt-ai/dari-router/protocols";
@@ -1,5 +1,5 @@
1
- import { HttpError } from "../http/errors";
2
- import type { InteractionTool, ProviderIdentity } from "./types";
1
+ import { HttpError } from "../http/errors.js";
2
+ import type { InteractionTool, ProviderIdentity } from "./types.js";
3
3
 
4
4
  export const TOOL_CALL_ID_MAX_LENGTH = 512;
5
5
 
@@ -235,6 +235,8 @@ export type InteractionRequest = {
235
235
  agentContext?: AgentRequestContext;
236
236
  // Claude Code's own user agent; Anthropic gates subscription models on it.
237
237
  claudeCodeUserAgent?: string;
238
+ // Muse Code's own x-client-id, which Meta attributes its requests by.
239
+ museCodeClientId?: string;
238
240
  anthropicSafeguards?: AnthropicSafeguards;
239
241
  model?: string;
240
242
  instructions?: string;
@@ -0,0 +1,310 @@
1
+ import { getSupportedThinkingLevels, type Api, type Model } from "@mupt-ai/pi-ai";
2
+ import {
3
+ getBuiltinModelDataGeneratedAt,
4
+ getBuiltinModels,
5
+ getBuiltinProviders,
6
+ } from "@mupt-ai/pi-ai/providers/all";
7
+ import {
8
+ REASONING_EFFORTS,
9
+ isReasoningEffort,
10
+ isRecord,
11
+ type ReasoningEffort,
12
+ } from "@mupt-ai/dari-router/policy-engine";
13
+ import { HttpError } from "../http/errors.js";
14
+
15
+ // The models each provider can serve to a coding agent, with the limits,
16
+ // thinking levels, and list prices a caller needs to pick and price one.
17
+ // Gateways (OpenRouter, Vercel AI Gateway) are listed live from their public
18
+ // models endpoints; model providers come from the bundled Pi catalog.
19
+
20
+ export type CatalogModel = {
21
+ // Canonical `provider/native-id`; request it as `dari/model/<id>`.
22
+ id: string;
23
+ provider: string;
24
+ native_model_id: string;
25
+ name: string;
26
+ context_window: number | null;
27
+ max_output_tokens: number | null;
28
+ input_modalities: string[];
29
+ // Accepted thinking levels; ["off"] for models that do not reason.
30
+ thinking_levels: ReasoningEffort[];
31
+ // List price in USD per million tokens; null when the source publishes
32
+ // none, e.g. meta-routers whose price depends on the model they pick.
33
+ price: CatalogModelPrice | null;
34
+ // When the price was read: the fetch time for gateways, the catalog's
35
+ // generation time for model providers.
36
+ price_as_of: string;
37
+ };
38
+
39
+ export type CatalogModelPrice = {
40
+ input: number;
41
+ output: number;
42
+ cached_input: number | null;
43
+ cache_write: number | null;
44
+ // Long-context rates, each applying to prompts above its token threshold.
45
+ tiers: CatalogPriceTier[];
46
+ };
47
+
48
+ export type CatalogPriceTier = {
49
+ input_tokens_above: number;
50
+ input: number;
51
+ output: number;
52
+ cached_input: number | null;
53
+ cache_write: number | null;
54
+ };
55
+
56
+ export type ModelCatalogOptions = {
57
+ // Providers to list; defaults to DEFAULT_CATALOG_PROVIDERS. Any Pi built-in
58
+ // provider id is accepted.
59
+ providers?: readonly string[] | undefined;
60
+ fetch?: ((url: string, init?: RequestInit) => Promise<Response>) | undefined;
61
+ signal?: AbortSignal | undefined;
62
+ };
63
+
64
+ export const DEFAULT_CATALOG_PROVIDERS: readonly string[] = [
65
+ "openai",
66
+ "anthropic",
67
+ "meta",
68
+ "xai",
69
+ "fireworks",
70
+ "openrouter",
71
+ "vercel-ai-gateway",
72
+ ];
73
+
74
+ type LiveListing = {
75
+ url: string;
76
+ models: (data: unknown[], asOf: string) => CatalogModel[];
77
+ };
78
+
79
+ const LIVE_LISTINGS: Record<string, LiveListing> = {
80
+ openrouter: { url: "https://openrouter.ai/api/v1/models", models: openRouterModels },
81
+ "vercel-ai-gateway": { url: "https://ai-gateway.vercel.sh/v1/models", models: vercelModels },
82
+ };
83
+
84
+ /** List the agent-capable models of each requested provider. */
85
+ export async function listModelCatalog(options: ModelCatalogOptions = {}): Promise<CatalogModel[]> {
86
+ const providers = [...new Set(options.providers ?? DEFAULT_CATALOG_PROVIDERS)];
87
+ const builtin = new Set<string>(getBuiltinProviders());
88
+ for (const provider of providers) {
89
+ if (LIVE_LISTINGS[provider] === undefined && !builtin.has(provider)) {
90
+ throw new HttpError(400, `Unknown catalog provider '${provider}'.`, "unknown_provider", "provider");
91
+ }
92
+ }
93
+ const lists = await Promise.all(providers.map(async (provider) => {
94
+ const listing = LIVE_LISTINGS[provider];
95
+ return listing === undefined
96
+ ? piModels(provider)
97
+ : listing.models(await fetchListing(listing.url, options), new Date().toISOString());
98
+ }));
99
+ return lists.flat();
100
+ }
101
+
102
+ async function fetchListing(url: string, options: ModelCatalogOptions): Promise<unknown[]> {
103
+ let status: number | undefined;
104
+ let body: unknown = null;
105
+ // Network errors, aborts, and unparseable bodies are upstream failures
106
+ // too: all of them surface as catalog_unavailable rather than a raw 500.
107
+ try {
108
+ const response = await (options.fetch ?? fetch)(url, {
109
+ headers: { accept: "application/json" },
110
+ ...(options.signal ? { signal: options.signal } : {}),
111
+ });
112
+ status = response.status;
113
+ body = response.ok ? await response.json() : null;
114
+ } catch {
115
+ // Leaves body null.
116
+ }
117
+ if (!isRecord(body) || !Array.isArray(body.data)) {
118
+ const detail = status === undefined ? "could not be reached" : `returned no model list (HTTP ${status})`;
119
+ throw new HttpError(502, `${url} ${detail}.`, "catalog_unavailable");
120
+ }
121
+ return body.data;
122
+ }
123
+
124
+ function piModels(provider: string): CatalogModel[] {
125
+ const generatedAt = getBuiltinModelDataGeneratedAt();
126
+ const asOf = generatedAt === undefined ? "" : new Date(generatedAt).toISOString();
127
+ const models = getBuiltinModels(provider as never) as unknown as Model<Api>[];
128
+ return models.map((model) => ({
129
+ id: `${provider}/${model.id}`,
130
+ provider,
131
+ native_model_id: model.id,
132
+ name: model.name,
133
+ context_window: model.contextWindow,
134
+ max_output_tokens: model.maxTokens,
135
+ input_modalities: [...model.input],
136
+ thinking_levels: orderedEfforts(getSupportedThinkingLevels(model)),
137
+ price: piPrice(model.cost),
138
+ price_as_of: asOf,
139
+ }));
140
+ }
141
+
142
+ function piPrice(cost: Model<Api>["cost"]): CatalogModelPrice {
143
+ return {
144
+ input: cost.input,
145
+ output: cost.output,
146
+ cached_input: cost.cacheRead,
147
+ cache_write: cost.cacheWrite,
148
+ tiers: (cost.tiers ?? []).map((tier) => ({
149
+ input_tokens_above: tier.inputTokensAbove,
150
+ input: tier.input,
151
+ output: tier.output,
152
+ cached_input: tier.cacheRead,
153
+ cache_write: tier.cacheWrite,
154
+ })),
155
+ };
156
+ }
157
+
158
+ // https://openrouter.ai/docs/api/api-reference/models/get-models
159
+ function openRouterModels(data: unknown[], asOf: string): CatalogModel[] {
160
+ return data.filter(isRecord).flatMap((model) => {
161
+ const architecture = isRecord(model.architecture) ? model.architecture : {};
162
+ const parameters = stringList(model.supported_parameters);
163
+ if (typeof model.id !== "string" || !parameters.includes("tools")) return [];
164
+ if (!stringList(architecture.output_modalities).includes("text")) return [];
165
+ const reasoning = isRecord(model.reasoning) ? model.reasoning : {};
166
+ const topProvider = isRecord(model.top_provider) ? model.top_provider : {};
167
+ return [{
168
+ id: `openrouter/${model.id}`,
169
+ provider: "openrouter",
170
+ native_model_id: model.id,
171
+ name: typeof model.name === "string" ? model.name : model.id,
172
+ context_window: positiveInteger(model.context_length),
173
+ max_output_tokens: positiveInteger(topProvider.max_completion_tokens),
174
+ input_modalities: stringList(architecture.input_modalities),
175
+ thinking_levels: gatewayThinkingLevels({
176
+ reasons: parameters.includes("reasoning"),
177
+ efforts: Array.isArray(reasoning.supported_efforts) ? stringList(reasoning.supported_efforts) : null,
178
+ canDisable: reasoning.mandatory !== true,
179
+ }),
180
+ price: isRecord(model.pricing) ? openRouterPrice(model.pricing) : null,
181
+ price_as_of: asOf,
182
+ }];
183
+ });
184
+ }
185
+
186
+ function openRouterPrice(pricing: Record<string, unknown>): CatalogModelPrice | null {
187
+ const base = rates(pricing, "prompt", "completion");
188
+ if (base === null) return null;
189
+ // Overrides restate only the rates they change; time-of-day overrides are
190
+ // not context tiers.
191
+ const tiers = (Array.isArray(pricing.overrides) ? pricing.overrides : [])
192
+ .filter(isRecord)
193
+ .flatMap((override) => {
194
+ const threshold = positiveInteger(override.min_prompt_tokens);
195
+ if (threshold === null || "utc_days" in override || "utc_start" in override || "utc_end" in override) {
196
+ return [];
197
+ }
198
+ const tier = rates({ ...pricing, ...override }, "prompt", "completion", override);
199
+ return tier === null ? [] : [{ input_tokens_above: threshold, ...tier }];
200
+ });
201
+ return { ...base, tiers };
202
+ }
203
+
204
+ // https://vercel.com/docs/ai-gateway/models-and-providers
205
+ function vercelModels(data: unknown[], asOf: string): CatalogModel[] {
206
+ return data.filter(isRecord).flatMap((model) => {
207
+ const modalities = isRecord(model.modalities) ? model.modalities : {};
208
+ const parameters = stringList(model.supported_parameters);
209
+ if (typeof model.id !== "string" || model.type !== "language" || !parameters.includes("tools")) return [];
210
+ if (!stringList(modalities.output).includes("text")) return [];
211
+ const options = Array.isArray(model.reasoning_options) ? model.reasoning_options.filter(isRecord) : [];
212
+ const effort = options.find((option) => option.type === "effort");
213
+ return [{
214
+ id: `vercel-ai-gateway/${model.id}`,
215
+ provider: "vercel-ai-gateway",
216
+ native_model_id: model.id,
217
+ name: typeof model.name === "string" ? model.name : model.id,
218
+ context_window: positiveInteger(model.context_window),
219
+ max_output_tokens: positiveInteger(model.max_tokens),
220
+ input_modalities: stringList(modalities.input),
221
+ thinking_levels: gatewayThinkingLevels({
222
+ reasons: parameters.includes("reasoning") || options.length > 0,
223
+ efforts: effort === undefined ? null : stringList(effort.values),
224
+ canDisable: options.length === 0 || options.some((option) => option.type === "toggle"),
225
+ }),
226
+ price: isRecord(model.pricing) ? vercelPrice(model.pricing) : null,
227
+ price_as_of: asOf,
228
+ }];
229
+ });
230
+ }
231
+
232
+ function vercelPrice(pricing: Record<string, unknown>): CatalogModelPrice | null {
233
+ const base = rates(pricing, "input", "output");
234
+ if (base === null) return null;
235
+ // Each rate lists its own {cost, min, max} ranges; a range covers prompts of
236
+ // at least `min` tokens, so it is the tier above `min - 1`.
237
+ const ranged = new Map<number, Record<string, unknown>>();
238
+ for (const key of ["input", "output", "input_cache_read", "input_cache_write"]) {
239
+ const ranges = Array.isArray(pricing[`${key}_tiers`]) ? pricing[`${key}_tiers`] as unknown[] : [];
240
+ for (const range of ranges.filter(isRecord)) {
241
+ const start = positiveInteger(range.min);
242
+ if (start === null || range.cost == null) continue;
243
+ ranged.set(start - 1, { ...ranged.get(start - 1), [key]: range.cost });
244
+ }
245
+ }
246
+ const tiers = [...ranged.entries()]
247
+ .sort(([left], [right]) => left - right)
248
+ .flatMap(([threshold, stated]) => {
249
+ const tier = rates({ ...pricing, ...stated }, "input", "output", stated);
250
+ return tier === null ? [] : [{ input_tokens_above: threshold, ...tier }];
251
+ });
252
+ return { ...base, tiers };
253
+ }
254
+
255
+ // Base rates from per-token strings. A tier inherits input and output from
256
+ // the base price but states its own cache rates, or has none.
257
+ function rates(
258
+ pricing: Record<string, unknown>,
259
+ inputKey: string,
260
+ outputKey: string,
261
+ cacheRates: Record<string, unknown> = pricing,
262
+ ): Omit<CatalogPriceTier, "input_tokens_above"> | null {
263
+ const input = perMillion(pricing[inputKey]);
264
+ const output = perMillion(pricing[outputKey]);
265
+ // Meta-routers with variable prices list negative rates.
266
+ if (input === null || output === null) return null;
267
+ return {
268
+ input,
269
+ output,
270
+ cached_input: perMillion(cacheRates.input_cache_read),
271
+ cache_write: perMillion(cacheRates.input_cache_write),
272
+ };
273
+ }
274
+
275
+ // USD per token as a decimal string -> USD per million tokens. Shifting the
276
+ // exponent in the string keeps "0.000001" exactly 1.
277
+ function perMillion(value: unknown): number | null {
278
+ const rate = typeof value === "string" ? Number(`${value.trim()}e6`)
279
+ : typeof value === "number" ? value * 1_000_000
280
+ : Number.NaN;
281
+ return Number.isFinite(rate) && rate >= 0 ? rate : null;
282
+ }
283
+
284
+ // Gateways forward `reasoning.effort`; models that reason without a stated
285
+ // effort list take the standard low/medium/high levels.
286
+ function gatewayThinkingLevels(args: {
287
+ reasons: boolean;
288
+ efforts: string[] | null;
289
+ canDisable: boolean;
290
+ }): ReasoningEffort[] {
291
+ if (!args.reasons) return ["off"];
292
+ const efforts = args.efforts ?? ["low", "medium", "high"];
293
+ return orderedEfforts([
294
+ ...efforts.map((effort) => effort === "none" ? "off" : effort),
295
+ ...(args.canDisable ? ["off"] : []),
296
+ ]);
297
+ }
298
+
299
+ function orderedEfforts(levels: readonly string[]): ReasoningEffort[] {
300
+ const accepted = new Set(levels.filter(isReasoningEffort));
301
+ return REASONING_EFFORTS.filter((effort) => accepted.has(effort));
302
+ }
303
+
304
+ function stringList(value: unknown): string[] {
305
+ return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
306
+ }
307
+
308
+ function positiveInteger(value: unknown): number | null {
309
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
310
+ }
@@ -1,4 +1,4 @@
1
- import type { ResolvedRouterModelConfig } from "../types";
1
+ import type { ResolvedRouterModelConfig } from "../types.js";
2
2
 
3
3
  export function effectiveContextWindow(config: ResolvedRouterModelConfig | undefined, allowLongContext = false): number | null {
4
4
  const window = config?.context_window;
@@ -1,5 +1,5 @@
1
1
  import { providerForModel } from "@mupt-ai/dari-router/policy-engine";
2
- import type { ProviderKeySource, ResolvedRouter } from "../types";
2
+ import type { ProviderKeySource, ResolvedRouter } from "../types.js";
3
3
 
4
4
  /** Actual serving provider for a canonical model on a resolved managed router. */
5
5
  export function executionProviderForModel(
@@ -11,12 +11,15 @@ export function executionProviderForModel(
11
11
  }
12
12
 
13
13
  /**
14
- * The key that serves a model on a resolved router. Missing declarations are
14
+ * The key that serves a model on a resolved router: a platform-supplied
15
+ * credential first, then the resolved provider key. Missing declarations are
15
16
  * user-owned so unknown platform data cannot trigger managed-key billing.
16
17
  */
17
18
  export function keySourceForModel(
18
19
  credentials: ResolvedRouter,
19
20
  model: string,
20
21
  ): ProviderKeySource {
22
+ const supplied = credentials.provider_credentials?.[model];
23
+ if (supplied) return supplied.subscription ? "subscription" : "user";
21
24
  return credentials.provider_key_sources?.[executionProviderForModel(credentials, model)] ?? "user";
22
25
  }
package/src/models/ids.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { providerForModel } from "@mupt-ai/dari-router/policy-engine";
2
- import { HttpError } from "../http/errors";
2
+ import { HttpError } from "../http/errors.js";
3
3
 
4
4
  export function requireCandidateModels(value: unknown): string[] {
5
5
  if (!Array.isArray(value) || value.length === 0) {
@@ -1,4 +1,4 @@
1
- import { gatewayFor } from "./gateways";
1
+ import { gatewayFor } from "./gateways.js";
2
2
 
3
3
  // Built-in model provider presentation and endpoint defaults; gateways carry
4
4
  // their own. Mirrors the hosted Dari model catalog's provider defaults; keep
@@ -33,6 +33,9 @@ const PROVIDER_BASE_URLS: Record<string, string> = {
33
33
  anthropic: "https://api.anthropic.com",
34
34
  fireworks: "https://api.fireworks.ai/inference/v1",
35
35
  xai: "https://api.x.ai/v1",
36
+ // Meta's Model API serves OpenAI Responses and Chat Completions here, and
37
+ // Anthropic Messages at https://api.meta.ai.
38
+ meta: "https://api.meta.ai/v1",
36
39
  // Pi-ai derives the effective AWS region from the endpoint unless the
37
40
  // model config overrides base_url or the native id is an inference profile
38
41
  // ARN, so this default only pins us-east-1 when nothing else is configured.
@@ -1,6 +1,6 @@
1
1
  import { canonicalModelId, isRecord } from "@mupt-ai/dari-router/policy-engine";
2
2
 
3
- import { gatewayFor } from "./gateways";
3
+ import { gatewayFor } from "./gateways.js";
4
4
 
5
5
  const MODEL_CONTEXT_OVERRIDES: Record<string, number> = {
6
6
  // Selector and title models are not router candidate configs, so their
@@ -169,6 +169,28 @@ const MODEL_OFF_WIRE_NONE: ReadonlySet<string> = new Set([
169
169
  "deepseek-ai/DeepSeek-V4.1-Flash-1017",
170
170
  ]);
171
171
 
172
+ // Wire values a provider's API accepts for thinking levels the Pi registry
173
+ // leaves unmapped. Meta's Model API takes reasoning effort "none" on every
174
+ // Muse model (dev.meta.ai/docs/coding-agents).
175
+ const PROVIDER_THINKING_LEVEL_OVERRIDES: Record<string, Record<string, string>> = {
176
+ meta: { off: "none" },
177
+ };
178
+
179
+ export function providerThinkingLevelOverrides(provider: string): Record<string, string> | undefined {
180
+ return PROVIDER_THINKING_LEVEL_OVERRIDES[provider];
181
+ }
182
+
183
+ /** Registered Pi metadata with the serving provider's thinking level overrides. */
184
+ export function withThinkingLevelOverrides(
185
+ provider: string,
186
+ registered: Record<string, unknown> | undefined,
187
+ ): Record<string, unknown> | undefined {
188
+ const override = providerThinkingLevelOverrides(provider);
189
+ if (registered === undefined || override === undefined) return registered;
190
+ const map = isRecord(registered.thinkingLevelMap) ? registered.thinkingLevelMap : {};
191
+ return { ...registered, thinkingLevelMap: { ...map, ...override } };
192
+ }
193
+
172
194
  export function offRequiresWireNone(modelId: string): boolean {
173
195
  return MODEL_OFF_WIRE_NONE.has(canonicalModelId(modelId));
174
196
  }
@@ -0,0 +1,54 @@
1
+ import {
2
+ nativeModelId,
3
+ providerForModel,
4
+ type RouterModelPrice,
5
+ } from "@mupt-ai/dari-router/policy-engine";
6
+
7
+ import type { ClientHarness, ResolvedRouterModelConfig, SubscriptionKind } from "../types.js";
8
+
9
+ const CODEX_BACKEND_URL = "https://chatgpt.com/backend-api";
10
+
11
+ // The model provider whose models each kind of plan serves.
12
+ const SUBSCRIPTION_MODEL_PROVIDERS: Record<SubscriptionKind, string> = {
13
+ openai_codex: "openai",
14
+ anthropic_claude_code: "anthropic",
15
+ meta_muse: "meta",
16
+ };
17
+
18
+ // The client each plan is limited to, as its provider limits it: a Claude Code
19
+ // plan serves only Claude Code, and a Muse Code plan only Muse Code.
20
+ const SUBSCRIPTION_CLIENTS: Partial<Record<SubscriptionKind, ClientHarness>> = {
21
+ anthropic_claude_code: "claude_code",
22
+ meta_muse: "muse_code",
23
+ };
24
+
25
+ /**
26
+ * Whether a plan may serve a model for this client: each plan serves only its
27
+ * own provider's models, and only to the client its provider allows.
28
+ */
29
+ export function subscriptionServes(
30
+ kind: SubscriptionKind,
31
+ model: string,
32
+ clientHarness: ClientHarness | undefined,
33
+ ): boolean {
34
+ if (SUBSCRIPTION_MODEL_PROVIDERS[kind] !== providerForModel(model)) return false;
35
+ const client = SUBSCRIPTION_CLIENTS[kind];
36
+ return client === undefined || clientHarness === client;
37
+ }
38
+
39
+ // A ChatGPT plan serves OpenAI models as the `openai-codex` provider through
40
+ // the Codex backend.
41
+ export function codexModelConfig(
42
+ modelId: string,
43
+ price: RouterModelPrice | null,
44
+ ): ResolvedRouterModelConfig {
45
+ return {
46
+ provider: "openai-codex",
47
+ native_model_id: nativeModelId(modelId),
48
+ api: "openai-codex-responses",
49
+ base_url: CODEX_BACKEND_URL,
50
+ // A plan bills no tokens; the catalog price only feeds cost estimates.
51
+ cost: price ?? { input: 0, output: 0 },
52
+ fast_mode: false,
53
+ };
54
+ }
@@ -2,9 +2,9 @@ import {
2
2
  gatewayPlatform,
3
3
  type OperationalErrorContext,
4
4
  type RequestErrorContext,
5
- } from "../platform/platform";
5
+ } from "../platform/platform.js";
6
6
 
7
- export type { OperationalErrorCode } from "../platform/platform";
7
+ export type { OperationalErrorCode } from "../platform/platform.js";
8
8
 
9
9
  export function captureRequestError(
10
10
  error: unknown,
@@ -3,15 +3,15 @@ import type {
3
3
  ReasoningEffort,
4
4
  RoutingStrategy,
5
5
  } from "@mupt-ai/dari-router/policy-engine";
6
- import type { HarnessConversationIdentity } from "../runtime/harness_identity";
7
- import type { InteractionRequest, SourceProtocol } from "../interaction/types";
8
- import type { SubscriptionUsageLimit } from "../providers/subscription_limits";
6
+ import type { HarnessConversationIdentity } from "../runtime/harness_identity/index.js";
7
+ import type { InteractionRequest, SourceProtocol } from "../interaction/types.js";
8
+ import type { SubscriptionUsageLimit } from "../providers/subscription_limits.js";
9
9
  import type {
10
10
  ClientHarness,
11
11
  ProviderCredential,
12
12
  ProviderKeySource,
13
13
  ResolvedRouter,
14
- } from "../types";
14
+ } from "../types.js";
15
15
 
16
16
  /**
17
17
  * Everything the gateway runtime needs from the deployment around it: router
@@ -33,7 +33,10 @@ export type GatewayPlatform = {
33
33
  * Optional. Supply the credential for one enabled model of this request,
34
34
  * consulted after `resolveRouter` and before its provider keys (for the
35
35
  * self-hosted gateway, its environment keys), so an embedder can serve
36
- * per-tenant keys from its own store. Undefined keeps the resolved key.
36
+ * per-tenant keys from its own store. Undefined keeps the resolved key. A
37
+ * credential with `subscription` serves the model on that plan, even on a
38
+ * strict router; a plan that cannot serve the model for this client (see
39
+ * SubscriptionKind) is ignored.
37
40
  */
38
41
  resolveProviderCredential?(
39
42
  request: ProviderCredentialRequest,
@@ -74,6 +77,7 @@ export type ProviderCredentialRequest = {
74
77
  organizationId: string;
75
78
  // The gateway key the request authenticated with.
76
79
  apiKey: string;
80
+ clientHarness?: ClientHarness;
77
81
  };
78
82
 
79
83
  export type PrefixStateWrite = {