@wardby/cli 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (555) hide show
  1. package/.env.example +53 -4
  2. package/README.md +52 -13
  3. package/dist/claude-coding-worker/driver.d.ts +6 -1
  4. package/dist/claude-coding-worker/driver.js +27 -1
  5. package/dist/claude-coding-worker/main.js +2 -0
  6. package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
  7. package/dist/claude-coding-worker/tool-socket.js +26 -0
  8. package/dist/cli-help.d.ts +1 -1
  9. package/dist/cli-help.js +14 -4
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.js +284 -36
  12. package/dist/coding/base-commit.d.ts +6 -0
  13. package/dist/coding/base-commit.js +12 -0
  14. package/dist/coding/collect-exclude.d.ts +25 -0
  15. package/dist/coding/collect-exclude.js +76 -0
  16. package/dist/coding/profile.d.ts +67 -22
  17. package/dist/coding/profile.js +58 -25
  18. package/dist/coding/protected-path-wording.d.ts +24 -0
  19. package/dist/coding/protected-path-wording.js +55 -0
  20. package/dist/coding/protected-paths.d.ts +31 -0
  21. package/dist/coding/protected-paths.js +48 -0
  22. package/dist/coding/protocol.d.ts +91 -4
  23. package/dist/coding/protocol.js +123 -12
  24. package/dist/coding/provider.d.ts +6 -1
  25. package/dist/coding/provider.js +16 -9
  26. package/dist/coding/registry/adapters.d.ts +2 -0
  27. package/dist/coding/registry/adapters.js +9 -0
  28. package/dist/coding/registry/allowlist.d.ts +9 -0
  29. package/dist/coding/registry/allowlist.js +28 -0
  30. package/dist/coding/registry/json-scan.d.ts +55 -0
  31. package/dist/coding/registry/json-scan.js +191 -0
  32. package/dist/coding/registry/lockfiles.d.ts +6 -0
  33. package/dist/coding/registry/lockfiles.js +89 -0
  34. package/dist/coding/registry/npm-lockfile.d.ts +9 -0
  35. package/dist/coding/registry/npm-lockfile.js +73 -0
  36. package/dist/coding/registry/npm-plan.d.ts +29 -0
  37. package/dist/coding/registry/npm-plan.js +289 -0
  38. package/dist/coding/registry/npm.d.ts +7 -0
  39. package/dist/coding/registry/npm.js +252 -0
  40. package/dist/coding/registry/pypi.d.ts +4 -0
  41. package/dist/coding/registry/pypi.js +210 -0
  42. package/dist/coding/registry/report.d.ts +37 -0
  43. package/dist/coding/registry/report.js +31 -0
  44. package/dist/coding/registry/token.d.ts +4 -0
  45. package/dist/coding/registry/token.js +7 -0
  46. package/dist/coding/registry/types.d.ts +286 -0
  47. package/dist/coding/registry/types.js +19 -0
  48. package/dist/coding/registry/worker-config.d.ts +14 -0
  49. package/dist/coding/registry/worker-config.js +31 -0
  50. package/dist/coding/services/builtins.d.ts +22 -0
  51. package/dist/coding/services/builtins.js +85 -0
  52. package/dist/coding/services/catalog.d.ts +443 -0
  53. package/dist/coding/services/catalog.js +159 -0
  54. package/dist/coding/services/declaration.d.ts +11 -0
  55. package/dist/coding/services/declaration.js +114 -0
  56. package/dist/coding/services/note.d.ts +8 -0
  57. package/dist/coding/services/note.js +15 -0
  58. package/dist/coding/services/resolve.d.ts +25 -0
  59. package/dist/coding/services/resolve.js +50 -0
  60. package/dist/coding/services/wording.d.ts +25 -0
  61. package/dist/coding/services/wording.js +70 -0
  62. package/dist/coding-proxy/main.js +24 -4
  63. package/dist/coding-worker/artifact.d.ts +6 -0
  64. package/dist/coding-worker/debug-trace.d.ts +37 -0
  65. package/dist/coding-worker/debug-trace.js +117 -0
  66. package/dist/coding-worker/driver.d.ts +13 -1
  67. package/dist/coding-worker/driver.js +102 -13
  68. package/dist/coding-worker/errors.js +8 -0
  69. package/dist/coding-worker/main.js +10 -2
  70. package/dist/coding-worker/sdk.d.ts +2 -2
  71. package/dist/coding-worker/sdk.js +7 -2
  72. package/dist/coding-worker/types.d.ts +3 -0
  73. package/dist/config/providers.d.ts +66 -0
  74. package/dist/config/providers.js +137 -0
  75. package/dist/core/attribution.d.ts +101 -0
  76. package/dist/core/attribution.js +208 -0
  77. package/dist/core/budget-groups.d.ts +120 -10
  78. package/dist/core/budget-groups.js +133 -24
  79. package/dist/core/budget-wording.d.ts +22 -0
  80. package/dist/core/budget-wording.js +55 -0
  81. package/dist/core/coding-queue.d.ts +3 -0
  82. package/dist/core/coding-queue.js +6 -2
  83. package/dist/core/coding-service-status.d.ts +11 -0
  84. package/dist/core/coding-service-status.js +17 -0
  85. package/dist/core/cost-report.d.ts +88 -0
  86. package/dist/core/cost-report.js +248 -0
  87. package/dist/core/datastores.js +18 -2
  88. package/dist/core/db.d.ts +5 -1
  89. package/dist/core/db.js +8 -2
  90. package/dist/core/dispatch.d.ts +74 -7
  91. package/dist/core/dispatch.js +382 -47
  92. package/dist/core/engine-native.js +44 -14
  93. package/dist/core/glob.d.ts +10 -0
  94. package/dist/core/glob.js +33 -0
  95. package/dist/core/grants.d.ts +86 -0
  96. package/dist/core/grants.js +126 -0
  97. package/dist/core/host-events.d.ts +72 -0
  98. package/dist/core/host-events.js +597 -0
  99. package/dist/core/host-identity-links.d.ts +54 -0
  100. package/dist/core/host-identity-links.js +189 -0
  101. package/dist/core/host-status.d.ts +78 -0
  102. package/dist/core/host-status.js +228 -0
  103. package/dist/core/in-flight-runs.d.ts +8 -0
  104. package/dist/core/in-flight-runs.js +56 -0
  105. package/dist/core/issue-bridge.d.ts +60 -0
  106. package/dist/core/issue-bridge.js +189 -0
  107. package/dist/core/issue-dedupe.d.ts +70 -0
  108. package/dist/core/issue-dedupe.js +255 -0
  109. package/dist/core/issue-events.d.ts +42 -0
  110. package/dist/core/issue-events.js +155 -0
  111. package/dist/core/issue-status.d.ts +29 -0
  112. package/dist/core/issue-status.js +241 -0
  113. package/dist/core/issue-tracker-tools.d.ts +64 -0
  114. package/dist/core/issue-tracker-tools.js +850 -0
  115. package/dist/core/model-usage.d.ts +10 -0
  116. package/dist/core/model-usage.js +24 -0
  117. package/dist/core/provider-wording.d.ts +12 -0
  118. package/dist/core/provider-wording.js +44 -0
  119. package/dist/core/reconciler.d.ts +42 -2
  120. package/dist/core/reconciler.js +97 -2
  121. package/dist/core/repo-access.d.ts +99 -0
  122. package/dist/core/repo-access.js +136 -0
  123. package/dist/core/review-host-checks.d.ts +11 -0
  124. package/dist/core/review-host-checks.js +41 -0
  125. package/dist/core/review-host-tools.d.ts +47 -0
  126. package/dist/core/review-host-tools.js +354 -0
  127. package/dist/core/run-heartbeat.d.ts +27 -0
  128. package/dist/core/run-heartbeat.js +54 -0
  129. package/dist/core/run-pricing.d.ts +61 -0
  130. package/dist/core/run-pricing.js +56 -0
  131. package/dist/core/runner.d.ts +33 -8
  132. package/dist/core/runner.js +410 -62
  133. package/dist/core/scheduler.d.ts +4 -1
  134. package/dist/core/scheduler.js +3 -2
  135. package/dist/core/secrets.d.ts +11 -2
  136. package/dist/core/secrets.js +25 -6
  137. package/dist/core/self-defects.d.ts +80 -0
  138. package/dist/core/self-defects.js +180 -0
  139. package/dist/core/subagent-memory-tools.d.ts +1 -1
  140. package/dist/core/subagent-memory-tools.js +16 -3
  141. package/dist/core/tool-admin.d.ts +81 -0
  142. package/dist/core/tool-admin.js +129 -0
  143. package/dist/core/tool-names.d.ts +42 -0
  144. package/dist/core/tool-names.js +67 -0
  145. package/dist/core/untrusted-content.d.ts +32 -0
  146. package/dist/core/untrusted-content.js +72 -0
  147. package/dist/core/webhooks.d.ts +17 -2
  148. package/dist/core/webhooks.js +42 -3
  149. package/dist/generated/prisma/browser.d.ts +166 -0
  150. package/dist/generated/prisma/client.d.ts +166 -0
  151. package/dist/generated/prisma/commonInputTypes.d.ts +152 -52
  152. package/dist/generated/prisma/enums.d.ts +13 -0
  153. package/dist/generated/prisma/enums.js +12 -1
  154. package/dist/generated/prisma/internal/class.d.ts +242 -0
  155. package/dist/generated/prisma/internal/class.js +4 -4
  156. package/dist/generated/prisma/internal/prismaNamespace.d.ts +2571 -577
  157. package/dist/generated/prisma/internal/prismaNamespace.js +312 -6
  158. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +328 -0
  159. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +312 -6
  160. package/dist/generated/prisma/models/Agent.d.ts +682 -1
  161. package/dist/generated/prisma/models/AgentIssueProject.d.ts +1838 -0
  162. package/dist/generated/prisma/models/AgentIssueProject.js +1 -0
  163. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  164. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  165. package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
  166. package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
  167. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
  168. package/dist/generated/prisma/models/CodingProxySession.d.ts +195 -2
  169. package/dist/generated/prisma/models/CodingRun.d.ts +1405 -95
  170. package/dist/generated/prisma/models/CodingRunServiceStatus.d.ts +1404 -0
  171. package/dist/generated/prisma/models/CodingRunServiceStatus.js +1 -0
  172. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  173. package/dist/generated/prisma/models/CodingService.js +1 -0
  174. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  175. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  176. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  177. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  178. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  179. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  180. package/dist/generated/prisma/models/IssueFingerprint.d.ts +1183 -0
  181. package/dist/generated/prisma/models/IssueFingerprint.js +1 -0
  182. package/dist/generated/prisma/models/IssuePullRequest.d.ts +1255 -0
  183. package/dist/generated/prisma/models/IssuePullRequest.js +1 -0
  184. package/dist/generated/prisma/models/ModelCatalogEntry.d.ts +1322 -0
  185. package/dist/generated/prisma/models/ModelCatalogEntry.js +1 -0
  186. package/dist/generated/prisma/models/Principal.d.ts +455 -0
  187. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  188. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  189. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  190. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  191. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  192. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  193. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  194. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  195. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  196. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  197. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  198. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  199. package/dist/generated/prisma/models/Run.d.ts +1402 -82
  200. package/dist/generated/prisma/models/RunAttribution.d.ts +1259 -0
  201. package/dist/generated/prisma/models/RunAttribution.js +1 -0
  202. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  203. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  204. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  205. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  206. package/dist/generated/prisma/models/RunIssueStatus.d.ts +1199 -0
  207. package/dist/generated/prisma/models/RunIssueStatus.js +1 -0
  208. package/dist/generated/prisma/models/RunModelUsage.d.ts +1316 -0
  209. package/dist/generated/prisma/models/RunModelUsage.js +1 -0
  210. package/dist/generated/prisma/models/Tool.d.ts +15 -3
  211. package/dist/generated/prisma/models/WorkItem.d.ts +1408 -0
  212. package/dist/generated/prisma/models/WorkItem.js +1 -0
  213. package/dist/generated/prisma/models.d.ts +22 -0
  214. package/dist/help/build.d.ts +1 -0
  215. package/dist/help/build.js +9 -0
  216. package/dist/help/catalog.d.ts +24 -0
  217. package/dist/help/catalog.js +160 -0
  218. package/dist/help/cli.d.ts +2 -0
  219. package/dist/help/cli.js +65 -0
  220. package/dist/help/runtime.d.ts +3 -0
  221. package/dist/help/runtime.js +44 -0
  222. package/dist/help/search.d.ts +9 -0
  223. package/dist/help/search.js +104 -0
  224. package/dist/help-index.json +999 -0
  225. package/dist/import/cli-args.js +3 -2
  226. package/dist/import/create.d.ts +5 -0
  227. package/dist/import/create.js +67 -13
  228. package/dist/import/index.js +19 -9
  229. package/dist/import/neutral-schema.d.ts +18 -18
  230. package/dist/knowledge/check.d.ts +13 -0
  231. package/dist/knowledge/check.js +69 -0
  232. package/dist/knowledge/cli.d.ts +14 -0
  233. package/dist/knowledge/cli.js +67 -0
  234. package/dist/knowledge/concept.d.ts +54 -0
  235. package/dist/knowledge/concept.js +78 -0
  236. package/dist/knowledge/note.d.ts +11 -0
  237. package/dist/knowledge/note.js +39 -0
  238. package/dist/knowledge/relevance.d.ts +11 -0
  239. package/dist/knowledge/relevance.js +14 -0
  240. package/dist/knowledge/span-hash.d.ts +3 -0
  241. package/dist/knowledge/span-hash.js +16 -0
  242. package/dist/mcp/auth/access.d.ts +72 -0
  243. package/dist/mcp/auth/access.js +58 -0
  244. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  245. package/dist/mcp/auth/grants-cli.js +518 -0
  246. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  247. package/dist/mcp/auth/host-account-cli.js +47 -0
  248. package/dist/mcp/auth/ownership.d.ts +25 -51
  249. package/dist/mcp/auth/ownership.js +19 -14
  250. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  251. package/dist/mcp/auth/repo-authorization.js +51 -0
  252. package/dist/mcp/auth/resource-server.d.ts +33 -2
  253. package/dist/mcp/auth/resource-server.js +99 -3
  254. package/dist/mcp/auth/self-hosted/browser.js +2 -2
  255. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  256. package/dist/mcp/auth/self-hosted/credentials.d.ts +23 -5
  257. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  258. package/dist/mcp/auth/self-hosted/session.d.ts +7 -6
  259. package/dist/mcp/context.d.ts +30 -1
  260. package/dist/mcp/errors.d.ts +25 -6
  261. package/dist/mcp/errors.js +98 -0
  262. package/dist/mcp/host-events/deliveries.d.ts +9 -0
  263. package/dist/mcp/host-events/deliveries.js +17 -0
  264. package/dist/mcp/host-events/github-ingress.d.ts +38 -0
  265. package/dist/mcp/host-events/github-ingress.js +83 -0
  266. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  267. package/dist/mcp/host-events/github-user-callback.js +50 -0
  268. package/dist/mcp/host-events/jira-ingress.d.ts +29 -0
  269. package/dist/mcp/host-events/jira-ingress.js +92 -0
  270. package/dist/mcp/index.d.ts +10 -1
  271. package/dist/mcp/index.js +187 -19
  272. package/dist/mcp/server.js +32 -11
  273. package/dist/mcp/tools/agents.js +519 -50
  274. package/dist/mcp/tools/budget-groups.js +3 -3
  275. package/dist/mcp/tools/cost-report.d.ts +8 -0
  276. package/dist/mcp/tools/cost-report.js +60 -0
  277. package/dist/mcp/tools/datastore.js +22 -15
  278. package/dist/mcp/tools/grants.d.ts +2 -0
  279. package/dist/mcp/tools/grants.js +239 -0
  280. package/dist/mcp/tools/help.d.ts +5 -0
  281. package/dist/mcp/tools/help.js +67 -0
  282. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  283. package/dist/mcp/tools/host-accounts.js +114 -0
  284. package/dist/mcp/tools/issue-projects.d.ts +2 -0
  285. package/dist/mcp/tools/issue-projects.js +238 -0
  286. package/dist/mcp/tools/memory.d.ts +7 -1
  287. package/dist/mcp/tools/memory.js +5 -5
  288. package/dist/mcp/tools/model-catalog.d.ts +22 -0
  289. package/dist/mcp/tools/model-catalog.js +423 -0
  290. package/dist/mcp/tools/repositories.d.ts +2 -0
  291. package/dist/mcp/tools/repositories.js +182 -0
  292. package/dist/mcp/tools/runs.d.ts +6 -0
  293. package/dist/mcp/tools/runs.js +60 -6
  294. package/dist/mcp/tools/scheduling.js +3 -6
  295. package/dist/mcp/tools/secrets.js +18 -6
  296. package/dist/mcp/tools/services.d.ts +2 -0
  297. package/dist/mcp/tools/services.js +222 -0
  298. package/dist/mcp/tools/subagents.js +52 -16
  299. package/dist/mcp/tools/tools.d.ts +41 -0
  300. package/dist/mcp/tools/tools.js +201 -40
  301. package/dist/mcp/tools/trigger.js +65 -7
  302. package/dist/mcp/tools/webhooks.js +15 -4
  303. package/dist/mcp/transport/streamable-http.d.ts +15 -0
  304. package/dist/mcp/transport/streamable-http.js +55 -3
  305. package/dist/mcp/webhooks/ingress.d.ts +2 -1
  306. package/dist/mcp/webhooks/ingress.js +9 -2
  307. package/dist/providers/auth/delegating.d.ts +19 -0
  308. package/dist/providers/auth/delegating.js +71 -0
  309. package/dist/providers/auth/index.d.ts +2 -0
  310. package/dist/providers/auth/index.js +11 -0
  311. package/dist/providers/auth/self-hosted.d.ts +10 -2
  312. package/dist/providers/auth/self-hosted.js +55 -6
  313. package/dist/providers/auth/types.d.ts +6 -0
  314. package/dist/providers/coding-proxy/memory-ledger.d.ts +4 -1
  315. package/dist/providers/coding-proxy/memory-ledger.js +31 -3
  316. package/dist/providers/coding-proxy/metering.d.ts +6 -1
  317. package/dist/providers/coding-proxy/metering.js +41 -4
  318. package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
  319. package/dist/providers/coding-proxy/prisma-ledger.js +106 -8
  320. package/dist/providers/coding-proxy/proxy.d.ts +25 -2
  321. package/dist/providers/coding-proxy/proxy.js +561 -38
  322. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  323. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  324. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  325. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  326. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  327. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  328. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  329. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  330. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  331. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  332. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  333. package/dist/providers/coding-proxy/registry/store.js +70 -0
  334. package/dist/providers/coding-proxy/runtime.d.ts +17 -0
  335. package/dist/providers/coding-proxy/runtime.js +63 -0
  336. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  337. package/dist/providers/coding-proxy/server.d.ts +11 -0
  338. package/dist/providers/coding-proxy/server.js +163 -0
  339. package/dist/providers/coding-proxy/types.d.ts +33 -1
  340. package/dist/providers/coding-proxy/types.js +12 -1
  341. package/dist/providers/engine/types.d.ts +29 -0
  342. package/dist/providers/executor/build.d.ts +2 -2
  343. package/dist/providers/executor/composition.d.ts +3 -0
  344. package/dist/providers/executor/composition.js +28 -1
  345. package/dist/providers/executor/container.d.ts +134 -4
  346. package/dist/providers/executor/container.js +394 -37
  347. package/dist/providers/executor/dbos.d.ts +4 -3
  348. package/dist/providers/executor/dbos.js +7 -5
  349. package/dist/providers/executor/in-process.d.ts +2 -3
  350. package/dist/providers/executor/routing.d.ts +13 -0
  351. package/dist/providers/executor/routing.js +18 -0
  352. package/dist/providers/executor/types.d.ts +34 -0
  353. package/dist/providers/issue-tracker/adf.d.ts +31 -0
  354. package/dist/providers/issue-tracker/adf.js +181 -0
  355. package/dist/providers/issue-tracker/index.d.ts +5 -0
  356. package/dist/providers/issue-tracker/index.js +12 -0
  357. package/dist/providers/issue-tracker/jira-client.d.ts +41 -0
  358. package/dist/providers/issue-tracker/jira-client.js +151 -0
  359. package/dist/providers/issue-tracker/jira-events.d.ts +3 -0
  360. package/dist/providers/issue-tracker/jira-events.js +98 -0
  361. package/dist/providers/issue-tracker/jira.d.ts +116 -0
  362. package/dist/providers/issue-tracker/jira.js +502 -0
  363. package/dist/providers/issue-tracker/types.d.ts +269 -0
  364. package/dist/providers/issue-tracker/types.js +16 -0
  365. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  366. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  367. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  368. package/dist/providers/jobs/collect-prune.js +27 -0
  369. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  370. package/dist/providers/jobs/docker-isolation.js +213 -22
  371. package/dist/providers/jobs/docker-services.d.ts +35 -0
  372. package/dist/providers/jobs/docker-services.js +191 -0
  373. package/dist/providers/jobs/docker.d.ts +53 -2
  374. package/dist/providers/jobs/docker.js +307 -32
  375. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  376. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  377. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  378. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  379. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  380. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  381. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  382. package/dist/providers/jobs/kubernetes.d.ts +24 -2
  383. package/dist/providers/jobs/kubernetes.js +153 -22
  384. package/dist/providers/jobs/service-state.d.ts +22 -0
  385. package/dist/providers/jobs/service-state.js +17 -0
  386. package/dist/providers/jobs/types.d.ts +18 -0
  387. package/dist/providers/llm/anthropic.d.ts +3 -3
  388. package/dist/providers/llm/anthropic.js +3 -5
  389. package/dist/providers/llm/bedrock.d.ts +3 -3
  390. package/dist/providers/llm/bedrock.js +3 -8
  391. package/dist/providers/llm/catalog-lookup.d.ts +10 -0
  392. package/dist/providers/llm/catalog-lookup.js +15 -0
  393. package/dist/providers/llm/catalog-shipped.d.ts +18 -0
  394. package/dist/providers/llm/catalog-shipped.js +197 -0
  395. package/dist/providers/llm/catalog-store.d.ts +58 -0
  396. package/dist/providers/llm/catalog-store.js +138 -0
  397. package/dist/providers/llm/catalog-types.d.ts +66 -0
  398. package/dist/providers/llm/catalog-types.js +64 -0
  399. package/dist/providers/llm/catalog.d.ts +61 -0
  400. package/dist/providers/llm/catalog.js +147 -0
  401. package/dist/providers/llm/claude-messages.d.ts +5 -1
  402. package/dist/providers/llm/claude-messages.js +1 -0
  403. package/dist/providers/llm/claude-provider.d.ts +10 -12
  404. package/dist/providers/llm/claude-provider.js +15 -6
  405. package/dist/providers/llm/index.d.ts +9 -6
  406. package/dist/providers/llm/index.js +8 -5
  407. package/dist/providers/llm/openai.d.ts +14 -5
  408. package/dist/providers/llm/openai.js +24 -14
  409. package/dist/providers/llm/pricing-core.d.ts +5 -3
  410. package/dist/providers/llm/registration.js +8 -12
  411. package/dist/providers/llm/routing.d.ts +21 -11
  412. package/dist/providers/llm/routing.js +47 -13
  413. package/dist/providers/llm/types.d.ts +12 -0
  414. package/dist/providers/llm/types.js +8 -1
  415. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  416. package/dist/providers/review-host/diff-lines.js +59 -0
  417. package/dist/providers/review-host/github-events.d.ts +6 -0
  418. package/dist/providers/review-host/github-events.js +226 -0
  419. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  420. package/dist/providers/review-host/github-user-auth.js +128 -0
  421. package/dist/providers/review-host/github.d.ts +57 -0
  422. package/dist/providers/review-host/github.js +568 -0
  423. package/dist/providers/review-host/index.d.ts +12 -0
  424. package/dist/providers/review-host/index.js +30 -0
  425. package/dist/providers/review-host/review-format.d.ts +19 -0
  426. package/dist/providers/review-host/review-format.js +59 -0
  427. package/dist/providers/review-host/types.d.ts +309 -0
  428. package/dist/providers/review-host/types.js +24 -0
  429. package/dist/providers/vcs/git.d.ts +16 -6
  430. package/dist/providers/vcs/git.js +78 -34
  431. package/dist/providers/vcs/github.d.ts +94 -3
  432. package/dist/providers/vcs/github.js +223 -17
  433. package/dist/providers/vcs/types.d.ts +48 -4
  434. package/dist/quickstart/index.d.ts +2 -0
  435. package/dist/quickstart/index.js +36 -8
  436. package/dist/sandbox/fetch-policy.d.ts +20 -2
  437. package/dist/sandbox/fetch-policy.js +64 -3
  438. package/dist/sandbox/host-functions.d.ts +9 -1
  439. package/dist/sandbox/host-functions.js +12 -5
  440. package/dist/serve.js +8 -2
  441. package/dist/viewer/api-schema.d.ts +2757 -0
  442. package/dist/viewer/api-schema.js +165 -0
  443. package/dist/viewer/build-schemas.d.ts +2 -0
  444. package/dist/viewer/build-schemas.js +18 -0
  445. package/dist/viewer/event-bus.d.ts +38 -0
  446. package/dist/viewer/event-bus.js +232 -0
  447. package/dist/viewer/graph.d.ts +40 -0
  448. package/dist/viewer/graph.js +243 -0
  449. package/dist/viewer/http.d.ts +30 -0
  450. package/dist/viewer/http.js +133 -0
  451. package/dist/viewer/run-detail.d.ts +4 -0
  452. package/dist/viewer/run-detail.js +61 -0
  453. package/dist/wardby-bin.js +11 -0
  454. package/docs/README.md +40 -0
  455. package/docs/agent-recipes.md +383 -0
  456. package/docs/architecture-runtime.md +90 -0
  457. package/docs/assets/brand/wardby-icon-512.png +0 -0
  458. package/docs/assets/brand/wardby-icon.svg +16 -0
  459. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  460. package/docs/assets/brand/wardby-mascot.png +0 -0
  461. package/docs/assets/brand/wardby-mascot.svg +5 -0
  462. package/docs/assets/wardby-workflow.svg +106 -0
  463. package/docs/code-review-agents.md +508 -0
  464. package/docs/coding-agent-setup.md +175 -0
  465. package/docs/coding-packages.md +455 -0
  466. package/docs/coding-services.md +300 -0
  467. package/docs/coding-worker-byo-images.md +98 -0
  468. package/docs/coding-worker-isolation.md +1068 -0
  469. package/docs/getting-started-gke.md +632 -0
  470. package/docs/getting-started-identity-provider.md +319 -0
  471. package/docs/getting-started.md +147 -0
  472. package/docs/jira-agents.md +649 -0
  473. package/docs/knowledge.md +387 -0
  474. package/docs/models.md +221 -0
  475. package/docs/observability.md +53 -0
  476. package/docs/release-verification.md +66 -0
  477. package/docs/security-deployment.md +667 -0
  478. package/docs/viewer-api.md +142 -0
  479. package/help/admin-viewer.md +39 -0
  480. package/help/agent-recipes.md +173 -0
  481. package/help/architecture-agent.md +189 -0
  482. package/help/builder-agent.md +80 -0
  483. package/help/code-review-agents.md +37 -0
  484. package/help/coding-packages.md +31 -0
  485. package/help/coding-services.md +71 -0
  486. package/help/cost-attribution.md +67 -0
  487. package/help/creating-agents.md +90 -0
  488. package/help/deploy-gke.md +45 -0
  489. package/help/deployment-targets.md +39 -0
  490. package/help/errors/budget-group-exhausted.md +25 -0
  491. package/help/errors/docker-isolation-unsupported.md +26 -0
  492. package/help/errors/model-unavailable.md +63 -0
  493. package/help/errors/protected-path.md +45 -0
  494. package/help/errors/repo-access.md +27 -0
  495. package/help/errors/service-declaration-invalid.md +27 -0
  496. package/help/errors/service-declaration-unavailable.md +25 -0
  497. package/help/errors/service-launcher-unsupported.md +30 -0
  498. package/help/errors/service-not-allowed.md +27 -0
  499. package/help/errors/service-unknown.md +23 -0
  500. package/help/errors/service-unready.md +49 -0
  501. package/help/getting-started.md +32 -0
  502. package/help/github.md +48 -0
  503. package/help/identity-and-access.md +44 -0
  504. package/help/jira.md +135 -0
  505. package/help/knowledge.md +47 -0
  506. package/help/mcp.md +30 -0
  507. package/help/models.md +90 -0
  508. package/help/native-capabilities.md +30 -0
  509. package/help/observability.md +41 -0
  510. package/help/operating-agents.md +36 -0
  511. package/help/security.md +27 -0
  512. package/help/troubleshooting/budgets.md +32 -0
  513. package/help/troubleshooting/coding-workers.md +47 -0
  514. package/help/troubleshooting/repository-access.md +27 -0
  515. package/package.json +14 -3
  516. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  517. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  518. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  519. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  520. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  521. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  522. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  523. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  524. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  525. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  526. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  527. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  528. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  529. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  530. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  531. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  532. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  533. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  534. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  535. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  536. package/prisma/migrations/20260930000000_jira_issue_projects/migration.sql +34 -0
  537. package/prisma/migrations/20261001000000_jira_phase2_allowlists/migration.sql +3 -0
  538. package/prisma/migrations/20261001010000_jira_link_types_allowlist/migration.sql +2 -0
  539. package/prisma/migrations/20261002000000_jira_coding_bridge/migration.sql +28 -0
  540. package/prisma/migrations/20261002010000_jira_issue_creation/migration.sql +25 -0
  541. package/prisma/migrations/20261003000000_issue_cost_attribution/migration.sql +56 -0
  542. package/prisma/migrations/20261003010000_coding_run_service_status/migration.sql +23 -0
  543. package/prisma/migrations/20261003020000_viewer_notify/migration.sql +54 -0
  544. package/prisma/migrations/20261003030000_viewer_notify_fixes/migration.sql +47 -0
  545. package/prisma/migrations/20261003040000_viewer_indexes/migration.sql +12 -0
  546. package/prisma/migrations/20261004000000_model_catalog/migration.sql +26 -0
  547. package/prisma/schema.prisma +663 -21
  548. package/dist/mcp/tools/models.d.ts +0 -8
  549. package/dist/mcp/tools/models.js +0 -15
  550. package/dist/providers/llm/pricing-anthropic.d.ts +0 -4
  551. package/dist/providers/llm/pricing-anthropic.js +0 -30
  552. package/dist/providers/llm/pricing-bedrock-claude.d.ts +0 -12
  553. package/dist/providers/llm/pricing-bedrock-claude.js +0 -37
  554. package/dist/providers/llm/pricing.d.ts +0 -30
  555. package/dist/providers/llm/pricing.js +0 -74
