@wascartech/devbot 0.0.0-stage → 2.1.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 (376) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +638 -2
  3. package/dist/access-grant-store.js +99 -0
  4. package/dist/access-grant-store.js.map +1 -0
  5. package/dist/access-resolve.js +11 -0
  6. package/dist/access-resolve.js.map +1 -0
  7. package/dist/access-rule-store.js +99 -0
  8. package/dist/access-rule-store.js.map +1 -0
  9. package/dist/admin/access-routes.js +73 -0
  10. package/dist/admin/access-routes.js.map +1 -0
  11. package/dist/admin/access-rule-routes.js +107 -0
  12. package/dist/admin/access-rule-routes.js.map +1 -0
  13. package/dist/admin/custom-repos-routes.js +93 -0
  14. package/dist/admin/custom-repos-routes.js.map +1 -0
  15. package/dist/admin/env-routes.js +74 -0
  16. package/dist/admin/env-routes.js.map +1 -0
  17. package/dist/admin/global-settings-routes.js +254 -0
  18. package/dist/admin/global-settings-routes.js.map +1 -0
  19. package/dist/admin/mcp-cleanup.js +12 -0
  20. package/dist/admin/mcp-cleanup.js.map +1 -0
  21. package/dist/admin/mcp-routes.js +169 -0
  22. package/dist/admin/mcp-routes.js.map +1 -0
  23. package/dist/admin/query-params.js +80 -0
  24. package/dist/admin/query-params.js.map +1 -0
  25. package/dist/admin/routes.js +150 -0
  26. package/dist/admin/routes.js.map +1 -0
  27. package/dist/admin/run-history-routes.js +44 -0
  28. package/dist/admin/run-history-routes.js.map +1 -0
  29. package/dist/admin/run-routes.js +99 -0
  30. package/dist/admin/run-routes.js.map +1 -0
  31. package/dist/admin/settings-routes.js +119 -0
  32. package/dist/admin/settings-routes.js.map +1 -0
  33. package/dist/admin/stats-routes.js +51 -0
  34. package/dist/admin/stats-routes.js.map +1 -0
  35. package/dist/admin/task-routes.js +213 -0
  36. package/dist/admin/task-routes.js.map +1 -0
  37. package/dist/admin/test-routes.js +38 -0
  38. package/dist/admin/test-routes.js.map +1 -0
  39. package/dist/admin/volume-routes.js +82 -0
  40. package/dist/admin/volume-routes.js.map +1 -0
  41. package/dist/admin/webhook-routes.js +174 -0
  42. package/dist/admin/webhook-routes.js.map +1 -0
  43. package/dist/agents.js +48 -0
  44. package/dist/agents.js.map +1 -0
  45. package/dist/assignee-value.js +6 -0
  46. package/dist/assignee-value.js.map +1 -0
  47. package/dist/attachments.js +76 -0
  48. package/dist/attachments.js.map +1 -0
  49. package/dist/auto-commands.js +88 -0
  50. package/dist/auto-commands.js.map +1 -0
  51. package/dist/auto-features.js +32 -0
  52. package/dist/auto-features.js.map +1 -0
  53. package/dist/base-branch-store.js +40 -0
  54. package/dist/base-branch-store.js.map +1 -0
  55. package/dist/base-branches.js +9 -0
  56. package/dist/base-branches.js.map +1 -0
  57. package/dist/build-workflow.js +116 -0
  58. package/dist/build-workflow.js.map +1 -0
  59. package/dist/change-request-lifecycle.js +16 -0
  60. package/dist/change-request-lifecycle.js.map +1 -0
  61. package/dist/change-request-store.js +72 -0
  62. package/dist/change-request-store.js.map +1 -0
  63. package/dist/ci-failure.js +80 -0
  64. package/dist/ci-failure.js.map +1 -0
  65. package/dist/cli.js +3 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/config.js +17 -0
  68. package/dist/config.js.map +1 -0
  69. package/dist/conflict-fix.js +178 -0
  70. package/dist/conflict-fix.js.map +1 -0
  71. package/dist/cookie.js +70 -0
  72. package/dist/cookie.js.map +1 -0
  73. package/dist/crypto-util.js +40 -0
  74. package/dist/crypto-util.js.map +1 -0
  75. package/dist/custom-repos-store.js +90 -0
  76. package/dist/custom-repos-store.js.map +1 -0
  77. package/dist/custom-repos-sync.js +118 -0
  78. package/dist/custom-repos-sync.js.map +1 -0
  79. package/dist/db.js +12 -0
  80. package/dist/db.js.map +1 -0
  81. package/dist/devbot-scripts.js +18 -0
  82. package/dist/devbot-scripts.js.map +1 -0
  83. package/dist/devcontainer.js +141 -0
  84. package/dist/devcontainer.js.map +1 -0
  85. package/dist/env-config-store.js +132 -0
  86. package/dist/env-config-store.js.map +1 -0
  87. package/dist/error-log-store.js +193 -0
  88. package/dist/error-log-store.js.map +1 -0
  89. package/dist/git.js +605 -0
  90. package/dist/git.js.map +1 -0
  91. package/dist/global-queue.js +127 -0
  92. package/dist/global-queue.js.map +1 -0
  93. package/dist/global-settings-store.js +307 -0
  94. package/dist/global-settings-store.js.map +1 -0
  95. package/dist/help.js +41 -0
  96. package/dist/help.js.map +1 -0
  97. package/dist/http-csp.js +15 -0
  98. package/dist/http-csp.js.map +1 -0
  99. package/dist/http-util.js +40 -0
  100. package/dist/http-util.js.map +1 -0
  101. package/dist/idempotency.js +50 -0
  102. package/dist/idempotency.js.map +1 -0
  103. package/dist/lifecycle.js +234 -0
  104. package/dist/lifecycle.js.map +1 -0
  105. package/dist/logger.js +33 -0
  106. package/dist/logger.js.map +1 -0
  107. package/dist/lsp-servers.js +81 -0
  108. package/dist/lsp-servers.js.map +1 -0
  109. package/dist/mcp/auth.js +62 -0
  110. package/dist/mcp/auth.js.map +1 -0
  111. package/dist/mcp/effective-mcp.js +42 -0
  112. package/dist/mcp/effective-mcp.js.map +1 -0
  113. package/dist/mcp/oauth-refresh.js +138 -0
  114. package/dist/mcp/oauth-refresh.js.map +1 -0
  115. package/dist/mcp/peer-sync.js +109 -0
  116. package/dist/mcp/peer-sync.js.map +1 -0
  117. package/dist/mcp/registry.js +54 -0
  118. package/dist/mcp/registry.js.map +1 -0
  119. package/dist/mcp/runner-bridge.js +93 -0
  120. package/dist/mcp/runner-bridge.js.map +1 -0
  121. package/dist/mcp/server.js +173 -0
  122. package/dist/mcp/server.js.map +1 -0
  123. package/dist/mcp/tools/_helpers.js +88 -0
  124. package/dist/mcp/tools/_helpers.js.map +1 -0
  125. package/dist/mcp/tools/attachments.js +117 -0
  126. package/dist/mcp/tools/attachments.js.map +1 -0
  127. package/dist/mcp/tools/cicd.js +105 -0
  128. package/dist/mcp/tools/cicd.js.map +1 -0
  129. package/dist/mcp/tools/discovery.js +34 -0
  130. package/dist/mcp/tools/discovery.js.map +1 -0
  131. package/dist/mcp/tools/issues.js +56 -0
  132. package/dist/mcp/tools/issues.js.map +1 -0
  133. package/dist/mcp/tools/merge_requests.js +67 -0
  134. package/dist/mcp/tools/merge_requests.js.map +1 -0
  135. package/dist/mcp/tools/metadata.js +127 -0
  136. package/dist/mcp/tools/metadata.js.map +1 -0
  137. package/dist/mcp/tools/peer_sync.js +43 -0
  138. package/dist/mcp/tools/peer_sync.js.map +1 -0
  139. package/dist/mcp/tools/repository.js +178 -0
  140. package/dist/mcp/tools/repository.js.map +1 -0
  141. package/dist/mcp/tools/work_tracking.js +125 -0
  142. package/dist/mcp/tools/work_tracking.js.map +1 -0
  143. package/dist/mcp/tools/workitems.js +30 -0
  144. package/dist/mcp/tools/workitems.js.map +1 -0
  145. package/dist/mcp/volume-files.js +187 -0
  146. package/dist/mcp/volume-files.js.map +1 -0
  147. package/dist/mcp-auth-store.js +134 -0
  148. package/dist/mcp-auth-store.js.map +1 -0
  149. package/dist/mcp-config-store.js +83 -0
  150. package/dist/mcp-config-store.js.map +1 -0
  151. package/dist/mention.js +512 -0
  152. package/dist/mention.js.map +1 -0
  153. package/dist/migrate.js +73 -0
  154. package/dist/migrate.js.map +1 -0
  155. package/dist/mr-assignee.js +71 -0
  156. package/dist/mr-assignee.js.map +1 -0
  157. package/dist/mr-content.js +90 -0
  158. package/dist/mr-content.js.map +1 -0
  159. package/dist/oauth-routes.js +54 -0
  160. package/dist/oauth-routes.js.map +1 -0
  161. package/dist/onboarding-allowlist.js +32 -0
  162. package/dist/onboarding-allowlist.js.map +1 -0
  163. package/dist/opencode.js +291 -0
  164. package/dist/opencode.js.map +1 -0
  165. package/dist/outbound-webhook-store.js +229 -0
  166. package/dist/outbound-webhook-store.js.map +1 -0
  167. package/dist/outbound-webhook.js +314 -0
  168. package/dist/outbound-webhook.js.map +1 -0
  169. package/dist/path-sandbox.js +200 -0
  170. package/dist/path-sandbox.js.map +1 -0
  171. package/dist/platform/git-auth.js +34 -0
  172. package/dist/platform/git-auth.js.map +1 -0
  173. package/dist/platform/gitealike/attachments.js +62 -0
  174. package/dist/platform/gitealike/attachments.js.map +1 -0
  175. package/dist/platform/gitealike/base.js +935 -0
  176. package/dist/platform/gitealike/base.js.map +1 -0
  177. package/dist/platform/gitealike/forgejo.js +16 -0
  178. package/dist/platform/gitealike/forgejo.js.map +1 -0
  179. package/dist/platform/gitealike/gitea.js +16 -0
  180. package/dist/platform/gitealike/gitea.js.map +1 -0
  181. package/dist/platform/gitealike/http.js +152 -0
  182. package/dist/platform/gitealike/http.js.map +1 -0
  183. package/dist/platform/gitealike/schemas.js +284 -0
  184. package/dist/platform/gitealike/schemas.js.map +1 -0
  185. package/dist/platform/github/attachments.js +52 -0
  186. package/dist/platform/github/attachments.js.map +1 -0
  187. package/dist/platform/github/http.js +153 -0
  188. package/dist/platform/github/http.js.map +1 -0
  189. package/dist/platform/github/index.js +936 -0
  190. package/dist/platform/github/index.js.map +1 -0
  191. package/dist/platform/github/schemas.js +308 -0
  192. package/dist/platform/github/schemas.js.map +1 -0
  193. package/dist/platform/github/zip.js +85 -0
  194. package/dist/platform/github/zip.js.map +1 -0
  195. package/dist/platform/gitlab/admin.js +105 -0
  196. package/dist/platform/gitlab/admin.js.map +1 -0
  197. package/dist/platform/gitlab/api.js +229 -0
  198. package/dist/platform/gitlab/api.js.map +1 -0
  199. package/dist/platform/gitlab/attachments.js +79 -0
  200. package/dist/platform/gitlab/attachments.js.map +1 -0
  201. package/dist/platform/gitlab/http.js +165 -0
  202. package/dist/platform/gitlab/http.js.map +1 -0
  203. package/dist/platform/gitlab/index.js +630 -0
  204. package/dist/platform/gitlab/index.js.map +1 -0
  205. package/dist/platform/gitlab/oauth.js +58 -0
  206. package/dist/platform/gitlab/oauth.js.map +1 -0
  207. package/dist/platform/gitlab/read.js +182 -0
  208. package/dist/platform/gitlab/read.js.map +1 -0
  209. package/dist/platform/gitlab/schemas-read.js +274 -0
  210. package/dist/platform/gitlab/schemas-read.js.map +1 -0
  211. package/dist/platform/gitlab/schemas.js +251 -0
  212. package/dist/platform/gitlab/schemas.js.map +1 -0
  213. package/dist/platform/gitlab/signature.js +52 -0
  214. package/dist/platform/gitlab/signature.js.map +1 -0
  215. package/dist/platform/index.js +38 -0
  216. package/dist/platform/index.js.map +1 -0
  217. package/dist/platform/port.js +26 -0
  218. package/dist/platform/port.js.map +1 -0
  219. package/dist/platform/types.js +80 -0
  220. package/dist/platform/types.js.map +1 -0
  221. package/dist/podman.js +119 -0
  222. package/dist/podman.js.map +1 -0
  223. package/dist/project-sync.js +69 -0
  224. package/dist/project-sync.js.map +1 -0
  225. package/dist/prompt.js +47 -0
  226. package/dist/prompt.js.map +1 -0
  227. package/dist/queue-store.js +236 -0
  228. package/dist/queue-store.js.map +1 -0
  229. package/dist/queue.js +129 -0
  230. package/dist/queue.js.map +1 -0
  231. package/dist/redact.js +23 -0
  232. package/dist/redact.js.map +1 -0
  233. package/dist/run-files.js +297 -0
  234. package/dist/run-files.js.map +1 -0
  235. package/dist/run-filters.js +54 -0
  236. package/dist/run-filters.js.map +1 -0
  237. package/dist/run-history-store.js +229 -0
  238. package/dist/run-history-store.js.map +1 -0
  239. package/dist/run-log-sink.js +270 -0
  240. package/dist/run-log-sink.js.map +1 -0
  241. package/dist/run-log.js +97 -0
  242. package/dist/run-log.js.map +1 -0
  243. package/dist/run-usage.js +29 -0
  244. package/dist/run-usage.js.map +1 -0
  245. package/dist/run-view.js +112 -0
  246. package/dist/run-view.js.map +1 -0
  247. package/dist/runner.js +1094 -0
  248. package/dist/runner.js.map +1 -0
  249. package/dist/runtime-apply.js +26 -0
  250. package/dist/runtime-apply.js.map +1 -0
  251. package/dist/runtime-settings.js +71 -0
  252. package/dist/runtime-settings.js.map +1 -0
  253. package/dist/runtime-state.js +19 -0
  254. package/dist/runtime-state.js.map +1 -0
  255. package/dist/server.js +119 -0
  256. package/dist/server.js.map +1 -0
  257. package/dist/settings-store.js +320 -0
  258. package/dist/settings-store.js.map +1 -0
  259. package/dist/status.js +121 -0
  260. package/dist/status.js.map +1 -0
  261. package/dist/stop.js +56 -0
  262. package/dist/stop.js.map +1 -0
  263. package/dist/sweeps.js +87 -0
  264. package/dist/sweeps.js.map +1 -0
  265. package/dist/task-log.js +279 -0
  266. package/dist/task-log.js.map +1 -0
  267. package/dist/task-view.js +62 -0
  268. package/dist/task-view.js.map +1 -0
  269. package/dist/token-store.js +68 -0
  270. package/dist/token-store.js.map +1 -0
  271. package/dist/types/access.js +74 -0
  272. package/dist/types/access.js.map +1 -0
  273. package/dist/types/custom-repos.js +28 -0
  274. package/dist/types/custom-repos.js.map +1 -0
  275. package/dist/types/env-config.js +25 -0
  276. package/dist/types/env-config.js.map +1 -0
  277. package/dist/types/env.js +190 -0
  278. package/dist/types/env.js.map +1 -0
  279. package/dist/types/global-settings.js +178 -0
  280. package/dist/types/global-settings.js.map +1 -0
  281. package/dist/types/lsp-servers.js +145 -0
  282. package/dist/types/lsp-servers.js.map +1 -0
  283. package/dist/types/mcp-config.js +77 -0
  284. package/dist/types/mcp-config.js.map +1 -0
  285. package/dist/types/opencode.js +59 -0
  286. package/dist/types/opencode.js.map +1 -0
  287. package/dist/types/outbound-webhook.js +56 -0
  288. package/dist/types/outbound-webhook.js.map +1 -0
  289. package/dist/types/project-settings.js +114 -0
  290. package/dist/types/project-settings.js.map +1 -0
  291. package/dist/types/provider-registry.js +37 -0
  292. package/dist/types/provider-registry.js.map +1 -0
  293. package/dist/types/runtime-settings.js +78 -0
  294. package/dist/types/runtime-settings.js.map +1 -0
  295. package/dist/usage-stats.js +159 -0
  296. package/dist/usage-stats.js.map +1 -0
  297. package/dist/version.js +19 -0
  298. package/dist/version.js.map +1 -0
  299. package/dist/volume-gc.js +193 -0
  300. package/dist/volume-gc.js.map +1 -0
  301. package/dist/volume-manage.js +191 -0
  302. package/dist/volume-manage.js.map +1 -0
  303. package/dist/volume-store.js +122 -0
  304. package/dist/volume-store.js.map +1 -0
  305. package/dist/webhook.js +1106 -0
  306. package/dist/webhook.js.map +1 -0
  307. package/dist/work-item-auto-store.js +75 -0
  308. package/dist/work-item-auto-store.js.map +1 -0
  309. package/dist/work-item-branch-store.js +37 -0
  310. package/dist/work-item-branch-store.js.map +1 -0
  311. package/migrations/0001_initial.sql +59 -0
  312. package/migrations/0002_queue_status.sql +15 -0
  313. package/migrations/0003_work_item_base_branch.sql +14 -0
  314. package/migrations/0004_project_settings.sql +15 -0
  315. package/migrations/0005_global_settings.sql +34 -0
  316. package/migrations/0006_model_variants.sql +8 -0
  317. package/migrations/0007_container_error_logs.sql +21 -0
  318. package/migrations/0008_project_access_grants.sql +16 -0
  319. package/migrations/0009_drop_imported_legacy.sql +4 -0
  320. package/migrations/0010_container_error_log_model.sql +6 -0
  321. package/migrations/0011_container_error_log_title.sql +5 -0
  322. package/migrations/0012_pending_task_cancel.sql +6 -0
  323. package/migrations/0013_builder_image.sql +6 -0
  324. package/migrations/0014_build_workflow.sql +7 -0
  325. package/migrations/0015_access_rules.sql +24 -0
  326. package/migrations/0016_trigger_policy.sql +17 -0
  327. package/migrations/0017_attachment_upload.sql +8 -0
  328. package/migrations/0018_work_item_branch.sql +11 -0
  329. package/migrations/0019_auto_push_mr.sql +18 -0
  330. package/migrations/0020_outbound_webhooks.sql +47 -0
  331. package/migrations/0021_runtime_settings.sql +12 -0
  332. package/migrations/0022_auto_resolve_conflicts.sql +17 -0
  333. package/migrations/0023_ci_fail_auto_report.sql +27 -0
  334. package/migrations/0024_work_item_auto_override.sql +22 -0
  335. package/migrations/0025_run_history.sql +37 -0
  336. package/migrations/0026_run_history_task_seq.sql +6 -0
  337. package/migrations/0027_custom_repos.sql +11 -0
  338. package/migrations/0028_run_usage.sql +14 -0
  339. package/migrations/0029_drop_ocr_langs.sql +6 -0
  340. package/migrations/0030_mr_assignee.sql +9 -0
  341. package/migrations/0031_lsp_servers.sql +14 -0
  342. package/opencode-config/managed/devbot-agent-policy.md +61 -0
  343. package/opencode-config/managed/opencode.json +77 -0
  344. package/opencode-config/opencode.json +211 -0
  345. package/opencode-config/plugins/devbot-path-guard.js +224 -0
  346. package/package.json +157 -4
  347. package/public/assets/DashboardSidebarCollapse-rIuzCmVm.js +1 -0
  348. package/public/assets/DashboardToolbar-DFCUqZ4Z.js +1 -0
  349. package/public/assets/ErrorLogModal.vue_vue_type_script_setup_true_lang-BCyNIf1E.js +1 -0
  350. package/public/assets/ErrorLogsPage-DyYK2Rop.js +1 -0
  351. package/public/assets/LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js +1 -0
  352. package/public/assets/OverviewPage-CFfa0uwg.js +1 -0
  353. package/public/assets/PageGrid-CBROIU87.js +1 -0
  354. package/public/assets/PeriodRangePicker.vue_vue_type_script_setup_true_lang-DiFUNem7.js +1 -0
  355. package/public/assets/ProjectDetailPage-CreyvUit.js +1 -0
  356. package/public/assets/ProjectsPage-CFx8-elJ.js +1 -0
  357. package/public/assets/RunDetailSlideover.vue_vue_type_script_setup_true_lang-DopYYmCT.js +1 -0
  358. package/public/assets/RunsPage-CRnnXU4P.js +1 -0
  359. package/public/assets/Select-Bvx32Diz.js +1 -0
  360. package/public/assets/SelectMenu-BjMxc4VB.js +1 -0
  361. package/public/assets/SettingsPage-Bb6LM3wO.js +60 -0
  362. package/public/assets/TimeCell.vue_vue_type_script_setup_true_lang-DW_UB0Fu.js +1 -0
  363. package/public/assets/UsagePage-BLMDEsv-.js +332 -0
  364. package/public/assets/UsagePage-DodEeAjB.css +1 -0
  365. package/public/assets/VolumesPage-CxcLc3L2.js +1 -0
  366. package/public/assets/WebhookConfigPanel.vue_vue_type_script_setup_true_lang-B2V2GF6b.js +1 -0
  367. package/public/assets/WorkItemCell.vue_vue_type_script_setup_true_lang-BQn6vTjd.js +1 -0
  368. package/public/assets/index-BMbMibyb.js +4 -0
  369. package/public/assets/index-C5RBBrPj.js +30 -0
  370. package/public/assets/index-CgX29UgC.css +1 -0
  371. package/public/assets/usage-format-jsb31_O8.js +1 -0
  372. package/public/assets/useManagedProjects-8rtjRqVJ.js +1 -0
  373. package/public/assets/useRouteTab-DfwrcMic.js +1 -0
  374. package/public/favicon.ico +0 -0
  375. package/public/favicon.png +0 -0
  376. package/public/index.html +15 -0
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ // OpenCode emits NDJSON: one event object per line from `opencode run --format json`.
3
+ // We model only what we consume. Schemas are permissive (passthrough) so unknown
4
+ // event/part types parse without throwing; narrowing happens via safeParse at use site.
5
+ // ---- Message parts ----------------------------------------------------------
6
+ // A part is any object with a `type` string. We recognize `text` parts specifically.
7
+ export const TextPartSchema = z.object({
8
+ type: z.literal("text"),
9
+ text: z.string(),
10
+ });
11
+ export const PartSchema = z.object({ type: z.string() }).passthrough();
12
+ // step-finish parts carry per-step token counts and the USD cost opencode
13
+ // computed for the model. Every field is optional so a partial upstream shape
14
+ // still parses; callers treat absent values as 0.
15
+ export const StepFinishPartSchema = z
16
+ .object({
17
+ type: z.literal("step-finish"),
18
+ cost: z.number().optional(),
19
+ tokens: z
20
+ .object({
21
+ input: z.number().optional(),
22
+ output: z.number().optional(),
23
+ reasoning: z.number().optional(),
24
+ cache: z
25
+ .object({ read: z.number().optional(), write: z.number().optional() })
26
+ .passthrough()
27
+ .optional(),
28
+ })
29
+ .passthrough()
30
+ .optional(),
31
+ })
32
+ .passthrough();
33
+ // ---- Events -----------------------------------------------------------------
34
+ // opencode run --format json emits one NDJSON event per line:
35
+ // { type, timestamp, sessionID, part }
36
+ // `part` is a SINGLE part object (text | tool | step-start | step-finish),
37
+ // not a parts[] array. Narrow on `part` at use site.
38
+ export const EventWithPartSchema = z
39
+ .object({
40
+ type: z.string(),
41
+ part: PartSchema,
42
+ })
43
+ .passthrough();
44
+ export const OpencodeEventSchema = z.object({ type: z.string() }).passthrough();
45
+ // Error event: opencode emits this on LLM/provider failures. Shape:
46
+ // {"type":"error","error":{"name":"UnknownError","data":{"message":"..."}}}
47
+ export const ErrorEventSchema = z
48
+ .object({
49
+ type: z.literal("error"),
50
+ error: z
51
+ .object({
52
+ name: z.string().optional(),
53
+ data: z.object({ message: z.string().optional() }).optional(),
54
+ message: z.string().optional(),
55
+ })
56
+ .passthrough(),
57
+ })
58
+ .passthrough();
59
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/types/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sFAAsF;AACtF,iFAAiF;AACjF,wFAAwF;AAExF,gFAAgF;AAChF,qFAAqF;AAErF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAGvE,0EAA0E;AAC1E,8EAA8E;AAC9E,kDAAkD;AAClD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,KAAK,EAAE,CAAC;aACL,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;aACrE,WAAW,EAAE;aACb,QAAQ,EAAE;KACd,CAAC;SACD,WAAW,EAAE;SACb,QAAQ,EAAE;CACd,CAAC;KACD,WAAW,EAAE,CAAC;AAGjB,gFAAgF;AAChF,8DAA8D;AAC9D,yCAAyC;AACzC,2EAA2E;AAC3E,qDAAqD;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC;KACjC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,UAAU;CACjB,CAAC;KACD,WAAW,EAAE,CAAC;AAGjB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAGhF,oEAAoE;AACpE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACxB,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE;QAC7D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC/B,CAAC;SACD,WAAW,EAAE;CACjB,CAAC;KACD,WAAW,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { z } from "zod";
2
+ // Outbound webhook types. DevBot emits signed JSON events to admin-configured
3
+ // URLs when a run reaches a terminal state or a change request is opened or
4
+ // refreshed. Forge-agnostic: no driver code, only neutral nouns.
5
+ // The subscribable event catalog. Run lifecycle (start + terminal outcomes)
6
+ // plus change-request lifecycle. Kept small on purpose — subscribers filter by
7
+ // event.
8
+ export const OUTBOUND_EVENTS = [
9
+ "run.started",
10
+ "run.succeeded",
11
+ "run.failed",
12
+ "run.cancelled",
13
+ "mr.created",
14
+ "mr.updated",
15
+ ];
16
+ export const OutboundEventSchema = z.enum(OUTBOUND_EVENTS);
17
+ // Human-readable labels for the WebUI event picker.
18
+ export const OUTBOUND_EVENT_LABELS = {
19
+ "run.started": "Run started",
20
+ "run.succeeded": "Run succeeded",
21
+ "run.failed": "Run failed",
22
+ "run.cancelled": "Run cancelled",
23
+ "mr.created": "Merge/pull request created",
24
+ "mr.updated": "Merge/pull request updated",
25
+ };
26
+ export const WEBHOOK_NAME_RE = /^[a-zA-Z0-9_-]+$/;
27
+ export const WEBHOOK_NAME_MAX = 50;
28
+ export const WEBHOOK_HEADERS_MAX = 20;
29
+ export const WEBHOOK_HEADER_NAME_RE = /^[a-zA-Z0-9-]+$/;
30
+ export const WEBHOOK_HEADER_NAME_MAX = 100;
31
+ export const WEBHOOK_HEADER_VALUE_MAX = 2048;
32
+ // Static headers an admin can attach to every delivery (e.g. an
33
+ // `Authorization` bearer for a receiver that doesn't implement HMAC).
34
+ const headersField = z
35
+ .record(z.string(), z.string())
36
+ .default({})
37
+ .refine((h) => Object.keys(h).length <= WEBHOOK_HEADERS_MAX, {
38
+ message: `at most ${WEBHOOK_HEADERS_MAX} headers`,
39
+ })
40
+ .refine((h) => Object.entries(h).every(([k, v]) => WEBHOOK_HEADER_NAME_RE.test(k) &&
41
+ k.length <= WEBHOOK_HEADER_NAME_MAX &&
42
+ v.length <= WEBHOOK_HEADER_VALUE_MAX), { message: "invalid header name or value too long" });
43
+ export const WebhookEndpointSchema = z
44
+ .object({
45
+ url: z
46
+ .string()
47
+ .url()
48
+ .refine((u) => u.startsWith("http://") || u.startsWith("https://"), {
49
+ message: "url must be http(s)",
50
+ }),
51
+ events: z.array(OutboundEventSchema).min(1),
52
+ headers: headersField,
53
+ enabled: z.boolean().default(true),
54
+ })
55
+ .strict();
56
+ //# sourceMappingURL=outbound-webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-webhook.js","sourceRoot":"","sources":["../../src/types/outbound-webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,4EAA4E;AAC5E,iEAAiE;AAEjE,4EAA4E;AAC5E,+EAA+E;AAC/E,SAAS;AACT,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,eAAe;IACf,YAAY;IACZ,eAAe;IACf,YAAY;IACZ,YAAY;CACJ,CAAC;AAGX,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAE3D,oDAAoD;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAAkC;IAClE,aAAa,EAAE,aAAa;IAC5B,eAAe,EAAE,eAAe;IAChC,YAAY,EAAE,YAAY;IAC1B,eAAe,EAAE,eAAe;IAChC,YAAY,EAAE,4BAA4B;IAC1C,YAAY,EAAE,4BAA4B;CAC3C,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AACtC,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;AACxD,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAE7C,gEAAgE;AAChE,sEAAsE;AACtE,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;KAC9B,OAAO,CAAC,EAAE,CAAC;KACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,mBAAmB,EAAE;IAC3D,OAAO,EAAE,WAAW,mBAAmB,UAAU;CAClD,CAAC;KACD,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CACrB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CACT,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,MAAM,IAAI,uBAAuB;IACnC,CAAC,CAAC,MAAM,IAAI,wBAAwB,CACvC,EACH,EAAE,OAAO,EAAE,uCAAuC,EAAE,CACrD,CAAC;AAEJ,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC;KACnC,MAAM,CAAC;IACN,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,EAAE;SACL,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QAClE,OAAO,EAAE,qBAAqB;KAC/B,CAAC;IACJ,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACnC,CAAC;KACD,MAAM,EAAE,CAAC"}
@@ -0,0 +1,114 @@
1
+ import { z } from "zod";
2
+ import { VARIANT_RE, VARIANT_STRING_MAX, BUILDER_IMAGE_RE, BUILDER_IMAGE_MAX, TEMPLATE_STRING_MAX } from "./global-settings.js";
3
+ import { ASSIGNEE_NONE, ASSIGNEE_RE } from "../assignee-value.js";
4
+ import { findUnknownPlaceholders, WORKFLOW_PLACEHOLDERS, MR_DESCRIPTION_PLACEHOLDERS, } from "../build-workflow.js";
5
+ import { projectMinRoleField, InheritableBoolSchema } from "./access.js";
6
+ import { isLspDisabledListValid, isLspServerId, splitLspDisabledList, splitLspServerList } from "../lsp-servers.js";
7
+ // Per-project run settings. All values are non-secret and stored plaintext.
8
+ // Empty string means "inherit the global setting". Model fields are
9
+ // "provider/model" and may use any configured provider (providers each carry
10
+ // their own API key). Variant fields are opencode `--variant` tokens.
11
+ export const SETTINGS_STRING_MAX = 2048;
12
+ export const MODEL_STRING_MAX = 256;
13
+ // Empty = inherit, otherwise must be "provider/model".
14
+ const modelField = z
15
+ .string()
16
+ .max(MODEL_STRING_MAX)
17
+ .transform((v) => v.trim())
18
+ .refine((v) => v === "" || v.includes("/"), { message: "must be 'provider/model' or empty" });
19
+ // Empty = inherit, otherwise a safe variant token.
20
+ const variantField = z
21
+ .string()
22
+ .max(VARIANT_STRING_MAX)
23
+ .transform((v) => v.trim())
24
+ .refine((v) => VARIANT_RE.test(v), { message: "must be letters, digits, dot, dash or underscore" })
25
+ .default("");
26
+ // Tri-state: "" inherits the global assignee, "none" assigns nobody on this
27
+ // project, and any other value must be a forge username.
28
+ const assigneeField = z
29
+ .string()
30
+ .max(255)
31
+ .transform((v) => v.trim())
32
+ .refine((v) => v === "" || v === ASSIGNEE_NONE || ASSIGNEE_RE.test(v), {
33
+ message: 'must be "", "none", or a forge username',
34
+ })
35
+ .default("");
36
+ // Empty = inherit global (which itself falls back to the BUILDER_IMAGE env
37
+ // var), otherwise a safe podman image reference.
38
+ const builderImageField = z
39
+ .string()
40
+ .max(BUILDER_IMAGE_MAX)
41
+ .transform((v) => v.trim())
42
+ .refine((v) => v === "" || BUILDER_IMAGE_RE.test(v), {
43
+ message: "must be a valid image reference (letters, digits, dot, dash, underscore, slash, colon, at)",
44
+ })
45
+ .default("");
46
+ // Empty = inherit global (which itself falls back to the built-in default),
47
+ // otherwise a template whose only placeholders are the allowed ones.
48
+ const workflowTemplateField = z
49
+ .string()
50
+ .max(TEMPLATE_STRING_MAX)
51
+ .transform((v) => v.trim())
52
+ .refine((v) => findUnknownPlaceholders(v, WORKFLOW_PLACEHOLDERS).length === 0, {
53
+ message: "unknown placeholder (allowed: {{iid}}, {{branch}}, {{mrTarget}}, {{mrBlock}})",
54
+ })
55
+ .default("");
56
+ const mrDescriptionTemplateField = z
57
+ .string()
58
+ .max(TEMPLATE_STRING_MAX)
59
+ .transform((v) => v.trim())
60
+ .refine((v) => findUnknownPlaceholders(v, MR_DESCRIPTION_PLACEHOLDERS).length === 0, {
61
+ message: "unknown placeholder (allowed: {{iid}}, {{branch}}, {{mrTarget}})",
62
+ })
63
+ .default("");
64
+ // Empty inherits the global list; a non-empty comma list is a full override.
65
+ const lspServersField = z
66
+ .string()
67
+ .max(SETTINGS_STRING_MAX)
68
+ .transform((v) => v.trim())
69
+ .refine((v) => {
70
+ if (v === "")
71
+ return true;
72
+ const ids = splitLspServerList(v);
73
+ return ids.length > 0 && ids.every(isLspServerId);
74
+ }, { message: "custom LSP list must contain at least one known server id" })
75
+ .default("");
76
+ // Empty = subtract nothing. Unknown ids are rejected, but ids that are not
77
+ // currently enabled globally are allowed (a no-op that may matter later).
78
+ const lspDisabledField = z
79
+ .string()
80
+ .max(SETTINGS_STRING_MAX)
81
+ .transform((v) => v.trim())
82
+ .refine((v) => v === "" || isLspDisabledListValid(v), {
83
+ message: "unknown LSP server id in disabled list",
84
+ })
85
+ .transform((v) => splitLspDisabledList(v).join(","))
86
+ .default("");
87
+ export const ProjectSettingsSchema = z
88
+ .object({
89
+ planModel: modelField,
90
+ buildModel: modelField,
91
+ planVariant: variantField,
92
+ buildVariant: variantField,
93
+ plugins: z.string().max(SETTINGS_STRING_MAX).transform((v) => v.trim()),
94
+ baseBranches: z.string().max(SETTINGS_STRING_MAX).transform((v) => v.trim()),
95
+ lspServers: lspServersField,
96
+ lspDisabled: lspDisabledField,
97
+ builderImage: builderImageField,
98
+ assignee: assigneeField,
99
+ buildWorkflow: workflowTemplateField,
100
+ mrDescription: mrDescriptionTemplateField,
101
+ minRole: projectMinRoleField,
102
+ requireAuthorOrAssignee: InheritableBoolSchema,
103
+ autoPush: InheritableBoolSchema,
104
+ autoMr: InheritableBoolSchema,
105
+ autoResolveConflicts: InheritableBoolSchema,
106
+ ciFailAutoReport: InheritableBoolSchema,
107
+ })
108
+ .strict();
109
+ // Provider = substring before the first "/". Retained for the frontend
110
+ // validator; providers are no longer restricted to a single global provider.
111
+ export function providerOf(model) {
112
+ return model.split("/")[0] ?? "";
113
+ }
114
+ //# sourceMappingURL=project-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-settings.js","sourceRoot":"","sources":["../../src/types/project-settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { normalizeModelId } from "./global-settings.js";
2
+ // models.dev provider registry shape. Fetched by the browser on Global settings
3
+ // load and normalized client-side; the server no longer fetches or caches it.
4
+ export const MODELS_DEV_URL = "https://models.dev/api.json";
5
+ export function normalizeRegistry(raw) {
6
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
7
+ return [];
8
+ const out = [];
9
+ for (const [key, value] of Object.entries(raw)) {
10
+ if (!value || typeof value !== "object" || Array.isArray(value))
11
+ continue;
12
+ const v = value;
13
+ const id = typeof v.id === "string" && v.id ? v.id : key;
14
+ const modelsRaw = v.models && typeof v.models === "object" && !Array.isArray(v.models)
15
+ ? v.models
16
+ : {};
17
+ const models = [];
18
+ for (const [modelKey, modelValue] of Object.entries(modelsRaw)) {
19
+ const m = (modelValue ?? {});
20
+ const rawId = typeof m.id === "string" && m.id ? m.id : modelKey;
21
+ models.push({
22
+ id: normalizeModelId(id, rawId),
23
+ name: typeof m.name === "string" && m.name ? m.name : rawId,
24
+ });
25
+ }
26
+ out.push({
27
+ id,
28
+ name: typeof v.name === "string" && v.name ? v.name : id,
29
+ npm: typeof v.npm === "string" ? v.npm : "",
30
+ api: typeof v.api === "string" ? v.api : "",
31
+ env: Array.isArray(v.env) ? v.env.filter((e) => typeof e === "string") : [],
32
+ models,
33
+ });
34
+ }
35
+ return out.sort((a, b) => a.id.localeCompare(b.id));
36
+ }
37
+ //# sourceMappingURL=provider-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-registry.js","sourceRoot":"","sources":["../../src/types/provider-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,gFAAgF;AAChF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAe5D,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACrE,MAAM,GAAG,GAAuB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;QAC1E,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,SAAS;QAC1E,MAAM,CAAC,GAAG,KAAgC,CAAC;QAC3C,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QACzD,MAAM,SAAS,GACb,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;YAClE,CAAC,CAAE,CAAC,CAAC,MAAkC;YACvC,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,MAAM,GAAoB,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/D,MAAM,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAA4B,CAAC;YACxD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YACjE,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,gBAAgB,CAAC,EAAE,EAAE,KAAK,CAAC;gBAC/B,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;aAC5D,CAAC,CAAC;QACL,CAAC;QACD,GAAG,CAAC,IAAI,CAAC;YACP,EAAE;YACF,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YACxD,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC3C,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC3C,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YACxF,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,78 @@
1
+ import { z } from "zod";
2
+ // Runtime settings (work item #55): operational knobs that used to be env-only,
3
+ // now editable in the WebUI. Stored as strings with "" = "inherit the env var"
4
+ // (matching the builderImage / InheritableBool convention), so an empty WebUI
5
+ // field falls back to the env value which itself falls back to the built-in
6
+ // default. The legacy env vars remain in EnvSchema as the fallback layer.
7
+ //
8
+ // DRY_RUN and LOG_LEVEL deliberately stay env-only: they gate test/CI behavior
9
+ // and per-process logging respectively, and must not be settable from the
10
+ // browser.
11
+ const boolField = z
12
+ .union([z.literal(""), z.literal("true"), z.literal("false")])
13
+ .default("");
14
+ // "" (inherit) or a non-negative integer string >= min.
15
+ function intField(min) {
16
+ return z
17
+ .union([
18
+ z.literal(""),
19
+ z
20
+ .string()
21
+ .regex(/^\d+$/, { message: "must be a whole number" })
22
+ .refine((v) => Number(v) >= min, { message: `must be >= ${min}` }),
23
+ ])
24
+ .default("");
25
+ }
26
+ export const DEVCONTAINER_DRIVERS = ["auto", "fuse-overlayfs", "vfs"];
27
+ const storageDriverField = z
28
+ .union([z.literal(""), z.enum(DEVCONTAINER_DRIVERS)])
29
+ .default("");
30
+ export const RuntimeSettingsSchema = z
31
+ .object({
32
+ planTimeoutMs: intField(1),
33
+ buildTimeoutMs: intField(1),
34
+ maxConcurrentRuns: intField(1),
35
+ maxGlobalQueue: intField(0),
36
+ maxQueuePerWorkItem: intField(1),
37
+ maxRetries: intField(0),
38
+ retryBackoffMs: intField(1),
39
+ queueFeedback: boolField,
40
+ attachmentMaxBytes: intField(1),
41
+ volumeGcEnabled: boolField,
42
+ volumeGcTtlMs: intField(1),
43
+ volumeGcIntervalMs: intField(1),
44
+ errorLogRetentionDays: intField(0),
45
+ runLogTtlHours: intField(0),
46
+ projectSyncEnabled: boolField,
47
+ projectSyncIntervalMs: intField(1),
48
+ mcpRefreshEnabled: boolField,
49
+ mcpRefreshIntervalMs: intField(1),
50
+ devcontainerEnabled: boolField,
51
+ devcontainerStorageDriver: storageDriverField,
52
+ gitSubmodulesEnabled: boolField,
53
+ })
54
+ .strict();
55
+ export const DEFAULT_RUNTIME_SETTINGS = {
56
+ planTimeoutMs: "",
57
+ buildTimeoutMs: "",
58
+ maxConcurrentRuns: "",
59
+ maxGlobalQueue: "",
60
+ maxQueuePerWorkItem: "",
61
+ maxRetries: "",
62
+ retryBackoffMs: "",
63
+ queueFeedback: "",
64
+ attachmentMaxBytes: "",
65
+ volumeGcEnabled: "",
66
+ volumeGcTtlMs: "",
67
+ volumeGcIntervalMs: "",
68
+ errorLogRetentionDays: "",
69
+ runLogTtlHours: "",
70
+ projectSyncEnabled: "",
71
+ projectSyncIntervalMs: "",
72
+ mcpRefreshEnabled: "",
73
+ mcpRefreshIntervalMs: "",
74
+ devcontainerEnabled: "",
75
+ devcontainerStorageDriver: "",
76
+ gitSubmodulesEnabled: "",
77
+ };
78
+ //# sourceMappingURL=runtime-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-settings.js","sourceRoot":"","sources":["../../src/types/runtime-settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ const DAY_MS = 86_400_000;
2
+ export function emptyTotals() {
3
+ return { runs: 0, input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0, costUsd: 0 };
4
+ }
5
+ export function localDayKey(ms) {
6
+ const d = new Date(ms);
7
+ const m = String(d.getMonth() + 1).padStart(2, "0");
8
+ const day = String(d.getDate()).padStart(2, "0");
9
+ return `${d.getFullYear()}-${m}-${day}`;
10
+ }
11
+ export function startOfLocalDay(ms) {
12
+ const d = new Date(ms);
13
+ d.setHours(0, 0, 0, 0);
14
+ return d.getTime();
15
+ }
16
+ // DST-safe day arithmetic: `setDate` moves by calendar day, so a spring-forward
17
+ // day (23h) or fall-back day (25h) cannot shift the resulting date.
18
+ export function addLocalDays(ms, n) {
19
+ const d = new Date(ms);
20
+ d.setDate(d.getDate() + n);
21
+ return d.getTime();
22
+ }
23
+ export function resolveUsageWindow(filters, now) {
24
+ const calendar = filters.from !== undefined && filters.to !== undefined;
25
+ const days = Math.max(1, Math.floor(filters.days));
26
+ if (calendar) {
27
+ const windowStart = startOfLocalDay(filters.from);
28
+ const endDay = startOfLocalDay(filters.to);
29
+ const windowEnd = addLocalDays(endDay, 1);
30
+ let dayCount = 0;
31
+ for (let cur = windowStart; cur < windowEnd && dayCount < 4000; cur = addLocalDays(cur, 1))
32
+ dayCount++;
33
+ return { windowStart, windowEnd, prevStart: addLocalDays(windowStart, -Math.max(1, dayCount)), dayCount, calendar };
34
+ }
35
+ const spanMs = days * DAY_MS;
36
+ const windowStart = now - spanMs;
37
+ return { windowStart, windowEnd: now + 1, prevStart: windowStart - spanMs, dayCount: days, calendar };
38
+ }
39
+ function addRow(t, r) {
40
+ t.runs += 1;
41
+ t.input += r.inputTokens;
42
+ t.output += r.outputTokens;
43
+ t.reasoning += r.reasoningTokens;
44
+ t.cacheRead += r.cacheReadTokens;
45
+ t.cacheWrite += r.cacheWriteTokens;
46
+ t.costUsd += r.costUsd;
47
+ }
48
+ function matchesFilters(r, f) {
49
+ if (f.projectId !== undefined && r.projectId !== f.projectId)
50
+ return false;
51
+ if (f.model !== undefined && r.model !== f.model)
52
+ return false;
53
+ if (f.mode !== undefined && r.mode !== f.mode)
54
+ return false;
55
+ return true;
56
+ }
57
+ function breakdown(map) {
58
+ const out = [];
59
+ for (const [key, totals] of map)
60
+ out.push({ key, ...totals });
61
+ out.sort((a, b) => (b.costUsd - a.costUsd) || a.key.localeCompare(b.key) || (b.runs - a.runs));
62
+ return out;
63
+ }
64
+ function bump(map, key, r) {
65
+ const t = map.get(key) ?? emptyTotals();
66
+ addRow(t, r);
67
+ map.set(key, t);
68
+ }
69
+ export function computeUsageStats(rows, filters, now) {
70
+ const days = Math.max(1, Math.floor(filters.days));
71
+ // Current window is `[windowStart, windowEnd)`; the previous window is the
72
+ // equally long window immediately before it. Presets keep the rolling
73
+ // `days`-back-from-now behaviour (windowEnd just past `now`); a custom range
74
+ // uses explicit local-day boundaries (#77).
75
+ const { windowStart, windowEnd, prevStart, calendar } = resolveUsageWindow(filters, now);
76
+ const dayBuckets = new Map();
77
+ const modelBuckets = new Map();
78
+ const projectBuckets = new Map();
79
+ const modeBuckets = new Map();
80
+ const totals = emptyTotals();
81
+ const previous = emptyTotals();
82
+ const recent = [];
83
+ // filterOptions span every row (ignoring the active filters) so a selected
84
+ // filter can always be cleared again.
85
+ const projects = new Set();
86
+ const models = new Set();
87
+ const modes = new Set();
88
+ for (const r of rows) {
89
+ projects.add(r.projectId);
90
+ models.add(r.model);
91
+ modes.add(r.mode);
92
+ if (!matchesFilters(r, filters))
93
+ continue;
94
+ if (r.finishedAt < prevStart || r.finishedAt >= windowEnd)
95
+ continue;
96
+ if (r.finishedAt < windowStart) {
97
+ addRow(previous, r);
98
+ continue;
99
+ }
100
+ addRow(totals, r);
101
+ bump(dayBuckets, localDayKey(r.finishedAt), r);
102
+ bump(modelBuckets, r.model, r);
103
+ bump(projectBuckets, String(r.projectId), r);
104
+ bump(modeBuckets, r.mode, r);
105
+ recent.push({
106
+ id: r.id,
107
+ projectId: r.projectId,
108
+ workItemIid: r.workItemIid,
109
+ workItemTitle: r.workItemTitle,
110
+ model: r.model,
111
+ mode: r.mode,
112
+ finishedAt: r.finishedAt,
113
+ inputTokens: r.inputTokens,
114
+ outputTokens: r.outputTokens,
115
+ reasoningTokens: r.reasoningTokens,
116
+ cacheReadTokens: r.cacheReadTokens,
117
+ cacheWriteTokens: r.cacheWriteTokens,
118
+ costUsd: r.costUsd,
119
+ });
120
+ }
121
+ // One zero-filled point per day, oldest → newest, walking by calendar date
122
+ // (not fixed ms) so DST transitions cannot shift the bucket labels.
123
+ const series = [];
124
+ if (calendar) {
125
+ const endDay = addLocalDays(windowEnd, -1);
126
+ for (let cur = windowStart; cur <= endDay; cur = addLocalDays(cur, 1)) {
127
+ const key = localDayKey(cur);
128
+ series.push({ date: key, ...(dayBuckets.get(key) ?? emptyTotals()) });
129
+ }
130
+ }
131
+ else {
132
+ const cursor = new Date(now);
133
+ cursor.setHours(12, 0, 0, 0);
134
+ for (let i = days - 1; i >= 0; i--) {
135
+ const d = new Date(cursor);
136
+ d.setDate(d.getDate() - i);
137
+ const key = localDayKey(d.getTime());
138
+ series.push({ date: key, ...(dayBuckets.get(key) ?? emptyTotals()) });
139
+ }
140
+ }
141
+ return {
142
+ totals,
143
+ previous,
144
+ series,
145
+ byModel: breakdown(modelBuckets),
146
+ byProject: breakdown(projectBuckets),
147
+ byMode: breakdown(modeBuckets),
148
+ recent: recent.sort((a, b) => b.finishedAt - a.finishedAt),
149
+ filterOptions: {
150
+ projects: [...projects].sort((a, b) => a - b),
151
+ models: [...models].sort(),
152
+ modes: [...modes].sort(),
153
+ },
154
+ recentTotal: recent.length,
155
+ byModelTotal: modelBuckets.size,
156
+ byProjectTotal: projectBuckets.size,
157
+ };
158
+ }
159
+ //# sourceMappingURL=usage-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-stats.js","sourceRoot":"","sources":["../src/usage-stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ // Resolve at runtime, not build time: the dev channel stamps its version with
5
+ // `npm version ...` in CI *after* `npm run build`, so a compile-time constant
6
+ // would report the pre-stamp version. Read the installed package.json (always
7
+ // at the package root, both for `src/` via tsx and `dist/` builds).
8
+ const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
9
+ function readVersion() {
10
+ try {
11
+ const pkg = JSON.parse(readFileSync(join(MODULE_DIR, "..", "package.json"), "utf8"));
12
+ return pkg.version ?? "";
13
+ }
14
+ catch {
15
+ return "";
16
+ }
17
+ }
18
+ export const APP_VERSION = readVersion();
19
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAC9E,oEAAoE;AACpE,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE3D,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAElF,CAAC;QACF,OAAO,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,EAAE,CAAC"}