@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,297 @@
1
+ import { dirname, join } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { readFileSync } from "node:fs";
4
+ import { config } from "./config.js";
5
+ import { log } from "./logger.js";
6
+ import { shq, redact } from "./redact.js";
7
+ import { podman } from "./podman.js";
8
+ import { volumeName, envArgs, podmanVolumeName, xdgVolumeName, XDG_HOME_DIR, logDriverArgs } from "./git.js";
9
+ import { storageConf, PODMAN_STORE_DIR } from "./devcontainer.js";
10
+ import { permissionGlobRule } from "./path-sandbox.js";
11
+ import { DEFAULT_LSP_SERVERS, normalizeLspServers } from "./lsp-servers.js";
12
+ const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
13
+ // Base opencode config, loaded once at startup (per user choice — restart to
14
+ // pick up edits, same as today's read-only bind mount). The per-run config
15
+ // written into the volume is this base + an injected mcp.servers block
16
+ // carrying the per-thread bearer token + a provider block per configured
17
+ // provider.
18
+ const OPENCODE_CONFIG_PATH = join(MODULE_DIR, "..", "opencode-config", "opencode.json");
19
+ let baseOpencodeConfig = {};
20
+ try {
21
+ baseOpencodeConfig = JSON.parse(readFileSync(OPENCODE_CONFIG_PATH, "utf8"));
22
+ }
23
+ catch (e) {
24
+ log.error("failed to load base opencode config", { path: OPENCODE_CONFIG_PATH, err: e instanceof Error ? e.message : String(e) });
25
+ }
26
+ // In-container path guard plugin (work item #46). Loaded by opencode from
27
+ // $XDG_CONFIG_HOME/opencode/plugins/ (Global.Path.config derives from
28
+ // XDG_CONFIG_HOME, which the runner points at the xdg volume). Read here and
29
+ // written into the volume per run so the agent's container always has the
30
+ // current policy without a bind mount.
31
+ const PATH_GUARD_PLUGIN_PATH = join(MODULE_DIR, "..", "opencode-config", "plugins", "devbot-path-guard.js");
32
+ let pathGuardPlugin = "";
33
+ try {
34
+ pathGuardPlugin = readFileSync(PATH_GUARD_PLUGIN_PATH, "utf8");
35
+ }
36
+ catch (e) {
37
+ log.error("failed to load path guard plugin", { path: PATH_GUARD_PLUGIN_PATH, err: e instanceof Error ? e.message : String(e) });
38
+ }
39
+ // Build the opencode `provider` map from configured providers: npm package,
40
+ // display name, optional baseURL, and the model catalog. `api_url` from the
41
+ // registry is the provider's default endpoint; `base_url` is an explicit
42
+ // override. Providers without either (e.g. anthropic, openai) rely on
43
+ // opencode's bundled defaults.
44
+ export function buildProviderBlock(providers) {
45
+ const out = {};
46
+ for (const p of providers) {
47
+ if (!p.enabled)
48
+ continue;
49
+ const entry = { npm: p.npm, name: p.name };
50
+ const baseURL = p.baseUrl || p.apiUrl;
51
+ if (baseURL)
52
+ entry.options = { baseURL };
53
+ const models = {};
54
+ for (const m of p.models) {
55
+ const c = p.modelCosts?.[m];
56
+ const priced = c && (c.input || c.output || c.cacheRead || c.cacheWrite);
57
+ models[m] = priced
58
+ ? { name: m, cost: { input: c.input, output: c.output, cache_read: c.cacheRead, cache_write: c.cacheWrite } }
59
+ : { name: m };
60
+ }
61
+ entry.models = models;
62
+ out[p.id] = entry;
63
+ }
64
+ return out;
65
+ }
66
+ export function buildOpencodeConfig(mcpToken, servers, plugins = "", providers = [], skillsPaths = [], lspServers = DEFAULT_LSP_SERVERS) {
67
+ const base = { ...baseOpencodeConfig };
68
+ // Per-run LSP allowlist (work item #102). Start from the shipped object and
69
+ // disable every id outside the resolved list. An empty resolved list is the
70
+ // off switch and emits `lsp: false`.
71
+ const selected = new Set(normalizeLspServers(lspServers));
72
+ const shippedLsp = base.lsp;
73
+ if (selected.size === 0) {
74
+ base.lsp = false;
75
+ }
76
+ else if (shippedLsp && typeof shippedLsp === "object" && !Array.isArray(shippedLsp)) {
77
+ const next = {};
78
+ for (const [id, entry] of Object.entries(shippedLsp)) {
79
+ if (!selected.has(id)) {
80
+ next[id] = { disabled: true };
81
+ continue;
82
+ }
83
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) {
84
+ const enabledEntry = { ...entry };
85
+ delete enabledEntry.disabled;
86
+ next[id] = enabledEntry;
87
+ }
88
+ else {
89
+ next[id] = entry;
90
+ }
91
+ }
92
+ base.lsp = next;
93
+ }
94
+ // Fold the resolved plugin string into the base config's `plugin` array
95
+ // (merge, not replace): union of base + resolved, dedup by exact name, base
96
+ // entries first. Absent/empty = no-op; the base `plugin` array (if any) is
97
+ // untouched. OpenCode reads this array as npm packages to bun-install at
98
+ // startup; see https://opencode.ai/docs/plugins#use-a-plugin — local plugins
99
+ // in .opencode/plugins/ are directory-loaded and out of scope.
100
+ const envPlugins = plugins
101
+ .split(",")
102
+ .map((s) => s.trim())
103
+ .filter(Boolean);
104
+ if (envPlugins.length) {
105
+ const basePlugins = Array.isArray(base.plugin) ? base.plugin : [];
106
+ base.plugin = Array.from(new Set([...basePlugins, ...envPlugins]));
107
+ }
108
+ // Provider block: configured providers replace any base `provider` entries.
109
+ // The shipped opencode.json no longer hardcodes openai-compatible; every
110
+ // provider (registry or custom) is injected per run.
111
+ const providerBlock = buildProviderBlock(providers);
112
+ const baseProvider = (base.provider && typeof base.provider === "object" && !Array.isArray(base.provider))
113
+ ? base.provider
114
+ : {};
115
+ const mergedProvider = { ...baseProvider, ...providerBlock };
116
+ if (Object.keys(mergedProvider).length > 0)
117
+ base.provider = mergedProvider;
118
+ const mcpBaseUrl = (config.MCP_BASE_URL ?? `http://host.containers.internal:${config.MCP_PORT}`).replace(/\/$/, "");
119
+ // ponytail: shallow merge — the caller passes the project's external servers;
120
+ // we inject two bundled internal servers: chrome-devtools (local, headless
121
+ // Chromium) then devbot-forge (remote, the bot's own forge tools).
122
+ // devbot-forge is assigned LAST so it always wins on name collision.
123
+ const mergedServers = { ...servers };
124
+ // Bundled chrome-devtools-mcp — always active, headless, no telemetry.
125
+ // The browser only launches when an agent invokes a browser tool; idle
126
+ // cost is just a Node stdio process. --executable-path points at Fedora's
127
+ // chromium-browser (installed in Dockerfile.builder); the MCP defaults to
128
+ // searching for Google Chrome which isn't in the image. --no-sandbox is
129
+ // required for non-root container execution; --disable-dev-shm-usage
130
+ // avoids crashes on the small container /dev/shm.
131
+ mergedServers["chrome-devtools"] = {
132
+ type: "local",
133
+ command: [
134
+ "chrome-devtools-mcp",
135
+ "--headless",
136
+ "--isolated",
137
+ "--no-usage-statistics",
138
+ "--no-performance-crux",
139
+ "--executable-path", "/usr/bin/chromium-browser",
140
+ "--chromeArg=--no-sandbox",
141
+ "--chromeArg=--disable-dev-shm-usage",
142
+ "--chromeArg=--disable-gpu",
143
+ ],
144
+ enabled: true,
145
+ environment: {
146
+ CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS: "1",
147
+ CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS: "1",
148
+ },
149
+ timeout: 10_000,
150
+ };
151
+ // Bot's own server — always present, always wins on name collision (assigned
152
+ // last). URL points at the internal MCP port (127.0.0.1 only), reached by
153
+ // the container via host.containers.internal (see --add-host in runner.ts).
154
+ mergedServers["devbot-forge"] = {
155
+ type: "remote",
156
+ url: `${mcpBaseUrl}/mcp`,
157
+ headers: { Authorization: `Bearer ${mcpToken}` },
158
+ oauth: false,
159
+ enabled: true,
160
+ };
161
+ // Every LOCAL MCP server (the bundled Chrome and any project-configured local
162
+ // server) runs as the unprivileged `agent` UID, so it cannot read
163
+ // /home/devbot/.xdg. Remote servers are HTTP and are left untouched.
164
+ for (const entry of Object.values(mergedServers)) {
165
+ if (entry && entry.type === "local" && Array.isArray(entry.command)) {
166
+ entry.command = ["/usr/local/bin/devbot-exec-agent", ...entry.command];
167
+ }
168
+ }
169
+ const merged = { ...base, mcp: mergedServers };
170
+ // Custom skills (work item #63): extra folders opencode scans for
171
+ // {skill,skills}/**/SKILL.md. Unioned with any base-config paths (same
172
+ // pattern as plugin) so an operator's base config is never clobbered.
173
+ if (skillsPaths.length > 0) {
174
+ const baseSkills = base.skills && typeof base.skills === "object" && !Array.isArray(base.skills)
175
+ ? base.skills
176
+ : {};
177
+ const basePaths = Array.isArray(baseSkills.paths) ? baseSkills.paths : [];
178
+ base.skills = { ...baseSkills, paths: Array.from(new Set([...basePaths, ...skillsPaths])) };
179
+ merged.skills = base.skills;
180
+ }
181
+ // Path-scope permission denies (work item #46). Merged LAST so a base config
182
+ // or a hand-edited DB row cannot weaken them. These are the fallback tier
183
+ // for custom builder images that predate the managed /etc/opencode config;
184
+ // the guard plugin remains the guaranteed in-process layer.
185
+ const basePermission = base.permission && typeof base.permission === "object" && !Array.isArray(base.permission)
186
+ ? base.permission
187
+ : {};
188
+ const denyRule = permissionGlobRule();
189
+ merged.permission = {
190
+ ...basePermission,
191
+ read: denyRule,
192
+ edit: denyRule,
193
+ glob: denyRule,
194
+ grep: denyRule,
195
+ list: denyRule,
196
+ };
197
+ return JSON.stringify(merged, null, 2);
198
+ }
199
+ // auth.json maps provider id -> { type, key }. One entry per enabled provider.
200
+ export function buildAuthJson(providers) {
201
+ const auth = {};
202
+ for (const p of providers) {
203
+ if (p.enabled && p.apiKey)
204
+ auth[p.id] = { type: "api", key: p.apiKey };
205
+ }
206
+ return JSON.stringify(auth, null, 2);
207
+ }
208
+ // Write auth.json, the per-run opencode.json, AND the per-run mcp-auth.json
209
+ // onto the per-work-item xdg volume (mounted at XDG_HOME_DIR — OUTSIDE
210
+ // /workspace, the cloned repo's working tree). auth.json lands at
211
+ // <XDG_HOME_DIR>/data/opencode/auth.json (where opencode reads it via
212
+ // $XDG_DATA_HOME). opencode.json lands at
213
+ // <XDG_HOME_DIR>/config/opencode/opencode.json (read via $XDG_CONFIG_HOME,
214
+ // which we pass to the run container). mcp-auth.json lands at
215
+ // <XDG_HOME_DIR>/data/opencode/mcp-auth.json (read via $XDG_DATA_HOME) and
216
+ // carries the project's pasted OAuth tokens for remote MCP servers. Keeping
217
+ // them off /workspace means the agent's `git add -A` cannot commit the MCP
218
+ // bearer token or the provider API keys into the target repository.
219
+ //
220
+ // We write INTO the volume rather than bind-mounting because podman rootless
221
+ // bind mounts land as root:root in the container namespace, which devbot can't
222
+ // read (SELinux blocks it even at 644). The container runs as devbot (uid
223
+ // 1000), which owns the volume, so the files end up devbot:devbot 600 —
224
+ // readable by opencode.
225
+ //
226
+ // The opencode.json carries a per-thread MCP bearer token scoped to this work
227
+ // item's project. The mcp-auth.json carries pasted OAuth entries; serverUrl is
228
+ // force-overwritten to match each stored config's url (see buildMcpAuthJson).
229
+ // Folding all three writes into one `podman run` keeps the spawn cost at one.
230
+ export async function writeRunFilesToVolume(workItemId, mcpToken, mcpServers, mcpAuthJson, envVars = [], plugins = "", providers = [], builderImage = config.BUILDER_IMAGE, skillsPaths = [], lspServers = DEFAULT_LSP_SERVERS) {
231
+ const vol = volumeName(workItemId);
232
+ const xdgVol = xdgVolumeName(workItemId);
233
+ const authJson = buildAuthJson(providers);
234
+ const opencodeJson = buildOpencodeConfig(mcpToken, mcpServers, plugins, providers, skillsPaths, lspServers);
235
+ const r = await podman([
236
+ "run", "--rm", ...logDriverArgs(), "--name", `devbot-wi-${workItemId}-auth`,
237
+ "-v", `${vol}:/workspace:Z`,
238
+ "-v", `${xdgVol}:${XDG_HOME_DIR}:Z`,
239
+ ...envArgs(envVars),
240
+ builderImage,
241
+ "sh", "-c",
242
+ // Stage in a devbot-owned directory on the xdg volume, NOT /workspace/.tmp
243
+ // or /workspace/.xdg-*: /workspace is the cloned target repo's working tree,
244
+ // so anything written there could be staged by the agent's `git add -A`. The
245
+ // staging dir lives on the same (xdg) volume for atomic renames and is safe
246
+ // to `rm -rf` because devbot owns the whole volume.
247
+ `mkdir -p ${XDG_HOME_DIR}/data/opencode ${XDG_HOME_DIR}/config/opencode ${XDG_HOME_DIR}/config/opencode/plugins ${XDG_HOME_DIR}/data/.tmp-write ` +
248
+ `&& printf %s ${shq(authJson)} > ${XDG_HOME_DIR}/data/.tmp-write/auth.json ` +
249
+ `&& chmod 600 ${XDG_HOME_DIR}/data/.tmp-write/auth.json ` +
250
+ `&& printf %s ${shq(opencodeJson)} > ${XDG_HOME_DIR}/data/.tmp-write/opencode.json ` +
251
+ `&& chmod 600 ${XDG_HOME_DIR}/data/.tmp-write/opencode.json ` +
252
+ `&& printf %s ${shq(mcpAuthJson)} > ${XDG_HOME_DIR}/data/.tmp-write/mcp-auth.json ` +
253
+ `&& chmod 600 ${XDG_HOME_DIR}/data/.tmp-write/mcp-auth.json ` +
254
+ `&& printf %s ${shq(pathGuardPlugin)} > ${XDG_HOME_DIR}/config/opencode/plugins/devbot-path-guard.js ` +
255
+ `&& chmod 600 ${XDG_HOME_DIR}/config/opencode/plugins/devbot-path-guard.js ` +
256
+ `&& mv ${XDG_HOME_DIR}/data/.tmp-write/auth.json ${XDG_HOME_DIR}/data/opencode/auth.json ` +
257
+ `&& mv ${XDG_HOME_DIR}/data/.tmp-write/opencode.json ${XDG_HOME_DIR}/config/opencode/opencode.json ` +
258
+ `&& mv ${XDG_HOME_DIR}/data/.tmp-write/mcp-auth.json ${XDG_HOME_DIR}/data/opencode/mcp-auth.json ` +
259
+ `&& rm -rf ${XDG_HOME_DIR}/data/.tmp-write ` +
260
+ // The credential volume is readable ONLY by opencode (uid devbot). The
261
+ // `agent` UID runs bash/MCP/podman and must be locked out by DAC.
262
+ `&& chmod 700 ${XDG_HOME_DIR} && chmod 700 ${XDG_HOME_DIR}/config ${XDG_HOME_DIR}/data`,
263
+ ]);
264
+ if (r.code !== 0) {
265
+ throw new Error(`writeRunFilesToVolume failed: ${redact(r.stderr.slice(-256))}`);
266
+ }
267
+ }
268
+ // Create the private nested-Podman store volume (if absent) and write the inner
269
+ // containers/storage.conf pinning the resolved driver and graphroot/runroot.
270
+ // One `podman run` folds volume auto-creation (named `-v` volumes are created on
271
+ // demand) and the config write. Only called for build-mode runs with
272
+ // DEVCONTAINER_ENABLED; throws on failure so the run aborts with a real error.
273
+ //
274
+ // --userns=keep-id is REQUIRED: the builder image's user is uid 1000 but the
275
+ // container's rootless subuid map differs from the host's, so a store volume
276
+ // populated WITHOUT keep-id is owned by an unmapped subuid and the actual run
277
+ // (launched with keep-id, see nestedPodmanArgs) cannot write its storage/
278
+ // subdir — nested podman then fails with "mkdir ... permission denied". Writing
279
+ // under the same userns mapping the run uses keeps the volume writable.
280
+ export async function ensurePodmanStore(workItemId, driver, builderImage = config.BUILDER_IMAGE) {
281
+ const vol = podmanVolumeName(workItemId);
282
+ const r = await podman([
283
+ "run", "--rm", ...logDriverArgs(), "--name", `devbot-wi-${workItemId}-podman-init`,
284
+ "--userns=keep-id",
285
+ "-v", `${vol}:${PODMAN_STORE_DIR}:Z`,
286
+ builderImage,
287
+ "sh", "-c",
288
+ // The nested podman runs as the unprivileged `agent` UID (gid devbot); make
289
+ // the store root group-writable so it can create storage/ + runroot/.
290
+ `printf %s ${shq(storageConf(driver))} > ${PODMAN_STORE_DIR}/storage.conf ` +
291
+ `&& chmod 0775 ${PODMAN_STORE_DIR}`,
292
+ ]);
293
+ if (r.code !== 0) {
294
+ throw new Error(`ensurePodmanStore failed: ${redact(r.stderr.slice(-256))}`);
295
+ }
296
+ }
297
+ //# sourceMappingURL=run-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-files.js","sourceRoot":"","sources":["../src/run-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ export function matchesActiveRun(v, f) {
2
+ if (f.projectId !== undefined && v.projectId !== f.projectId)
3
+ return false;
4
+ if (f.model !== undefined && v.model !== f.model)
5
+ return false;
6
+ if (f.mode !== undefined && v.mode !== f.mode)
7
+ return false;
8
+ if (f.title !== undefined && !v.workItemTitle.toLowerCase().includes(f.title.toLowerCase()))
9
+ return false;
10
+ if (f.window !== undefined && !(v.enqueuedAt >= f.window.start && v.enqueuedAt < f.window.end))
11
+ return false;
12
+ return true;
13
+ }
14
+ // The settled-history filter for a given status: `errored` pins the row state
15
+ // to `failed`, `cancelled` to `cancelled`; `all`/`settled` leave it open. The
16
+ // date window maps to `finished_at` bounds.
17
+ export function historyFilter(f, status) {
18
+ const out = {};
19
+ if (status === "errored")
20
+ out.status = "failed";
21
+ else if (status === "cancelled")
22
+ out.status = "cancelled";
23
+ if (f.projectId !== undefined)
24
+ out.projectId = f.projectId;
25
+ if (f.model !== undefined)
26
+ out.model = f.model;
27
+ if (f.mode !== undefined)
28
+ out.mode = f.mode;
29
+ if (f.title !== undefined)
30
+ out.title = f.title;
31
+ if (f.window !== undefined) {
32
+ out.sinceMs = f.window.start;
33
+ out.untilMs = f.window.end;
34
+ }
35
+ return out;
36
+ }
37
+ // Union of the settled-history options and the in-flight rows' values, so a
38
+ // filter can select a project/model/mode that only exists in-flight.
39
+ export function mergeFilterOptions(history, active) {
40
+ const projects = new Set(history.projects);
41
+ const models = new Set(history.models);
42
+ const modes = new Set(history.modes);
43
+ for (const v of active) {
44
+ projects.add(v.projectId);
45
+ models.add(v.model);
46
+ modes.add(v.mode);
47
+ }
48
+ return {
49
+ projects: [...projects].sort((a, b) => a - b),
50
+ models: [...models].sort(),
51
+ modes: [...modes].sort(),
52
+ };
53
+ }
54
+ //# sourceMappingURL=run-filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-filters.js","sourceRoot":"","sources":["../src/run-filters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,229 @@
1
+ import { db } from "./db.js";
2
+ function escLike(term) {
3
+ return term.replace(/[\\%_]/g, (ch) => `\\${ch}`);
4
+ }
5
+ function buildHistoryWhere(filter) {
6
+ if (!filter)
7
+ return { sql: "", params: [] };
8
+ const clauses = [];
9
+ const params = [];
10
+ if (filter.status !== undefined) {
11
+ clauses.push("status = ?");
12
+ params.push(filter.status);
13
+ }
14
+ if (filter.projectId !== undefined) {
15
+ clauses.push("project_id = ?");
16
+ params.push(filter.projectId);
17
+ }
18
+ if (filter.model !== undefined) {
19
+ clauses.push("model = ?");
20
+ params.push(filter.model);
21
+ }
22
+ if (filter.mode !== undefined) {
23
+ clauses.push("mode = ?");
24
+ params.push(filter.mode);
25
+ }
26
+ if (filter.title !== undefined) {
27
+ clauses.push("work_item_title LIKE ? ESCAPE '\\'");
28
+ params.push(`%${escLike(filter.title)}%`);
29
+ }
30
+ if (filter.sinceMs !== undefined) {
31
+ clauses.push("finished_at >= ?");
32
+ params.push(filter.sinceMs);
33
+ }
34
+ if (filter.untilMs !== undefined) {
35
+ clauses.push("finished_at < ?");
36
+ params.push(filter.untilMs);
37
+ }
38
+ return { sql: clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "", params };
39
+ }
40
+ export function initRunHistoryTables() {
41
+ // Belt-and-braces: migration 0025 is authoritative; keep the idempotent
42
+ // CREATE so a test DB opened without migrate() still works.
43
+ db.exec(`
44
+ CREATE TABLE IF NOT EXISTS run_history (
45
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
46
+ task_seq INTEGER,
47
+ project_id INTEGER NOT NULL,
48
+ work_item_id INTEGER NOT NULL,
49
+ work_item_iid INTEGER NOT NULL,
50
+ work_item_title TEXT NOT NULL DEFAULT '',
51
+ mode TEXT NOT NULL,
52
+ model TEXT NOT NULL DEFAULT '',
53
+ variant TEXT NOT NULL DEFAULT '',
54
+ status TEXT NOT NULL,
55
+ phase TEXT NOT NULL DEFAULT '',
56
+ kind TEXT NOT NULL DEFAULT '',
57
+ exit_code INTEGER,
58
+ message TEXT NOT NULL DEFAULT '',
59
+ attempts INTEGER NOT NULL DEFAULT 0,
60
+ enqueued_at INTEGER NOT NULL DEFAULT 0,
61
+ started_at INTEGER NOT NULL DEFAULT 0,
62
+ finished_at INTEGER NOT NULL,
63
+ log_file TEXT NOT NULL DEFAULT '',
64
+ log_truncated INTEGER NOT NULL DEFAULT 0
65
+ )
66
+ `);
67
+ db.exec("CREATE INDEX IF NOT EXISTS idx_run_history_finished ON run_history(finished_at)");
68
+ db.exec("CREATE INDEX IF NOT EXISTS idx_run_history_project ON run_history(project_id)");
69
+ // A pre-0026 DB lacks the task_seq index. CREATE errors if it exists.
70
+ try {
71
+ db.exec("CREATE INDEX IF NOT EXISTS idx_run_history_task_seq ON run_history(task_seq)");
72
+ }
73
+ catch { /* exists */ }
74
+ // Pre-0028 DBs lack the token-usage columns (work item #66).
75
+ for (const col of [
76
+ "input_tokens INTEGER NOT NULL DEFAULT 0",
77
+ "output_tokens INTEGER NOT NULL DEFAULT 0",
78
+ "reasoning_tokens INTEGER NOT NULL DEFAULT 0",
79
+ "cache_read_tokens INTEGER NOT NULL DEFAULT 0",
80
+ "cache_write_tokens INTEGER NOT NULL DEFAULT 0",
81
+ "cost_usd REAL NOT NULL DEFAULT 0",
82
+ ]) {
83
+ try {
84
+ db.exec(`ALTER TABLE run_history ADD COLUMN ${col}`);
85
+ }
86
+ catch { /* exists */ }
87
+ }
88
+ }
89
+ function toSummary(r) {
90
+ return {
91
+ id: r.id,
92
+ taskSeq: r.task_seq,
93
+ projectId: r.project_id,
94
+ workItemId: r.work_item_id,
95
+ workItemIid: r.work_item_iid,
96
+ workItemTitle: r.work_item_title,
97
+ mode: r.mode,
98
+ model: r.model,
99
+ variant: r.variant,
100
+ status: r.status,
101
+ phase: r.phase,
102
+ kind: r.kind,
103
+ exitCode: r.exit_code,
104
+ message: r.message,
105
+ attempts: r.attempts,
106
+ enqueuedAt: r.enqueued_at,
107
+ startedAt: r.started_at,
108
+ finishedAt: r.finished_at,
109
+ logFile: r.log_file,
110
+ logTruncated: r.log_truncated === 1,
111
+ inputTokens: r.input_tokens,
112
+ outputTokens: r.output_tokens,
113
+ reasoningTokens: r.reasoning_tokens,
114
+ cacheReadTokens: r.cache_read_tokens,
115
+ cacheWriteTokens: r.cache_write_tokens,
116
+ costUsd: r.cost_usd,
117
+ };
118
+ }
119
+ export function recordRunHistory(input) {
120
+ const r = db
121
+ .prepare(`INSERT INTO run_history
122
+ (task_seq, project_id, work_item_id, work_item_iid, work_item_title, mode, model, variant,
123
+ status, phase, kind, exit_code, message, attempts, enqueued_at, started_at, finished_at,
124
+ log_file, log_truncated, input_tokens, output_tokens, reasoning_tokens, cache_read_tokens,
125
+ cache_write_tokens, cost_usd)
126
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
127
+ .run(input.taskSeq, input.projectId, input.workItemId, input.workItemNumber, input.workItemTitle ?? "", input.mode, input.model ?? "", input.variant ?? "", input.status, input.phase ?? "", input.kind ?? "", input.exitCode, input.message ?? "", input.attempts ?? 0, input.enqueuedAt ?? 0, input.startedAt ?? 0, Date.now(), input.logFile, input.logTruncated ? 1 : 0, input.inputTokens ?? 0, input.outputTokens ?? 0, input.reasoningTokens ?? 0, input.cacheReadTokens ?? 0, input.cacheWriteTokens ?? 0, input.costUsd ?? 0);
128
+ return Number(r.lastInsertRowid);
129
+ }
130
+ const SUMMARY_COLS = `id, task_seq, project_id, work_item_id, work_item_iid, work_item_title, mode, model, variant,
131
+ status, phase, kind, exit_code, message, attempts, enqueued_at, started_at, finished_at,
132
+ log_file, log_truncated, input_tokens, output_tokens, reasoning_tokens, cache_read_tokens,
133
+ cache_write_tokens, cost_usd`;
134
+ // Newest-first by task seq (work item #61). The unified Runs page merges these
135
+ // with in-flight queue rows on the shared seq, so both sources order by seq
136
+ // DESC. Rows with no task_seq (null) sort last. `id DESC` is a deterministic
137
+ // tiebreaker: without it, LIMIT/OFFSET paging over many null-seq rows could
138
+ // return ties in a different order per request and skip/repeat rows.
139
+ export function listRunHistoryBySeq(limit, offset, filter) {
140
+ const { sql: where, params } = buildHistoryWhere(filter);
141
+ const sql = `SELECT ${SUMMARY_COLS} FROM run_history${where} ORDER BY task_seq IS NULL, task_seq DESC, id DESC` +
142
+ (limit === undefined ? "" : " LIMIT ? OFFSET ?");
143
+ const args = limit === undefined ? params : [...params, limit, offset ?? 0];
144
+ const rows = db.prepare(sql).all(...args);
145
+ return rows.map(toSummary);
146
+ }
147
+ export function countRunHistory(filter) {
148
+ const { sql: where, params } = buildHistoryWhere(filter);
149
+ const row = db.prepare(`SELECT COUNT(*) AS c FROM run_history${where}`).get(...params);
150
+ return row.c;
151
+ }
152
+ // Distinct filter values across all settled history, ignoring any active
153
+ // filter, so a selected value can always be cleared again. Mirrors
154
+ // `computeUsageStats().filterOptions`.
155
+ export function listRunHistoryFilterOptions() {
156
+ const rows = db
157
+ .prepare("SELECT DISTINCT project_id, model, mode FROM run_history")
158
+ .all();
159
+ const projects = new Set();
160
+ const models = new Set();
161
+ const modes = new Set();
162
+ for (const r of rows) {
163
+ projects.add(r.project_id);
164
+ models.add(r.model);
165
+ modes.add(r.mode);
166
+ }
167
+ return {
168
+ projects: [...projects].sort((a, b) => a - b),
169
+ models: [...models].sort(),
170
+ modes: [...modes].sort(),
171
+ };
172
+ }
173
+ export function getRunHistory(id) {
174
+ const row = db.prepare(`SELECT ${SUMMARY_COLS} FROM run_history WHERE id = ?`).get(id);
175
+ return row ? toSummary(row) : null;
176
+ }
177
+ // Newest history row for a task seq. Backs the live-log route's settle fallback:
178
+ // a task that just finished has no pending_tasks row, but its history row
179
+ // points at the archived log file. Null when the task never settled.
180
+ export function getRunHistoryByTaskSeq(taskSeq) {
181
+ const row = db
182
+ .prepare(`SELECT ${SUMMARY_COLS} FROM run_history WHERE task_seq = ? ORDER BY id DESC LIMIT 1`)
183
+ .get(taskSeq);
184
+ return row ? toSummary(row) : null;
185
+ }
186
+ // Blank the log-file reference on the given rows (the TTL purger deleted the
187
+ // files). The row itself is kept. Returns the number of rows updated.
188
+ export function clearLogFile(ids) {
189
+ if (ids.length === 0)
190
+ return 0;
191
+ const stmt = db.prepare("UPDATE run_history SET log_file = '' WHERE id = ?");
192
+ let n = 0;
193
+ for (const id of ids)
194
+ n += Number(stmt.run(id).changes);
195
+ return n;
196
+ }
197
+ // Rows whose log file is older than `cutoffMs` and still carry a reference —
198
+ // the candidates the TTL purge must unlink and clear. `finished_at` is epoch
199
+ // MILLISECONDS (matching enqueued_at/started_at), so the cutoff is ms too.
200
+ export function listExpiredLogRows(cutoffMs) {
201
+ const rows = db
202
+ .prepare("SELECT id, log_file FROM run_history WHERE log_file != '' AND finished_at < ?")
203
+ .all(cutoffMs);
204
+ return rows.map((r) => ({ id: r.id, logFile: r.log_file }));
205
+ }
206
+ export function listUsageRows(sinceMs) {
207
+ const rows = db
208
+ .prepare(`SELECT id, finished_at, project_id, work_item_iid, work_item_title, model, mode,
209
+ input_tokens, output_tokens, reasoning_tokens, cache_read_tokens,
210
+ cache_write_tokens, cost_usd
211
+ FROM run_history WHERE finished_at >= ? ORDER BY finished_at DESC`)
212
+ .all(sinceMs);
213
+ return rows.map((r) => ({
214
+ id: r.id,
215
+ finishedAt: r.finished_at,
216
+ projectId: r.project_id,
217
+ workItemIid: r.work_item_iid,
218
+ workItemTitle: r.work_item_title,
219
+ model: r.model,
220
+ mode: r.mode,
221
+ inputTokens: r.input_tokens,
222
+ outputTokens: r.output_tokens,
223
+ reasoningTokens: r.reasoning_tokens,
224
+ cacheReadTokens: r.cache_read_tokens,
225
+ cacheWriteTokens: r.cache_write_tokens,
226
+ costUsd: r.cost_usd,
227
+ }));
228
+ }
229
+ //# sourceMappingURL=run-history-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-history-store.js","sourceRoot":"","sources":["../src/run-history-store.ts"],"names":[],"mappings":"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"}