@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,92 @@
1
+ /**
2
+ * Jira Cloud webhook ingress — framework-agnostic, mounted unauthenticated
3
+ * (by OAuth) in streamable-http.ts at /hosts/jira/events. Authenticated by the
4
+ * webhook secret (X-Hub-Signature, WebSub style) over the raw body. The
5
+ * delivery id (X-Atlassian-Webhook-Identifier) is stable across Jira's
6
+ * retries, so it is the dedupe key. Nothing from the body is logged.
7
+ */
8
+ import { Prisma } from "#prisma";
9
+ import { maybePruneHostEventDeliveries } from "./deliveries.js";
10
+ import { routeIssueEvent } from "../../core/issue-events.js";
11
+ import { logger } from "../../core/logger.js";
12
+ import { normalizeJiraEvent, verifyJiraSignature } from "../../providers/issue-tracker/jira-events.js";
13
+ const log = logger.child({ module: "jira-ingress" });
14
+ const SAFE_DELIVERY = /^[A-Za-z0-9._:-]{1,200}$/;
15
+ /** Jira retries a delivery up to 5 times, 5-15 min apart, so 2 h comfortably covers a legitimate replay. */
16
+ const MAX_AGE_MS = 2 * 60 * 60 * 1000;
17
+ const MAX_FUTURE_MS = 5 * 60 * 1000;
18
+ /**
19
+ * Whether the payload's top-level `timestamp` is inside the replay window.
20
+ * Assumed to be epoch milliseconds; a value below 1e12 (before 2001 in ms)
21
+ * is read as seconds. The unit is unverified against a live delivery.
22
+ * A missing or non-numeric timestamp is not fresh.
23
+ */
24
+ function isFresh(payload, nowMs) {
25
+ const raw = payload?.timestamp;
26
+ if (typeof raw !== "number" || !Number.isFinite(raw) || raw <= 0)
27
+ return false;
28
+ const ts = raw < 1e12 ? raw * 1000 : raw;
29
+ return ts >= nowMs - MAX_AGE_MS && ts <= nowMs + MAX_FUTURE_MS;
30
+ }
31
+ export async function handleJiraEventIngress(req, deps) {
32
+ const tracker = deps.trackers.jira;
33
+ if (!tracker)
34
+ return { status: 404, body: { error: "not_found" } };
35
+ if (!verifyJiraSignature(req.rawBody, req.headers["x-hub-signature"], deps.webhookSecret)) {
36
+ return { status: 401, body: { error: "invalid_signature" } };
37
+ }
38
+ // wardby must not act as a person. A lookup failure throws (5xx), so Jira retries the delivery.
39
+ const identity = await tracker.identity();
40
+ if (identity.accountType === "atlassian") {
41
+ log.error("Jira token belongs to a person; refusing deliveries (use a service account)");
42
+ return { status: 503, body: { error: "jira_personal_account" } };
43
+ }
44
+ const deliveryId = req.headers["x-atlassian-webhook-identifier"];
45
+ if (!deliveryId || !SAFE_DELIVERY.test(deliveryId)) {
46
+ return { status: 400, body: { error: "missing_delivery_headers" } };
47
+ }
48
+ let payload;
49
+ try {
50
+ payload = JSON.parse(req.rawBody);
51
+ }
52
+ catch {
53
+ return { status: 400, body: { error: "invalid_json" } };
54
+ }
55
+ // Replay protection: the signature covers the body, so an old captured delivery would otherwise verify forever.
56
+ if (!isFresh(payload, (deps.now ?? Date.now)()))
57
+ return { status: 202, body: { ignored: "stale" } };
58
+ const event = normalizeJiraEvent(payload, identity.accountId);
59
+ // An event we don't act on must never claim the delivery id (see the GitHub ingress).
60
+ if (!event)
61
+ return { status: 202, body: { ignored: true } };
62
+ try {
63
+ await deps.db.hostEventDelivery.create({ data: { provider: "jira", deliveryId } });
64
+ }
65
+ catch (err) {
66
+ if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002") {
67
+ return { status: 202, body: { duplicate: true } };
68
+ }
69
+ throw err;
70
+ }
71
+ await maybePruneHostEventDeliveries(deps.db, new Date());
72
+ // A routing failure must not leave the delivery permanently marked done:
73
+ // un-record it and rethrow so Jira's retry is routed for real.
74
+ try {
75
+ const routed = await routeIssueEvent(event, { db: deps.db, executor: deps.executor, trackers: deps.trackers });
76
+ log.info({ kinds: event.kinds, deliveryId, runIds: routed.runIds }, "jira event routed");
77
+ return {
78
+ status: 202,
79
+ body: { runIds: routed.runIds },
80
+ afterResponse: async () => {
81
+ for (const followUp of routed.followUps)
82
+ await followUp();
83
+ },
84
+ };
85
+ }
86
+ catch (err) {
87
+ await deps.db.hostEventDelivery
88
+ .deleteMany({ where: { provider: "jira", deliveryId } })
89
+ .catch((delErr) => log.warn({ err: delErr }, "could not roll back the delivery record after a routing failure"));
90
+ throw err;
91
+ }
92
+ }
@@ -1,10 +1,19 @@
1
1
  import { type WardbyMcpServer } from "./server.js";
