@wascartech/devbot 0.0.0-stage → 2.1.1

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 +150 -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 +438 -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 +158 -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,320 @@
1
+ import { db } from "./db.js";
2
+ import { log } from "./logger.js";
3
+ import { getGlobalSettings } from "./global-settings-store.js";
4
+ import { parseBaseBranches } from "./base-branches.js";
5
+ import { ProjectSettingsSchema } from "./types/project-settings.js";
6
+ import { resolveLspServerList } from "./lsp-servers.js";
7
+ // Per-project run settings. Same DB file as project_tokens, project_env_vars,
8
+ // and project_mcp_servers (devbot.db, 0600). Keyed by project_id; values are
9
+ // non-secret and stored plaintext. Re-validated on read — the runner is the
10
+ // trust boundary; a corrupt row is skipped (logged at warn) and treated as
11
+ // "inherit globals", never crashing a run.
12
+ export function initProjectSettingsTables() {
13
+ db.exec(`
14
+ CREATE TABLE IF NOT EXISTS project_settings (
15
+ project_id INTEGER PRIMARY KEY,
16
+ plan_model TEXT,
17
+ build_model TEXT,
18
+ plan_variant TEXT,
19
+ build_variant TEXT,
20
+ plugins TEXT,
21
+ base_branches TEXT,
22
+ builder_image TEXT,
23
+ assignee TEXT,
24
+ build_workflow TEXT,
25
+ mr_description TEXT,
26
+ min_role TEXT,
27
+ require_author_or_assignee TEXT,
28
+ auto_push TEXT,
29
+ auto_mr TEXT,
30
+ auto_resolve_conflicts TEXT,
31
+ ci_fail_auto_report TEXT,
32
+ lsp_servers TEXT,
33
+ lsp_disabled TEXT,
34
+ created_at INTEGER NOT NULL,
35
+ updated_at INTEGER NOT NULL
36
+ )
37
+ `);
38
+ // A pre-0005 DB still has base_model; the migration drops it. Belt-and-braces
39
+ // for test DBs that skip migrate and were created with the old shape.
40
+ try {
41
+ db.exec("ALTER TABLE project_settings DROP COLUMN base_model");
42
+ }
43
+ catch {
44
+ // Column already gone (or never existed) — fine.
45
+ }
46
+ // A pre-0006 DB lacks the variant columns. ADD COLUMN errors if present.
47
+ try {
48
+ db.exec("ALTER TABLE project_settings ADD COLUMN plan_variant TEXT");
49
+ }
50
+ catch { /* exists */ }
51
+ try {
52
+ db.exec("ALTER TABLE project_settings ADD COLUMN build_variant TEXT");
53
+ }
54
+ catch { /* exists */ }
55
+ // Pre-0013 DBs lack the builder_image column.
56
+ try {
57
+ db.exec("ALTER TABLE project_settings ADD COLUMN builder_image TEXT");
58
+ }
59
+ catch { /* exists */ }
60
+ // Pre-0030 DBs lack the MR assignee column.
61
+ try {
62
+ db.exec("ALTER TABLE project_settings ADD COLUMN assignee TEXT");
63
+ }
64
+ catch { /* exists */ }
65
+ // Pre-0014 DBs lack the build-mode template columns.
66
+ try {
67
+ db.exec("ALTER TABLE project_settings ADD COLUMN build_workflow TEXT");
68
+ }
69
+ catch { /* exists */ }
70
+ try {
71
+ db.exec("ALTER TABLE project_settings ADD COLUMN mr_description TEXT");
72
+ }
73
+ catch { /* exists */ }
74
+ // Pre-0016 DBs lack the trigger-policy columns.
75
+ try {
76
+ db.exec("ALTER TABLE project_settings ADD COLUMN min_role TEXT");
77
+ }
78
+ catch { /* exists */ }
79
+ try {
80
+ db.exec("ALTER TABLE project_settings ADD COLUMN require_author_or_assignee TEXT");
81
+ }
82
+ catch { /* exists */ }
83
+ // Pre-0019 DBs lack the auto-push / auto-MR columns.
84
+ try {
85
+ db.exec("ALTER TABLE project_settings ADD COLUMN auto_push TEXT");
86
+ }
87
+ catch { /* exists */ }
88
+ try {
89
+ db.exec("ALTER TABLE project_settings ADD COLUMN auto_mr TEXT");
90
+ }
91
+ catch { /* exists */ }
92
+ // Pre-0022 DBs lack the conflict auto-fix column.
93
+ try {
94
+ db.exec("ALTER TABLE project_settings ADD COLUMN auto_resolve_conflicts TEXT");
95
+ }
96
+ catch { /* exists */ }
97
+ // Pre-0022 DBs lack the CI-failure auto-report column.
98
+ try {
99
+ db.exec("ALTER TABLE project_settings ADD COLUMN ci_fail_auto_report TEXT");
100
+ }
101
+ catch { /* exists */ }
102
+ // Pre-0031 DBs lack the per-project LSP server override / subtractive list.
103
+ try {
104
+ db.exec("ALTER TABLE project_settings ADD COLUMN lsp_servers TEXT");
105
+ }
106
+ catch { /* exists */ }
107
+ try {
108
+ db.exec("ALTER TABLE project_settings ADD COLUMN lsp_disabled TEXT");
109
+ }
110
+ catch { /* exists */ }
111
+ }
112
+ export function getProjectSettings(projectId) {
113
+ const row = db
114
+ .prepare("SELECT plan_model, build_model, plan_variant, build_variant, plugins, base_branches, builder_image, assignee, build_workflow, mr_description, min_role, require_author_or_assignee, auto_push, auto_mr, auto_resolve_conflicts, ci_fail_auto_report, lsp_servers, lsp_disabled FROM project_settings WHERE project_id = ?")
115
+ .get(projectId);
116
+ if (!row)
117
+ return null;
118
+ const parsed = ProjectSettingsSchema.safeParse({
119
+ planModel: row.plan_model ?? "",
120
+ buildModel: row.build_model ?? "",
121
+ planVariant: row.plan_variant ?? "",
122
+ buildVariant: row.build_variant ?? "",
123
+ plugins: row.plugins ?? "",
124
+ baseBranches: row.base_branches ?? "",
125
+ builderImage: row.builder_image ?? "",
126
+ assignee: row.assignee ?? "",
127
+ buildWorkflow: row.build_workflow ?? "",
128
+ mrDescription: row.mr_description ?? "",
129
+ minRole: row.min_role ?? "",
130
+ requireAuthorOrAssignee: row.require_author_or_assignee === "true"
131
+ ? "true"
132
+ : row.require_author_or_assignee === "false"
133
+ ? "false"
134
+ : "",
135
+ autoPush: row.auto_push === "true" ? "true" : row.auto_push === "false" ? "false" : "",
136
+ autoMr: row.auto_mr === "true" ? "true" : row.auto_mr === "false" ? "false" : "",
137
+ autoResolveConflicts: row.auto_resolve_conflicts === "true" ? "true" : row.auto_resolve_conflicts === "false" ? "false" : "",
138
+ ciFailAutoReport: row.ci_fail_auto_report === "true" ? "true" : row.ci_fail_auto_report === "false" ? "false" : "",
139
+ lspServers: row.lsp_servers ?? "",
140
+ lspDisabled: row.lsp_disabled ?? "",
141
+ });
142
+ if (!parsed.success) {
143
+ log.warn("project settings row failed schema, treating as inherit", { projectId });
144
+ return null;
145
+ }
146
+ return parsed.data;
147
+ }
148
+ export function upsertProjectSettings(projectId, s) {
149
+ const parsed = ProjectSettingsSchema.safeParse(s);
150
+ if (!parsed.success)
151
+ throw new Error("invalid project settings");
152
+ const v = parsed.data;
153
+ const now = Math.floor(Date.now() / 1000);
154
+ db.prepare(`INSERT OR REPLACE INTO project_settings
155
+ (project_id, plan_model, build_model, plan_variant, build_variant, plugins, base_branches, builder_image, assignee, build_workflow, mr_description, min_role, require_author_or_assignee, auto_push, auto_mr, auto_resolve_conflicts, ci_fail_auto_report, lsp_servers, lsp_disabled, created_at, updated_at)
156
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
157
+ COALESCE((SELECT created_at FROM project_settings WHERE project_id = ?), ?),
158
+ ?)`).run(projectId, v.planModel, v.buildModel, v.planVariant, v.buildVariant, v.plugins, v.baseBranches, v.builderImage, v.assignee, v.buildWorkflow, v.mrDescription, v.minRole, v.requireAuthorOrAssignee, v.autoPush, v.autoMr, v.autoResolveConflicts, v.ciFailAutoReport, v.lspServers, v.lspDisabled, projectId, now, now);
159
+ }
160
+ export function deleteAllProjectSettings(projectId) {
161
+ db.prepare("DELETE FROM project_settings WHERE project_id = ?").run(projectId);
162
+ }
163
+ // Resolve the model for a run mode. Chain (first non-empty wins):
164
+ // project.<mode>_model -> global.<mode>_model.
165
+ export function resolveModelForMode(projectId, mode) {
166
+ const s = getProjectSettings(projectId);
167
+ const modeValue = mode === "plan" ? s?.planModel : s?.buildModel;
168
+ if (modeValue)
169
+ return modeValue;
170
+ const g = getGlobalSettings();
171
+ return mode === "plan" ? g.planModel : g.buildModel;
172
+ }
173
+ // Resolve the opencode `--variant` for a run mode. Chain (first non-empty wins):
174
+ // project.<mode>_variant -> global.<mode>_variant -> "" (opencode default).
175
+ export function resolveVariantForMode(projectId, mode) {
176
+ const s = getProjectSettings(projectId);
177
+ const modeValue = mode === "plan" ? s?.planVariant : s?.buildVariant;
178
+ if (modeValue)
179
+ return modeValue;
180
+ const g = getGlobalSettings();
181
+ return mode === "plan" ? g.planVariant : g.buildVariant;
182
+ }
183
+ // Resolve the plugin list string. A set project value REPLACES the global
184
+ // plugins; empty inherits it. The shipped base opencode.json plugin array is
185
+ // always applied on top by buildOpencodeConfig (union, dedup).
186
+ export function resolvePlugins(projectId) {
187
+ const s = getProjectSettings(projectId);
188
+ if (s && s.plugins)
189
+ return s.plugins;
190
+ return getGlobalSettings().plugins;
191
+ }
192
+ // Resolve the LSP allowlist. A set project list REPLACES the global list;
193
+ // empty inherits it. Resolution always returns the canonical shipped order.
194
+ export function resolveLspServers(projectId) {
195
+ const s = getProjectSettings(projectId);
196
+ return resolveLspServerList(s?.lspServers ?? "", getGlobalSettings().lspServers, s?.lspDisabled ?? "");
197
+ }
198
+ // Resolve the base-branch walk. A set project value REPLACES the global
199
+ // baseBranches; empty inherits it. Per-work-item /base still wins over both.
200
+ export function resolveBaseBranches(projectId) {
201
+ const s = getProjectSettings(projectId);
202
+ if (s && s.baseBranches)
203
+ return parseBaseBranches(s.baseBranches);
204
+ return parseBaseBranches(getGlobalSettings().baseBranches || "dev,master");
205
+ }
206
+ // Resolve the builder image. Chain (first non-empty wins):
207
+ // project.builderImage -> global.builderImage -> "" (caller falls back to the
208
+ // BUILDER_IMAGE env var). Kept env-free here so stores stay config-independent;
209
+ // the caller (bridge / routes) applies the env fallback.
210
+ export function resolveBuilderImage(projectId) {
211
+ const s = getProjectSettings(projectId);
212
+ if (s && s.builderImage)
213
+ return s.builderImage;
214
+ return getGlobalSettings().builderImage;
215
+ }
216
+ // Resolve the build-mode workflow template. Chain (first non-empty wins):
217
+ // project.buildWorkflow -> global.buildWorkflow -> "" (caller falls back to
218
+ // the built-in default in build-workflow.ts).
219
+ export function resolveBuildWorkflow(projectId) {
220
+ const s = getProjectSettings(projectId);
221
+ if (s && s.buildWorkflow)
222
+ return s.buildWorkflow;
223
+ return getGlobalSettings().buildWorkflow;
224
+ }
225
+ // Resolve the MR-description template. Chain (first non-empty wins):
226
+ // project.mrDescription -> global.mrDescription -> "" (built-in default).
227
+ export function resolveMrDescription(projectId) {
228
+ const s = getProjectSettings(projectId);
229
+ if (s && s.mrDescription)
230
+ return s.mrDescription;
231
+ return getGlobalSettings().mrDescription;
232
+ }
233
+ // Resolve the minimum project role for the trigger gate. Chain (first non-empty
234
+ // wins): project.minRole -> global.minRole -> "write" (the default).
235
+ export function resolveMinRole(projectId) {
236
+ const s = getProjectSettings(projectId);
237
+ if (s && s.minRole)
238
+ return s.minRole;
239
+ return getGlobalSettings().minRole;
240
+ }
241
+ // Resolve whether the actor must be the work item's author/assignee. Chain:
242
+ // project.requireAuthorOrAssignee -> global.requireAuthorOrAssignee -> true.
243
+ export function resolveRequireAuthorOrAssignee(projectId) {
244
+ const s = getProjectSettings(projectId);
245
+ if (s) {
246
+ if (s.requireAuthorOrAssignee === "true")
247
+ return true;
248
+ if (s.requireAuthorOrAssignee === "false")
249
+ return false;
250
+ }
251
+ return getGlobalSettings().requireAuthorOrAssignee;
252
+ }
253
+ // Resolve whether a build run auto-pushes its branch. Chain:
254
+ // project.autoPush -> global.autoPush -> false (disabled by default).
255
+ // The /push and /force-push mention tokens override this per run.
256
+ export function resolveAutoPush(projectId) {
257
+ const s = getProjectSettings(projectId);
258
+ if (s) {
259
+ if (s.autoPush === "true")
260
+ return true;
261
+ if (s.autoPush === "false")
262
+ return false;
263
+ }
264
+ return getGlobalSettings().autoPush;
265
+ }
266
+ // Resolve whether a pushed build run auto-creates/updates its merge request.
267
+ // Chain: project.autoMr -> global.autoMr -> false. Only meaningful when
268
+ // auto-push resolves true (or the run explicitly pushed via /push //force-push).
269
+ export function resolveAutoMr(projectId) {
270
+ const s = getProjectSettings(projectId);
271
+ if (s) {
272
+ if (s.autoMr === "true")
273
+ return true;
274
+ if (s.autoMr === "false")
275
+ return false;
276
+ }
277
+ return getGlobalSettings().autoMr;
278
+ }
279
+ // Resolve whether a pushed run checks for and auto-resolves merge conflicts
280
+ // before creating/updating the MR. Chain:
281
+ // project.autoResolveConflicts -> global.autoResolveConflicts -> false.
282
+ export function resolveAutoResolveConflicts(projectId) {
283
+ const s = getProjectSettings(projectId);
284
+ if (s) {
285
+ if (s.autoResolveConflicts === "true")
286
+ return true;
287
+ if (s.autoResolveConflicts === "false")
288
+ return false;
289
+ }
290
+ return getGlobalSettings().autoResolveConflicts;
291
+ }
292
+ // Resolve whether a failed pipeline on a DevBot-created merge/pull request
293
+ // triggers an automatic plan run seeded with the failing job logs. Chain:
294
+ // project.ciFailAutoReport -> global.ciFailAutoReport -> false (opt-in).
295
+ export function resolveCiFailAutoReport(projectId) {
296
+ const s = getProjectSettings(projectId);
297
+ if (s) {
298
+ if (s.ciFailAutoReport === "true")
299
+ return true;
300
+ if (s.ciFailAutoReport === "false")
301
+ return false;
302
+ }
303
+ return getGlobalSettings().ciFailAutoReport;
304
+ }
305
+ // Resolve any auto-* feature by its neutral key. Pure dispatch so callers
306
+ // (the per-work-item override store, the runner bridge) can stay feature-
307
+ // agnostic. Chain for every feature: project -> global -> false.
308
+ export function resolveAutoFeature(projectId, feature) {
309
+ switch (feature) {
310
+ case "autoPush":
311
+ return resolveAutoPush(projectId);
312
+ case "autoMr":
313
+ return resolveAutoMr(projectId);
314
+ case "autoResolveConflicts":
315
+ return resolveAutoResolveConflicts(projectId);
316
+ case "ciFailAutoReport":
317
+ return resolveCiFailAutoReport(projectId);
318
+ }
319
+ }
320
+ //# sourceMappingURL=settings-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-store.js","sourceRoot":"","sources":["../src/settings-store.ts"],"names":[],"mappings":"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"}
package/dist/status.js ADDED
@@ -0,0 +1,121 @@
1
+ import { AUTO_FEATURES } from "./auto-features.js";
2
+ // Short labels used by the /status line (the auto-* command labels are longer:
3
+ // "auto-push", "auto-resolve-conflicts", …).
4
+ const AUTO_LABEL = {
5
+ autoPush: "push",
6
+ autoMr: "mr",
7
+ autoResolveConflicts: "resolve-conflicts",
8
+ ciFailAutoReport: "ci-report",
9
+ };
10
+ export function taskLabel(t) {
11
+ if (t.mrOnly)
12
+ return "mr";
13
+ if (t.fixConflictsOnly)
14
+ return "fix-conflicts";
15
+ if (t.pushOnly)
16
+ return "push";
17
+ if (t.forcePushOnly)
18
+ return "force-push";
19
+ return t.mode;
20
+ }
21
+ // First line, whitespace compacted, ~80 code points, ellipsis when cut. An
22
+ // empty prompt returns "" (the caller omits the excerpt entirely rather than
23
+ // echoing the task label back at itself).
24
+ export function messageExcerpt(prompt, maxLength = 80) {
25
+ if (typeof prompt !== "string")
26
+ return "";
27
+ const first = prompt.replace(/\r\n/g, "\n").trim().split("\n")[0] ?? "";
28
+ const text = first.replace(/\s+/g, " ").replace(/`/g, "'").trim();
29
+ if (!text)
30
+ return "";
31
+ const chars = Array.from(text);
32
+ if (chars.length <= maxLength)
33
+ return text;
34
+ return `${chars.slice(0, Math.max(0, maxLength - 1)).join("").trimEnd()}…`;
35
+ }
36
+ export function formatDuration(ms) {
37
+ const total = Math.max(0, Math.floor(ms / 1000));
38
+ const hours = Math.floor(total / 3600);
39
+ const minutes = Math.floor((total % 3600) / 60);
40
+ const seconds = total % 60;
41
+ if (hours > 0) {
42
+ return `${hours} h ${String(minutes).padStart(2, "0")} min ${String(seconds).padStart(2, "0")} s`;
43
+ }
44
+ if (minutes > 0) {
45
+ return `${minutes} min ${String(seconds).padStart(2, "0")} s`;
46
+ }
47
+ return `${seconds} s`;
48
+ }
49
+ function branchLine(input) {
50
+ const mr = input.changeRequestNumber === null
51
+ ? "no MR yet"
52
+ : `MR !${input.changeRequestNumber} (created by DevBot)`;
53
+ return `branch \`${input.branch}\` · ${mr}`;
54
+ }
55
+ function autoLine(features) {
56
+ const states = AUTO_FEATURES.map((f) => `${AUTO_LABEL[f]} ${features[f] ? "✅" : "❌"}`);
57
+ return `⚙️ auto-* — ${states.join(" · ")}`;
58
+ }
59
+ function retrySuffix(task, maxRetries) {
60
+ return task.attempts > 0 ? ` · retry ${task.attempts}/${maxRetries}` : "";
61
+ }
62
+ export function buildStatusBody(input) {
63
+ const now = input.now ?? Date.now();
64
+ const header = `📊 DevBot status — work item #${input.workItemNumber}`;
65
+ if (!input.running && input.queued.length === 0) {
66
+ return [header, "Nothing running, nothing queued.", branchLine(input), autoLine(input.autoFeatures)].join("\n");
67
+ }
68
+ const lines = [
69
+ header,
70
+ `Global: ${input.gate.active}/${input.gate.max} slots busy · ${input.gate.waiting} waiting for a slot`,
71
+ ];
72
+ if (input.running) {
73
+ const r = input.running;
74
+ const state = input.runningGatePosition !== null
75
+ ? `waiting for a global slot (position ${input.runningGatePosition})`
76
+ : `started ${formatDuration(r.claimedAt === null ? 0 : now - r.claimedAt)} ago`;
77
+ lines.push("", `▶️ Running — ${r.label} · ${state}${retrySuffix(r, input.maxRetries)}`, ` ${branchLine(input)}`);
78
+ const excerpt = messageExcerpt(r.prompt);
79
+ if (excerpt)
80
+ lines.push(` \`${excerpt}\``);
81
+ }
82
+ else {
83
+ lines.push("", "Nothing running.", branchLine(input));
84
+ }
85
+ if (input.queued.length > 0) {
86
+ lines.push("", `🗒 This work item's queue — ${input.queued.length} waiting (cap ${input.maxQueuePerWorkItem})`);
87
+ for (const [i, q] of input.queued.entries()) {
88
+ const excerpt = messageExcerpt(q.prompt);
89
+ const detail = excerpt ? ` — \`${excerpt}\`` : "";
90
+ const age = q.enqueuedAt > 0 ? now - q.enqueuedAt : 0;
91
+ lines.push(` ${i + 1}. ${q.label}${detail} · queued ${formatDuration(age)} ago${retrySuffix(q, input.maxRetries)}`);
92
+ }
93
+ const head = input.queued[0];
94
+ const rank = head.globalPosition ?? 0;
95
+ const rankText = rank === 0 ? "next in line globally" : `${rank} ahead globally`;
96
+ lines.push("", `⏭ Next to start — #1 ${head.label} · ${rankText}`);
97
+ }
98
+ lines.push("", autoLine(input.autoFeatures));
99
+ return lines.join("\n");
100
+ }
101
+ // One start note per attempt, posted only when the task actually waited — in
102
+ // this work item's own queue or for a global slot. The timer starts at the
103
+ // row's enqueued_at, so a stacked run reports its full wait, not gate wait only.
104
+ export function buildStartNote(input) {
105
+ // Retries are already announced by the 🔁 note; one start note per task.
106
+ if (input.attempts > 0)
107
+ return null;
108
+ if (!input.queuedBehind && !input.gateQueued)
109
+ return null;
110
+ const excerpt = messageExcerpt(input.prompt);
111
+ const label = excerpt ? `${input.label} \`${excerpt}\`` : input.label;
112
+ const head = `▶️ Starting — ${label} (waited ${formatDuration(input.startedAt - input.enqueuedAt)})`;
113
+ const next = input.remaining[0];
114
+ if (!next)
115
+ return head;
116
+ const nextExcerpt = messageExcerpt(next.prompt);
117
+ const nextLabel = nextExcerpt ? `${next.label} \`${nextExcerpt}\`` : next.label;
118
+ const waiting = `${input.remaining.length} task${input.remaining.length === 1 ? "" : "s"} waiting`;
119
+ return `${head}\n${waiting} — ${nextLabel} · next in line`;
120
+ }
121
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
package/dist/stop.js ADDED
@@ -0,0 +1,56 @@
1
+ import { log } from "./logger.js";
2
+ import { getPlatform } from "./platform/index.js";
3
+ import { podman } from "./podman.js";
4
+ import { workItemContainerNames } from "./git.js";
5
+ import { getTask, countPendingForWorkItem, requestCancelWorkItem, requestCancelSeq, deleteQueuedForWorkItem, deletePending, } from "./queue-store.js";
6
+ // Force-stop every phase container for a work item (clone/sync/run/push/…).
7
+ // Best-effort: absent containers make podman exit non-zero, logged at debug.
8
+ async function killContainers(workItemId) {
9
+ const names = workItemContainerNames(workItemId);
10
+ const r = await podman(["rm", "-f", ...names]);
11
+ if (r.code !== 0)
12
+ log.debug("stop: no phase container to kill", { workItemId, code: r.code });
13
+ }
14
+ // Work-item scope (/stop): flag every queued+running row (durably), drop the
15
+ // queued backlog, and kill the phase containers. The running row stays in the
16
+ // DB until run() unwinds as cancelled so the worker still marks it done.
17
+ export async function stopWorkItem(workItemId) {
18
+ const before = countPendingForWorkItem(workItemId);
19
+ requestCancelWorkItem(workItemId);
20
+ deleteQueuedForWorkItem(workItemId);
21
+ await killContainers(workItemId);
22
+ if (before === 0)
23
+ return { ok: true, message: "ℹ️ Nothing to stop." };
24
+ return { ok: true, message: "🛑 Stopped." };
25
+ }
26
+ // Task scope (WebUI row): queued -> delete this row only; running -> flag this
27
+ // seq and kill the work item's phase containers.
28
+ export async function stopTask(seq) {
29
+ const row = getTask(seq);
30
+ if (!row)
31
+ return { ok: false, message: "⚠️ Task not found." };
32
+ if (row.status === "running") {
33
+ requestCancelSeq(seq);
34
+ await killContainers(row.work_item_id);
35
+ return { ok: true, message: "🛑 Stopped." };
36
+ }
37
+ deletePending(seq);
38
+ return { ok: true, message: "🛑 Removed from queue." };
39
+ }
40
+ // /stop mention entrypoint. Mirrors handleResetNote: the trigger-authorization
41
+ // gate (the configured trigger policy, refined by per-project rules) is
42
+ // enforced by webhook.ts before this is called. Posts the result in-thread on
43
+ // success; on failure posts an error reply in-thread (triggeringNoteId) or
44
+ // top-level on the creation path.
45
+ export async function handleStopNote(projectId, workItemNumber, workItemId, triggeringNoteId) {
46
+ try {
47
+ const result = await stopWorkItem(workItemId);
48
+ await getPlatform().workItems.postComment(projectId, workItemNumber, result.message).catch((e) => log.warn("stop-result note failed", e));
49
+ }
50
+ catch (e) {
51
+ log.warn("stop failed", { workItemId, err: e });
52
+ await getPlatform().workItems.postErrorReply(projectId, workItemNumber, triggeringNoteId, "⚠️ Stop failed; see logs.")
53
+ .catch((e2) => log.warn("stop-error note failed", e2));
54
+ }
55
+ }
56
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../src/stop.ts"],"names":[],"mappings":"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"}
package/dist/sweeps.js ADDED
@@ -0,0 +1,87 @@
1
+ import { runtime } from "./runtime-state.js";
2
+ import { log } from "./logger.js";
3
+ import { purgeInactiveVolumes } from "./volume-gc.js";
4
+ import { refreshManagedProjectPaths } from "./project-sync.js";
5
+ import { purgeErrorLogsOlderThan } from "./error-log-store.js";
6
+ import { purgeRunLogs } from "./run-log.js";
7
+ import { refreshDueMcpAuth } from "./mcp/oauth-refresh.js";
8
+ // Periodic maintenance sweeps whose cadence + on/off switches moved into the
9
+ // runtime settings (work item #55). Kept out of lifecycle.ts so the settings PUT
10
+ // can rearm them live: a changed VOLUME_GC_INTERVAL_MS / PROJECT_SYNC_INTERVAL_MS
11
+ // / ERROR_LOG_RETENTION_DAYS takes effect without a process restart.
12
+ //
13
+ // All timers are .unref()'d so they never keep an idle process alive.
14
+ const ERROR_LOG_SWEEP_INTERVAL_MS = 24 * 60 * 60_000;
15
+ // Run-log files carry an hours-scale TTL (default 48h), so the sweep runs
16
+ // hourly rather than daily — a file should not linger most of a day past TTL.
17
+ const RUN_LOG_SWEEP_INTERVAL_MS = 60 * 60_000;
18
+ // Refresh MCP tokens expiring within this window. Kept at 12h — longer than the
19
+ // maximum sweep interval (8h), so a token cannot expire between two checks
20
+ // without having been eligible for refresh at the previous one.
21
+ export const MCP_REFRESH_HORIZON_MS = 12 * 60 * 60_000;
22
+ let timers = [];
23
+ function clearSweeps() {
24
+ for (const t of timers)
25
+ clearInterval(t);
26
+ timers = [];
27
+ }
28
+ // (Re)schedule the periodic sweeps from the current runtime snapshot. Clearing
29
+ // first makes this idempotent: boot calls it once, and each settings PUT calls it
30
+ // again to apply a changed interval or toggle.
31
+ export function armSweeps() {
32
+ const rt = runtime();
33
+ clearSweeps();
34
+ if (rt.volumeGcEnabled) {
35
+ timers.push(setInterval(() => {
36
+ void purgeInactiveVolumes().catch((e) => log.warn("volume gc sweep failed", { err: e }));
37
+ }, rt.volumeGcIntervalMs).unref());
38
+ log.info("volume gc scheduled", { intervalMs: rt.volumeGcIntervalMs, ttlMs: rt.volumeGcTtlMs });
39
+ }
40
+ if (rt.projectSyncEnabled) {
41
+ timers.push(setInterval(() => {
42
+ void refreshManagedProjectPaths().catch((e) => log.warn("project path sync failed", { err: e }));
43
+ }, rt.projectSyncIntervalMs).unref());
44
+ log.info("project path sync scheduled", { intervalMs: rt.projectSyncIntervalMs });
45
+ }
46
+ if (rt.errorLogRetentionDays > 0) {
47
+ timers.push(setInterval(() => {
48
+ try {
49
+ const n = purgeErrorLogsOlderThan(rt.errorLogRetentionDays);
50
+ if (n > 0)
51
+ log.info("error log sweep purged", { count: n, days: rt.errorLogRetentionDays });
52
+ }
53
+ catch (e) {
54
+ log.warn("error log sweep failed", { err: e });
55
+ }
56
+ }, ERROR_LOG_SWEEP_INTERVAL_MS).unref());
57
+ log.info("error log retention scheduled", { days: rt.errorLogRetentionDays });
58
+ }
59
+ if (rt.mcpRefreshEnabled) {
60
+ timers.push(setInterval(() => {
61
+ void refreshDueMcpAuth(MCP_REFRESH_HORIZON_MS).catch((e) => log.warn("mcp token refresh sweep failed", { err: e }));
62
+ }, rt.mcpRefreshIntervalMs).unref());
63
+ log.info("mcp token refresh scheduled", { intervalMs: rt.mcpRefreshIntervalMs, horizonMs: MCP_REFRESH_HORIZON_MS });
64
+ }
65
+ if (rt.runLogTtlHours > 0) {
66
+ timers.push(setInterval(() => {
67
+ try {
68
+ const n = purgeRunLogs(rt.runLogTtlHours);
69
+ if (n > 0)
70
+ log.info("run log sweep purged", { count: n, hours: rt.runLogTtlHours });
71
+ }
72
+ catch (e) {
73
+ log.warn("run log sweep failed", { err: e });
74
+ }
75
+ }, RUN_LOG_SWEEP_INTERVAL_MS).unref());
76
+ log.info("run log retention scheduled", { hours: rt.runLogTtlHours });
77
+ }
78
+ }
79
+ // Test-only: number of live sweep timers (0 when all disabled).
80
+ export function activeSweepCount() {
81
+ return timers.length;
82
+ }
83
+ // Test-only: tear everything down.
84
+ export function stopSweepsForTest() {
85
+ clearSweeps();
86
+ }
87
+ //# sourceMappingURL=sweeps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweeps.js","sourceRoot":"","sources":["../src/sweeps.ts"],"names":[],"mappings":"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"}