@bastani/atomic 0.9.21-alpha.1 → 0.9.21-alpha.2

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 (514) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/CHANGELOG.md +11 -0
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/subagents/src/extension/index.bundle.mjs +292 -60
  7. package/dist/builtin/web-access/package.json +1 -1
  8. package/dist/builtin/workflows/CHANGELOG.md +11 -0
  9. package/dist/builtin/workflows/builtin/adversarial-verification.js +3 -3
  10. package/dist/builtin/workflows/builtin/{chunk-cw86srkf.js → chunk-632fxeb8.js} +1 -1
  11. package/dist/builtin/workflows/builtin/{chunk-w18kbz63.js → chunk-94f8zfz1.js} +1 -1
  12. package/dist/builtin/workflows/builtin/{chunk-kspvwc24.js → chunk-9cm2ckq2.js} +1 -1
  13. package/dist/builtin/workflows/builtin/{chunk-jaj27rqc.js → chunk-a1ar035d.js} +1 -1
  14. package/dist/builtin/workflows/builtin/{chunk-wh19f5ee.js → chunk-d3xhj946.js} +5 -4
  15. package/dist/builtin/workflows/builtin/{chunk-crw7q5g1.js → chunk-gyjck9z8.js} +1 -1
  16. package/dist/builtin/workflows/builtin/{chunk-maqv731g.js → chunk-hj8mh07f.js} +10 -6
  17. package/dist/builtin/workflows/builtin/{chunk-0nrgfbag.js → chunk-kb7s3gx2.js} +1 -1
  18. package/dist/builtin/workflows/builtin/{chunk-73c5tayt.js → chunk-kgn5wz1c.js} +19 -1
  19. package/dist/builtin/workflows/builtin/{chunk-2hak3b7g.js → chunk-nkj4qhj6.js} +1 -1
  20. package/dist/builtin/workflows/builtin/{chunk-bzdvx2xr.js → chunk-r97ndfvt.js} +1 -1
  21. package/dist/builtin/workflows/builtin/{chunk-vkmpdat4.js → chunk-wf876n16.js} +1 -1
  22. package/dist/builtin/workflows/builtin/classify-and-act.js +3 -3
  23. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +3 -3
  24. package/dist/builtin/workflows/builtin/generate-and-filter.js +3 -3
  25. package/dist/builtin/workflows/builtin/goal.js +4 -4
  26. package/dist/builtin/workflows/builtin/index.js +12 -12
  27. package/dist/builtin/workflows/builtin/loop-until-done.js +3 -3
  28. package/dist/builtin/workflows/builtin/open-claude-design.js +3 -3
  29. package/dist/builtin/workflows/builtin/ralph.js +4 -4
  30. package/dist/builtin/workflows/builtin/steering-context.js +1 -1
  31. package/dist/builtin/workflows/builtin/tournament.js +3 -3
  32. package/dist/builtin/workflows/package.json +1 -1
  33. package/dist/builtin/workflows/src/extension/index.bundle.mjs +40 -11
  34. package/dist/builtin/workflows/src/index.js +9 -3
  35. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +6 -1
  36. package/dist/cli/auth-command.js +5 -0
  37. package/dist/cli/auth-command.js.map +1 -1
  38. package/dist/cli/credential-print.js +2 -0
  39. package/dist/cli/credential-print.js.map +1 -1
  40. package/dist/cli/experimental/command.js +5 -2
  41. package/dist/cli/experimental/command.js.map +1 -1
  42. package/dist/cli.js +1 -1
  43. package/dist/cli.js.map +1 -1
  44. package/dist/config.d.ts +4 -4
  45. package/dist/config.js +4 -4
  46. package/dist/config.js.map +1 -1
  47. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  48. package/dist/core/agent-session-extension-bindings.js +9 -4
  49. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  50. package/dist/core/agent-session-methods.d.ts +4 -4
  51. package/dist/core/agent-session-methods.d.ts.map +1 -1
  52. package/dist/core/agent-session-methods.js.map +1 -1
  53. package/dist/core/agent-session-prompt.d.ts +4 -4
  54. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  55. package/dist/core/agent-session-prompt.js +38 -15
  56. package/dist/core/agent-session-prompt.js.map +1 -1
  57. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  58. package/dist/core/agent-session-runtime.js +14 -9
  59. package/dist/core/agent-session-runtime.js.map +1 -1
  60. package/dist/core/agent-session-types.d.ts +4 -1
  61. package/dist/core/agent-session-types.d.ts.map +1 -1
  62. package/dist/core/agent-session-types.js.map +1 -1
  63. package/dist/core/agent-session.d.ts +1 -1
  64. package/dist/core/agent-session.d.ts.map +1 -1
  65. package/dist/core/agent-session.js +140 -95
  66. package/dist/core/agent-session.js.map +1 -1
  67. package/dist/core/auth-storage-backends.js +2 -3
  68. package/dist/core/auth-storage-backends.js.map +1 -1
  69. package/dist/core/auth-storage.js +4 -1
  70. package/dist/core/auth-storage.js.map +1 -1
  71. package/dist/core/builtin-resource-loader.js +9 -0
  72. package/dist/core/builtin-resource-loader.js.map +1 -1
  73. package/dist/core/cache-warmer.js +8 -1
  74. package/dist/core/cache-warmer.js.map +1 -1
  75. package/dist/core/compaction/range-planner.js +6 -0
  76. package/dist/core/compaction/range-planner.js.map +1 -1
  77. package/dist/core/execution-model-router.d.ts +13 -3
  78. package/dist/core/execution-model-router.d.ts.map +1 -1
  79. package/dist/core/execution-model-router.js +227 -131
  80. package/dist/core/execution-model-router.js.map +1 -1
  81. package/dist/core/export-html/template-js/entries-navigation.js +16 -6
  82. package/dist/core/export-html/template-js/initialization.js +34 -11
  83. package/dist/core/export-html/template.css +10 -0
  84. package/dist/core/export-html/template.js +50 -17
  85. package/dist/core/extensions/context-types.d.ts +2 -0
  86. package/dist/core/extensions/context-types.d.ts.map +1 -1
  87. package/dist/core/extensions/context-types.js.map +1 -1
  88. package/dist/core/extensions/host-input.js +8 -4
  89. package/dist/core/extensions/host-input.js.map +1 -1
  90. package/dist/core/extensions/reactive-widget.js +1 -0
  91. package/dist/core/extensions/reactive-widget.js.map +1 -1
  92. package/dist/core/extensions/runner-context.d.ts +1 -0
  93. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  94. package/dist/core/extensions/runner-context.js +4 -0
  95. package/dist/core/extensions/runner-context.js.map +1 -1
  96. package/dist/core/extensions/runner.d.ts +1 -0
  97. package/dist/core/extensions/runner.d.ts.map +1 -1
  98. package/dist/core/extensions/runner.js +48 -30
  99. package/dist/core/extensions/runner.js.map +1 -1
  100. package/dist/core/extensions/runtime-types.d.ts +1 -0
  101. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  102. package/dist/core/extensions/runtime-types.js.map +1 -1
  103. package/dist/core/extensions/workflow-activity-hub.js +9 -7
  104. package/dist/core/extensions/workflow-activity-hub.js.map +1 -1
  105. package/dist/core/footer-data-provider.js +24 -23
  106. package/dist/core/footer-data-provider.js.map +1 -1
  107. package/dist/core/keybindings.js +1 -0
  108. package/dist/core/keybindings.js.map +1 -1
  109. package/dist/core/mandatory-resource-loader.js +4 -1
  110. package/dist/core/mandatory-resource-loader.js.map +1 -1
  111. package/dist/core/model-config.js +2 -0
  112. package/dist/core/model-config.js.map +1 -1
  113. package/dist/core/model-registry.js +1 -0
  114. package/dist/core/model-registry.js.map +1 -1
  115. package/dist/core/{model-routing-task.d.ts → model-routing-bytes.d.ts} +1 -4
  116. package/dist/core/model-routing-bytes.d.ts.map +1 -0
  117. package/dist/core/model-routing-bytes.js +33 -0
  118. package/dist/core/model-routing-bytes.js.map +1 -0
  119. package/dist/core/model-routing-candidates.d.ts +42 -0
  120. package/dist/core/model-routing-candidates.d.ts.map +1 -0
  121. package/dist/core/model-routing-candidates.js +309 -0
  122. package/dist/core/model-routing-candidates.js.map +1 -0
  123. package/dist/core/model-routing-constraints.d.ts +4 -0
  124. package/dist/core/model-routing-constraints.d.ts.map +1 -1
  125. package/dist/core/model-routing-constraints.js +13 -1
  126. package/dist/core/model-routing-constraints.js.map +1 -1
  127. package/dist/core/model-routing-debug.d.ts +9 -0
  128. package/dist/core/model-routing-debug.d.ts.map +1 -0
  129. package/dist/core/model-routing-debug.js +14 -0
  130. package/dist/core/model-routing-debug.js.map +1 -0
  131. package/dist/core/model-routing-evals.d.ts +50 -0
  132. package/dist/core/model-routing-evals.d.ts.map +1 -0
  133. package/dist/core/model-routing-evals.js +190 -0
  134. package/dist/core/model-routing-evals.js.map +1 -0
  135. package/dist/core/model-routing-needs.d.ts +75 -0
  136. package/dist/core/model-routing-needs.d.ts.map +1 -0
  137. package/dist/core/model-routing-needs.js +176 -0
  138. package/dist/core/model-routing-needs.js.map +1 -0
  139. package/dist/core/model-runtime-streaming.js +3 -0
  140. package/dist/core/model-runtime-streaming.js.map +1 -1
  141. package/dist/core/model-runtime.js +26 -14
  142. package/dist/core/model-runtime.js.map +1 -1
  143. package/dist/core/models-store.js +2 -3
  144. package/dist/core/models-store.js.map +1 -1
  145. package/dist/core/output-guard.js +1 -0
  146. package/dist/core/output-guard.js.map +1 -1
  147. package/dist/core/package-manager-paths.d.ts +2 -1
  148. package/dist/core/package-manager-paths.d.ts.map +1 -1
  149. package/dist/core/package-manager-paths.js +4 -3
  150. package/dist/core/package-manager-paths.js.map +1 -1
  151. package/dist/core/package-manager.js +1 -0
  152. package/dist/core/package-manager.js.map +1 -1
  153. package/dist/core/resource-loader-assets.d.ts.map +1 -1
  154. package/dist/core/resource-loader-assets.js +9 -7
  155. package/dist/core/resource-loader-assets.js.map +1 -1
  156. package/dist/core/resource-loader-core.js +49 -0
  157. package/dist/core/resource-loader-core.js.map +1 -1
  158. package/dist/core/runtime-credentials.js +2 -1
  159. package/dist/core/runtime-credentials.js.map +1 -1
  160. package/dist/core/session-cwd.js +1 -0
  161. package/dist/core/session-cwd.js.map +1 -1
  162. package/dist/core/session-manager-archive.d.ts.map +1 -1
  163. package/dist/core/session-manager-archive.js +4 -2
  164. package/dist/core/session-manager-archive.js.map +1 -1
  165. package/dist/core/session-manager-core.js +11 -7
  166. package/dist/core/session-manager-core.js.map +1 -1
  167. package/dist/core/session-manager-storage.d.ts +10 -4
  168. package/dist/core/session-manager-storage.d.ts.map +1 -1
  169. package/dist/core/session-manager-storage.js +12 -6
  170. package/dist/core/session-manager-storage.js.map +1 -1
  171. package/dist/core/settings-manager-basic-accessors.d.ts +2 -1
  172. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  173. package/dist/core/settings-manager-basic-accessors.js +21 -0
  174. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  175. package/dist/core/settings-manager-core.js +13 -7
  176. package/dist/core/settings-manager-core.js.map +1 -1
  177. package/dist/core/settings-manager.d.ts +1 -1
  178. package/dist/core/settings-manager.d.ts.map +1 -1
  179. package/dist/core/settings-manager.js.map +1 -1
  180. package/dist/core/settings-storage.js +6 -0
  181. package/dist/core/settings-storage.js.map +1 -1
  182. package/dist/core/settings-types.d.ts +8 -0
  183. package/dist/core/settings-types.d.ts.map +1 -1
  184. package/dist/core/settings-types.js.map +1 -1
  185. package/dist/core/structured-output/index.d.ts.map +1 -1
  186. package/dist/core/structured-output/index.js +4 -1
  187. package/dist/core/structured-output/index.js.map +1 -1
  188. package/dist/core/structured-output/invalid-output.js +1 -0
  189. package/dist/core/structured-output/invalid-output.js.map +1 -1
  190. package/dist/core/tasks/agent-adapter.js +5 -3
  191. package/dist/core/tasks/agent-adapter.js.map +1 -1
  192. package/dist/core/tasks/child-command-owner.js +3 -7
  193. package/dist/core/tasks/child-command-owner.js.map +1 -1
  194. package/dist/core/tasks/completion.js +5 -1
  195. package/dist/core/tasks/completion.js.map +1 -1
  196. package/dist/core/tasks/owner-store.js +12 -8
  197. package/dist/core/tasks/owner-store.js.map +1 -1
  198. package/dist/core/tasks/supervisor.js +14 -35
  199. package/dist/core/tasks/supervisor.js.map +1 -1
  200. package/dist/core/tools/ask-user-question/state/build-questionnaire.js +13 -4
  201. package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -1
  202. package/dist/core/tools/ask-user-question/state/questionnaire-session.js +11 -1
  203. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
  204. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js +1 -0
  205. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js.map +1 -1
  206. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js +1 -0
  207. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -1
  208. package/dist/core/tools/ask-user-question/view/components/option-list-view.js +1 -0
  209. package/dist/core/tools/ask-user-question/view/components/option-list-view.js.map +1 -1
  210. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js +5 -0
  211. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js.map +1 -1
  212. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js +2 -0
  213. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -1
  214. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js +13 -8
  215. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js.map +1 -1
  216. package/dist/core/tools/ask-user-question/view/components/submit-picker.js +1 -0
  217. package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -1
  218. package/dist/core/tools/ask-user-question/view/components/tab-bar.js +1 -0
  219. package/dist/core/tools/ask-user-question/view/components/tab-bar.js.map +1 -1
  220. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +30 -24
  221. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -1
  222. package/dist/core/tools/ask-user-question/view/dialog-builder.js +5 -0
  223. package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -1
  224. package/dist/core/tools/ask-user-question/view/props-adapter.js +8 -0
  225. package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -1
  226. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js +4 -4
  227. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js.map +1 -1
  228. package/dist/core/tools/bash.js +5 -8
  229. package/dist/core/tools/bash.js.map +1 -1
  230. package/dist/core/tools/edit-batch.js +4 -0
  231. package/dist/core/tools/edit-batch.js.map +1 -1
  232. package/dist/core/tools/edit.js +2 -0
  233. package/dist/core/tools/edit.js.map +1 -1
  234. package/dist/core/tools/file-mutation-coordinator.js +9 -0
  235. package/dist/core/tools/file-mutation-coordinator.js.map +1 -1
  236. package/dist/core/tools/find.js +1 -1
  237. package/dist/core/tools/find.js.map +1 -1
  238. package/dist/core/tools/hashline-engine/fs.js +1 -1
  239. package/dist/core/tools/hashline-engine/fs.js.map +1 -1
  240. package/dist/core/tools/hashline-engine/input.js +4 -0
  241. package/dist/core/tools/hashline-engine/input.js.map +1 -1
  242. package/dist/core/tools/hashline-engine/mismatch.js +6 -0
  243. package/dist/core/tools/hashline-engine/mismatch.js.map +1 -1
  244. package/dist/core/tools/hashline-engine/patcher.js +13 -0
  245. package/dist/core/tools/hashline-engine/patcher.js.map +1 -1
  246. package/dist/core/tools/hashline-engine/recovery.js +1 -0
  247. package/dist/core/tools/hashline-engine/recovery.js.map +1 -1
  248. package/dist/core/tools/output-accumulator.js +20 -13
  249. package/dist/core/tools/output-accumulator.js.map +1 -1
  250. package/dist/core/tools/persisted-output-file.js +9 -3
  251. package/dist/core/tools/persisted-output-file.js.map +1 -1
  252. package/dist/core/tools/resource-selectors.js +1 -0
  253. package/dist/core/tools/resource-selectors.js.map +1 -1
  254. package/dist/core/tools/write.js +1 -0
  255. package/dist/core/tools/write.js.map +1 -1
  256. package/dist/core/trust-manager.js +1 -0
  257. package/dist/core/trust-manager.js.map +1 -1
  258. package/dist/core/workflow-stage-admission.js +17 -10
  259. package/dist/core/workflow-stage-admission.js.map +1 -1
  260. package/dist/extensions/llama/client.js +2 -0
  261. package/dist/extensions/llama/client.js.map +1 -1
  262. package/dist/extensions/llama/huggingface-ui.js +17 -9
  263. package/dist/extensions/llama/huggingface-ui.js.map +1 -1
  264. package/dist/extensions/llama/huggingface.js +2 -0
  265. package/dist/extensions/llama/huggingface.js.map +1 -1
  266. package/dist/extensions/llama/ui.js +11 -3
  267. package/dist/extensions/llama/ui.js.map +1 -1
  268. package/dist/index.d.ts +4 -2
  269. package/dist/index.d.ts.map +1 -1
  270. package/dist/index.js +3 -1
  271. package/dist/index.js.map +1 -1
  272. package/dist/modes/interactive/components/armin.js +10 -6
  273. package/dist/modes/interactive/components/armin.js.map +1 -1
  274. package/dist/modes/interactive/components/assistant-message.js +10 -2
  275. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  276. package/dist/modes/interactive/components/atomic-working-status.js +10 -2
  277. package/dist/modes/interactive/components/atomic-working-status.js.map +1 -1
  278. package/dist/modes/interactive/components/bash-execution.js +9 -4
  279. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  280. package/dist/modes/interactive/components/bordered-loader.js +3 -0
  281. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  282. package/dist/modes/interactive/components/branch-summary-message.js +4 -1
  283. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  284. package/dist/modes/interactive/components/chat-message-renderer.js +2 -1
  285. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  286. package/dist/modes/interactive/components/chat-session-host-state.js +63 -31
  287. package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
  288. package/dist/modes/interactive/components/chat-session-host.js +8 -1
  289. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  290. package/dist/modes/interactive/components/chat-transcript.js +24 -14
  291. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  292. package/dist/modes/interactive/components/compaction-boundary-message.js +2 -1
  293. package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
  294. package/dist/modes/interactive/components/config-selector-list.js +15 -6
  295. package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
  296. package/dist/modes/interactive/components/config-selector.js +7 -1
  297. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  298. package/dist/modes/interactive/components/countdown-timer.js +2 -0
  299. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  300. package/dist/modes/interactive/components/custom-editor.js +21 -1
  301. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  302. package/dist/modes/interactive/components/custom-entry.js +4 -1
  303. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  304. package/dist/modes/interactive/components/custom-message.js +9 -1
  305. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  306. package/dist/modes/interactive/components/daxnuts.js +8 -6
  307. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  308. package/dist/modes/interactive/components/dynamic-border.js +1 -0
  309. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  310. package/dist/modes/interactive/components/extension-editor.js +7 -1
  311. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  312. package/dist/modes/interactive/components/extension-input.js +8 -2
  313. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  314. package/dist/modes/interactive/components/extension-selector.js +9 -1
  315. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  316. package/dist/modes/interactive/components/first-time-setup.js +4 -2
  317. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  318. package/dist/modes/interactive/components/footer.js +5 -2
  319. package/dist/modes/interactive/components/footer.js.map +1 -1
  320. package/dist/modes/interactive/components/host-input-form.js +13 -2
  321. package/dist/modes/interactive/components/host-input-form.js.map +1 -1
  322. package/dist/modes/interactive/components/login-dialog.js +9 -3
  323. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  324. package/dist/modes/interactive/components/model-selector.js +24 -12
  325. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  326. package/dist/modes/interactive/components/oauth-selector.js +12 -3
  327. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  328. package/dist/modes/interactive/components/reserved-bottom-overlay.js +11 -2
  329. package/dist/modes/interactive/components/reserved-bottom-overlay.js.map +1 -1
  330. package/dist/modes/interactive/components/scoped-models-selector.js +13 -8
  331. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  332. package/dist/modes/interactive/components/scroll-widget.js +4 -0
  333. package/dist/modes/interactive/components/scroll-widget.js.map +1 -1
  334. package/dist/modes/interactive/components/session-selector-header.js +11 -7
  335. package/dist/modes/interactive/components/session-selector-header.js.map +1 -1
  336. package/dist/modes/interactive/components/session-selector-list.js +25 -12
  337. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  338. package/dist/modes/interactive/components/session-selector.js +23 -15
  339. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  340. package/dist/modes/interactive/components/settings-selector-submenus.js +19 -1
  341. package/dist/modes/interactive/components/settings-selector-submenus.js.map +1 -1
  342. package/dist/modes/interactive/components/settings-selector.js +1 -0
  343. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  344. package/dist/modes/interactive/components/show-images-selector.js +1 -0
  345. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  346. package/dist/modes/interactive/components/skill-invocation-message.js +4 -1
  347. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  348. package/dist/modes/interactive/components/startup-identity.js +8 -3
  349. package/dist/modes/interactive/components/startup-identity.js.map +1 -1
  350. package/dist/modes/interactive/components/task-completion-message.js +2 -0
  351. package/dist/modes/interactive/components/task-completion-message.js.map +1 -1
  352. package/dist/modes/interactive/components/task-detail.js +2 -0
  353. package/dist/modes/interactive/components/task-detail.js.map +1 -1
  354. package/dist/modes/interactive/components/task-inspector.js +22 -12
  355. package/dist/modes/interactive/components/task-inspector.js.map +1 -1
  356. package/dist/modes/interactive/components/task-list.js +2 -0
  357. package/dist/modes/interactive/components/task-list.js.map +1 -1
  358. package/dist/modes/interactive/components/task-live-transcript.js +8 -3
  359. package/dist/modes/interactive/components/task-live-transcript.js.map +1 -1
  360. package/dist/modes/interactive/components/task-navigation.js +5 -2
  361. package/dist/modes/interactive/components/task-navigation.js.map +1 -1
  362. package/dist/modes/interactive/components/task-row.js +2 -0
  363. package/dist/modes/interactive/components/task-row.js.map +1 -1
  364. package/dist/modes/interactive/components/theme-selector.js +2 -0
  365. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  366. package/dist/modes/interactive/components/thinking-selector.js +7 -1
  367. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  368. package/dist/modes/interactive/components/tool-execution.js +25 -10
  369. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  370. package/dist/modes/interactive/components/transcript-follow-indicator.js +1 -0
  371. package/dist/modes/interactive/components/transcript-follow-indicator.js.map +1 -1
  372. package/dist/modes/interactive/components/tree-selector-component.js +7 -3
  373. package/dist/modes/interactive/components/tree-selector-component.js.map +1 -1
  374. package/dist/modes/interactive/components/tree-selector-help.js +1 -0
  375. package/dist/modes/interactive/components/tree-selector-help.js.map +1 -1
  376. package/dist/modes/interactive/components/tree-selector-label-input.js +6 -2
  377. package/dist/modes/interactive/components/tree-selector-label-input.js.map +1 -1
  378. package/dist/modes/interactive/components/tree-selector-list.js +4 -0
  379. package/dist/modes/interactive/components/tree-selector-list.js.map +1 -1
  380. package/dist/modes/interactive/components/trust-selector.js +6 -0
  381. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/user-message-selector.js +6 -3
  383. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  384. package/dist/modes/interactive/components/user-message.js +5 -0
  385. package/dist/modes/interactive/components/user-message.js.map +1 -1
  386. package/dist/modes/interactive/components/working-status.js +1 -0
  387. package/dist/modes/interactive/components/working-status.js.map +1 -1
  388. package/dist/modes/interactive/interactive-autocomplete.js +2 -0
  389. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  390. package/dist/modes/interactive/interactive-extension-runtime.js +1 -0
  391. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  392. package/dist/modes/interactive/interactive-mode-base.js +162 -120
  393. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  394. package/dist/modes/interactive/interactive-mode-helpers.js +3 -0
  395. package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
  396. package/dist/modes/interactive/interactive-mode-surface.d.ts +0 -6
  397. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  398. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  399. package/dist/modes/interactive/interactive-resource-disclosure.js +0 -4
  400. package/dist/modes/interactive/interactive-resource-disclosure.js.map +1 -1
  401. package/dist/modes/interactive/interactive-resource-rendering.js +0 -12
  402. package/dist/modes/interactive/interactive-resource-rendering.js.map +1 -1
  403. package/dist/modes/interactive/interactive-startup-chat-container.js +1 -4
  404. package/dist/modes/interactive/interactive-startup-chat-container.js.map +1 -1
  405. package/dist/modes/interactive/model-catalog-refresh.js +1 -3
  406. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  407. package/dist/modes/interactive/theme/color-utils.d.ts +5 -0
  408. package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
  409. package/dist/modes/interactive/theme/color-utils.js +11 -0
  410. package/dist/modes/interactive/theme/color-utils.js.map +1 -1
  411. package/dist/modes/interactive/theme/global-theme.d.ts.map +1 -1
  412. package/dist/modes/interactive/theme/global-theme.js +4 -3
  413. package/dist/modes/interactive/theme/global-theme.js.map +1 -1
  414. package/dist/modes/interactive/theme/theme-class.js +7 -0
  415. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  416. package/dist/modes/interactive/theme/theme-controller.js +9 -2
  417. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  418. package/dist/modes/interactive-engine/activity-watchdog.js +8 -3
  419. package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -1
  420. package/dist/modes/interactive-engine/engine-custom-ui.js +12 -8
  421. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  422. package/dist/modes/interactive-engine/engine-dialog-host.js +7 -3
  423. package/dist/modes/interactive-engine/engine-dialog-host.js.map +1 -1
  424. package/dist/modes/interactive-engine/engine-health.js +23 -13
  425. package/dist/modes/interactive-engine/engine-health.js.map +1 -1
  426. package/dist/modes/interactive-engine/engine-input-form.js +3 -2
  427. package/dist/modes/interactive-engine/engine-input-form.js.map +1 -1
  428. package/dist/modes/interactive-engine/engine-monitor.js +13 -1
  429. package/dist/modes/interactive-engine/engine-monitor.js.map +1 -1
  430. package/dist/modes/interactive-engine/engine-project-trust.js +2 -1
  431. package/dist/modes/interactive-engine/engine-project-trust.js.map +1 -1
  432. package/dist/modes/interactive-engine/engine-render-service.js +7 -4
  433. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
  434. package/dist/modes/interactive-engine/engine-session-picker.js +3 -2
  435. package/dist/modes/interactive-engine/engine-session-picker.js.map +1 -1
  436. package/dist/modes/interactive-engine/input-form-host.js +5 -1
  437. package/dist/modes/interactive-engine/input-form-host.js.map +1 -1
  438. package/dist/modes/interactive-engine/isolated-runtime.js +37 -23
  439. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  440. package/dist/modes/interactive-engine/remote-command-catalog.js +4 -3
  441. package/dist/modes/interactive-engine/remote-command-catalog.js.map +1 -1
  442. package/dist/modes/interactive-engine/remote-component.js +24 -12
  443. package/dist/modes/interactive-engine/remote-component.js.map +1 -1
  444. package/dist/modes/interactive-engine/remote-frame-clamp.js +3 -3
  445. package/dist/modes/interactive-engine/remote-frame-clamp.js.map +1 -1
  446. package/dist/modes/interactive-engine/remote-model-catalog.js +5 -4
  447. package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
  448. package/dist/modes/interactive-engine/remote-queue-pause.js +3 -1
  449. package/dist/modes/interactive-engine/remote-queue-pause.js.map +1 -1
  450. package/dist/modes/interactive-engine/remote-renderer.js +24 -13
  451. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
  452. package/dist/modes/interactive-engine/resource-readiness-error.js +1 -0
  453. package/dist/modes/interactive-engine/resource-readiness-error.js.map +1 -1
  454. package/dist/modes/interactive-engine/session-picker-host.js +5 -1
  455. package/dist/modes/interactive-engine/session-picker-host.js.map +1 -1
  456. package/dist/modes/interactive-engine/terminal-mode-controller.js +2 -1
  457. package/dist/modes/interactive-engine/terminal-mode-controller.js.map +1 -1
  458. package/dist/modes/rpc/queued-writer.js +13 -4
  459. package/dist/modes/rpc/queued-writer.js.map +1 -1
  460. package/dist/modes/rpc/rpc-bash-request-owners.js +2 -1
  461. package/dist/modes/rpc/rpc-bash-request-owners.js.map +1 -1
  462. package/dist/modes/rpc/rpc-client-api.d.ts +8 -4
  463. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  464. package/dist/modes/rpc/rpc-client-api.js +10 -3
  465. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  466. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  467. package/dist/modes/rpc/rpc-client.js +35 -22
  468. package/dist/modes/rpc/rpc-client.js.map +1 -1
  469. package/dist/modes/rpc/rpc-command-handler.js +6 -6
  470. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  471. package/dist/modes/rpc/rpc-event-buffer.js +3 -1
  472. package/dist/modes/rpc/rpc-event-buffer.js.map +1 -1
  473. package/dist/modes/rpc/rpc-generation-buffer.js +1 -3
  474. package/dist/modes/rpc/rpc-generation-buffer.js.map +1 -1
  475. package/dist/modes/rpc/rpc-keybindings-reload.js +4 -1
  476. package/dist/modes/rpc/rpc-keybindings-reload.js.map +1 -1
  477. package/dist/modes/rpc/rpc-output-buffer.js +3 -4
  478. package/dist/modes/rpc/rpc-output-buffer.js.map +1 -1
  479. package/dist/modes/rpc/rpc-pending-requests.js +1 -3
  480. package/dist/modes/rpc/rpc-pending-requests.js.map +1 -1
  481. package/dist/modes/rpc/rpc-provider-auth.js +3 -1
  482. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  483. package/dist/modes/rpc/rpc-resource-readiness.js +4 -5
  484. package/dist/modes/rpc/rpc-resource-readiness.js.map +1 -1
  485. package/dist/modes/rpc/rpc-session-binding.js +15 -0
  486. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  487. package/dist/modes/rpc/rpc-terminal-drain.js +3 -0
  488. package/dist/modes/rpc/rpc-terminal-drain.js.map +1 -1
  489. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  490. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  491. package/dist/modes/rpc/rpc-types.js.map +1 -1
  492. package/docs/models/evals.md +883 -39
  493. package/docs/models/model-selection.md +7 -8
  494. package/docs/rpc/examples.md +1 -1
  495. package/docs/rpc/protocol.md +9 -3
  496. package/docs/sdk/structured-decisions.md +1 -1
  497. package/docs/sdk.md +3 -3
  498. package/docs/settings.md +24 -3
  499. package/docs/subagents/reference.md +22 -4
  500. package/docs/subagents.md +2 -0
  501. package/docs/usage.md +3 -3
  502. package/docs/workflows/api-reference.md +1 -1
  503. package/docs/workflows/authoring.md +1 -7
  504. package/docs/workflows/builtins.md +1 -1
  505. package/docs/workflows/reliable-design.md +1 -1
  506. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  507. package/examples/extensions/gondolin/package.json +1 -1
  508. package/examples/rpc-client.ts +1 -1
  509. package/examples/rpc-extension-ui.ts +1 -1
  510. package/npm-shrinkwrap.json +70 -33
  511. package/package.json +6 -7
  512. package/dist/core/model-routing-task.d.ts.map +0 -1
  513. package/dist/core/model-routing-task.js +0 -120
  514. package/dist/core/model-routing-task.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"model-routing-constraints.js","sourceRoot":"","sources":["../../src/core/model-routing-constraints.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@bastani/pi-ai\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\n\nexport const ModelConstraintsSchema = Type.Object(\n\t{\n\t\tallowedModels: Type.Optional(\n\t\t\tType.Array(Type.String({ minLength: 1 }), {\n\t\t\t\tdescription: \"Exact provider/model IDs; omitted uses the full available catalog.\",\n\t\t\t}),\n\t\t),\n\t\tmaxInputCost: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Maximum catalog input rate in USD per million tokens, including pricing tiers; not total task spending.\",\n\t\t\t}),\n\t\t),\n\t\tmaxOutputCost: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Maximum catalog output rate in USD per million tokens, including pricing tiers; not total task spending.\",\n\t\t\t}),\n\t\t),\n\t\tminContextWindow: Type.Optional(\n\t\t\tType.Number({ minimum: 0, description: \"Minimum catalog context window in tokens.\" }),\n\t\t),\n\t\trequiredInputs: Type.Optional(\n\t\t\tType.Array(Type.Unsafe<\"text\" | \"image\">(Type.String({ enum: [\"text\", \"image\"] }))),\n\t\t),\n\t\tallowedEfforts: Type.Optional(\n\t\t\tType.Array(\n\t\t\t\tType.Union([\n\t\t\t\t\tType.String({ enum: [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] }),\n\t\t\t\t\tType.Null(),\n\t\t\t\t]),\n\t\t\t),\n\t\t),\n\t},\n\t{\n\t\tadditionalProperties: false,\n\t\tdescription:\n\t\t\t\"Hard constraints for auto selection and execution fallback. Applicable definition and call constraints must all hold; concrete model calls keep existing behavior.\",\n\t},\n);\nexport type ModelConstraints = Static<typeof ModelConstraintsSchema>;\nconst validator = Compile(ModelConstraintsSchema);\nexport function parseModelConstraints(value: unknown): ModelConstraints | undefined {\n\tif (value === undefined) return undefined;\n\tif (\n\t\t!validator.Check(value) ||\n\t\t[value.maxInputCost, value.maxOutputCost, value.minContextWindow].some(\n\t\t\t(n) => n !== undefined && !Number.isFinite(n),\n\t\t)\n\t) {\n\t\tthrow new Error(\"Invalid modelConstraints: use known fields and finite nonnegative numeric limits.\");\n\t}\n\treturn value;\n}\nexport type ModelRouterOutput = {\n\treadonly model: string;\n\treadonly effort: string | null;\n\t/** Ranked alternatives, excluding the primary. Absent on legacy recorded selections. */\n\treadonly fallbacks?: readonly { readonly model: string; readonly effort: string | null }[];\n};\n/** Every applicable declaration must hold; a caller never widens a definition restriction. */\nexport function eligiblePair(\n\tmodel: Model<Api>,\n\tpair: ModelRouterOutput,\n\tconstraints: readonly ModelConstraints[],\n): boolean {\n\treturn constraints.every(\n\t\t(c) =>\n\t\t\t(c.allowedModels === undefined || c.allowedModels.includes(pair.model)) &&\n\t\t\t(c.allowedEfforts === undefined || c.allowedEfforts.some((e) => e === pair.effort)) &&\n\t\t\t(c.maxInputCost === undefined ||\n\t\t\t\t[model.cost, ...(model.cost.tiers ?? [])].every((rate) => rate.input <= c.maxInputCost!)) &&\n\t\t\t(c.maxOutputCost === undefined ||\n\t\t\t\t[model.cost, ...(model.cost.tiers ?? [])].every((rate) => rate.output <= c.maxOutputCost!)) &&\n\t\t\t(c.minContextWindow === undefined || model.contextWindow >= c.minContextWindow) &&\n\t\t\t(c.requiredInputs === undefined || c.requiredInputs.every((input) => model.input.includes(input))),\n\t);\n}\n"]}