2
- import type { McpProviders } from "./context.js";
2
+ import type { McpProviders, McpRequestContext } from "./context.js";
3
+ import type { Principal, PrismaClient } from "#prisma";
3
4
  import { type SecretElicitationUrlBuilder } from "./tools/secrets.js";
5
+ /**
6
+ * stdio's one fixed identity: the local operator (LOCAL_PRINCIPAL), trusted
7
+ * with every supported scope and every role — whoever can start the
8
+ * process already holds the database and its keys.
9
+ */
10
+ export declare function localOperatorContext(principal: Principal, providers: McpProviders, db: PrismaClient): McpRequestContext;
4
11
  /** Registers the full Phase 4 tool surface — every module, in one place. */
5
12
  export declare function registerAllTools(mcp: WardbyMcpServer, opts: {
6
13
  secretElicitationUrl: SecretElicitationUrlBuilder;
7
14
  secretElicitationProtocol: boolean;
15
+ /** Rebuilds the process's installed model CatalogStore after set_model/disable_model/reset_model. */
16
+ refreshModelCatalog?: () => Promise<void>;
8
17
  }): void;
9
18
  export interface McpProviderComposition {
10
19
  providers: McpProviders;
package/dist/mcp/index.js CHANGED
@@ -1,28 +1,59 @@
1
- import { loadProviderConfig, loadMcpConfig, loadAuthConfig } from "../config/providers.js";
1
+ /**
2
+ * MCP composition root: assembles the real providers, builds one
3
+ * WardbyMcpServer, registers every tool module, and starts whichever
4
+ * transport MCP_TRANSPORT selects. No business logic lives here — this
5
+ * file only wires together pieces every earlier task already built and
6
+ * tested on their own.
7
+ *
8
+ * stdio vs. HTTP diverge on two things a live smoke test surfaced (see the
9
+ * ledger): stdio needs no `MCP_CANONICAL_URI` (there's no HTTP endpoint or
10
+ * OAuth challenge to identify) and constructs no real `AuthProvider` at all
11
+ * (per the design: "stdio local mode: no token; the operator is trusted") —
12
+ * building one unconditionally would make `wardby mcp` over stdio fail on
13
+ * missing `AUTH_JWKS_URI`/`AUTH_SIGNING_KEY` a deployment running stdio-only
14
+ * never needed to set.
15
+ */
16
+ import { loadProviderConfig, loadMcpConfig, loadShutdownDrainSeconds, loadAuthConfig, loadGitHubEventConfig, loadJiraConfig, loadGitHubVcsConfig, } from "../config/providers.js";
2
17
  import { prisma } from "../core/db.js";
18
+ import { waitForInFlightRuns } from "../core/in-flight-runs.js";
3
19
  import { NativeEngine } from "../core/engine-native.js";
4
20
  import { resolveLlmRegistrations, RoutingLlmProvider } from "../providers/llm/index.js";
21
+ import { startModelCatalog } from "../providers/llm/catalog-store.js";
5
22
  import { PostgresDatastore } from "../providers/datastore/index.js";
6
23
  import { PostgresAgentMemory } from "../providers/memory/index.js";
7
24
  import { buildConfiguredExecutor, buildExecutor } from "../providers/executor/index.js";
8
25
  import { buildSecretCipher } from "../providers/secrets/index.js";
26
+ import { buildIssueTrackers } from "../providers/issue-tracker/index.js";
27
+ import { buildHostUserAuthorizers, buildReviewHosts } from "../providers/review-host/index.js";
28
+ import { createRepoAccessGate } from "../core/repo-access.js";
29
+ import { userCallbackPath } from "../core/host-identity-links.js";
9
30
  import { buildAuthProvider } from "../providers/auth/index.js";
31
+ import { GitHubAppClient } from "../providers/vcs/github.js";
10
32
  import { buildMcpServer } from "./server.js";
11
33
  import { countUnattendedSchedules, unattendedSchedulesWarning } from "./unattended-schedules.js";
12
34
  import { runStdioServer } from "./transport/stdio.js";
13
35
  import { startHttpServer } from "./transport/streamable-http.js";
14
36
  import { resolvePrincipal } from "./auth/principal.js";
15
- import { SCOPES_SUPPORTED } from "./auth/resource-server.js";
37
+ import { ROLE_NAMES, SCOPES_SUPPORTED, authenticate } from "./auth/resource-server.js";
16
38
  import { canonicalUrl } from "./transport/http-limits.js";
39
+ import { createViewerApi } from "../viewer/http.js";
40
+ import { createViewerEventBus } from "../viewer/event-bus.js";
17
41
  import { registerAgentTools } from "./tools/agents.js";
42
+ import { registerServiceTools } from "./tools/services.js";
18
43
  import { registerBudgetGroupTools } from "./tools/budget-groups.js";
19
- import { registerModelTools } from "./tools/models.js";
44
+ import { registerModelCatalogTools } from "./tools/model-catalog.js";
45
+ import { registerHelpTools } from "./tools/help.js";
20
46
  import { registerTriggerTool } from "./tools/trigger.js";
21
47
  import { registerToolAuthoringTools } from "./tools/tools.js";
22
48
  import { registerSchedulingTools } from "./tools/scheduling.js";
23
49
  import { registerRunTools } from "./tools/runs.js";
50
+ import { registerCostReportTools } from "./tools/cost-report.js";
24
51
  import { registerDatastoreTools } from "./tools/datastore.js";
25
52
  import { registerSubAgentTools } from "./tools/subagents.js";
53
+ import { registerGrantTools } from "./tools/grants.js";
54
+ import { registerRepositoryTools } from "./tools/repositories.js";
55
+ import { registerIssueProjectTools } from "./tools/issue-projects.js";
56
+ import { registerHostAccountTools } from "./tools/host-accounts.js";
26
57
  import { registerMemoryTools } from "./tools/memory.js";
27
58
  import { registerSecretsTools } from "./tools/secrets.js";
28
59
  import { registerWebhookTools } from "./tools/webhooks.js";
@@ -45,17 +76,46 @@ async function warnIfNothingWillFireSchedules() {
45
76
  }
46
77
  /** Placeholder identifier for stdio, which has no HTTP endpoint to name. Never surfaced: stdio's fixed context always holds every scope, so no scope challenge is ever built against it. */
47
78
  const STDIO_PLACEHOLDER_URI = "urn:wardby:local-stdio";
79
+ /**
80
+ * stdio's one fixed identity: the local operator (LOCAL_PRINCIPAL), trusted
81
+ * with every supported scope and every role — whoever can start the
82
+ * process already holds the database and its keys.
83
+ */
84
+ export function localOperatorContext(principal, providers, db) {
85
+ return {
86
+ principal,
87
+ scopes: new Set(SCOPES_SUPPORTED),
88
+ roles: [...ROLE_NAMES],
89
+ // Full access to every resource (resource-sharing grants spec §3.9),
90
+ // but never past the binding rules.
91
+ operator: true,
92
+ canonicalUri: STDIO_PLACEHOLDER_URI,
93
+ providers,
94
+ db,
95
+ clientSupportsTasks: false,
96
+ // Placeholder — server.ts's resolveCtx overwrites this with the
97
+ // current call's real mcpReq on every dispatch.
98
+ mcpReq: { requestState: () => undefined },
99
+ };
100
+ }
48
101
  /** Registers the full Phase 4 tool surface — every module, in one place. */
49
102
  export function registerAllTools(mcp, opts) {
50
103
  registerAgentTools(mcp);
104
+ registerServiceTools(mcp);
51
105
  registerBudgetGroupTools(mcp);
52
- registerModelTools(mcp);
106
+ registerModelCatalogTools(mcp, { refresh: opts.refreshModelCatalog });
107
+ registerHelpTools(mcp);
53
108
  registerTriggerTool(mcp);
54
109
  registerToolAuthoringTools(mcp);
55
110
  registerSchedulingTools(mcp);
56
111
  registerRunTools(mcp);
112
+ registerCostReportTools(mcp);
57
113
  registerDatastoreTools(mcp);
58
114
  registerSubAgentTools(mcp);
115
+ registerGrantTools(mcp);
116
+ registerRepositoryTools(mcp);
117
+ registerIssueProjectTools(mcp);
118
+ registerHostAccountTools(mcp);
59
119
  registerMemoryTools(mcp);
60
120
  registerSecretsTools(mcp, {
61
121
  buildElicitationUrl: opts.secretElicitationUrl,
@@ -75,6 +135,12 @@ export function buildMcpProviders() {
75
135
  const secrets = buildSecretCipher(providerConfig);
76
136
  const datastore = new PostgresDatastore(prisma, secrets);
77
137
  const memory = new PostgresAgentMemory(prisma);
138
+ const reviewHosts = buildReviewHosts();
139
+ const issueTrackers = buildIssueTrackers();
140
+ const hostUserAuthorizers = buildHostUserAuthorizers();
141
+ // One gate (and one cache) for the whole process: set-time checks in the
142
+ // MCP tools, repo_* calls in native runs, coding runs, and host events.
143
+ const repoAccess = createRepoAccessGate({ db: prisma, hosts: reviewHosts });
78
144
  // `nativeProviders` is passed by reference into buildExecutor, and native
79
145
  // runs it drives read `this.providers.executor` at call time (not at
80
146
  // construction time) — so patching `.executor` on afterward, once the
@@ -83,11 +149,33 @@ export function buildMcpProviders() {
83
149
  // through the same composed executor everything else uses. There's no
84
150
  // way to hand the native executor a reference to its own wrapping
85
151
  // RoutingExecutor before that wrapper is constructed.
86
- const nativeProviders = { llm, engine, datastore, secrets, memory };
152
+ const nativeProviders = {
153
+ llm,
154
+ engine,
155
+ datastore,
156
+ secrets,
157
+ memory,
158
+ reviewHosts,
159
+ issueTrackers,
160
+ repoAccess,
161
+ };
87
162
  const nativeExecutor = buildExecutor(providerConfig, nativeProviders, prisma);
88
- const executor = buildConfiguredExecutor({ native: nativeExecutor, db: prisma, providerConfig });
163
+ const executor = buildConfiguredExecutor({ native: nativeExecutor, db: prisma, providerConfig, repoAccess });
89
164
  nativeProviders.executor = executor;
90
- return { providers: { llm, engine, datastore, secrets, executor, memory } };
165
+ return {
166
+ providers: {
167
+ llm,
168
+ engine,
169
+ datastore,
170
+ secrets,
171
+ executor,
172
+ memory,
173
+ reviewHosts,
174
+ issueTrackers,
175
+ hostUserAuthorizers,
176
+ repoAccess,
177
+ },
178
+ };
91
179
  }
92
180
  /** Awaits `promise` (if any), logging and swallowing a rejection instead of propagating it. */
93
181
  async function closeQuietly(promise, what) {
@@ -101,6 +189,16 @@ async function closeQuietly(promise, what) {
101
189
  /** The real CLI entry point: `wardby mcp`. Reads config from the environment, starts stdio or HTTP per MCP_TRANSPORT. */
102
190
  export async function startMcp(options = {}) {
103
191
  const mcpConfig = loadMcpConfig();
192
+ // Parsed up front so a malformed value fails at startup, not at shutdown.
193
+ const drainSeconds = loadShutdownDrainSeconds();
194
+ // Loads the model catalog before anything else: running on the shipped
195
+ // catalog alone (the fallback currentModelCatalog() uses before a store
196
+ // is installed) would quietly re-enable models an admin turned off.
197
+ // `modelCatalog` is handed to registerAllTools as `refreshModelCatalog`,
198
+ // which the model catalog tools (set_model, disable_model, reset_model)
199
+ // call via `modelCatalog.refreshNow()` after each write — there is no
200
+ // separate refresh tool.
201
+ const modelCatalog = await startModelCatalog(prisma);
104
202
  const providers = options.providers ?? buildMcpProviders().providers;
105
203
  await providers.executor.launch?.();
106
204
  if (!options.schedulerAttached)
@@ -115,27 +213,19 @@ export async function startMcp(options = {}) {
115
213
  registerAllTools(mcp, {
116
214
  secretElicitationUrl: (token) => secretElicitationHost.urlFor(token),
117
215
  secretElicitationProtocol: mcpConfig.secretElicitationProtocol,
216
+ refreshModelCatalog: () => modelCatalog.refreshNow(),
118
217
  });
119
218
  // stdio never carries per-call AuthInfo — one fixed, fully-trusted
120
219
  // local identity for the whole connection, per the design's own
121
220
  // "stdio local mode: no token; the operator is trusted."
122
221
  const principal = await resolvePrincipal(mcpConfig.localPrincipal, prisma);
123
- mcp.setFixedContext({
124
- principal,
125
- scopes: new Set(SCOPES_SUPPORTED),
126
- canonicalUri: STDIO_PLACEHOLDER_URI,
127
- providers,
128
- db: prisma,
129
- clientSupportsTasks: false,
130
- // Placeholder — server.ts's resolveCtx overwrites this with the
131
- // current call's real mcpReq on every dispatch.
132
- mcpReq: { requestState: () => undefined },
133
- });
222
+ mcp.setFixedContext(localOperatorContext(principal, providers, prisma));
134
223
  const stdio = runStdioServer(mcp);
135
224
  return {
136
225
  close: async () => {
137
226
  await closeQuietly(stdio.close(), "stdio transport close");
138
227
  await closeQuietly(providers.executor.close?.(), "executor close");
228
+ modelCatalog.close();
139
229
  },
140
230
  };
141
231
  }
@@ -158,11 +248,81 @@ export async function startMcp(options = {}) {
158
248
  registerAllTools(mcp, {
159
249
  secretElicitationUrl: (token) => Promise.resolve(`${httpOrigin}${SECRET_ELICITATION_PATH}?t=${encodeURIComponent(token)}`),
160
250
  secretElicitationProtocol: mcpConfig.secretElicitationProtocol,
251
+ refreshModelCatalog: () => modelCatalog.refreshNow(),
161
252
  });
253
+ const eventConfig = loadGitHubEventConfig();
254
+ const githubConfig = loadGitHubVcsConfig();
255
+ const reviewHosts = providers.reviewHosts;
256
+ const githubEvents = eventConfig.webhookSecret && reviewHosts?.github && githubConfig.appId && githubConfig.privateKey
257
+ ? {
258
+ github: {
259
+ db: prisma,
260
+ executor: providers.executor,
261
+ hosts: reviewHosts,
262
+ repoAccess: providers.repoAccess ?? createRepoAccessGate({ db: prisma, hosts: reviewHosts }),
263
+ ...(providers.issueTrackers ? { issueTrackers: providers.issueTrackers } : {}),
264
+ webhookSecret: eventConfig.webhookSecret,
265
+ appIdentity: (() => {
266
+ const client = new GitHubAppClient({
267
+ appId: githubConfig.appId,
268
+ privateKey: githubConfig.privateKey,
269
+ apiVersion: githubConfig.apiVersion,
270
+ });
271
+ return () => client.appIdentity();
272
+ })(),
273
+ },
274
+ }
275
+ : undefined;
276
+ mcpLog.info({ enabled: Boolean(githubEvents) }, "GitHub host events ingress");
277
+ const jiraConfig = loadJiraConfig();
278
+ const jiraEvents = jiraConfig && providers.issueTrackers?.jira
279
+ ? {
280
+ db: prisma,
281
+ executor: providers.executor,
282
+ trackers: providers.issueTrackers,
283
+ webhookSecret: jiraConfig.webhookSecret,
284
+ }
285
+ : undefined;
286
+ mcpLog.info({ enabled: Boolean(jiraEvents) }, "Jira host events ingress");
287
+ if (jiraEvents) {
288
+ // Best effort: show which Jira account wardby acts as; never blocks startup.
289
+ void providers.issueTrackers?.jira?.identity().then(({ accountId, displayName, accountType }) => accountType === "atlassian"
290
+ ? mcpLog.error({ accountId, displayName, accountType }, "Jira token belongs to a person's account; wardby refuses to act and the Jira ingress answers 503 until a service account token is configured")
291
+ : mcpLog.info({ accountId, displayName, accountType }, "Jira acting as"), (err) => mcpLog.warn({ err: err instanceof Error ? err.message : String(err) }, "could not read the Jira account identity"));
292
+ }
293
+ if (jiraConfig?.tokenExpiresAt && jiraConfig.tokenExpiresAt.getTime() - Date.now() < 14 * 24 * 60 * 60 * 1000) {
294
+ mcpLog.warn({ expiresAt: jiraConfig.tokenExpiresAt.toISOString() }, "the Jira API token expires within 14 days; rotate WARDBY_JIRA_API_TOKEN");
295
+ }
296
+ const hostEvents = githubEvents || jiraEvents
297
+ ? { ...(githubEvents ? githubEvents : {}), ...(jiraEvents ? { jira: jiraEvents } : {}) }
298
+ : undefined;
299
+ const githubAuthorizer = providers.hostUserAuthorizers?.github;
300
+ const hostUserAuth = githubAuthorizer
301
+ ? {
302
+ github: {
303
+ db: prisma,
304
+ authorizer: githubAuthorizer,
305
+ redirectUri: `${httpOrigin}${userCallbackPath("github")}`,
306
+ },
307
+ }
308
+ : undefined;
309
+ mcpLog.info({ enabled: Boolean(hostUserAuth) }, "GitHub account linking");
310
+ const canonicalHref = canonicalUrl(mcpConfig.canonicalUri).href;
311
+ const viewerBus = process.env.DATABASE_URL
312
+ ? createViewerEventBus({ connectionString: process.env.DATABASE_URL })
313
+ : undefined;
314
+ const viewer = viewerBus
315
+ ? createViewerApi({
316
+ db: prisma,
317
+ bus: viewerBus,
318
+ authenticate: (authorization) => authenticate({ authorization }, { authProvider, db: prisma, providers, canonicalUri: canonicalHref }),
319
+ canonicalUri: canonicalHref,
320
+ })
321
+ : undefined;
162
322
  const http = await startHttpServer({
163
323
  mcp,
164
324
  config: {
165
- canonicalUri: canonicalUrl(mcpConfig.canonicalUri).href,
325
+ canonicalUri: canonicalHref,
166
326
  httpBind: mcpConfig.httpBind,
167
327
  authProviderKind,
168
328
  authorizationServer: authConfig.issuer,
@@ -170,6 +330,9 @@ export async function startMcp(options = {}) {
170
330
  },
171
331
  auth: { authProvider, db: prisma, providers },
172
332
  selfHosted,
333
+ hostEvents,
334
+ hostUserAuth,
335
+ viewer,
173
336
  });
174
337
  const cleanupTimer = selfHosted
175
338
  ? setInterval(() => {
@@ -181,7 +344,12 @@ export async function startMcp(options = {}) {
181
344
  if (cleanupTimer)
182
345
  clearInterval(cleanupTimer);
183
346
  await closeQuietly(http.close(), "HTTP transport close");
347
+ await closeQuietly(viewerBus?.close(), "viewer event bus close");
348
+ // Let the runs this instance is executing finish before the executor
349
+ // closes under them; a run abandoned here is lost, never resumed.
350
+ await waitForInFlightRuns(drainSeconds * 1000);
184
351
  await closeQuietly(providers.executor.close?.(), "executor close");
352
+ modelCatalog.close();
185
353
  },
186
354
  };
187
355
  }
@@ -24,11 +24,15 @@
24
24
  */
25
25
  import { McpServer, fromJsonSchema, createRequestStateCodec, CLIENT_CAPABILITIES_META_KEY, } from "@modelcontextprotocol/server";
26
26
  import { randomBytes } from "node:crypto";
27
+ import { readFileSync } from "node:fs";
27
28
  import { requireScope } from "./auth/resource-server.js";
28
- import { McpError } from "./errors.js";
29
+ import { McpError, mapPrismaError } from "./errors.js";
29
30
  import { TASKS_EXTENSION_ID, clientSupportsTasks } from "./capabilities.js";
30
- import { visibleToPrincipal } from "./auth/ownership.js";
31
+ import { readableAgentsWhere } from "./auth/access.js";
32
+ import { grantedIds } from "../core/grants.js";
31
33
  import { logger } from "../core/logger.js";
34
+ /** The package version, reported in MCP server info (package.json sits two levels up from src/mcp and dist/mcp). */
35
+ const SERVER_VERSION = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version;
32
36
  const REQUEST_STATE_KEY_BYTES = 32;
33
37
  /**
34
38
  * REQUEST_STATE_KEY (hex, 32 bytes) shares the requestState HMAC key across
@@ -54,7 +58,7 @@ function loadRequestStateKey(env) {
54
58
  * with the per-agent MCP prompts registered below, which are the concrete,
55
59
  * one-call way to actually do it.
56
60
  */
57
- const SERVER_INSTRUCTIONS = 'wardby hosts reusable LLM agents (a system prompt, model, budget, and attached tools) that normally run on a schedule or webhook trigger. Every agent\'s full system prompt is available via list_agents/get_agent ("systemPrompt" field), and agents you can see are also registered as MCP prompts by name — you can adopt an agent\'s instructions and run them yourself, in this session, right now. This is a good way to shift work like code review left: e.g., before committing, run the "systemPrompt" of a code-review agent against your own working tree using your own tools, rather than waiting for a separately triggered run. Where a pulled prompt names a wardby-specific sandboxed tool, use your own equivalent tool for the same purpose instead.';
61
+ const SERVER_INSTRUCTIONS = 'wardby hosts reusable LLM agents (a system prompt, model, budget, and attached tools) that normally run on a schedule or webhook trigger. Every agent\'s full system prompt is available via list_agents/get_agent ("systemPrompt" field), and agents you can see are also registered as MCP prompts by name — you can adopt an agent\'s instructions and run them yourself, in this session, right now. This is a good way to shift work like code review left: e.g., before committing, run the "systemPrompt" of a code-review agent against your own working tree using your own tools, rather than waiting for a separately triggered run. Where a pulled prompt names a wardby-specific sandboxed tool, use your own equivalent tool for the same purpose instead. To set up a first agent — an architecture keeper or a builder — read the help article "agent-recipes" with get_help_article and follow its procedure.';
58
62
  /** The MCP prompt body for one Agent — the message a client injects when a user invokes it (e.g. as a slash command). */
59
63
  function agentPromptText(agent) {
60
64
  return [
@@ -97,6 +101,7 @@ export function buildMcpServer(opts) {
97
101
  return {
98
102
  principal: extra.principal,
99
103
  scopes: new Set(authInfo.scopes),
104
+ roles: extra.roles ?? [],
100
105
  canonicalUri: opts.config.canonicalUri,
101
106
  providers: opts.providers,
102
107
  db: opts.db,
@@ -117,7 +122,7 @@ export function buildMcpServer(opts) {
117
122
  requestHandlers.push({ method, scope: Array.isArray(scope) ? scope : [scope], handler });
118
123
  }
119
124
  const factory = async () => {
120
- const mcpServer = new McpServer({ name: "wardby", version: "0.0.0" }, {
125
+ const mcpServer = new McpServer({ name: "wardby", version: SERVER_VERSION }, {
121
126
  requestState: { verify: (state, ctx) => requestStateCodec.verify(state, ctx) },
122
127
  instructions: SERVER_INSTRUCTIONS,
123
128
  });
@@ -130,7 +135,14 @@ export function buildMcpServer(opts) {
130
135
  }, async (args, sdkCtx) => {
131
136
  const ctx = resolveCtx(sdkCtx);
132
137
  requireScope(ctx, opts.config.canonicalUri, ...requiredScopes);
133
- return spec.handler(args, ctx);
138
+ try {
139
+ return await spec.handler(args, ctx);
140
+ }
141
+ catch (err) {
142
+ // A raw Prisma error would reach the client verbatim (the SDK
143
+ // renders any thrown error's message) -- see mapPrismaError.
144
+ throw mapPrismaError(err);
145
+ }
134
146
  });
135
147
  }
136
148
  // Non-spec (extension) methods need a { params, result } schema bundle
@@ -143,7 +155,12 @@ export function buildMcpServer(opts) {
143
155
  mcpServer.server.setRequestHandler(method, { params: PERMISSIVE_SCHEMA }, async (params, sdkCtx) => {
144
156
  const ctx = resolveCtx(sdkCtx);
145
157
  requireScope(ctx, opts.config.canonicalUri, ...scope);
146
- return (await handler(params, ctx));
158
+ try {
159
+ return (await handler(params, ctx));
160
+ }
161
+ catch (err) {
162
+ throw mapPrismaError(err);
163
+ }
147
164
  });
148
165
  }
149
166
  // One MCP prompt per Agent this connection can see, so a client that
@@ -154,12 +171,16 @@ export function buildMcpServer(opts) {
154
171
  // resolves it per-dispatch from the SDK's own per-call ServerContext,
155
172
  // not at factory time) — stdio's fixedContext IS set by now
156
173
  // (mcp/index.ts calls setFixedContext before serveStdio ever invokes
157
- // this factory), so stdio sees every agent it owns plus public ones;
158
- // HTTP conservatively falls back to public-only until this factory can
159
- // see request-scoped identity. A DB hiccup here must not break tool
160
- // registration — this is a discoverability nicety, not core function.
174
+ // this factory), so stdio sees every agent it can read;
175
+ // HTTP conservatively falls back to agents shared with everyone (a
176
+ // grant of at least read) until this factory can see request-scoped
177
+ // identity; stdio sees what its principal can read (the operator: all).
178
+ // A DB hiccup here must not break tool registration — this is a
179
+ // discoverability nicety, not core function.
161
180
  try {
162
- const where = fixedContext ? visibleToPrincipal(fixedContext.principal.id) : { ownerId: null };
181
+ const where = fixedContext
182
+ ? await readableAgentsWhere(fixedContext, opts.db)
183
+ : { id: { in: await grantedIds(opts.db, "agent", null, "read") } };
163
184
  const agents = await opts.db.agent.findMany({ where });
164
185
  for (const agent of agents) {
165
186
  mcpServer.registerPrompt(agent.name, {