@@ -0,0 +1,197 @@
1
+ export const SHIPPED_CATALOG_VERSION = "2026-10-03";
2
+ const ALL_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
3
+ export const SHIPPED_CATALOG = [
4
+ // OpenAI
5
+ {
6
+ provider: "openai",
7
+ modelId: "gpt-4o",
8
+ encoding: "o200k_base",
9
+ inputPerMTok: 2.5,
10
+ outputPerMTok: 10.0,
11
+ cachedInputPerMTok: 1.25,
12
+ cacheWritePerMTok: 2.5,
13
+ efforts: [],
14
+ thinkingMode: "none",
15
+ },
16
+ {
17
+ provider: "openai",
18
+ modelId: "gpt-4o-mini",
19
+ encoding: "o200k_base",
20
+ inputPerMTok: 0.15,
21
+ outputPerMTok: 0.6,
22
+ cachedInputPerMTok: 0.075,
23
+ cacheWritePerMTok: 0.15,
24
+ efforts: [],
25
+ thinkingMode: "none",
26
+ },
27
+ {
28
+ provider: "openai",
29
+ modelId: "gpt-4.1",
30
+ encoding: "o200k_base",
31
+ inputPerMTok: 2.0,
32
+ outputPerMTok: 8.0,
33
+ cachedInputPerMTok: 0.5,
34
+ cacheWritePerMTok: 2.0,
35
+ efforts: [],
36
+ thinkingMode: "none",
37
+ },
38
+ {
39
+ provider: "openai",
40
+ modelId: "gpt-4.1-mini",
41
+ encoding: "o200k_base",
42
+ inputPerMTok: 0.4,
43
+ outputPerMTok: 1.6,
44
+ cachedInputPerMTok: 0.1,
45
+ cacheWritePerMTok: 0.4,
46
+ efforts: [],
47
+ thinkingMode: "none",
48
+ },
49
+ {
50
+ provider: "openai",
51
+ modelId: "gpt-4.1-nano",
52
+ encoding: "o200k_base",
53
+ inputPerMTok: 0.1,
54
+ outputPerMTok: 0.4,
55
+ cachedInputPerMTok: 0.025,
56
+ cacheWritePerMTok: 0.1,
57
+ efforts: [],
58
+ thinkingMode: "none",
59
+ },
60
+ {
61
+ provider: "openai",
62
+ modelId: "gpt-6-astra",
63
+ encoding: "o200k_base",
64
+ inputPerMTok: 10.0,
65
+ outputPerMTok: 50.0,
66
+ cachedInputPerMTok: 1.0,
67
+ cacheWritePerMTok: 12.5,
68
+ efforts: [],
69
+ thinkingMode: "none",
70
+ },
71
+ {
72
+ provider: "openai",
73
+ modelId: "gpt-5.6-sol",
74
+ encoding: "o200k_base",
75
+ inputPerMTok: 4.0,
76
+ outputPerMTok: 20.0,
77
+ cachedInputPerMTok: 0.4,
78
+ cacheWritePerMTok: 5.0,
79
+ efforts: [],
80
+ thinkingMode: "none",
81
+ },
82
+ {
83
+ provider: "openai",
84
+ modelId: "gpt-5.6-terra",
85
+ encoding: "o200k_base",
86
+ inputPerMTok: 2.0,
87
+ outputPerMTok: 12.0,
88
+ cachedInputPerMTok: 0.2,
89
+ cacheWritePerMTok: 2.5,
90
+ efforts: [],
91
+ thinkingMode: "none",
92
+ },
93
+ {
94
+ provider: "openai",
95
+ modelId: "gpt-5.6-luna",
96
+ encoding: "o200k_base",
97
+ inputPerMTok: 0.2,
98
+ outputPerMTok: 1.2,
99
+ cachedInputPerMTok: 0.02,
100
+ cacheWritePerMTok: 0.25,
101
+ efforts: [],
102
+ thinkingMode: "none",
103
+ },
104
+ // Anthropic (direct API)
105
+ {
106
+ provider: "anthropic",
107
+ modelId: "claude-opus-5",
108
+ encoding: "o200k_base",
109
+ inputPerMTok: 5,
110
+ outputPerMTok: 25,
111
+ cachedInputPerMTok: 0.5,
112
+ cacheWritePerMTok: 6.25,
113
+ efforts: ALL_EFFORTS,
114
+ thinkingMode: "adaptive",
115
+ },
116
+ {
117
+ provider: "anthropic",
118
+ modelId: "claude-sonnet-5",
119
+ encoding: "o200k_base",
120
+ inputPerMTok: 2,
121
+ outputPerMTok: 10,
122
+ cachedInputPerMTok: 0.2,
123
+ cacheWritePerMTok: 2.5,
124
+ efforts: ALL_EFFORTS,
125
+ thinkingMode: "adaptive",
126
+ },
127
+ {
128
+ provider: "anthropic",
129
+ modelId: "claude-fable-5",
130
+ encoding: "o200k_base",
131
+ inputPerMTok: 10,
132
+ outputPerMTok: 50,
133
+ cachedInputPerMTok: 1,
134
+ cacheWritePerMTok: 12.5,
135
+ efforts: ALL_EFFORTS,
136
+ thinkingMode: "adaptive",
137
+ },
138
+ // Haiku 4.5 rejects adaptive thinking and any effort level.
139
+ {
140
+ provider: "anthropic",
141
+ modelId: "claude-haiku-4-5",
142
+ encoding: "o200k_base",
143
+ inputPerMTok: 1,
144
+ outputPerMTok: 5,
145
+ cachedInputPerMTok: 0.1,
146
+ cacheWritePerMTok: 1.25,
147
+ efforts: [],
148
+ thinkingMode: "manual",
149
+ },
150
+ // Bedrock-Claude (`us.` cross-region inference profiles). Effort is never sent
151
+ // through Bedrock (unconfirmed per model), and wardby sends Bedrock no thinking
152
+ // parameter at all, so thinkingMode is inert here; "adaptive" by convention.
153
+ {
154
+ provider: "bedrock-claude",
155
+ modelId: "us.anthropic.claude-sonnet-4-6",
156
+ encoding: "o200k_base",
157
+ inputPerMTok: 3,
158
+ outputPerMTok: 15,
159
+ cachedInputPerMTok: 0.3,
160
+ cacheWritePerMTok: 3.75,
161
+ efforts: [],
162
+ thinkingMode: "adaptive",
163
+ },
164
+ {
165
+ provider: "bedrock-claude",
166
+ modelId: "us.anthropic.claude-opus-4-6-v1",
167
+ encoding: "o200k_base",
168
+ inputPerMTok: 5,
169
+ outputPerMTok: 25,
170
+ cachedInputPerMTok: 0.5,
171
+ cacheWritePerMTok: 6.25,
172
+ efforts: [],
173
+ thinkingMode: "adaptive",
174
+ },
175
+ {
176
+ provider: "bedrock-claude",
177
+ modelId: "us.anthropic.claude-opus-4-8",
178
+ encoding: "o200k_base",
179
+ inputPerMTok: 5,
180
+ outputPerMTok: 25,
181
+ cachedInputPerMTok: 0.5,
182
+ cacheWritePerMTok: 6.25,
183
+ efforts: [],
184
+ thinkingMode: "adaptive",
185
+ },
186
+ {
187
+ provider: "bedrock-claude",
188
+ modelId: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
189
+ encoding: "o200k_base",
190
+ inputPerMTok: 1,
191
+ outputPerMTok: 5,
192
+ cachedInputPerMTok: 0.1,
193
+ cacheWritePerMTok: 1.25,
194
+ efforts: [],
195
+ thinkingMode: "adaptive",
196
+ },
197
+ ];
@@ -0,0 +1,58 @@
1
+ import { type ModelCatalog } from "./catalog.js";
2
+ export interface CatalogDb {
3
+ modelCatalogEntry: {
4
+ findMany(): Promise<Record<string, unknown>[]>;
5
+ };
6
+ }
7
+ export interface CatalogLog {
8
+ warn(payload: Record<string, unknown>, message: string): void;
9
+ info(payload: Record<string, unknown>, message: string): void;
10
+ }
11
+ export declare function refreshIntervalMs(env?: NodeJS.ProcessEnv): number;
12
+ export declare class CatalogStore {
13
+ private readonly db;
14
+ private catalog;
15
+ private timer;
16
+ private readonly intervalMs;
17
+ private readonly log;
18
+ /** Monotonic id handed out per load attempt (poll or refreshNow), taken before the
19
+ * awaited fetch starts so loads can be ordered by when they were *initiated*, not
20
+ * when they happen to resolve. */
21
+ private loadSeq;
22
+ /** The seq of the load currently reflected in `catalog`. A load whose result arrives
23
+ * after a newer one already applied is discarded — see `applyLoad`. */
24
+ private appliedSeq;
25
+ /** True once `close()` has run; a load already in flight at that point must not
26
+ * assign into `catalog` or log on failure when it eventually settles. */
27
+ private closed;
28
+ /** True while a poll-triggered load is in flight, so a slow load doesn't overlap
29
+ * with the next interval tick. */
30
+ private polling;
31
+ constructor(db: CatalogDb, options?: {
32
+ intervalMs?: number;
33
+ log?: CatalogLog;
34
+ });
35
+ start(): Promise<void>;
36
+ current(): ModelCatalog;
37
+ refreshNow(): Promise<void>;
38
+ close(): void;
39
+ /** Runs one load, then applies it only if it is still the newest load to have
40
+ * started and the store hasn't been closed in the meantime. Rejects (without
41
+ * touching `catalog`) if the underlying load fails. */
42
+ private applyLoad;
43
+ private load;
44
+ }
45
+ /**
46
+ * Starts a store against `db`, installs it as what `currentModelCatalog()`
47
+ * returns process-wide, and returns it. Throws (via `CatalogStore.start()`)
48
+ * if the database is unreachable — every process that calls this fails
49
+ * fast at startup rather than silently running on the shipped catalog
50
+ * alone, which would quietly re-enable models an admin turned off.
51
+ */
52
+ export declare function startModelCatalog(db: CatalogDb, options?: {
53
+ intervalMs?: number;
54
+ log?: CatalogLog;
55
+ }): Promise<CatalogStore>;
56
+ export declare function installModelCatalog(store: CatalogStore): void;
57
+ export declare function currentModelCatalog(): ModelCatalog;
58
+ export declare function uninstallModelCatalogForTests(): void;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Holds this process's merged model catalog. Loads it at startup (failing
3
+ * the process if the database is unreachable: running on the shipped catalog
4
+ * alone would quietly re-enable models an admin turned off), then polls
5
+ * ModelCatalogEntry every WARDBY_MODEL_CATALOG_REFRESH_SECONDS (default 45)
6
+ * and swaps in a new immutable catalog. A failed poll keeps the last good
7
+ * catalog. current() is synchronous: per-token pricing reads it.
8
+ *
9
+ * One store per process (serve, mcp, scheduler); installModelCatalog makes
10
+ * it what currentModelCatalog() returns everywhere. Before a store is
11
+ * installed (unit tests, offline CLI commands) currentModelCatalog() is the
12
+ * shipped catalog.
13
+ */
14
+ import { logger } from "../../core/logger.js";
15
+ import { buildCatalog, rowFromRecord, shippedCatalog } from "./catalog.js";
16
+ import { SHIPPED_CATALOG, SHIPPED_CATALOG_VERSION } from "./catalog-shipped.js";
17
+ const DEFAULT_REFRESH_SECONDS = 45;
18
+ export function refreshIntervalMs(env = process.env) {
19
+ const raw = env.WARDBY_MODEL_CATALOG_REFRESH_SECONDS;
20
+ if (raw === undefined || raw === "")
21
+ return DEFAULT_REFRESH_SECONDS * 1000;
22
+ if (!/^[1-9]\d*$/.test(raw)) {
23
+ throw new Error(`WARDBY_MODEL_CATALOG_REFRESH_SECONDS must be a positive whole number of seconds (got "${raw}").`);
24
+ }
25
+ return Number(raw) * 1000;
26
+ }
27
+ export class CatalogStore {
28
+ db;
29
+ catalog = shippedCatalog();
30
+ timer;
31
+ intervalMs;
32
+ log;
33
+ /** Monotonic id handed out per load attempt (poll or refreshNow), taken before the
34
+ * awaited fetch starts so loads can be ordered by when they were *initiated*, not
35
+ * when they happen to resolve. */
36
+ loadSeq = 0;
37
+ /** The seq of the load currently reflected in `catalog`. A load whose result arrives
38
+ * after a newer one already applied is discarded — see `applyLoad`. */
39
+ appliedSeq = 0;
40
+ /** True once `close()` has run; a load already in flight at that point must not
41
+ * assign into `catalog` or log on failure when it eventually settles. */
42
+ closed = false;
43
+ /** True while a poll-triggered load is in flight, so a slow load doesn't overlap
44
+ * with the next interval tick. */
45
+ polling = false;
46
+ constructor(db, options = {}) {
47
+ this.db = db;
48
+ this.intervalMs = options.intervalMs ?? refreshIntervalMs();
49
+ this.log = options.log ?? logger.child({ module: "model-catalog" });
50
+ }
51
+ async start() {
52
+ if (this.timer) {
53
+ clearInterval(this.timer);
54
+ this.timer = undefined;
55
+ }
56
+ this.closed = false;
57
+ try {
58
+ await this.applyLoad();
59
+ }
60
+ catch (err) {
61
+ throw new Error(`Could not load the model catalog from the database: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
62
+ }
63
+ this.timer = setInterval(() => {
64
+ if (this.polling)
65
+ return;
66
+ this.polling = true;
67
+ this.applyLoad().then(() => {
68
+ this.polling = false;
69
+ }, (err) => {
70
+ this.polling = false;
71
+ if (this.closed)
72
+ return;
73
+ this.log.warn({ event: "models.catalog.refresh_failed", err: err instanceof Error ? err.message : String(err) }, "model catalog refresh failed; keeping the last good catalog");
74
+ });
75
+ }, this.intervalMs);
76
+ this.timer.unref?.();
77
+ }
78
+ current() {
79
+ return this.catalog;
80
+ }
81
+ async refreshNow() {
82
+ await this.applyLoad();
83
+ }
84
+ close() {
85
+ this.closed = true;
86
+ if (this.timer)
87
+ clearInterval(this.timer);
88
+ this.timer = undefined;
89
+ }
90
+ /** Runs one load, then applies it only if it is still the newest load to have
91
+ * started and the store hasn't been closed in the meantime. Rejects (without
92
+ * touching `catalog`) if the underlying load fails. */
93
+ async applyLoad() {
94
+ const seq = ++this.loadSeq;
95
+ const next = await this.load();
96
+ if (this.closed)
97
+ return;
98
+ if (seq > this.appliedSeq) {
99
+ this.catalog = next;
100
+ this.appliedSeq = seq;
101
+ }
102
+ }
103
+ async load() {
104
+ const records = await this.db.modelCatalogEntry.findMany();
105
+ const rows = [];
106
+ for (const record of records) {
107
+ const row = rowFromRecord(record);
108
+ if (row)
109
+ rows.push(row);
110
+ else
111
+ this.log.warn({ event: "models.catalog.row_invalid", provider: record.provider, modelId: record.modelId }, "skipping a malformed ModelCatalogEntry row");
112
+ }
113
+ return buildCatalog(SHIPPED_CATALOG, rows, SHIPPED_CATALOG_VERSION, (message) => this.log.warn({ event: "models.catalog.conflict" }, message));
114
+ }
115
+ }
116
+ /**
117
+ * Starts a store against `db`, installs it as what `currentModelCatalog()`
118
+ * returns process-wide, and returns it. Throws (via `CatalogStore.start()`)
119
+ * if the database is unreachable — every process that calls this fails
120
+ * fast at startup rather than silently running on the shipped catalog
121
+ * alone, which would quietly re-enable models an admin turned off.
122
+ */
123
+ export async function startModelCatalog(db, options = {}) {
124
+ const store = new CatalogStore(db, options);
125
+ await store.start();
126
+ installModelCatalog(store);
127
+ return store;
128
+ }
129
+ let installed;
130
+ export function installModelCatalog(store) {
131
+ installed = store;
132
+ }
133
+ export function currentModelCatalog() {
134
+ return installed?.current() ?? shippedCatalog();
135
+ }
136
+ export function uninstallModelCatalogForTests() {
137
+ installed = undefined;
138
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The model catalog's shapes. A CatalogEntry is everything wardby needs to
3
+ * route, price, tokenize and shape requests for one model; every field is
4
+ * required (CLAUDE.md "LLM pricing tables — STRICT": cache rates are never
5
+ * omitted and never derived).
6
+ */
7
+ import type { TokenizerEncoding } from "./pricing-core.js";
8
+ import { type LlmEffort } from "./types.js";
9
+ export declare const MODEL_PROVIDERS: readonly ["openai", "anthropic", "bedrock-claude"];
10
+ export type ModelProvider = (typeof MODEL_PROVIDERS)[number];
11
+ /**
12
+ * How a Claude model takes extended thinking. adaptive: `{type: "adaptive"}`
13
+ * plus an effort level. manual: `{type: "enabled", budget_tokens}` and no
14
+ * effort (Claude Haiku 4.5 returns a 400 for adaptive). none: no thinking
15
+ * parameter (OpenAI models).
16
+ */
17
+ export declare const THINKING_MODES: readonly ["adaptive", "manual", "none"];
18
+ export type ThinkingMode = (typeof THINKING_MODES)[number];
19
+ export declare const TOKENIZER_ENCODINGS: readonly ["cl100k_base", "o200k_base"];
20
+ export interface CatalogEntry {
21
+ provider: ModelProvider;
22
+ /** Exact string an Agent.model must equal. */
23
+ modelId: string;
24
+ encoding: TokenizerEncoding;
25
+ inputPerMTok: number;
26
+ outputPerMTok: number;
27
+ cachedInputPerMTok: number;
28
+ cacheWritePerMTok: number;
29
+ /** Effort levels the model accepts; empty = never send one. */
30
+ efforts: readonly LlmEffort[];
31
+ thinkingMode: ThinkingMode;
32
+ }
33
+ /** An entry as the merged catalog serves it. */
34
+ export interface ResolvedCatalogEntry extends CatalogEntry {
35
+ origin: "shipped" | "override";
36
+ /** "shipped:<SHIPPED_CATALOG_VERSION>" or the override row's updatedAt (ISO). */
37
+ priceVersion: string;
38
+ /** Overrides of a shipped model only: whether the shipped entry now differs. */
39
+ shippedDiffers?: boolean;
40
+ /** Overrides only. */
41
+ sourceUrl?: string;
42
+ updatedBy?: string;
43
+ updatedAt?: Date;
44
+ }
45
+ /** A ModelCatalogEntry row, validated. */
46
+ export interface CatalogRow extends CatalogEntry {
47
+ enabled: boolean;
48
+ sourceUrl: string;
49
+ updatedBy: string;
50
+ /** When the row was first written: decides which provider owns a non-shipped id (ownerOf). */
51
+ createdAt: Date;
52
+ updatedAt: Date;
53
+ }
54
+ export type ModelUnavailableReason = "not_in_catalog" | "disabled" | "provider_not_configured";
55
+ /** A model the deployment cannot run. Thrown before any spend. */
56
+ export declare class ModelUnavailableError extends Error {
57
+ readonly modelId: string;
58
+ readonly reason: ModelUnavailableReason;
59
+ readonly code: "model_unavailable";
60
+ constructor(modelId: string, reason: ModelUnavailableReason);
61
+ }
62
+ /** Strips a resolved entry down to the stored snapshot shape. */
63
+ export declare function entryOf(entry: CatalogEntry): CatalogEntry;
64
+ export declare function sameEntry(a: CatalogEntry, b: CatalogEntry): boolean;
65
+ /** Parses a stored snapshot (Run.pricingSnapshot, CodingProxySession.catalogEntry); null if absent or malformed. */
66
+ export declare function parseStoredEntry(value: unknown): CatalogEntry | null;
@@ -0,0 +1,64 @@
1
+ import { isLlmEffort } from "./types.js";
2
+ export const MODEL_PROVIDERS = ["openai", "anthropic", "bedrock-claude"];
3
+ /**
4
+ * How a Claude model takes extended thinking. adaptive: `{type: "adaptive"}`
5
+ * plus an effort level. manual: `{type: "enabled", budget_tokens}` and no
6
+ * effort (Claude Haiku 4.5 returns a 400 for adaptive). none: no thinking
7
+ * parameter (OpenAI models).
8
+ */
9
+ export const THINKING_MODES = ["adaptive", "manual", "none"];
10
+ export const TOKENIZER_ENCODINGS = ["cl100k_base", "o200k_base"];
11
+ const REASON_TEXT = {
12
+ not_in_catalog: "is not in this deployment's model catalog",
13
+ disabled: "is disabled in this deployment's model catalog",
14
+ provider_not_configured: "belongs to a provider with no credentials configured in this deployment",
15
+ };
16
+ /** A model the deployment cannot run. Thrown before any spend. */
17
+ export class ModelUnavailableError extends Error {
18
+ modelId;
19
+ reason;
20
+ code = "model_unavailable";
21
+ constructor(modelId, reason) {
22
+ super(`model_unavailable: Model "${modelId}" ${REASON_TEXT[reason]} (reason: ${reason}). See list_models.`);
23
+ this.modelId = modelId;
24
+ this.reason = reason;
25
+ this.name = "ModelUnavailableError";
26
+ }
27
+ }
28
+ /** Strips a resolved entry down to the stored snapshot shape. */
29
+ export function entryOf(entry) {
30
+ return {
31
+ provider: entry.provider,
32
+ modelId: entry.modelId,
33
+ encoding: entry.encoding,
34
+ inputPerMTok: entry.inputPerMTok,
35
+ outputPerMTok: entry.outputPerMTok,
36
+ cachedInputPerMTok: entry.cachedInputPerMTok,
37
+ cacheWritePerMTok: entry.cacheWritePerMTok,
38
+ efforts: [...entry.efforts],
39
+ thinkingMode: entry.thinkingMode,
40
+ };
41
+ }
42
+ export function sameEntry(a, b) {
43
+ return JSON.stringify(entryOf(a)) === JSON.stringify(entryOf(b));
44
+ }
45
+ const rate = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
46
+ /** Parses a stored snapshot (Run.pricingSnapshot, CodingProxySession.catalogEntry); null if absent or malformed. */
47
+ export function parseStoredEntry(value) {
48
+ if (!value || typeof value !== "object" || Array.isArray(value))
49
+ return null;
50
+ const v = value;
51
+ if (!MODEL_PROVIDERS.includes(v.provider))
52
+ return null;
53
+ if (typeof v.modelId !== "string" || v.modelId.length === 0)
54
+ return null;
55
+ if (!TOKENIZER_ENCODINGS.includes(v.encoding))
56
+ return null;
57
+ if (![v.inputPerMTok, v.outputPerMTok, v.cachedInputPerMTok, v.cacheWritePerMTok].every(rate))
58
+ return null;
59
+ if (!Array.isArray(v.efforts) || !v.efforts.every(isLlmEffort))
60
+ return null;
61
+ if (!THINKING_MODES.includes(v.thinkingMode))
62
+ return null;
63
+ return entryOf(v);
64
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The merged model catalog: the shipped catalog (code) overlaid with a
3
+ * deployment's ModelCatalogEntry rows (admins, via set_model). Immutable;
4
+ * CatalogStore swaps in a new one on each refresh. Pure — no I/O.
5
+ *
6
+ * A row replaces the shipped entry with the same (provider, modelId)
7
+ * completely; enabled=false removes the model; a row with no shipped match
8
+ * adds one. Routing is by model id alone, so one model id can belong to only
9
+ * one provider (ownerOf): a row that would claim an id another provider owns
10
+ * is skipped (set_model refuses it at write time; this is the backstop).
11
+ */
12
+ import { type CatalogEntry, type CatalogRow, type ResolvedCatalogEntry } from "./catalog-types.js";
13
+ export declare class ModelCatalog {
14
+ private readonly active;
15
+ private readonly disabled;
16
+ private readonly shipped;
17
+ constructor(active: ReadonlyMap<string, ResolvedCatalogEntry>, disabled: ReadonlyMap<string, ResolvedCatalogEntry>, shipped: ReadonlyMap<string, CatalogEntry>);
18
+ get(modelId: string): ResolvedCatalogEntry | undefined;
19
+ /** Throws ModelUnavailableError (not_in_catalog | disabled). */
20
+ require(modelId: string): ResolvedCatalogEntry;
21
+ entries(): ResolvedCatalogEntry[];
22
+ disabledEntries(): ResolvedCatalogEntry[];
23
+ shippedEntry(modelId: string): CatalogEntry | undefined;
24
+ }
25
+ /** What deciding a model id's owner needs from one of its ModelCatalogEntry rows. */
26
+ export interface CatalogClaim {
27
+ provider: string;
28
+ enabled: boolean;
29
+ createdAt: Date;
30
+ }
31
+ /**
32
+ * Orders claims on one model id: the earliest-created row first, ties broken
33
+ * by provider name. createdAt, never updatedAt: an owner editing its own row
34
+ * (set_model, disable_model) must not hand the id to a row claimed after it.
35
+ */
36
+ export declare function compareClaims(a: CatalogClaim, b: CatalogClaim): number;
37
+ /**
38
+ * The one ownership rule, shared by buildCatalog (the merge) and set_model
39
+ * (its write-time conflict check), so the two can never disagree. A shipped
40
+ * model id ALWAYS belongs to its shipped provider: any row for it under
41
+ * another provider is a dead orphan, however many there are and whenever
42
+ * they were written. A non-shipped id belongs to the provider of its
43
+ * earliest-created row (compareClaims) until reset_model clears every row.
44
+ * `enabled` is the owner's row's (a disabled row still reserves the id); a
45
+ * shipped provider with no row is the untouched, enabled shipped entry.
46
+ * Null only for an id that is neither shipped nor claimed by any row.
47
+ *
48
+ * Which rows count as claims is the caller's call: buildCatalog passes only
49
+ * rows that passed rowFromRecord (CatalogStore drops malformed ones), while
50
+ * set_model passes every raw row, malformed included, so a malformed row
51
+ * still reserves its id until reset_model clears it.
52
+ */
53
+ export declare function ownerOf(shippedEntry: Pick<CatalogEntry, "provider"> | undefined, claims: readonly CatalogClaim[]): {
54
+ provider: string;
55
+ enabled: boolean;
56
+ } | null;
57
+ export declare function buildCatalog(shipped: readonly CatalogEntry[], rows: readonly CatalogRow[], shippedVersion: string, onConflict?: (message: string) => void): ModelCatalog;
58
+ /** The shipped catalog with no overrides (tests, tools without a database, old proxy sessions). */
59
+ export declare function shippedCatalog(): ModelCatalog;
60
+ /** Validates one ModelCatalogEntry record; null (and the caller logs) if it is malformed. */
61
+ export declare function rowFromRecord(record: Record<string, unknown>): CatalogRow | null;