1
+ {"version":3,"file":"model-routing-constraints.js","sourceRoot":"","sources":["../../src/core/model-routing-constraints.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@bastani/pi-ai\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\n\nexport const ModelConstraintsSchema = Type.Object(\n\t{\n\t\tallowedModels: Type.Optional(\n\t\t\tType.Array(Type.String({ minLength: 1 }), {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Exact provider/model IDs; omitted uses the full available catalog. With model 'auto', these are the candidates the router chooses between (as many as fit one routing request, roughly 100), so list the models that suit the task. Prefer the user's subscription models (for example ChatGPT/Codex, GitHub Copilot, a Claude subscription, or a coding or token plan) over pay-per-token API models, unless the user asked for API models or has no subscription models.\",\n\t\t\t}),\n\t\t),\n\t\tallowedProviders: Type.Optional(\n\t\t\tType.Array(Type.String({ minLength: 1 }), {\n\t\t\t\tdescription:\n\t\t\t\t\t'Provider IDs whose models may be used, for example [\"openai-codex\", \"github-copilot\"]. Setting this or excludedProviders replaces the user\\'s modelRouting provider settings for this call, so set them only when the user asks to use or avoid specific providers.',\n\t\t\t}),\n\t\t),\n\t\texcludedProviders: Type.Optional(\n\t\t\tType.Array(Type.String({ minLength: 1 }), {\n\t\t\t\tdescription:\n\t\t\t\t\t'Provider IDs whose models are never used, for example [\"openrouter\"]. Setting this or allowedProviders replaces the user\\'s modelRouting provider settings for this call, so set them only when the user asks.',\n\t\t\t}),\n\t\t),\n\t\tmaxInputCost: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Maximum catalog input rate in USD per million tokens, including pricing tiers; not total task spending.\",\n\t\t\t}),\n\t\t),\n\t\tmaxOutputCost: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Maximum catalog output rate in USD per million tokens, including pricing tiers; not total task spending.\",\n\t\t\t}),\n\t\t),\n\t\tminContextWindow: Type.Optional(\n\t\t\tType.Number({ minimum: 0, description: \"Minimum catalog context window in tokens.\" }),\n\t\t),\n\t\trequiredInputs: Type.Optional(\n\t\t\tType.Array(Type.Unsafe<\"text\" | \"image\">(Type.String({ enum: [\"text\", \"image\"] }))),\n\t\t),\n\t\tallowedEfforts: Type.Optional(\n\t\t\tType.Array(\n\t\t\t\tType.Union([\n\t\t\t\t\tType.String({ enum: [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] }),\n\t\t\t\t\tType.Null(),\n\t\t\t\t]),\n\t\t\t),\n\t\t),\n\t},\n\t{\n\t\tadditionalProperties: false,\n\t\tdescription:\n\t\t\t\"Hard constraints for auto selection and execution fallback. Applicable definition and call constraints must all hold; concrete model calls keep existing behavior.\",\n\t},\n);\nexport type ModelConstraints = Static<typeof ModelConstraintsSchema>;\nconst validator = Compile(ModelConstraintsSchema);\nexport function parseModelConstraints(value: unknown): ModelConstraints | undefined {\n\tif (value === undefined) return undefined;\n\tif (\n\t\t!validator.Check(value) ||\n\t\t[value.maxInputCost, value.maxOutputCost, value.minContextWindow].some(\n\t\t\t(n) => n !== undefined && !Number.isFinite(n),\n\t\t)\n\t) {\n\t\tthrow new Error(\"Invalid modelConstraints: use known fields and finite nonnegative numeric limits.\");\n\t}\n\treturn value;\n}\nexport type ModelRouterOutput = {\n\treadonly model: string;\n\treadonly effort: string | null;\n\t/** Ranked alternatives, excluding the primary. Absent on legacy recorded selections. */\n\treadonly fallbacks?: readonly { readonly model: string; readonly effort: string | null }[];\n};\n/** Whether a constraint sets its own provider list. */\nexport function setsProviders(constraints: ModelConstraints | undefined): boolean {\n\treturn constraints?.allowedProviders !== undefined || constraints?.excludedProviders !== undefined;\n}\n\n/** Every applicable declaration must hold; a caller never widens a definition restriction. */\nexport function eligiblePair(\n\tmodel: Model<Api>,\n\tpair: ModelRouterOutput,\n\tconstraints: readonly ModelConstraints[],\n): boolean {\n\treturn constraints.every(\n\t\t(c) =>\n\t\t\t(c.allowedModels === undefined || c.allowedModels.includes(pair.model)) &&\n\t\t\t(c.allowedProviders === undefined || c.allowedProviders.includes(model.provider)) &&\n\t\t\t!c.excludedProviders?.includes(model.provider) &&\n\t\t\t(c.allowedEfforts === undefined || c.allowedEfforts.some((e) => e === pair.effort)) &&\n\t\t\t(c.maxInputCost === undefined ||\n\t\t\t\t[model.cost, ...(model.cost.tiers ?? [])].every((rate) => rate.input <= c.maxInputCost!)) &&\n\t\t\t(c.maxOutputCost === undefined ||\n\t\t\t\t[model.cost, ...(model.cost.tiers ?? [])].every((rate) => rate.output <= c.maxOutputCost!)) &&\n\t\t\t(c.minContextWindow === undefined || model.contextWindow >= c.minContextWindow) &&\n\t\t\t(c.requiredInputs === undefined || c.requiredInputs.every((input) => model.input.includes(input))),\n\t);\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /** Set to `1` to print automatic model routing fallbacks and failures. */
2
+ export declare const MODEL_ROUTING_DEBUG_ENV = "ATOMIC_MODEL_ROUTING_DEBUG";
3
+ export declare function isModelRoutingDebugEnabled(env?: NodeJS.ProcessEnv): boolean;
4
+ /**
5
+ * Routing fallbacks are recoverable and already recorded in routing metadata, so
6
+ * they stay out of the terminal and agent context unless routing debugging is on.
7
+ */
8
+ export declare function reportModelRoutingDebug(message: string, env?: NodeJS.ProcessEnv): void;
9
+ //# sourceMappingURL=model-routing-debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-routing-debug.d.ts","sourceRoot":"","sources":["../../src/core/model-routing-debug.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;AAEpE,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAExF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI,CAEnG"}
@@ -0,0 +1,14 @@
1
+ /** Set to `1` to print automatic model routing fallbacks and failures. */
2
+ export const MODEL_ROUTING_DEBUG_ENV = "ATOMIC_MODEL_ROUTING_DEBUG";
3
+ export function isModelRoutingDebugEnabled(env = process.env) {
4
+ return env[MODEL_ROUTING_DEBUG_ENV] === "1";
5
+ }
6
+ /**
7
+ * Routing fallbacks are recoverable and already recorded in routing metadata, so
8
+ * they stay out of the terminal and agent context unless routing debugging is on.
9
+ */
10
+ export function reportModelRoutingDebug(message, env = process.env) {
11
+ if (isModelRoutingDebugEnabled(env))
12
+ console.warn(message);
13
+ }
14
+ //# sourceMappingURL=model-routing-debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-routing-debug.js","sourceRoot":"","sources":["../../src/core/model-routing-debug.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,CAAC,MAAM,uBAAuB,GAAG,4BAA4B,CAAC;AAEpE,MAAM,UAAU,0BAA0B,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAC9E,OAAO,GAAG,CAAC,uBAAuB,CAAC,KAAK,GAAG,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,GAAG,GAAsB,OAAO,CAAC,GAAG;IAC5F,IAAI,0BAA0B,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5D,CAAC","sourcesContent":["/** Set to `1` to print automatic model routing fallbacks and failures. */\nexport const MODEL_ROUTING_DEBUG_ENV = \"ATOMIC_MODEL_ROUTING_DEBUG\";\n\nexport function isModelRoutingDebugEnabled(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn env[MODEL_ROUTING_DEBUG_ENV] === \"1\";\n}\n\n/**\n * Routing fallbacks are recoverable and already recorded in routing metadata, so\n * they stay out of the terminal and agent context unless routing debugging is on.\n */\nexport function reportModelRoutingDebug(message: string, env: NodeJS.ProcessEnv = process.env): void {\n\tif (isModelRoutingDebugEnabled(env)) console.warn(message);\n}\n"]}
@@ -0,0 +1,50 @@
1
+ /** Bounds the evaluation evidence sent with one routing request. */
2
+ export declare const MODEL_SELECTION_EVALS_JSON_BYTES = 14200;
3
+ /** Provider-independent model tokens: `us.anthropic.claude-opus-4-6-v1` and `anthropic/claude-opus-4.6` agree. */
4
+ export declare function modelEvidenceTokens(id: string): string[];
5
+ interface CatalogRow {
6
+ readonly line: string;
7
+ readonly section: number;
8
+ readonly order: number;
9
+ readonly tokens: readonly string[];
10
+ readonly releaseDate?: string;
11
+ }
12
+ /** One `## ` section of `evals.md` that holds a model table keyed by `slug`. */
13
+ interface CatalogSection {
14
+ /** The section heading, its notes and key, the table header and separator. */
15
+ readonly intro: readonly string[];
16
+ }
17
+ /** `evals.md` parsed once so batch packing can query evidence per candidate cheaply. */
18
+ export interface EvalsCatalog {
19
+ /** Text before the first table section: title, access date and the shared key. */
20
+ readonly preamble: readonly string[];
21
+ readonly sections: readonly CatalogSection[];
22
+ readonly rows: readonly CatalogRow[];
23
+ /** The unparsed document when it has no model table. */
24
+ readonly raw?: string;
25
+ readonly matches: Map<string, readonly CatalogRow[]>;
26
+ }
27
+ export declare function parseEvalsCatalog(evals: string): EvalsCatalog;
28
+ /**
29
+ * Rows describing `candidate`: in each section, its own model and variants, or
30
+ * its base model when that section has none. Sections resolve independently, so
31
+ * an exact snapshot row in one table does not hide the base model's rows in another.
32
+ */
33
+ export declare function candidateEvidenceRows(catalog: EvalsCatalog, candidate: string): readonly CatalogRow[];
34
+ /** Latest release date among the candidate's evidence rows, when any row has one. */
35
+ export declare function candidateReleaseDate(catalog: EvalsCatalog, candidate: string): string | undefined;
36
+ /**
37
+ * The catalog preamble plus, for every section with rows for `candidates`, that
38
+ * section's heading, key and table header followed by only those rows.
39
+ * Sections without a matching row are left out. `maxBytes` bounds the
40
+ * JSON-encoded result; batched routing omits it because its request budget
41
+ * already decides how many candidates, and so how many rows, one batch holds.
42
+ */
43
+ export declare function catalogEvidence(catalog: EvalsCatalog, candidates: readonly string[], maxBytes?: number): string;
44
+ /**
45
+ * Keep the catalog preamble and only the table rows that describe an eligible
46
+ * candidate model, bounded to the routing evidence budget.
47
+ */
48
+ export declare function filterModelSelectionEvals(evals: string, candidates: readonly string[]): string;
49
+ export {};
50
+ //# sourceMappingURL=model-routing-evals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-routing-evals.d.ts","sourceRoot":"","sources":["../../src/core/model-routing-evals.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,eAAO,MAAM,gCAAgC,QAAS,CAAC;AA2CvD,kHAAkH;AAClH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAexD;AA6BD,UAAU,UAAU;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,gFAAgF;AAChF,UAAU,cAAc;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,CAAC;IACrC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAAC;CACrD;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAmC7D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAcrG;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGjG;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,QAAQ,SAA2B,GACjC,MAAM,CAeR;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE9F"}
@@ -0,0 +1,190 @@
1
+ import { jsonBytes, truncateToBytes } from "./model-routing-bytes.js";
2
+ /** Bounds the evaluation evidence sent with one routing request. */
3
+ export const MODEL_SELECTION_EVALS_JSON_BYTES = 14_200;
4
+ const VENDOR_OR_REGION_PREFIX = /^(?:[a-z][a-z-]*\.)+/u;
5
+ const SNAPSHOT_TOKEN = /^\d{4}$/u;
6
+ const DEPLOYMENT_TOKENS = new Set([
7
+ "fast",
8
+ "highspeed",
9
+ "ultraspeed",
10
+ "lightning",
11
+ "beta",
12
+ "exp",
13
+ "free",
14
+ "it",
15
+ "instruct",
16
+ "contributor",
17
+ ]);
18
+ const ROW_EDITION_TOKENS = new Set(["preview", "instruct", "it"]);
19
+ const VARIANT_TOKENS = new Set([
20
+ "off",
21
+ "minimal",
22
+ "low",
23
+ "medium",
24
+ "high",
25
+ "xhigh",
26
+ "max",
27
+ "adaptive",
28
+ "thinking",
29
+ "reasoning",
30
+ "non",
31
+ "effort",
32
+ "preview",
33
+ ]);
34
+ const CLAUDE_FAMILIES = new Set(["opus", "sonnet", "haiku", "fable"]);
35
+ /** Artificial Analysis names older Claude models `claude-4-5-sonnet`; catalogs use `claude-sonnet-4-5`. */
36
+ function canonicalClaudeOrder(tokens) {
37
+ if (tokens[0] !== "claude" || !CLAUDE_FAMILIES.has(tokens[1] ?? ""))
38
+ return tokens;
39
+ const versionEnd = tokens.findIndex((token, index) => index > 1 && !/^\d+$/u.test(token));
40
+ const end = versionEnd < 0 ? tokens.length : versionEnd;
41
+ if (end === 2)
42
+ return tokens;
43
+ return ["claude", ...tokens.slice(2, end), tokens[1], ...tokens.slice(end)];
44
+ }
45
+ /** Provider-independent model tokens: `us.anthropic.claude-opus-4-6-v1` and `anthropic/claude-opus-4.6` agree. */
46
+ export function modelEvidenceTokens(id) {
47
+ const normalized = id.trim().toLowerCase();
48
+ const model = normalized
49
+ .slice(normalized.lastIndexOf("/") + 1)
50
+ .replace(/^~/u, "")
51
+ .replace(VENDOR_OR_REGION_PREFIX, "")
52
+ .replace(/(?<=[a-z])-\d+:\d+$/u, "")
53
+ .replace(/:[a-z0-9]+$/u, "")
54
+ .replace(/-v\d+$/u, "")
55
+ .replace(/-\d{8}$/u, "");
56
+ const tokens = model
57
+ .split(/[-._]/u)
58
+ .filter(Boolean)
59
+ .map((token) => (token === "thinking" ? "reasoning" : token));
60
+ return canonicalClaudeOrder(tokens);
61
+ }
62
+ /** True when `slug` is the candidate model or one of its effort, edition or snapshot variants. */
63
+ function slugMatchesCandidate(slug, candidate) {
64
+ if (slug.length < candidate.length || candidate.some((token, index) => slug[index] !== token))
65
+ return false;
66
+ return slug
67
+ .slice(candidate.length)
68
+ .every((token) => VARIANT_TOKENS.has(token) || ROW_EDITION_TOKENS.has(token) || SNAPSHOT_TOKEN.test(token));
69
+ }
70
+ /**
71
+ * The candidate's own tokens first, then the same model without trailing
72
+ * deployment, reasoning-mode or snapshot suffixes (`gpt-5.4-fast`,
73
+ * `grok-4.20-reasoning`, `qwen3.8-max-0902`). A fallback applies only when the
74
+ * more specific form matched no row, so a model that is itself named `-fast`
75
+ * keeps its own evidence.
76
+ */
77
+ function candidateForms(tokens) {
78
+ const forms = [[...tokens]];
79
+ let current = [...tokens];
80
+ while (current.length > 1) {
81
+ const last = current[current.length - 1];
82
+ if (!DEPLOYMENT_TOKENS.has(last) && !VARIANT_TOKENS.has(last) && !SNAPSHOT_TOKEN.test(last))
83
+ break;
84
+ current = current.slice(0, -1);
85
+ forms.push(current);
86
+ }
87
+ return forms;
88
+ }
89
+ const TABLE_HEADER = /^\|\s*slug\s*\|/u;
90
+ export function parseEvalsCatalog(evals) {
91
+ const lines = evals.split("\n");
92
+ const headers = lines.flatMap((line, index) => (TABLE_HEADER.test(line) ? [index] : []));
93
+ if (headers.length === 0)
94
+ return { preamble: [], sections: [], rows: [], raw: evals, matches: new Map() };
95
+ const sections = [];
96
+ const rows = [];
97
+ let preambleEnd = 0;
98
+ let previousTableEnd = 0;
99
+ for (const [section, headerIndex] of headers.entries()) {
100
+ let start = headerIndex;
101
+ for (let index = headerIndex - 1; index >= previousTableEnd; index--)
102
+ if (lines[index].startsWith("## ")) {
103
+ start = index;
104
+ break;
105
+ }
106
+ if (section === 0)
107
+ preambleEnd = start;
108
+ sections.push({ intro: lines.slice(start, headerIndex + 2) });
109
+ const header = lines[headerIndex].split("|").map((cell) => cell.trim());
110
+ const releaseColumn = header.indexOf("Release date");
111
+ let index = headerIndex + 2;
112
+ for (; index < lines.length && lines[index].startsWith("|"); index++) {
113
+ const cells = lines[index].split("|").map((cell) => cell.trim());
114
+ if (!cells[1])
115
+ continue;
116
+ const release = releaseColumn > 0 ? cells[releaseColumn] : undefined;
117
+ rows.push({
118
+ line: lines[index],
119
+ section,
120
+ order: rows.length,
121
+ tokens: modelEvidenceTokens(cells[1]),
122
+ ...(release && /^\d{4}-\d{2}-\d{2}$/u.test(release) ? { releaseDate: release } : {}),
123
+ });
124
+ }
125
+ previousTableEnd = index;
126
+ }
127
+ return { preamble: lines.slice(0, preambleEnd), sections, rows, matches: new Map() };
128
+ }
129
+ /**
130
+ * Rows describing `candidate`: in each section, its own model and variants, or
131
+ * its base model when that section has none. Sections resolve independently, so
132
+ * an exact snapshot row in one table does not hide the base model's rows in another.
133
+ */
134
+ export function candidateEvidenceRows(catalog, candidate) {
135
+ const cached = catalog.matches.get(candidate);
136
+ if (cached)
137
+ return cached;
138
+ const forms = candidateForms(modelEvidenceTokens(candidate));
139
+ const matches = catalog.sections.flatMap((_, section) => {
140
+ const sectionRows = catalog.rows.filter((row) => row.section === section);
141
+ for (const form of forms) {
142
+ const found = sectionRows.filter((row) => slugMatchesCandidate(row.tokens, form));
143
+ if (found.length > 0)
144
+ return found;
145
+ }
146
+ return [];
147
+ });
148
+ catalog.matches.set(candidate, matches);
149
+ return matches;
150
+ }
151
+ /** Latest release date among the candidate's evidence rows, when any row has one. */
152
+ export function candidateReleaseDate(catalog, candidate) {
153
+ const dates = candidateEvidenceRows(catalog, candidate).flatMap((row) => (row.releaseDate ? [row.releaseDate] : []));
154
+ return dates.length ? dates.sort().at(-1) : undefined;
155
+ }
156
+ /**
157
+ * The catalog preamble plus, for every section with rows for `candidates`, that
158
+ * section's heading, key and table header followed by only those rows.
159
+ * Sections without a matching row are left out. `maxBytes` bounds the
160
+ * JSON-encoded result; batched routing omits it because its request budget
161
+ * already decides how many candidates, and so how many rows, one batch holds.
162
+ */
163
+ export function catalogEvidence(catalog, candidates, maxBytes = Number.POSITIVE_INFINITY) {
164
+ if (catalog.raw !== undefined)
165
+ return truncateToBytes(catalog.raw, maxBytes);
166
+ const selected = new Set();
167
+ for (const candidate of new Set(candidates))
168
+ for (const row of candidateEvidenceRows(catalog, candidate))
169
+ selected.add(row.order);
170
+ const kept = catalog.rows.filter((row) => selected.has(row.order));
171
+ const parts = [...catalog.preamble];
172
+ for (const [index, section] of catalog.sections.entries()) {
173
+ const sectionRows = kept.filter((row) => row.section === index);
174
+ if (index > 0 && sectionRows.length === 0)
175
+ continue;
176
+ if (index > 0 && parts.at(-1) !== "")
177
+ parts.push("");
178
+ parts.push(...section.intro, ...sectionRows.map((row) => row.line));
179
+ }
180
+ const filtered = parts.join("\n");
181
+ return jsonBytes(filtered) <= maxBytes ? filtered : truncateToBytes(filtered, maxBytes);
182
+ }
183
+ /**
184
+ * Keep the catalog preamble and only the table rows that describe an eligible
185
+ * candidate model, bounded to the routing evidence budget.
186
+ */
187
+ export function filterModelSelectionEvals(evals, candidates) {
188
+ return catalogEvidence(parseEvalsCatalog(evals), candidates, MODEL_SELECTION_EVALS_JSON_BYTES);
189
+ }
190
+ //# sourceMappingURL=model-routing-evals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-routing-evals.js","sourceRoot":"","sources":["../../src/core/model-routing-evals.ts"],"names":[],"mappings":"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","sourcesContent":["import { jsonBytes, truncateToBytes } from \"./model-routing-bytes.js\";\n\n/** Bounds the evaluation evidence sent with one routing request. */\nexport const MODEL_SELECTION_EVALS_JSON_BYTES = 14_200;\n\nconst VENDOR_OR_REGION_PREFIX = /^(?:[a-z][a-z-]*\\.)+/u;\nconst SNAPSHOT_TOKEN = /^\\d{4}$/u;\nconst DEPLOYMENT_TOKENS = new Set([\n\t\"fast\",\n\t\"highspeed\",\n\t\"ultraspeed\",\n\t\"lightning\",\n\t\"beta\",\n\t\"exp\",\n\t\"free\",\n\t\"it\",\n\t\"instruct\",\n\t\"contributor\",\n]);\nconst ROW_EDITION_TOKENS = new Set([\"preview\", \"instruct\", \"it\"]);\nconst VARIANT_TOKENS = new Set([\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n\t\"adaptive\",\n\t\"thinking\",\n\t\"reasoning\",\n\t\"non\",\n\t\"effort\",\n\t\"preview\",\n]);\nconst CLAUDE_FAMILIES = new Set([\"opus\", \"sonnet\", \"haiku\", \"fable\"]);\n\n/** Artificial Analysis names older Claude models `claude-4-5-sonnet`; catalogs use `claude-sonnet-4-5`. */\nfunction canonicalClaudeOrder(tokens: string[]): string[] {\n\tif (tokens[0] !== \"claude\" || !CLAUDE_FAMILIES.has(tokens[1] ?? \"\")) return tokens;\n\tconst versionEnd = tokens.findIndex((token, index) => index > 1 && !/^\\d+$/u.test(token));\n\tconst end = versionEnd < 0 ? tokens.length : versionEnd;\n\tif (end === 2) return tokens;\n\treturn [\"claude\", ...tokens.slice(2, end), tokens[1]!, ...tokens.slice(end)];\n}\n\n/** Provider-independent model tokens: `us.anthropic.claude-opus-4-6-v1` and `anthropic/claude-opus-4.6` agree. */\nexport function modelEvidenceTokens(id: string): string[] {\n\tconst normalized = id.trim().toLowerCase();\n\tconst model = normalized\n\t\t.slice(normalized.lastIndexOf(\"/\") + 1)\n\t\t.replace(/^~/u, \"\")\n\t\t.replace(VENDOR_OR_REGION_PREFIX, \"\")\n\t\t.replace(/(?<=[a-z])-\\d+:\\d+$/u, \"\")\n\t\t.replace(/:[a-z0-9]+$/u, \"\")\n\t\t.replace(/-v\\d+$/u, \"\")\n\t\t.replace(/-\\d{8}$/u, \"\");\n\tconst tokens = model\n\t\t.split(/[-._]/u)\n\t\t.filter(Boolean)\n\t\t.map((token) => (token === \"thinking\" ? \"reasoning\" : token));\n\treturn canonicalClaudeOrder(tokens);\n}\n\n/** True when `slug` is the candidate model or one of its effort, edition or snapshot variants. */\nfunction slugMatchesCandidate(slug: readonly string[], candidate: readonly string[]): boolean {\n\tif (slug.length < candidate.length || candidate.some((token, index) => slug[index] !== token)) return false;\n\treturn slug\n\t\t.slice(candidate.length)\n\t\t.every((token) => VARIANT_TOKENS.has(token) || ROW_EDITION_TOKENS.has(token) || SNAPSHOT_TOKEN.test(token));\n}\n\n/**\n * The candidate's own tokens first, then the same model without trailing\n * deployment, reasoning-mode or snapshot suffixes (`gpt-5.4-fast`,\n * `grok-4.20-reasoning`, `qwen3.8-max-0902`). A fallback applies only when the\n * more specific form matched no row, so a model that is itself named `-fast`\n * keeps its own evidence.\n */\nfunction candidateForms(tokens: readonly string[]): string[][] {\n\tconst forms = [[...tokens]];\n\tlet current = [...tokens];\n\twhile (current.length > 1) {\n\t\tconst last = current[current.length - 1]!;\n\t\tif (!DEPLOYMENT_TOKENS.has(last) && !VARIANT_TOKENS.has(last) && !SNAPSHOT_TOKEN.test(last)) break;\n\t\tcurrent = current.slice(0, -1);\n\t\tforms.push(current);\n\t}\n\treturn forms;\n}\n\ninterface CatalogRow {\n\treadonly line: string;\n\treadonly section: number;\n\treadonly order: number;\n\treadonly tokens: readonly string[];\n\treadonly releaseDate?: string;\n}\n\n/** One `## ` section of `evals.md` that holds a model table keyed by `slug`. */\ninterface CatalogSection {\n\t/** The section heading, its notes and key, the table header and separator. */\n\treadonly intro: readonly string[];\n}\n\n/** `evals.md` parsed once so batch packing can query evidence per candidate cheaply. */\nexport interface EvalsCatalog {\n\t/** Text before the first table section: title, access date and the shared key. */\n\treadonly preamble: readonly string[];\n\treadonly sections: readonly CatalogSection[];\n\treadonly rows: readonly CatalogRow[];\n\t/** The unparsed document when it has no model table. */\n\treadonly raw?: string;\n\treadonly matches: Map<string, readonly CatalogRow[]>;\n}\n\nconst TABLE_HEADER = /^\\|\\s*slug\\s*\\|/u;\n\nexport function parseEvalsCatalog(evals: string): EvalsCatalog {\n\tconst lines = evals.split(\"\\n\");\n\tconst headers = lines.flatMap((line, index) => (TABLE_HEADER.test(line) ? [index] : []));\n\tif (headers.length === 0) return { preamble: [], sections: [], rows: [], raw: evals, matches: new Map() };\n\tconst sections: CatalogSection[] = [];\n\tconst rows: CatalogRow[] = [];\n\tlet preambleEnd = 0;\n\tlet previousTableEnd = 0;\n\tfor (const [section, headerIndex] of headers.entries()) {\n\t\tlet start = headerIndex;\n\t\tfor (let index = headerIndex - 1; index >= previousTableEnd; index--)\n\t\t\tif (lines[index]!.startsWith(\"## \")) {\n\t\t\t\tstart = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif (section === 0) preambleEnd = start;\n\t\tsections.push({ intro: lines.slice(start, headerIndex + 2) });\n\t\tconst header = lines[headerIndex]!.split(\"|\").map((cell) => cell.trim());\n\t\tconst releaseColumn = header.indexOf(\"Release date\");\n\t\tlet index = headerIndex + 2;\n\t\tfor (; index < lines.length && lines[index]!.startsWith(\"|\"); index++) {\n\t\t\tconst cells = lines[index]!.split(\"|\").map((cell) => cell.trim());\n\t\t\tif (!cells[1]) continue;\n\t\t\tconst release = releaseColumn > 0 ? cells[releaseColumn] : undefined;\n\t\t\trows.push({\n\t\t\t\tline: lines[index]!,\n\t\t\t\tsection,\n\t\t\t\torder: rows.length,\n\t\t\t\ttokens: modelEvidenceTokens(cells[1]),\n\t\t\t\t...(release && /^\\d{4}-\\d{2}-\\d{2}$/u.test(release) ? { releaseDate: release } : {}),\n\t\t\t});\n\t\t}\n\t\tpreviousTableEnd = index;\n\t}\n\treturn { preamble: lines.slice(0, preambleEnd), sections, rows, matches: new Map() };\n}\n\n/**\n * Rows describing `candidate`: in each section, its own model and variants, or\n * its base model when that section has none. Sections resolve independently, so\n * an exact snapshot row in one table does not hide the base model's rows in another.\n */\nexport function candidateEvidenceRows(catalog: EvalsCatalog, candidate: string): readonly CatalogRow[] {\n\tconst cached = catalog.matches.get(candidate);\n\tif (cached) return cached;\n\tconst forms = candidateForms(modelEvidenceTokens(candidate));\n\tconst matches = catalog.sections.flatMap((_, section) => {\n\t\tconst sectionRows = catalog.rows.filter((row) => row.section === section);\n\t\tfor (const form of forms) {\n\t\t\tconst found = sectionRows.filter((row) => slugMatchesCandidate(row.tokens, form));\n\t\t\tif (found.length > 0) return found;\n\t\t}\n\t\treturn [];\n\t});\n\tcatalog.matches.set(candidate, matches);\n\treturn matches;\n}\n\n/** Latest release date among the candidate's evidence rows, when any row has one. */\nexport function candidateReleaseDate(catalog: EvalsCatalog, candidate: string): string | undefined {\n\tconst dates = candidateEvidenceRows(catalog, candidate).flatMap((row) => (row.releaseDate ? [row.releaseDate] : []));\n\treturn dates.length ? dates.sort().at(-1) : undefined;\n}\n\n/**\n * The catalog preamble plus, for every section with rows for `candidates`, that\n * section's heading, key and table header followed by only those rows.\n * Sections without a matching row are left out. `maxBytes` bounds the\n * JSON-encoded result; batched routing omits it because its request budget\n * already decides how many candidates, and so how many rows, one batch holds.\n */\nexport function catalogEvidence(\n\tcatalog: EvalsCatalog,\n\tcandidates: readonly string[],\n\tmaxBytes = Number.POSITIVE_INFINITY,\n): string {\n\tif (catalog.raw !== undefined) return truncateToBytes(catalog.raw, maxBytes);\n\tconst selected = new Set<number>();\n\tfor (const candidate of new Set(candidates))\n\t\tfor (const row of candidateEvidenceRows(catalog, candidate)) selected.add(row.order);\n\tconst kept = catalog.rows.filter((row) => selected.has(row.order));\n\tconst parts = [...catalog.preamble];\n\tfor (const [index, section] of catalog.sections.entries()) {\n\t\tconst sectionRows = kept.filter((row) => row.section === index);\n\t\tif (index > 0 && sectionRows.length === 0) continue;\n\t\tif (index > 0 && parts.at(-1) !== \"\") parts.push(\"\");\n\t\tparts.push(...section.intro, ...sectionRows.map((row) => row.line));\n\t}\n\tconst filtered = parts.join(\"\\n\");\n\treturn jsonBytes(filtered) <= maxBytes ? filtered : truncateToBytes(filtered, maxBytes);\n}\n\n/**\n * Keep the catalog preamble and only the table rows that describe an eligible\n * candidate model, bounded to the routing evidence budget.\n */\nexport function filterModelSelectionEvals(evals: string, candidates: readonly string[]): string {\n\treturn catalogEvidence(parseEvalsCatalog(evals), candidates, MODEL_SELECTION_EVALS_JSON_BYTES);\n}\n"]}
@@ -0,0 +1,75 @@
1
+ import { Type } from "typebox";
2
+ /** Kinds of work a routed task can be, each described for the router in plain words. */
3
+ export declare const WORK_KINDS: {
4
+ readonly computer_use: "Operating desktop or mobile apps through screenshots, clicks and typing";
5
+ readonly coding: "Writing, changing or debugging code in a repository";
6
+ readonly code_review: "Reviewing code or systems for defects or security problems";
7
+ readonly codebase_lookup: "Finding files, definitions or facts in a codebase without changing anything";
8
+ readonly research: "Reading documents or the web and summarizing findings";
9
+ readonly business_workflow: "Multi-step work across business tools or APIs";
10
+ readonly math_science: "Math, physics or scientific computation";
11
+ readonly writing: "Writing or editing prose, documents or slides";
12
+ };
13
+ export declare const DIFFICULTY_LEVELS: {
14
+ readonly trivial: "One obvious step";
15
+ readonly easy: "A few simple steps";
16
+ readonly moderate: "Several steps with some judgment";
17
+ readonly hard: "Many dependent steps, debugging or verification";
18
+ readonly very_hard: "Long work across many tools with frequent recovery";
19
+ };
20
+ export declare const MISTAKE_COST_LEVELS: {
21
+ readonly negligible: "Easily noticed and redone";
22
+ readonly low: "Minor rework";
23
+ readonly moderate: "Wasted time or a confusing result";
24
+ readonly high: "Broken builds, bad data or wrong conclusions";
25
+ readonly severe: "Security, money, data loss or production impact";
26
+ };
27
+ export type WorkKind = keyof typeof WORK_KINDS;
28
+ export type Difficulty = keyof typeof DIFFICULTY_LEVELS;
29
+ export type MistakeCost = keyof typeof MISTAKE_COST_LEVELS;
30
+ /** What a caller may state about a task so routing need not infer it. Every field is optional. */
31
+ export interface TaskNeeds {
32
+ readonly work?: WorkKind;
33
+ readonly difficulty?: Difficulty;
34
+ readonly mistakeCost?: MistakeCost;
35
+ readonly needsImages?: boolean;
36
+ readonly longContext?: boolean;
37
+ readonly latencySensitive?: boolean;
38
+ }
39
+ export type ResolvedTaskNeeds = Required<TaskNeeds>;
40
+ /** Tool and stage schema for caller-stated task needs. */
41
+ export declare const TaskNeedsSchema: Type.TObject<{
42
+ work: Type.TOptional<Type.TUnsafe<"business_workflow" | "code_review" | "codebase_lookup" | "coding" | "computer_use" | "math_science" | "research" | "writing">>;
43
+ difficulty: Type.TOptional<Type.TUnsafe<"easy" | "hard" | "moderate" | "trivial" | "very_hard">>;
44
+ mistakeCost: Type.TOptional<Type.TUnsafe<"high" | "low" | "moderate" | "negligible" | "severe">>;
45
+ needsImages: Type.TOptional<Type.TBoolean>;
46
+ longContext: Type.TOptional<Type.TBoolean>;
47
+ latencySensitive: Type.TOptional<Type.TBoolean>;
48
+ }>;
49
+ /** Validate caller-stated needs. Unknown keys and values fail rather than being guessed. */
50
+ export declare function parseTaskNeeds(value: unknown): TaskNeeds | undefined;
51
+ /** Later stated needs win field by field (for example a call over an agent default). */
52
+ export declare function mergeTaskNeeds(...needs: readonly (TaskNeeds | undefined)[]): TaskNeeds | undefined;
53
+ export interface NeedsQuestion {
54
+ readonly id: "work" | "difficulty" | "mistake_cost" | "needs_images" | "long_context" | "latency_sensitive";
55
+ readonly instructions: string;
56
+ readonly criteria: Record<string, string>;
57
+ }
58
+ /** Questions for only the needs the caller did not state, in a fixed order. */
59
+ export declare function missingNeedsQuestions(stated: TaskNeeds | undefined): NeedsQuestion[];
60
+ /**
61
+ * Combine stated needs with the router's answers keyed by question id. Computer
62
+ * use always works from screenshots, so it needs image input unless the caller
63
+ * explicitly said otherwise.
64
+ */
65
+ export declare function resolveTaskNeeds(stated: TaskNeeds | undefined, answers: Record<string, string>): ResolvedTaskNeeds;
66
+ /** 0 for the easiest or cheapest-to-get-wrong task, 1 for the hardest or costliest. */
67
+ export declare function taskDemand(needs: ResolvedTaskNeeds): number;
68
+ /**
69
+ * Effort for a model from the task's difficulty, one level lower (never below
70
+ * `minimal`) when speed matters: the supported level closest to the target,
71
+ * preferring the lower one on a tie. `null` for models without
72
+ * configurable reasoning.
73
+ */
74
+ export declare function effortForDifficulty(efforts: readonly (string | null)[], difficulty: Difficulty, latencySensitive?: boolean): string | null;
75
+ //# sourceMappingURL=model-routing-needs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-routing-needs.d.ts","sourceRoot":"","sources":["../../src/core/model-routing-needs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,wFAAwF;AACxF,eAAO,MAAM,UAAU;aACtB,YAAY,EAAE,yEAAyE;aACvF,MAAM,EAAE,qDAAqD;aAC7D,WAAW,EAAE,4DAA4D;aACzE,eAAe,EAAE,6EAA6E;aAC9F,QAAQ,EAAE,uDAAuD;aACjE,iBAAiB,EAAE,+CAA+C;aAClE,YAAY,EAAE,yCAAyC;aACvD,OAAO,EAAE,+CAA+C;CAC/C,CAAC;AAEX,eAAO,MAAM,iBAAiB;aAC7B,OAAO,EAAE,kBAAkB;aAC3B,IAAI,EAAE,oBAAoB;aAC1B,QAAQ,EAAE,kCAAkC;aAC5C,IAAI,EAAE,iDAAiD;aACvD,SAAS,EAAE,oDAAoD;CACtD,CAAC;AAEX,eAAO,MAAM,mBAAmB;aAC/B,UAAU,EAAE,2BAA2B;aACvC,GAAG,EAAE,cAAc;aACnB,QAAQ,EAAE,mCAAmC;aAC7C,IAAI,EAAE,8CAA8C;aACpD,MAAM,EAAE,iDAAiD;CAChD,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,UAAU,CAAC;AAC/C,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,iBAAiB,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAE3D,kGAAkG;AAClG,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAKpD,0DAA0D;AAC1D,eAAO,MAAM,eAAe;;;;;;;EAoB3B,CAAC;AAcF,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAyBpE;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,GAAG,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,EAAE,GAAG,SAAS,GAAG,SAAS,CAGlG;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,GAAG,cAAc,GAAG,mBAAmB,CAAC;IAC5G,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,EAAE,CAgDpF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,iBAAiB,CAYlH;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAI3D;AAWD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EACnC,UAAU,EAAE,UAAU,EACtB,gBAAgB,UAAQ,GACtB,MAAM,GAAG,IAAI,CASf"}
@@ -0,0 +1,176 @@
1
+ import { Type } from "typebox";
2
+ /** Kinds of work a routed task can be, each described for the router in plain words. */
3
+ export const WORK_KINDS = {
4
+ computer_use: "Operating desktop or mobile apps through screenshots, clicks and typing",
5
+ coding: "Writing, changing or debugging code in a repository",
6
+ code_review: "Reviewing code or systems for defects or security problems",
7
+ codebase_lookup: "Finding files, definitions or facts in a codebase without changing anything",
8
+ research: "Reading documents or the web and summarizing findings",
9
+ business_workflow: "Multi-step work across business tools or APIs",
10
+ math_science: "Math, physics or scientific computation",
11
+ writing: "Writing or editing prose, documents or slides",
12
+ };
13
+ export const DIFFICULTY_LEVELS = {
14
+ trivial: "One obvious step",
15
+ easy: "A few simple steps",
16
+ moderate: "Several steps with some judgment",
17
+ hard: "Many dependent steps, debugging or verification",
18
+ very_hard: "Long work across many tools with frequent recovery",
19
+ };
20
+ export const MISTAKE_COST_LEVELS = {
21
+ negligible: "Easily noticed and redone",
22
+ low: "Minor rework",
23
+ moderate: "Wasted time or a confusing result",
24
+ high: "Broken builds, bad data or wrong conclusions",
25
+ severe: "Security, money, data loss or production impact",
26
+ };
27
+ const enumOf = (values, description) => Type.Unsafe(Type.String({ enum: Object.keys(values), description }));
28
+ /** Tool and stage schema for caller-stated task needs. */
29
+ export const TaskNeedsSchema = Type.Object({
30
+ work: Type.Optional(enumOf(WORK_KINDS, `Main kind of work: ${Object.keys(WORK_KINDS).join(", ")}.`)),
31
+ difficulty: Type.Optional(enumOf(DIFFICULTY_LEVELS, "How hard the task is for a capable agent.")),
32
+ mistakeCost: Type.Optional(enumOf(MISTAKE_COST_LEVELS, "How bad a wrong result would be.")),
33
+ needsImages: Type.Optional(Type.Boolean({ description: "Whether the agent must read screenshots or images." })),
34
+ longContext: Type.Optional(Type.Boolean({ description: "Whether the agent must hold a very large codebase or document set in context." })),
35
+ latencySensitive: Type.Optional(Type.Boolean({
36
+ description: "Whether a fast answer matters more than extra reasoning, for example quick lookups.",
37
+ })),
38
+ }, {
39
+ additionalProperties: false,
40
+ description: "For model 'auto': what you know about the task. Fill in every field you can judge; routing uses these answers instead of reading the task, and a language model reads the task only for omitted fields.",
41
+ });
42
+ const WORK_KEYS = Object.keys(WORK_KINDS);
43
+ const DIFFICULTY_KEYS = Object.keys(DIFFICULTY_LEVELS);
44
+ const MISTAKE_COST_KEYS = Object.keys(MISTAKE_COST_LEVELS);
45
+ const CHOICE_FIELDS = ["work", "difficulty", "mistakeCost"];
46
+ const BOOLEAN_FIELDS = ["needsImages", "longContext", "latencySensitive"];
47
+ const oneOf = (keys, value, field) => {
48
+ if (typeof value === "string" && keys.includes(value))
49
+ return value;
50
+ throw new Error(`Invalid taskNeeds.${field}: expected one of ${keys.join(", ")}.`);
51
+ };
52
+ /** Validate caller-stated needs. Unknown keys and values fail rather than being guessed. */
53
+ export function parseTaskNeeds(value) {
54
+ if (value === undefined)
55
+ return undefined;
56
+ if (value === null || typeof value !== "object" || Array.isArray(value))
57
+ throw new Error("Invalid taskNeeds: expected an object with work, difficulty, mistakeCost, needsImages, longContext or latencySensitive.");
58
+ const record = value;
59
+ for (const key of Object.keys(record))
60
+ if (![...CHOICE_FIELDS, ...BOOLEAN_FIELDS].includes(key))
61
+ throw new Error(`Invalid taskNeeds: unknown field ${key}.`);
62
+ for (const field of BOOLEAN_FIELDS)
63
+ if (record[field] !== undefined && typeof record[field] !== "boolean")
64
+ throw new Error(`Invalid taskNeeds.${field}: expected true or false.`);
65
+ return {
66
+ ...(record.work !== undefined ? { work: oneOf(WORK_KEYS, record.work, "work") } : {}),
67
+ ...(record.difficulty !== undefined
68
+ ? { difficulty: oneOf(DIFFICULTY_KEYS, record.difficulty, "difficulty") }
69
+ : {}),
70
+ ...(record.mistakeCost !== undefined
71
+ ? { mistakeCost: oneOf(MISTAKE_COST_KEYS, record.mistakeCost, "mistakeCost") }
72
+ : {}),
73
+ ...Object.fromEntries(BOOLEAN_FIELDS.flatMap((field) => (record[field] === undefined ? [] : [[field, record[field]]]))),
74
+ };
75
+ }
76
+ /** Later stated needs win field by field (for example a call over an agent default). */
77
+ export function mergeTaskNeeds(...needs) {
78
+ const merged = Object.assign({}, ...needs.filter((entry) => entry !== undefined));
79
+ return Object.keys(merged).length ? merged : undefined;
80
+ }
81
+ /** Questions for only the needs the caller did not state, in a fixed order. */
82
+ export function missingNeedsQuestions(stated) {
83
+ const questions = [];
84
+ if (!stated?.work)
85
+ questions.push({
86
+ id: "work",
87
+ instructions: "What kind of work is this task mainly?",
88
+ criteria: { ...WORK_KINDS },
89
+ });
90
+ if (!stated?.difficulty)
91
+ questions.push({
92
+ id: "difficulty",
93
+ instructions: "How hard is this task for a capable AI agent to complete correctly?",
94
+ criteria: { ...DIFFICULTY_LEVELS },
95
+ });
96
+ if (!stated?.mistakeCost)
97
+ questions.push({
98
+ id: "mistake_cost",
99
+ instructions: "How bad is it if the agent gets this task wrong?",
100
+ criteria: { ...MISTAKE_COST_LEVELS },
101
+ });
102
+ if (stated?.needsImages === undefined)
103
+ questions.push({
104
+ id: "needs_images",
105
+ instructions: "Does doing this task require the agent to look at screenshots or images?",
106
+ criteria: {
107
+ yes: "The agent must read screenshots, images or a GUI",
108
+ no: "Text and tool output are enough",
109
+ },
110
+ });
111
+ if (stated?.longContext === undefined)
112
+ questions.push({
113
+ id: "long_context",
114
+ instructions: "Must the agent hold a very large codebase, log or document set in context at once?",
115
+ criteria: {
116
+ yes: "Hundreds of thousands of tokens of material at once",
117
+ no: "Ordinary amounts, read piece by piece",
118
+ },
119
+ });
120
+ if (stated?.latencySensitive === undefined)
121
+ questions.push({
122
+ id: "latency_sensitive",
123
+ instructions: "Does a fast answer matter more than extra reasoning?",
124
+ criteria: {
125
+ yes: "Speed matters: a quick lookup, an interactive step or many small calls",
126
+ no: "Quality matters more than speed",
127
+ },
128
+ });
129
+ return questions;
130
+ }
131
+ /**
132
+ * Combine stated needs with the router's answers keyed by question id. Computer
133
+ * use always works from screenshots, so it needs image input unless the caller
134
+ * explicitly said otherwise.
135
+ */
136
+ export function resolveTaskNeeds(stated, answers) {
137
+ const work = stated?.work ?? oneOf(WORK_KEYS, answers.work, "work");
138
+ const yes = (answer, field) => answer !== undefined && oneOf(["yes", "no"], answer, field) === "yes";
139
+ return {
140
+ work,
141
+ difficulty: stated?.difficulty ?? oneOf(DIFFICULTY_KEYS, answers.difficulty, "difficulty"),
142
+ mistakeCost: stated?.mistakeCost ?? oneOf(MISTAKE_COST_KEYS, answers.mistake_cost, "mistakeCost"),
143
+ needsImages: stated?.needsImages ?? (work === "computer_use" || yes(answers.needs_images, "needsImages")),
144
+ longContext: stated?.longContext ?? yes(answers.long_context, "longContext"),
145
+ latencySensitive: stated?.latencySensitive ?? yes(answers.latency_sensitive, "latencySensitive"),
146
+ };
147
+ }
148
+ /** 0 for the easiest or cheapest-to-get-wrong task, 1 for the hardest or costliest. */
149
+ export function taskDemand(needs) {
150
+ const difficulty = DIFFICULTY_KEYS.indexOf(needs.difficulty) / (DIFFICULTY_KEYS.length - 1);
151
+ const mistake = MISTAKE_COST_KEYS.indexOf(needs.mistakeCost) / (MISTAKE_COST_KEYS.length - 1);
152
+ return Math.max(difficulty, mistake);
153
+ }
154
+ const EFFORT_ORDER = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
155
+ const EFFORT_FOR_DIFFICULTY = {
156
+ trivial: "minimal",
157
+ easy: "low",
158
+ moderate: "medium",
159
+ hard: "high",
160
+ very_hard: "xhigh",
161
+ };
162
+ /**
163
+ * Effort for a model from the task's difficulty, one level lower (never below
164
+ * `minimal`) when speed matters: the supported level closest to the target,
165
+ * preferring the lower one on a tie. `null` for models without
166
+ * configurable reasoning.
167
+ */
168
+ export function effortForDifficulty(efforts, difficulty, latencySensitive = false) {
169
+ const supported = efforts.filter((effort) => effort !== null && EFFORT_ORDER.includes(effort));
170
+ if (supported.length === 0)
171
+ return efforts.includes(null) ? null : (efforts[0] ?? null);
172
+ const target = Math.max(1, EFFORT_ORDER.indexOf(EFFORT_FOR_DIFFICULTY[difficulty]) - (latencySensitive ? 1 : 0));
173
+ return [...supported].sort((a, b) => Math.abs(EFFORT_ORDER.indexOf(a) - target) - Math.abs(EFFORT_ORDER.indexOf(b) - target) ||
174
+ EFFORT_ORDER.indexOf(a) - EFFORT_ORDER.indexOf(b))[0];
175
+ }
176
+ //# sourceMappingURL=model-routing-needs.js.map