agent-nuvira 3.3.13 → 3.3.14

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 (387) hide show
  1. package/README.md +67 -1
  2. package/dist/agents/agents/planner.d.ts.map +1 -1
  3. package/dist/agents/agents/planner.js +9 -0
  4. package/dist/agents/agents/planner.js.map +1 -1
  5. package/dist/agents/orchestrator.d.ts +31 -0
  6. package/dist/agents/orchestrator.d.ts.map +1 -1
  7. package/dist/agents/orchestrator.js +74 -126
  8. package/dist/agents/orchestrator.js.map +1 -1
  9. package/dist/cli/chat.d.ts +89 -0
  10. package/dist/cli/chat.d.ts.map +1 -1
  11. package/dist/cli/chat.js +765 -33
  12. package/dist/cli/chat.js.map +1 -1
  13. package/dist/cli/cli-program.d.ts.map +1 -1
  14. package/dist/cli/cli-program.js +12 -0
  15. package/dist/cli/cli-program.js.map +1 -1
  16. package/dist/cli/config.d.ts +12 -0
  17. package/dist/cli/config.d.ts.map +1 -1
  18. package/dist/cli/config.js +86 -0
  19. package/dist/cli/config.js.map +1 -1
  20. package/dist/cli/decisions.d.ts +28 -0
  21. package/dist/cli/decisions.d.ts.map +1 -0
  22. package/dist/cli/decisions.js +140 -0
  23. package/dist/cli/decisions.js.map +1 -0
  24. package/dist/cli/doctor.d.ts +6 -0
  25. package/dist/cli/doctor.d.ts.map +1 -1
  26. package/dist/cli/doctor.js +46 -0
  27. package/dist/cli/doctor.js.map +1 -1
  28. package/dist/cli/failover-runner.d.ts.map +1 -1
  29. package/dist/cli/failover-runner.js +19 -1
  30. package/dist/cli/failover-runner.js.map +1 -1
  31. package/dist/cli/feedback.d.ts.map +1 -1
  32. package/dist/cli/feedback.js +5 -1
  33. package/dist/cli/feedback.js.map +1 -1
  34. package/dist/cli/hooks.d.ts +30 -0
  35. package/dist/cli/hooks.d.ts.map +1 -0
  36. package/dist/cli/hooks.js +224 -0
  37. package/dist/cli/hooks.js.map +1 -0
  38. package/dist/cli/knowledge.d.ts +9 -1
  39. package/dist/cli/knowledge.d.ts.map +1 -1
  40. package/dist/cli/knowledge.js +93 -2
  41. package/dist/cli/knowledge.js.map +1 -1
  42. package/dist/cli/loop-executor.d.ts.map +1 -1
  43. package/dist/cli/loop-executor.js +47 -12
  44. package/dist/cli/loop-executor.js.map +1 -1
  45. package/dist/cli/model.d.ts +20 -0
  46. package/dist/cli/model.d.ts.map +1 -1
  47. package/dist/cli/model.js +294 -14
  48. package/dist/cli/model.js.map +1 -1
  49. package/dist/cli/rate.d.ts +78 -0
  50. package/dist/cli/rate.d.ts.map +1 -0
  51. package/dist/cli/rate.js +294 -0
  52. package/dist/cli/rate.js.map +1 -0
  53. package/dist/config/process-env.d.ts.map +1 -1
  54. package/dist/config/process-env.js +10 -0
  55. package/dist/config/process-env.js.map +1 -1
  56. package/dist/enterprise/vault.d.ts.map +1 -1
  57. package/dist/enterprise/vault.js +5 -21
  58. package/dist/enterprise/vault.js.map +1 -1
  59. package/dist/gateway/hook-contract.d.ts +33 -0
  60. package/dist/gateway/hook-contract.d.ts.map +1 -1
  61. package/dist/gateway/hook-contract.js +97 -0
  62. package/dist/gateway/hook-contract.js.map +1 -1
  63. package/dist/inference/gemini-adapter.d.ts.map +1 -1
  64. package/dist/inference/gemini-adapter.js +4 -0
  65. package/dist/inference/gemini-adapter.js.map +1 -1
  66. package/dist/inference/interface.d.ts +37 -0
  67. package/dist/inference/interface.d.ts.map +1 -1
  68. package/dist/inference/native-tools.d.ts +16 -1
  69. package/dist/inference/native-tools.d.ts.map +1 -1
  70. package/dist/inference/native-tools.js +34 -10
  71. package/dist/inference/native-tools.js.map +1 -1
  72. package/dist/inference/route-resolver.d.ts +30 -0
  73. package/dist/inference/route-resolver.d.ts.map +1 -1
  74. package/dist/inference/route-resolver.js +158 -1
  75. package/dist/inference/route-resolver.js.map +1 -1
  76. package/dist/inference/tools.d.ts +16 -1
  77. package/dist/inference/tools.d.ts.map +1 -1
  78. package/dist/inference/tools.js +51 -18
  79. package/dist/inference/tools.js.map +1 -1
  80. package/dist/learning/acceptance-model.d.ts +247 -0
  81. package/dist/learning/acceptance-model.d.ts.map +1 -0
  82. package/dist/learning/acceptance-model.js +708 -0
  83. package/dist/learning/acceptance-model.js.map +1 -0
  84. package/dist/learning/auto-router.d.ts +68 -24
  85. package/dist/learning/auto-router.d.ts.map +1 -1
  86. package/dist/learning/auto-router.js +301 -96
  87. package/dist/learning/auto-router.js.map +1 -1
  88. package/dist/learning/autonomy-policy.d.ts +12 -16
  89. package/dist/learning/autonomy-policy.d.ts.map +1 -1
  90. package/dist/learning/autonomy-policy.js +50 -48
  91. package/dist/learning/autonomy-policy.js.map +1 -1
  92. package/dist/learning/behavioural-labels.d.ts +86 -0
  93. package/dist/learning/behavioural-labels.d.ts.map +1 -0
  94. package/dist/learning/behavioural-labels.js +166 -0
  95. package/dist/learning/behavioural-labels.js.map +1 -0
  96. package/dist/learning/capability-evidence.d.ts +167 -0
  97. package/dist/learning/capability-evidence.d.ts.map +1 -0
  98. package/dist/learning/capability-evidence.js +210 -0
  99. package/dist/learning/capability-evidence.js.map +1 -0
  100. package/dist/learning/capability-readiness.d.ts +64 -0
  101. package/dist/learning/capability-readiness.d.ts.map +1 -0
  102. package/dist/learning/capability-readiness.js +74 -0
  103. package/dist/learning/capability-readiness.js.map +1 -0
  104. package/dist/learning/capability-types.d.ts +169 -0
  105. package/dist/learning/capability-types.d.ts.map +1 -0
  106. package/dist/learning/capability-types.js +20 -0
  107. package/dist/learning/capability-types.js.map +1 -0
  108. package/dist/learning/catalog-feed.d.ts +89 -0
  109. package/dist/learning/catalog-feed.d.ts.map +1 -0
  110. package/dist/learning/catalog-feed.js +211 -0
  111. package/dist/learning/catalog-feed.js.map +1 -0
  112. package/dist/learning/cli-intent-effects.d.ts +60 -0
  113. package/dist/learning/cli-intent-effects.d.ts.map +1 -0
  114. package/dist/learning/cli-intent-effects.js +153 -0
  115. package/dist/learning/cli-intent-effects.js.map +1 -0
  116. package/dist/learning/command-adaptation.d.ts +41 -0
  117. package/dist/learning/command-adaptation.d.ts.map +1 -0
  118. package/dist/learning/command-adaptation.js +122 -0
  119. package/dist/learning/command-adaptation.js.map +1 -0
  120. package/dist/learning/consent-picture.d.ts +42 -0
  121. package/dist/learning/consent-picture.d.ts.map +1 -0
  122. package/dist/learning/consent-picture.js +53 -0
  123. package/dist/learning/consent-picture.js.map +1 -0
  124. package/dist/learning/context-budget.d.ts +37 -6
  125. package/dist/learning/context-budget.d.ts.map +1 -1
  126. package/dist/learning/context-budget.js +38 -9
  127. package/dist/learning/context-budget.js.map +1 -1
  128. package/dist/learning/decision-log.d.ts +114 -0
  129. package/dist/learning/decision-log.d.ts.map +1 -0
  130. package/dist/learning/decision-log.js +296 -0
  131. package/dist/learning/decision-log.js.map +1 -0
  132. package/dist/learning/deliverable-class.d.ts.map +1 -1
  133. package/dist/learning/deliverable-class.js +19 -0
  134. package/dist/learning/deliverable-class.js.map +1 -1
  135. package/dist/learning/deliverable-corpus.d.ts +117 -0
  136. package/dist/learning/deliverable-corpus.d.ts.map +1 -0
  137. package/dist/learning/deliverable-corpus.js +176 -0
  138. package/dist/learning/deliverable-corpus.js.map +1 -0
  139. package/dist/learning/error-repair.d.ts +22 -1
  140. package/dist/learning/error-repair.d.ts.map +1 -1
  141. package/dist/learning/error-repair.js +37 -0
  142. package/dist/learning/error-repair.js.map +1 -1
  143. package/dist/learning/exhaustion-report.d.ts +136 -0
  144. package/dist/learning/exhaustion-report.d.ts.map +1 -0
  145. package/dist/learning/exhaustion-report.js +239 -0
  146. package/dist/learning/exhaustion-report.js.map +1 -0
  147. package/dist/learning/failure-bookkeeping.d.ts +16 -0
  148. package/dist/learning/failure-bookkeeping.d.ts.map +1 -1
  149. package/dist/learning/failure-bookkeeping.js +51 -5
  150. package/dist/learning/failure-bookkeeping.js.map +1 -1
  151. package/dist/learning/gate-friction.d.ts +39 -0
  152. package/dist/learning/gate-friction.d.ts.map +1 -0
  153. package/dist/learning/gate-friction.js +91 -0
  154. package/dist/learning/gate-friction.js.map +1 -0
  155. package/dist/learning/harness-narration.d.ts +34 -0
  156. package/dist/learning/harness-narration.d.ts.map +1 -0
  157. package/dist/learning/harness-narration.js +58 -0
  158. package/dist/learning/harness-narration.js.map +1 -0
  159. package/dist/learning/hub-skill-catalog.d.ts.map +1 -1
  160. package/dist/learning/hub-skill-catalog.js +1 -2
  161. package/dist/learning/hub-skill-catalog.js.map +1 -1
  162. package/dist/learning/hybrid-router.d.ts +65 -0
  163. package/dist/learning/hybrid-router.d.ts.map +1 -1
  164. package/dist/learning/hybrid-router.js +186 -0
  165. package/dist/learning/hybrid-router.js.map +1 -1
  166. package/dist/learning/knowledge-base.d.ts +229 -3
  167. package/dist/learning/knowledge-base.d.ts.map +1 -1
  168. package/dist/learning/knowledge-base.js +593 -24
  169. package/dist/learning/knowledge-base.js.map +1 -1
  170. package/dist/learning/knowledge-eval.d.ts +171 -0
  171. package/dist/learning/knowledge-eval.d.ts.map +1 -0
  172. package/dist/learning/knowledge-eval.js +196 -0
  173. package/dist/learning/knowledge-eval.js.map +1 -0
  174. package/dist/learning/knowledge-turn.d.ts +92 -0
  175. package/dist/learning/knowledge-turn.d.ts.map +1 -0
  176. package/dist/learning/knowledge-turn.js +190 -0
  177. package/dist/learning/knowledge-turn.js.map +1 -0
  178. package/dist/learning/learned-commands.d.ts +64 -0
  179. package/dist/learning/learned-commands.d.ts.map +1 -0
  180. package/dist/learning/learned-commands.js +108 -0
  181. package/dist/learning/learned-commands.js.map +1 -0
  182. package/dist/learning/lexical-search.d.ts +50 -0
  183. package/dist/learning/lexical-search.d.ts.map +1 -0
  184. package/dist/learning/lexical-search.js +111 -0
  185. package/dist/learning/lexical-search.js.map +1 -0
  186. package/dist/learning/machine-facts.d.ts +71 -0
  187. package/dist/learning/machine-facts.d.ts.map +1 -0
  188. package/dist/learning/machine-facts.js +164 -0
  189. package/dist/learning/machine-facts.js.map +1 -0
  190. package/dist/learning/markdown-outline.d.ts +73 -0
  191. package/dist/learning/markdown-outline.d.ts.map +1 -0
  192. package/dist/learning/markdown-outline.js +136 -0
  193. package/dist/learning/markdown-outline.js.map +1 -0
  194. package/dist/learning/model-first-router.d.ts +33 -1
  195. package/dist/learning/model-first-router.d.ts.map +1 -1
  196. package/dist/learning/model-first-router.js +123 -9
  197. package/dist/learning/model-first-router.js.map +1 -1
  198. package/dist/learning/model-identity.d.ts +80 -0
  199. package/dist/learning/model-identity.d.ts.map +1 -0
  200. package/dist/learning/model-identity.js +115 -0
  201. package/dist/learning/model-identity.js.map +1 -0
  202. package/dist/learning/model-registry.d.ts +141 -2
  203. package/dist/learning/model-registry.d.ts.map +1 -1
  204. package/dist/learning/model-registry.js +324 -38
  205. package/dist/learning/model-registry.js.map +1 -1
  206. package/dist/learning/model-scoring.d.ts.map +1 -1
  207. package/dist/learning/model-scoring.js +8 -1
  208. package/dist/learning/model-scoring.js.map +1 -1
  209. package/dist/learning/model-selection.d.ts.map +1 -1
  210. package/dist/learning/model-selection.js +41 -0
  211. package/dist/learning/model-selection.js.map +1 -1
  212. package/dist/learning/outcome-observation.d.ts +49 -0
  213. package/dist/learning/outcome-observation.d.ts.map +1 -0
  214. package/dist/learning/outcome-observation.js +95 -0
  215. package/dist/learning/outcome-observation.js.map +1 -0
  216. package/dist/learning/pair-entitlement.d.ts +184 -0
  217. package/dist/learning/pair-entitlement.d.ts.map +1 -0
  218. package/dist/learning/pair-entitlement.js +214 -0
  219. package/dist/learning/pair-entitlement.js.map +1 -0
  220. package/dist/learning/provider-fallback.d.ts +23 -1
  221. package/dist/learning/provider-fallback.d.ts.map +1 -1
  222. package/dist/learning/provider-fallback.js +24 -0
  223. package/dist/learning/provider-fallback.js.map +1 -1
  224. package/dist/learning/reasoning-trace.d.ts +65 -1
  225. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  226. package/dist/learning/reasoning-trace.js +123 -1
  227. package/dist/learning/reasoning-trace.js.map +1 -1
  228. package/dist/learning/requirement-probe.d.ts +55 -0
  229. package/dist/learning/requirement-probe.d.ts.map +1 -0
  230. package/dist/learning/requirement-probe.js +77 -0
  231. package/dist/learning/requirement-probe.js.map +1 -0
  232. package/dist/learning/resilient-call.d.ts +20 -1
  233. package/dist/learning/resilient-call.d.ts.map +1 -1
  234. package/dist/learning/resilient-call.js +42 -4
  235. package/dist/learning/resilient-call.js.map +1 -1
  236. package/dist/learning/response-usability.d.ts +85 -0
  237. package/dist/learning/response-usability.d.ts.map +1 -0
  238. package/dist/learning/response-usability.js +135 -0
  239. package/dist/learning/response-usability.js.map +1 -0
  240. package/dist/learning/router-bandit.d.ts +132 -0
  241. package/dist/learning/router-bandit.d.ts.map +1 -1
  242. package/dist/learning/router-bandit.js +253 -0
  243. package/dist/learning/router-bandit.js.map +1 -1
  244. package/dist/learning/routing-history.d.ts +41 -2
  245. package/dist/learning/routing-history.d.ts.map +1 -1
  246. package/dist/learning/routing-history.js.map +1 -1
  247. package/dist/learning/run-trace.d.ts +21 -0
  248. package/dist/learning/run-trace.d.ts.map +1 -1
  249. package/dist/learning/run-trace.js +38 -0
  250. package/dist/learning/run-trace.js.map +1 -1
  251. package/dist/learning/session-grant.d.ts +75 -0
  252. package/dist/learning/session-grant.d.ts.map +1 -0
  253. package/dist/learning/session-grant.js +112 -0
  254. package/dist/learning/session-grant.js.map +1 -0
  255. package/dist/learning/task-model-continuity.d.ts +73 -0
  256. package/dist/learning/task-model-continuity.d.ts.map +1 -0
  257. package/dist/learning/task-model-continuity.js +87 -0
  258. package/dist/learning/task-model-continuity.js.map +1 -0
  259. package/dist/learning/turn-feedback.d.ts +93 -0
  260. package/dist/learning/turn-feedback.d.ts.map +1 -0
  261. package/dist/learning/turn-feedback.js +127 -0
  262. package/dist/learning/turn-feedback.js.map +1 -0
  263. package/dist/learning/turn-report.d.ts +104 -2
  264. package/dist/learning/turn-report.d.ts.map +1 -1
  265. package/dist/learning/turn-report.js +161 -6
  266. package/dist/learning/turn-report.js.map +1 -1
  267. package/dist/learning/verdict-routing.d.ts +51 -0
  268. package/dist/learning/verdict-routing.d.ts.map +1 -0
  269. package/dist/learning/verdict-routing.js +122 -0
  270. package/dist/learning/verdict-routing.js.map +1 -0
  271. package/dist/mcp/client.d.ts.map +1 -1
  272. package/dist/mcp/client.js +5 -0
  273. package/dist/mcp/client.js.map +1 -1
  274. package/dist/mcp/manager.d.ts +10 -0
  275. package/dist/mcp/manager.d.ts.map +1 -1
  276. package/dist/mcp/manager.js +20 -0
  277. package/dist/mcp/manager.js.map +1 -1
  278. package/dist/mcp/mcp-discovery.d.ts +34 -0
  279. package/dist/mcp/mcp-discovery.d.ts.map +1 -0
  280. package/dist/mcp/mcp-discovery.js +71 -0
  281. package/dist/mcp/mcp-discovery.js.map +1 -0
  282. package/dist/mcp/mcp-schema-cache.d.ts +17 -0
  283. package/dist/mcp/mcp-schema-cache.d.ts.map +1 -1
  284. package/dist/mcp/mcp-schema-cache.js +47 -3
  285. package/dist/mcp/mcp-schema-cache.js.map +1 -1
  286. package/dist/mcp/types.d.ts +28 -0
  287. package/dist/mcp/types.d.ts.map +1 -1
  288. package/dist/mcp/types.js.map +1 -1
  289. package/dist/tools/ask-user.d.ts.map +1 -1
  290. package/dist/tools/ask-user.js +4 -0
  291. package/dist/tools/ask-user.js.map +1 -1
  292. package/dist/tools/capability-registry.d.ts +150 -0
  293. package/dist/tools/capability-registry.d.ts.map +1 -0
  294. package/dist/tools/capability-registry.js +400 -0
  295. package/dist/tools/capability-registry.js.map +1 -0
  296. package/dist/tools/child-agent-runtime.d.ts.map +1 -1
  297. package/dist/tools/child-agent-runtime.js +19 -5
  298. package/dist/tools/child-agent-runtime.js.map +1 -1
  299. package/dist/tools/coding-tools.d.ts +17 -5
  300. package/dist/tools/coding-tools.d.ts.map +1 -1
  301. package/dist/tools/coding-tools.js +80 -11
  302. package/dist/tools/coding-tools.js.map +1 -1
  303. package/dist/tools/command-memo.d.ts +116 -0
  304. package/dist/tools/command-memo.d.ts.map +1 -0
  305. package/dist/tools/command-memo.js +202 -0
  306. package/dist/tools/command-memo.js.map +1 -0
  307. package/dist/tools/git-tool.d.ts.map +1 -1
  308. package/dist/tools/git-tool.js +13 -3
  309. package/dist/tools/git-tool.js.map +1 -1
  310. package/dist/tools/harness-directive.d.ts +42 -0
  311. package/dist/tools/harness-directive.d.ts.map +1 -0
  312. package/dist/tools/harness-directive.js +45 -0
  313. package/dist/tools/harness-directive.js.map +1 -0
  314. package/dist/tools/loop-skill-hint.d.ts +74 -174
  315. package/dist/tools/loop-skill-hint.d.ts.map +1 -1
  316. package/dist/tools/loop-skill-hint.js +110 -536
  317. package/dist/tools/loop-skill-hint.js.map +1 -1
  318. package/dist/tools/mcp-client-tool.d.ts +2 -0
  319. package/dist/tools/mcp-client-tool.d.ts.map +1 -1
  320. package/dist/tools/mcp-client-tool.js +3 -0
  321. package/dist/tools/mcp-client-tool.js.map +1 -1
  322. package/dist/tools/modality/shared.d.ts +1 -4
  323. package/dist/tools/modality/shared.d.ts.map +1 -1
  324. package/dist/tools/modality/shared.js +7 -22
  325. package/dist/tools/modality/shared.js.map +1 -1
  326. package/dist/tools/plan-store.d.ts +20 -2
  327. package/dist/tools/plan-store.d.ts.map +1 -1
  328. package/dist/tools/plan-store.js +51 -7
  329. package/dist/tools/plan-store.js.map +1 -1
  330. package/dist/tools/registry.d.ts +76 -3
  331. package/dist/tools/registry.d.ts.map +1 -1
  332. package/dist/tools/registry.js +486 -26
  333. package/dist/tools/registry.js.map +1 -1
  334. package/dist/tools/remediation-ladder.d.ts.map +1 -1
  335. package/dist/tools/remediation-ladder.js +8 -0
  336. package/dist/tools/remediation-ladder.js.map +1 -1
  337. package/dist/tools/run-cli.d.ts.map +1 -1
  338. package/dist/tools/run-cli.js +29 -4
  339. package/dist/tools/run-cli.js.map +1 -1
  340. package/dist/tools/run-terminal.d.ts +11 -0
  341. package/dist/tools/run-terminal.d.ts.map +1 -1
  342. package/dist/tools/run-terminal.js +265 -10
  343. package/dist/tools/run-terminal.js.map +1 -1
  344. package/dist/tools/tool-loop.d.ts +321 -13
  345. package/dist/tools/tool-loop.d.ts.map +1 -1
  346. package/dist/tools/tool-loop.js +867 -66
  347. package/dist/tools/tool-loop.js.map +1 -1
  348. package/dist/utils/atomic-store.d.ts +53 -0
  349. package/dist/utils/atomic-store.d.ts.map +1 -0
  350. package/dist/utils/atomic-store.js +178 -0
  351. package/dist/utils/atomic-store.js.map +1 -0
  352. package/dist/utils/binary-probe.d.ts +25 -0
  353. package/dist/utils/binary-probe.d.ts.map +1 -0
  354. package/dist/utils/binary-probe.js +48 -0
  355. package/dist/utils/binary-probe.js.map +1 -0
  356. package/dist/utils/workspace-path.d.ts +50 -0
  357. package/dist/utils/workspace-path.d.ts.map +1 -0
  358. package/dist/utils/workspace-path.js +86 -0
  359. package/dist/utils/workspace-path.js.map +1 -0
  360. package/dist/web-dashboard/chat-console.d.ts +24 -0
  361. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  362. package/dist/web-dashboard/chat-console.js +38 -0
  363. package/dist/web-dashboard/chat-console.js.map +1 -1
  364. package/dist/web-dashboard/project-context.d.ts +27 -2
  365. package/dist/web-dashboard/project-context.d.ts.map +1 -1
  366. package/dist/web-dashboard/project-context.js +32 -2
  367. package/dist/web-dashboard/project-context.js.map +1 -1
  368. package/dist/web-dashboard/server.d.ts +11 -0
  369. package/dist/web-dashboard/server.d.ts.map +1 -1
  370. package/dist/web-dashboard/server.js +362 -11
  371. package/dist/web-dashboard/server.js.map +1 -1
  372. package/dist/web-dashboard/src/types.d.ts +170 -1
  373. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  374. package/dist/web-dashboard/workspace-guard.d.ts +11 -2
  375. package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
  376. package/dist/web-dashboard/workspace-guard.js +24 -12
  377. package/dist/web-dashboard/workspace-guard.js.map +1 -1
  378. package/dist/web-dashboard/workspace-resolution.d.ts +87 -0
  379. package/dist/web-dashboard/workspace-resolution.d.ts.map +1 -0
  380. package/dist/web-dashboard/workspace-resolution.js +105 -0
  381. package/dist/web-dashboard/workspace-resolution.js.map +1 -0
  382. package/package.json +1 -1
  383. package/src/web-dashboard/public/assets/index-zjbdJnO-.js +210 -0
  384. package/src/web-dashboard/public/assets/index-zjbdJnO-.js.map +1 -0
  385. package/src/web-dashboard/public/index.html +1 -1
  386. package/src/web-dashboard/public/assets/index-DhiuR4S2.js +0 -210
  387. package/src/web-dashboard/public/assets/index-DhiuR4S2.js.map +0 -1
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Capability readiness — the dashboard's one view of what the agent can DO here.
3
+ *
4
+ * This is the read-model behind `GET /api/capabilities`. It answers the question
5
+ * a user actually has before asking the agent for something ("will this work on
6
+ * my machine?") by probing the curated high-level verbs' declared requirements
7
+ * against the host:
8
+ *
9
+ * - each verb's READINESS (a missing executable blocks; a credential that is
10
+ * not an env var is reported but never blocks — see requirement-probe.ts);
11
+ * - the MISSING EXECUTABLES aggregated across the verbs, so the same `gh` is
12
+ * one row naming every verb that needs it rather than nine;
13
+ * - the per-OS command, where the OS genuinely decides it (`onThisMachine`).
14
+ *
15
+ * It is the SAME `actionCapabilities()` the capability search serves and the SAME
16
+ * `probeRequirements` the `tool_search` pre-flight runs, so the dashboard cannot
17
+ * disagree with what a run actually sees. Live session grants are served by the
18
+ * existing `/api/session-grants` (one source), so this module stays about
19
+ * capability, not consent.
20
+ *
21
+ * No phrase lists, no guessing: everything is derived from the declarations.
22
+ */
23
+ import type { CapabilityRequires, PlatformCommand, PlatformKey } from './capability-types.js';
24
+ /** One curated verb as the dashboard shows it. */
25
+ export interface CapabilityReadinessRow {
26
+ id: string;
27
+ ref: string;
28
+ name: string;
29
+ does: string;
30
+ effect: string;
31
+ reversible: boolean;
32
+ undo?: string;
33
+ grantable?: string;
34
+ requires?: CapabilityRequires;
35
+ /** True when nothing HARD is missing (only a binary gap can make this false). */
36
+ ready: boolean;
37
+ /** Human lines: an executable that is missing, or a credential not in the env. */
38
+ gaps: string[];
39
+ /** Inputs the model must still decide (never probed — not facts). */
40
+ ask: string[];
41
+ /** The command for the machine this server runs on, where the OS decides it. */
42
+ onThisMachine?: PlatformCommand;
43
+ /** Every declared per-OS command, where the OS genuinely decides it. */
44
+ platforms?: Partial<Record<PlatformKey, PlatformCommand>>;
45
+ }
46
+ /** An executable the curated verbs need that is not on PATH. */
47
+ export interface MissingExecutable {
48
+ /** The verbs (refs) that need it. */
49
+ forRefs: string[];
50
+ anyOf: string[];
51
+ remedy: string;
52
+ }
53
+ export interface CapabilityReadiness {
54
+ verbs: CapabilityReadinessRow[];
55
+ missingExecutables: MissingExecutable[];
56
+ readyCount: number;
57
+ blockedCount: number;
58
+ }
59
+ /**
60
+ * Build the readiness view. `platform` is injectable so a test can prove the
61
+ * per-OS resolution without the host's real platform.
62
+ */
63
+ export declare function capabilityReadiness(platform?: string): CapabilityReadiness;
64
+ //# sourceMappingURL=capability-readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-readiness.d.ts","sourceRoot":"","sources":["../../src/learning/capability-readiness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE9F,kDAAkD;AAClD,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;IACf,kFAAkF;IAClF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qEAAqE;IACrE,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,gFAAgF;IAChF,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;CAC3D;AAED,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,MAAyB,GAAG,mBAAmB,CA+C5F"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Capability readiness — the dashboard's one view of what the agent can DO here.
3
+ *
4
+ * This is the read-model behind `GET /api/capabilities`. It answers the question
5
+ * a user actually has before asking the agent for something ("will this work on
6
+ * my machine?") by probing the curated high-level verbs' declared requirements
7
+ * against the host:
8
+ *
9
+ * - each verb's READINESS (a missing executable blocks; a credential that is
10
+ * not an env var is reported but never blocks — see requirement-probe.ts);
11
+ * - the MISSING EXECUTABLES aggregated across the verbs, so the same `gh` is
12
+ * one row naming every verb that needs it rather than nine;
13
+ * - the per-OS command, where the OS genuinely decides it (`onThisMachine`).
14
+ *
15
+ * It is the SAME `actionCapabilities()` the capability search serves and the SAME
16
+ * `probeRequirements` the `tool_search` pre-flight runs, so the dashboard cannot
17
+ * disagree with what a run actually sees. Live session grants are served by the
18
+ * existing `/api/session-grants` (one source), so this module stays about
19
+ * capability, not consent.
20
+ *
21
+ * No phrase lists, no guessing: everything is derived from the declarations.
22
+ */
23
+ import { actionCapabilities } from '../tools/capability-registry.js';
24
+ import { probeRequirements, describeGap } from './requirement-probe.js';
25
+ /**
26
+ * Build the readiness view. `platform` is injectable so a test can prove the
27
+ * per-OS resolution without the host's real platform.
28
+ */
29
+ export function capabilityReadiness(platform = process.platform) {
30
+ const verbs = [];
31
+ const missing = new Map();
32
+ for (const cap of actionCapabilities()) {
33
+ const requires = cap.requires && Object.keys(cap.requires).length > 0 ? cap.requires : undefined;
34
+ const readiness = requires
35
+ ? probeRequirements(requires)
36
+ : { ready: true, gaps: [], ask: [] };
37
+ // Aggregate the executable gaps: the same `gh` is one row naming every verb
38
+ // that needs it, not one row per verb.
39
+ for (const gap of readiness.gaps) {
40
+ if (gap.kind !== 'binary')
41
+ continue;
42
+ const key = gap.anyOf.join('|');
43
+ const existing = missing.get(key) ?? { forRefs: [], anyOf: gap.anyOf, remedy: gap.remedy };
44
+ if (!existing.forRefs.includes(cap.ref))
45
+ existing.forRefs.push(cap.ref);
46
+ missing.set(key, existing);
47
+ }
48
+ const onThisMachine = cap.platforms ? cap.platforms[platform] : undefined;
49
+ verbs.push({
50
+ id: cap.id,
51
+ ref: cap.ref,
52
+ name: cap.name,
53
+ does: cap.oneLiner,
54
+ effect: cap.effectClass,
55
+ reversible: cap.reversible,
56
+ ...(cap.reversibleHow ? { undo: cap.reversibleHow } : {}),
57
+ ...(cap.grantCategory ? { grantable: cap.grantCategory } : {}),
58
+ ...(requires ? { requires } : {}),
59
+ ready: readiness.ready,
60
+ gaps: readiness.gaps.map(describeGap),
61
+ ask: readiness.ask,
62
+ ...(onThisMachine ? { onThisMachine } : {}),
63
+ ...(cap.platforms ? { platforms: cap.platforms } : {}),
64
+ });
65
+ }
66
+ const readyCount = verbs.filter((v) => v.ready).length;
67
+ return {
68
+ verbs,
69
+ missingExecutables: [...missing.values()],
70
+ readyCount,
71
+ blockedCount: verbs.length - readyCount,
72
+ };
73
+ }
74
+ //# sourceMappingURL=capability-readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-readiness.js","sourceRoot":"","sources":["../../src/learning/capability-readiness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAyCxE;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB,OAAO,CAAC,QAAQ;IACrE,MAAM,KAAK,GAA6B,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;IAErD,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,EAAE,CAAC;QACvC,MAAM,QAAQ,GACZ,GAAG,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAClF,MAAM,SAAS,GAAG,QAAQ;YACxB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC;YAC7B,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAkD,EAAE,GAAG,EAAE,EAAc,EAAE,CAAC;QAEnG,4EAA4E;QAC5E,uCAAuC;QACvC,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAS;YACpC,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;YAC3F,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAuB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,KAAK,CAAC,IAAI,CAAC;YACT,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ;YAClB,MAAM,EAAE,GAAG,CAAC,WAAW;YACvB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;YACrC,GAAG,EAAE,SAAS,CAAC,GAAG;YAClB,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACvD,OAAO;QACL,KAAK;QACL,kBAAkB,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACzC,UAAU;QACV,YAAY,EAAE,KAAK,CAAC,MAAM,GAAG,UAAU;KACxC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Capability types — ONE descriptor for everything the agent can DO.
3
+ *
4
+ * WHY THIS EXISTS. "What an action needs, what it costs, and what it touches"
5
+ * was scattered: tools carried it in prose descriptions, each gate hardcoded its
6
+ * own effect class, skills carried only methodology, and the CLI manifest carried
7
+ * a single boolean. Adding a verb (install / uninstall / publish / deploy / push)
8
+ * meant editing all of them. The capability descriptor is the ONE shape those
9
+ * sources are normalized into, so discovery, gating, the consent picture and the
10
+ * refusal wording all read from one place and cannot drift.
11
+ *
12
+ * A capability is the ENVELOPE (`kind`, `ref`, `requires`, `effectClass`,
13
+ * `reversible`); a SKILL is one implementation of it (`kind: 'skill'`) alongside
14
+ * a TOOL (`kind: 'tool'`) and a curated high-level ACTION (`kind: 'action'`).
15
+ *
16
+ * These are pure types — no imports, no side effects — so both the tool side and
17
+ * the learning side can depend on them without a cycle.
18
+ */
19
+ /** What an action does to the world. The gate's source of truth (Phase 2). */
20
+ export type EffectClass = 'read' | 'local-write' | 'local-state' | 'external' | 'destructive';
21
+ /** Which session grant may cover the action (see `session-grant.ts`). */
22
+ export type GrantCategory = 'write' | 'terminal' | 'external';
23
+ /**
24
+ * ONE requirement, in a shape that can be both SHOWN and CHECKED.
25
+ *
26
+ * The alternative — a human phrase like `'NPM_TOKEN or a GitHub token'` — can be
27
+ * displayed but never probed, so the agent could only discover it was missing by
28
+ * failing halfway through. `anyOf` is machine-checkable (an env var NAMES list
29
+ * for a credential, an executable list for a binary) and `join(' or ')` renders
30
+ * the same sentence a reader used to see. One source, so the displayed and the
31
+ * checked forms cannot drift.
32
+ */
33
+ export interface CapabilityNeed {
34
+ /** Satisfied when ANY of these is present. */
35
+ anyOf: string[];
36
+ /** How to satisfy it — shown when it is missing. */
37
+ note?: string;
38
+ }
39
+ /** What has to exist before the capability can run. */
40
+ export interface CapabilityRequires {
41
+ /** Env var names; satisfied when any one is set and non-empty. */
42
+ credentials?: CapabilityNeed[];
43
+ /** Executables; satisfied when any one resolves on PATH. */
44
+ binaries?: CapabilityNeed[];
45
+ /**
46
+ * Things only the MODEL can supply (a bump type, a target host) — a decision,
47
+ * not an environment fact, so never probed.
48
+ */
49
+ inputs?: string[];
50
+ }
51
+ /**
52
+ * How to satisfy a capability on ONE operating system.
53
+ *
54
+ * WHY THIS IS NOT ON EVERY CAPABILITY. The OS determines the command for some
55
+ * verbs and not others, and saying otherwise would be inventing a mapping that
56
+ * does not exist:
57
+ *
58
+ * - `install-system-tool` IS OS-determined — winget on Windows, brew on macOS,
59
+ * apt-get on Linux. There is no portable form.
60
+ * - `store-credential` IS OS-determined — the OS keychain on macOS/Linux versus
61
+ * a credentials file on Windows.
62
+ * - `add-dependency` is NOT — `npm install` is the same command everywhere, and
63
+ * npm-vs-pnpm is a USER PREFERENCE, not an OS affordance.
64
+ * - `deploy-app` is NOT — the choice between vercel and flyctl is a platform
65
+ * choice, not an OS one. (Windows and macOS both deploy to Vercel.)
66
+ *
67
+ * So `platforms` is present exactly where the OS genuinely decides, and ABSENT
68
+ * means "there is one command, or the model/user picks" — which is a different and
69
+ * equally truthful statement.
70
+ */
71
+ export interface PlatformCommand {
72
+ /** The command to run on this OS, with the variable part in angle brackets. */
73
+ command: string;
74
+ /**
75
+ * The binary it runs, WHEN an external one does. MUST be a binary this
76
+ * capability also declares it needs — a test asserts it, so a platform hint can
77
+ * never name a tool the requirement pre-flight did not check for.
78
+ *
79
+ * ABSENT means the command runs through nuvira itself, not through a binary on
80
+ * PATH. `store-credential` is the case that forced this: the OS decides WHERE a
81
+ * secret can safely live (Keychain / secret-tool / a vault file), but the command
82
+ * is identical on all three, so claiming a PATH binary would be a false fact.
83
+ */
84
+ binary?: string;
85
+ /** A caveat worth showing (a privilege requirement, or a fallback). */
86
+ note?: string;
87
+ }
88
+ /** The OSes a `platforms` map may key on. */
89
+ export type PlatformKey = 'win32' | 'darwin' | 'linux';
90
+ /**
91
+ * How to actually invoke a capability whose `ref` is NOT a callable tool name.
92
+ * An ingested MCP tool, for instance, is invoked through the `mcp_tool`
93
+ * dispatcher with the server and tool it names, so a discovery hit must say so
94
+ * rather than hand the model a name it cannot call.
95
+ */
96
+ export interface CapabilityInvoke {
97
+ /** The real tool to call. */
98
+ tool: string;
99
+ /** Fixed arguments that identify the capability (e.g. server + tool). */
100
+ args: Record<string, string>;
101
+ }
102
+ /** One thing the agent can do, normalized from a tool, a skill, an MCP server, or the catalog. */
103
+ export interface Capability {
104
+ /** Stable id (`tool:write_file`, `action:publish-site`, `skill:deploy-vercel`). */
105
+ id: string;
106
+ /**
107
+ * Which registry this came from. `mcp` is a FOREIGN tool, discovered from an
108
+ * external MCP server at runtime — it has no place in this repo's registry, so
109
+ * it carries `invoke` to say how it is reached.
110
+ */
111
+ kind: 'tool' | 'skill' | 'action' | 'mcp';
112
+ /** The thing to invoke: a tool name, a skill id, a curated action key, or `<server>/<tool>`. */
113
+ ref: string;
114
+ /** How to reach it, when `ref` is not itself a callable tool name. */
115
+ invoke?: CapabilityInvoke;
116
+ /** Short human name. */
117
+ name: string;
118
+ /** ONE sentence: what it does. Used for display and refusal wording. */
119
+ oneLiner: string;
120
+ effectClass: EffectClass;
121
+ reversible: boolean;
122
+ /** How to undo it, when it is reversible. */
123
+ reversibleHow?: string;
124
+ /** The session grant that can cover it (absent = no grant covers it). */
125
+ grantCategory?: GrantCategory;
126
+ requires: CapabilityRequires;
127
+ /** Discovery keywords — a hint for search, NEVER a decision rule. */
128
+ tags: string[];
129
+ /**
130
+ * How to do it on each OS — present ONLY where the OS genuinely determines the
131
+ * command (see {@link PlatformCommand}). Absent everywhere else, deliberately.
132
+ */
133
+ platforms?: Partial<Record<PlatformKey, PlatformCommand>>;
134
+ }
135
+ /**
136
+ * A TOOL's own capability declaration — the fact the descriptor used to hold in
137
+ * one hand-maintained name-keyed map (`EFFECT_BY_TOOL`).
138
+ *
139
+ * WHY IT LIVES ON THE TOOL. The map meant a tool could be born unclassified and
140
+ * its gate could hardcode a different answer than its descriptor; the map was the
141
+ * last place the layer did not let the TOOL own its own facts. The tool declares
142
+ * these at `registerTool`, `registry.ts` records them, and every consumer
143
+ * (fan-out, the write/terminal/external grants, the capability descriptor) reads
144
+ * the same declaration.
145
+ *
146
+ * `reversible` defaults to `true` (matching the old map's every read/write
147
+ * entry), and every field except `effectClass` is optional so a silent tool still
148
+ * declares the one fact that matters.
149
+ */
150
+ export interface ToolCapabilityDeclaration {
151
+ /** What the action does to the world — the one REQUIRED fact. */
152
+ effectClass: EffectClass;
153
+ /** Can re-running undo it? Defaults to true; set false for off-machine effects. */
154
+ reversible?: boolean;
155
+ /** How to undo it, when it is reversible. */
156
+ reversibleHow?: string;
157
+ /** The session grant that may cover it (absent = no grant covers it). */
158
+ grantCategory?: GrantCategory;
159
+ /** What has to exist before it can run. */
160
+ requires?: CapabilityRequires;
161
+ }
162
+ /** A ranked discovery result. */
163
+ export interface CapabilityHit {
164
+ capability: Capability;
165
+ score: number;
166
+ /** The tokens that matched — so a reader can see WHY it ranked. */
167
+ matched: string[];
168
+ }
169
+ //# sourceMappingURL=capability-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-types.d.ts","sourceRoot":"","sources":["../../src/learning/capability-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,aAAa,GAAG,UAAU,GAAG,aAAa,CAAC;AAE9F,yEAAyE;AACzE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uDAAuD;AACvD,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,kGAAkG;AAClG,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC1C,gGAAgG;IAChG,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,qEAAqE;IACrE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;CAC3D;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,yBAAyB;IACxC,iEAAiE;IACjE,WAAW,EAAE,WAAW,CAAC;IACzB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Capability types — ONE descriptor for everything the agent can DO.
3
+ *
4
+ * WHY THIS EXISTS. "What an action needs, what it costs, and what it touches"
5
+ * was scattered: tools carried it in prose descriptions, each gate hardcoded its
6
+ * own effect class, skills carried only methodology, and the CLI manifest carried
7
+ * a single boolean. Adding a verb (install / uninstall / publish / deploy / push)
8
+ * meant editing all of them. The capability descriptor is the ONE shape those
9
+ * sources are normalized into, so discovery, gating, the consent picture and the
10
+ * refusal wording all read from one place and cannot drift.
11
+ *
12
+ * A capability is the ENVELOPE (`kind`, `ref`, `requires`, `effectClass`,
13
+ * `reversible`); a SKILL is one implementation of it (`kind: 'skill'`) alongside
14
+ * a TOOL (`kind: 'tool'`) and a curated high-level ACTION (`kind: 'action'`).
15
+ *
16
+ * These are pure types — no imports, no side effects — so both the tool side and
17
+ * the learning side can depend on them without a cycle.
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=capability-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-types.js","sourceRoot":"","sources":["../../src/learning/capability-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
@@ -0,0 +1,89 @@
1
+ /** The opt-in switch. Absent / 0 / false / off / no ⇒ DISABLED (rule 5). */
2
+ export declare const CATALOG_FEED_ENV = "NUVIRA_CATALOG_FEED";
3
+ export declare const CATALOG_FEED_URL = "https://openrouter.ai/api/v1/models";
4
+ /** A snapshot older than this is treated as ABSENT (rule 5), not as a slightly-wrong prior. */
5
+ export declare const CATALOG_FEED_TTL_MS: number;
6
+ /**
7
+ * `ecosystem` priors derived from the catalogue's TOOL-SUPPORT fact.
8
+ *
9
+ * WHY THESE NUMBERS ARE ALL BELOW 0.7. §7.2 decided that `ecosystem`'s cold-start prior is 0.5 and that
10
+ * this "keeps a pair OUT of the `Frontier` tier (that needs ≥ 0.7) — a pair we have never watched call a
11
+ * tool is not a frontier agent model". A catalogue row saying `tools` is advertised is still not us
12
+ * having watched it call a tool, so it must not cross that gate either: 0.6 informs the ranking without
13
+ * promoting the tier. The demotion is factual and may be stronger than the promotion — a model the
14
+ * catalogue says CANNOT call tools is a real negative, and no amount of measurement-free optimism should
15
+ * hide it.
16
+ */
17
+ export declare const ECOSYSTEM_PRIOR_WITH_TOOLS = 0.6;
18
+ export declare const ECOSYSTEM_PRIOR_WITHOUT_TOOLS = 0.25;
19
+ /** One catalogue row, normalised. Pricing is USD per 1K tokens (the router's own unit). */
20
+ export interface CatalogModelRow {
21
+ id: string;
22
+ /** USD per 1K input tokens, from the catalogue's per-token figure. */
23
+ inputPer1K?: number;
24
+ /** USD per 1K output tokens. */
25
+ outputPer1K?: number;
26
+ contextLength?: number;
27
+ /** Lower-cased catalogue parameter names, verbatim. */
28
+ supportedParameters: string[];
29
+ }
30
+ export interface CatalogSnapshot {
31
+ version: number;
32
+ source: 'openrouter';
33
+ /** Epoch ms of the fetch this snapshot came from. */
34
+ fetchedAt: number;
35
+ ttlMs: number;
36
+ models: Record<string, CatalogModelRow>;
37
+ }
38
+ /** A prior that knows where it came from — rule 4's whole point. */
39
+ export interface ExternalPrior {
40
+ parameter: 'cost' | 'ecosystem';
41
+ /** 0–1, on the scorecard's scale. */
42
+ value: number;
43
+ /** e.g. `openrouter catalogue` — printed beside the number, never omitted. */
44
+ source: string;
45
+ fetchedAt: number;
46
+ /** Human basis: the fact the number was derived FROM (so a reader can disagree with it). */
47
+ basis: string;
48
+ }
49
+ /**
50
+ * Is the feed switched on?
51
+ *
52
+ * The vocabulary is EXACTLY the dashboard's `asks` rule (`1`/`true`/`yes` enable; everything else,
53
+ * including unset, is off) rather than something friendlier like `truthy`. Two reasons: this switch
54
+ * causes a NETWORK fetch, so an unrecognised value must fail CLOSED; and the dashboard's process-env page
55
+ * states a rule per variable, so a reader that behaved differently from its declared rule would make that
56
+ * page lie — the one thing it exists not to do. `nuvira config catalog-feed set on` writes the canonical `1`.
57
+ */
58
+ export declare function catalogFeedEnabled(env?: NodeJS.ProcessEnv): boolean;
59
+ export declare function catalogSnapshotPath(): string;
60
+ /** Parse an OpenRouter `/api/v1/models` payload into a snapshot. Pure — no clock, no I/O. */
61
+ export declare function parseOpenRouterModels(payload: unknown, fetchedAt: number): CatalogSnapshot;
62
+ /**
63
+ * Read the cached snapshot, or `undefined` when there is none OR it has expired.
64
+ *
65
+ * Expiry is deliberately indistinguishable from absence: rule 5 says an expired entry is treated as
66
+ * absent rather than kept, so callers need no separate staleness branch.
67
+ */
68
+ export declare function loadCatalogSnapshot(now?: number): CatalogSnapshot | undefined;
69
+ export declare function saveCatalogSnapshot(snapshot: CatalogSnapshot): void;
70
+ /** Fetch and store a fresh snapshot. Out-of-band only — the CLI/dashboard call this, the router does not. */
71
+ export declare function refreshCatalogFeed(fetchImpl?: typeof fetch, now?: () => number): Promise<{
72
+ ok: true;
73
+ snapshot: CatalogSnapshot;
74
+ } | {
75
+ ok: false;
76
+ reason: string;
77
+ }>;
78
+ /** The catalogue row for OUR `provider × model`, or `undefined` — identity-mapped, never guessed (rule 3). */
79
+ export declare function catalogRowFor(provider: string, model: string, snapshot?: CatalogSnapshot | undefined): CatalogModelRow | undefined;
80
+ /**
81
+ * The priors this feed can supply for one pair, with provenance. Empty when disabled, expired or
82
+ * unmatched — every one of which is a legitimate "no prior", never a invented number.
83
+ */
84
+ export declare function externalPriorsFor(provider: string, model: string, opts?: {
85
+ now?: number;
86
+ snapshot?: CatalogSnapshot;
87
+ env?: NodeJS.ProcessEnv;
88
+ }): ExternalPrior[];
89
+ //# sourceMappingURL=catalog-feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-feed.d.ts","sourceRoot":"","sources":["../../src/learning/catalog-feed.ts"],"names":[],"mappings":"AAuCA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AAEtD,eAAO,MAAM,gBAAgB,wCAAwC,CAAC;AAEtE,+FAA+F;AAC/F,eAAO,MAAM,mBAAmB,QAAsB,CAAC;AAIvD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,2FAA2F;AAC3F,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACzC;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAIhF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAK5C;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CA0B1F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAmB,GAAG,eAAe,GAAG,SAAS,CAazF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAKnE;AAED,6GAA6G;AAC7G,wBAAsB,kBAAkB,CACtC,SAAS,GAAE,OAAO,KAAa,EAC/B,GAAG,GAAE,MAAM,MAAiB,GAC3B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAYlF;AAED,8GAA8G;AAC9G,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,8BAAwB,GAC/B,eAAe,GAAG,SAAS,CAS7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAO,GAC/E,aAAa,EAAE,CAyCjB"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * The OpenRouter model catalogue as a SOURCE OF PRIORS — never measurements.
3
+ *
4
+ * WHY THIS ONE FEED, AND NOT A LEADERBOARD. `docs/DESIGN_CAPABILITY_BY_MEASUREMENT.md` §6 assessed every
5
+ * public ranking source proposed for the scorecard and found two retired (the HF Open LLM Leaderboard,
6
+ * Papers With Code), one unrelated (Graphify), and one whose sample names cannot be verified at all —
7
+ * and then identified exactly one value that attaches to a pair **without an identity guess**:
8
+ * `GET https://openrouter.ai/api/v1/models`, keyless and documented, returning each catalogue model's
9
+ * pricing, `context_length` and `supported_parameters` for the ids this router actually routes to.
10
+ *
11
+ * It supplies `cost` and `ecosystem` priors. Nothing else, and never `accuracy`: an offline catalogue
12
+ * says what a model costs and what it advertises, and says nothing about whether OUR work succeeded.
13
+ *
14
+ * THE FIVE RULES FROM §6.2 ARE EACH A LINE OF CODE HERE, not an aspiration:
15
+ *
16
+ * 1. PRIOR ONLY. Every value this module returns is labelled with its source and fetch time, and
17
+ * `capabilityLines` prints it as a prior. Samples always outrank it.
18
+ * 2. NEVER ON THE ROUTING PATH. Nothing in the router imports this module; a turn cannot wait on —
19
+ * or fail because of — a third-party network call. Only the CLI and the dashboard refresh it.
20
+ * 3. IDENTITY-MAPPED OR UNUSED. A catalogue row attaches to our pair only through A1's `sameModel`
21
+ * (exact id, bare id, or a DECLARED alias). No similarity, no prefixes, no vendor guessing —
22
+ * an unmatched row is dropped, which is the whole reason the catalogue was chosen over LMArena.
23
+ * 4. PROVENANCE IS PRINTED. `source` + `fetchedAt` travel with every prior to the scorecard.
24
+ * 5. OPT-IN, WITH A TTL. Default OFF (`NUVIRA_CATALOG_FEED`); an EXPIRED snapshot is treated as
25
+ * absent rather than kept, because a stale prior is worse than none.
26
+ *
27
+ * The snapshot lives in the memory dir and is written through `atomic-store`, so two processes cannot
28
+ * tear it and a reader never parses a half-written file.
29
+ */
30
+ import { existsSync, readFileSync } from 'node:fs';
31
+ import { join } from 'node:path';
32
+ import { envBuff, resolveNuviraHome } from '../config/paths.js';
33
+ import { withFileLockSync, writeFileAtomicSync } from '../utils/atomic-store.js';
34
+ import { sameModel } from './model-identity.js';
35
+ // Static, not lazy: nothing imports THIS module, so there is no cycle to avoid — and a lazy `require`
36
+ // would simply not exist in this ESM build.
37
+ import { computeCostScore } from './auto-router.js';
38
+ /** The opt-in switch. Absent / 0 / false / off / no ⇒ DISABLED (rule 5). */
39
+ export const CATALOG_FEED_ENV = 'NUVIRA_CATALOG_FEED';
40
+ export const CATALOG_FEED_URL = 'https://openrouter.ai/api/v1/models';
41
+ /** A snapshot older than this is treated as ABSENT (rule 5), not as a slightly-wrong prior. */
42
+ export const CATALOG_FEED_TTL_MS = 24 * 60 * 60 * 1000;
43
+ const SNAPSHOT_VERSION = 1;
44
+ /**
45
+ * `ecosystem` priors derived from the catalogue's TOOL-SUPPORT fact.
46
+ *
47
+ * WHY THESE NUMBERS ARE ALL BELOW 0.7. §7.2 decided that `ecosystem`'s cold-start prior is 0.5 and that
48
+ * this "keeps a pair OUT of the `Frontier` tier (that needs ≥ 0.7) — a pair we have never watched call a
49
+ * tool is not a frontier agent model". A catalogue row saying `tools` is advertised is still not us
50
+ * having watched it call a tool, so it must not cross that gate either: 0.6 informs the ranking without
51
+ * promoting the tier. The demotion is factual and may be stronger than the promotion — a model the
52
+ * catalogue says CANNOT call tools is a real negative, and no amount of measurement-free optimism should
53
+ * hide it.
54
+ */
55
+ export const ECOSYSTEM_PRIOR_WITH_TOOLS = 0.6;
56
+ export const ECOSYSTEM_PRIOR_WITHOUT_TOOLS = 0.25;
57
+ /**
58
+ * Is the feed switched on?
59
+ *
60
+ * The vocabulary is EXACTLY the dashboard's `asks` rule (`1`/`true`/`yes` enable; everything else,
61
+ * including unset, is off) rather than something friendlier like `truthy`. Two reasons: this switch
62
+ * causes a NETWORK fetch, so an unrecognised value must fail CLOSED; and the dashboard's process-env page
63
+ * states a rule per variable, so a reader that behaved differently from its declared rule would make that
64
+ * page lie — the one thing it exists not to do. `nuvira config catalog-feed set on` writes the canonical `1`.
65
+ */
66
+ export function catalogFeedEnabled(env = process.env) {
67
+ const raw = env[CATALOG_FEED_ENV] ?? envBuff(CATALOG_FEED_ENV);
68
+ if (raw === undefined)
69
+ return false;
70
+ return ['1', 'true', 'yes'].includes(String(raw).trim().toLowerCase());
71
+ }
72
+ export function catalogSnapshotPath() {
73
+ return join(envBuff('MEMORY_DIR') || join(resolveNuviraHome(), 'memory'), 'catalog-feed.json');
74
+ }
75
+ /** Parse an OpenRouter `/api/v1/models` payload into a snapshot. Pure — no clock, no I/O. */
76
+ export function parseOpenRouterModels(payload, fetchedAt) {
77
+ const models = {};
78
+ const data = payload?.data;
79
+ if (Array.isArray(data)) {
80
+ for (const raw of data) {
81
+ const id = typeof raw?.id === 'string' ? raw.id : '';
82
+ if (!id)
83
+ continue;
84
+ // The catalogue gives USD per TOKEN as a decimal string. This router's pricing unit is per 1K,
85
+ // and the earlier per-1K/per-MTok mix-up is recorded in the parity tracker — so convert exactly
86
+ // once, here, and never re-derive it downstream.
87
+ const prompt = Number(raw.pricing?.prompt);
88
+ const completion = Number(raw.pricing?.completion);
89
+ const context = Number(raw.context_length);
90
+ const params = Array.isArray(raw.supported_parameters)
91
+ ? raw.supported_parameters.filter((p) => typeof p === 'string')
92
+ : [];
93
+ models[id] = {
94
+ id,
95
+ ...(Number.isFinite(prompt) ? { inputPer1K: prompt * 1000 } : {}),
96
+ ...(Number.isFinite(completion) ? { outputPer1K: completion * 1000 } : {}),
97
+ ...(Number.isFinite(context) && context > 0 ? { contextLength: context } : {}),
98
+ supportedParameters: params.map((p) => p.toLowerCase()),
99
+ };
100
+ }
101
+ }
102
+ return { version: SNAPSHOT_VERSION, source: 'openrouter', fetchedAt, ttlMs: CATALOG_FEED_TTL_MS, models };
103
+ }
104
+ /**
105
+ * Read the cached snapshot, or `undefined` when there is none OR it has expired.
106
+ *
107
+ * Expiry is deliberately indistinguishable from absence: rule 5 says an expired entry is treated as
108
+ * absent rather than kept, so callers need no separate staleness branch.
109
+ */
110
+ export function loadCatalogSnapshot(now = Date.now()) {
111
+ try {
112
+ const path = catalogSnapshotPath();
113
+ if (!existsSync(path))
114
+ return undefined;
115
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
116
+ if (!parsed || typeof parsed !== 'object' || !parsed.models)
117
+ return undefined;
118
+ if (typeof parsed.fetchedAt !== 'number')
119
+ return undefined;
120
+ const ttl = typeof parsed.ttlMs === 'number' ? parsed.ttlMs : CATALOG_FEED_TTL_MS;
121
+ if (now - parsed.fetchedAt > ttl)
122
+ return undefined;
123
+ return parsed;
124
+ }
125
+ catch {
126
+ return undefined;
127
+ }
128
+ }
129
+ export function saveCatalogSnapshot(snapshot) {
130
+ const path = catalogSnapshotPath();
131
+ withFileLockSync(`${path}.lock`, () => {
132
+ writeFileAtomicSync(path, `${JSON.stringify(snapshot, null, 2)}\n`);
133
+ });
134
+ }
135
+ /** Fetch and store a fresh snapshot. Out-of-band only — the CLI/dashboard call this, the router does not. */
136
+ export async function refreshCatalogFeed(fetchImpl = fetch, now = Date.now) {
137
+ try {
138
+ const res = await fetchImpl(CATALOG_FEED_URL, { headers: { accept: 'application/json' } });
139
+ if (!res.ok)
140
+ return { ok: false, reason: `catalogue returned HTTP ${res.status}` };
141
+ const snapshot = parseOpenRouterModels(await res.json(), now());
142
+ const count = Object.keys(snapshot.models).length;
143
+ if (count === 0)
144
+ return { ok: false, reason: 'catalogue returned no models' };
145
+ saveCatalogSnapshot(snapshot);
146
+ return { ok: true, snapshot };
147
+ }
148
+ catch (err) {
149
+ return { ok: false, reason: err instanceof Error ? err.message : 'fetch failed' };
150
+ }
151
+ }
152
+ /** The catalogue row for OUR `provider × model`, or `undefined` — identity-mapped, never guessed (rule 3). */
153
+ export function catalogRowFor(provider, model, snapshot = loadCatalogSnapshot()) {
154
+ if (!snapshot)
155
+ return undefined;
156
+ // A catalogue row is an OpenRouter row. For any OTHER provider the id may still be the same model
157
+ // (A1's whole subject), so the match goes through `sameModel`, which only widens by DECLARATION.
158
+ if (snapshot.models[model])
159
+ return snapshot.models[model];
160
+ for (const row of Object.values(snapshot.models)) {
161
+ if (sameModel(row.id, model))
162
+ return row;
163
+ }
164
+ return undefined;
165
+ }
166
+ /**
167
+ * The priors this feed can supply for one pair, with provenance. Empty when disabled, expired or
168
+ * unmatched — every one of which is a legitimate "no prior", never a invented number.
169
+ */
170
+ export function externalPriorsFor(provider, model, opts = {}) {
171
+ // The gate is checked HERE, not at each call site: rule 5 makes the feed opt-in, and a consumer that
172
+ // forgot to ask would silently use priors the operator switched off. One place, impossible to miss.
173
+ if (!catalogFeedEnabled(opts.env))
174
+ return [];
175
+ const snapshot = opts.snapshot ?? loadCatalogSnapshot(opts.now ?? Date.now());
176
+ if (!snapshot)
177
+ return [];
178
+ const row = catalogRowFor(provider, model, snapshot);
179
+ if (!row)
180
+ return [];
181
+ const priors = [];
182
+ const base = { source: `${snapshot.source} catalogue`, fetchedAt: snapshot.fetchedAt };
183
+ // `cost` — only from real pricing, only through the router's OWN scoring formula, so a catalogue
184
+ // number lands on the same scale as a measured one instead of on a second, private scale.
185
+ if (typeof row.inputPer1K === 'number' && typeof row.outputPer1K === 'number') {
186
+ const value = computeCostScore('openrouter', {
187
+ inputPer1K: row.inputPer1K,
188
+ outputPer1K: row.outputPer1K,
189
+ });
190
+ priors.push({
191
+ ...base,
192
+ parameter: 'cost',
193
+ value,
194
+ basis: `$${row.inputPer1K.toFixed(5)}/1K in, $${row.outputPer1K.toFixed(5)}/1K out`,
195
+ });
196
+ }
197
+ // `ecosystem` — from the TOOL-SUPPORT fact only. The context window is deliberately NOT scored here:
198
+ // it already reaches routing as `contextWindowTokens` from the listModels probe, so turning it into a
199
+ // second, invented 0–1 curve would be a number nobody measured.
200
+ if (row.supportedParameters.length > 0) {
201
+ const hasTools = row.supportedParameters.some((p) => p === 'tools' || p === 'tool_choice');
202
+ priors.push({
203
+ ...base,
204
+ parameter: 'ecosystem',
205
+ value: hasTools ? ECOSYSTEM_PRIOR_WITH_TOOLS : ECOSYSTEM_PRIOR_WITHOUT_TOOLS,
206
+ basis: hasTools ? 'catalogue advertises tool calling' : 'catalogue advertises no tool calling',
207
+ });
208
+ }
209
+ return priors;
210
+ }
211
+ //# sourceMappingURL=catalog-feed.js.map