@fideliosai/server 2026.331.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (753) hide show
  1. package/LICENSE +22 -0
  2. package/dist/adapters/codex-models.d.ts +4 -0
  3. package/dist/adapters/codex-models.d.ts.map +1 -0
  4. package/dist/adapters/codex-models.js +98 -0
  5. package/dist/adapters/codex-models.js.map +1 -0
  6. package/dist/adapters/cursor-models.d.ts +13 -0
  7. package/dist/adapters/cursor-models.d.ts.map +1 -0
  8. package/dist/adapters/cursor-models.js +148 -0
  9. package/dist/adapters/cursor-models.js.map +1 -0
  10. package/dist/adapters/http/execute.d.ts +3 -0
  11. package/dist/adapters/http/execute.d.ts.map +1 -0
  12. package/dist/adapters/http/execute.js +39 -0
  13. package/dist/adapters/http/execute.js.map +1 -0
  14. package/dist/adapters/http/index.d.ts +3 -0
  15. package/dist/adapters/http/index.d.ts.map +1 -0
  16. package/dist/adapters/http/index.js +20 -0
  17. package/dist/adapters/http/index.js.map +1 -0
  18. package/dist/adapters/http/test.d.ts +3 -0
  19. package/dist/adapters/http/test.d.ts.map +1 -0
  20. package/dist/adapters/http/test.js +106 -0
  21. package/dist/adapters/http/test.js.map +1 -0
  22. package/dist/adapters/index.d.ts +4 -0
  23. package/dist/adapters/index.d.ts.map +1 -0
  24. package/dist/adapters/index.js +3 -0
  25. package/dist/adapters/index.js.map +1 -0
  26. package/dist/adapters/process/execute.d.ts +3 -0
  27. package/dist/adapters/process/execute.d.ts.map +1 -0
  28. package/dist/adapters/process/execute.js +63 -0
  29. package/dist/adapters/process/execute.js.map +1 -0
  30. package/dist/adapters/process/index.d.ts +3 -0
  31. package/dist/adapters/process/index.d.ts.map +1 -0
  32. package/dist/adapters/process/index.js +23 -0
  33. package/dist/adapters/process/index.js.map +1 -0
  34. package/dist/adapters/process/test.d.ts +3 -0
  35. package/dist/adapters/process/test.d.ts.map +1 -0
  36. package/dist/adapters/process/test.js +77 -0
  37. package/dist/adapters/process/test.js.map +1 -0
  38. package/dist/adapters/registry.d.ts +14 -0
  39. package/dist/adapters/registry.d.ts.map +1 -0
  40. package/dist/adapters/registry.js +164 -0
  41. package/dist/adapters/registry.js.map +1 -0
  42. package/dist/adapters/types.d.ts +2 -0
  43. package/dist/adapters/types.d.ts.map +1 -0
  44. package/dist/adapters/types.js +2 -0
  45. package/dist/adapters/types.js.map +1 -0
  46. package/dist/adapters/utils.d.ts +10 -0
  47. package/dist/adapters/utils.d.ts.map +1 -0
  48. package/dist/adapters/utils.js +14 -0
  49. package/dist/adapters/utils.js.map +1 -0
  50. package/dist/agent-auth-jwt.d.ts +14 -0
  51. package/dist/agent-auth-jwt.d.ts.map +1 -0
  52. package/dist/agent-auth-jwt.js +117 -0
  53. package/dist/agent-auth-jwt.js.map +1 -0
  54. package/dist/app.d.ts +25 -0
  55. package/dist/app.d.ts.map +1 -0
  56. package/dist/app.js +265 -0
  57. package/dist/app.js.map +1 -0
  58. package/dist/attachment-types.d.ts +33 -0
  59. package/dist/attachment-types.d.ts.map +1 -0
  60. package/dist/attachment-types.js +67 -0
  61. package/dist/attachment-types.js.map +1 -0
  62. package/dist/auth/better-auth.d.ts +24 -0
  63. package/dist/auth/better-auth.d.ts.map +1 -0
  64. package/dist/auth/better-auth.js +108 -0
  65. package/dist/auth/better-auth.js.map +1 -0
  66. package/dist/board-claim.d.ts +23 -0
  67. package/dist/board-claim.d.ts.map +1 -0
  68. package/dist/board-claim.js +115 -0
  69. package/dist/board-claim.js.map +1 -0
  70. package/dist/config-file.d.ts +3 -0
  71. package/dist/config-file.d.ts.map +1 -0
  72. package/dist/config-file.js +16 -0
  73. package/dist/config-file.js.map +1 -0
  74. package/dist/config.d.ts +45 -0
  75. package/dist/config.d.ts.map +1 -0
  76. package/dist/config.js +171 -0
  77. package/dist/config.js.map +1 -0
  78. package/dist/dev-server-status.d.ts +27 -0
  79. package/dist/dev-server-status.d.ts.map +1 -0
  80. package/dist/dev-server-status.js +70 -0
  81. package/dist/dev-server-status.js.map +1 -0
  82. package/dist/dev-watch-ignore.d.ts +2 -0
  83. package/dist/dev-watch-ignore.d.ts.map +1 -0
  84. package/dist/dev-watch-ignore.js +33 -0
  85. package/dist/dev-watch-ignore.js.map +1 -0
  86. package/dist/errors.d.ts +12 -0
  87. package/dist/errors.d.ts.map +1 -0
  88. package/dist/errors.js +28 -0
  89. package/dist/errors.js.map +1 -0
  90. package/dist/home-paths.d.ts +17 -0
  91. package/dist/home-paths.d.ts.map +1 -0
  92. package/dist/home-paths.js +75 -0
  93. package/dist/home-paths.js.map +1 -0
  94. package/dist/index.d.ts +10 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +642 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/log-redaction.d.ts +11 -0
  99. package/dist/log-redaction.d.ts.map +1 -0
  100. package/dist/log-redaction.js +118 -0
  101. package/dist/log-redaction.js.map +1 -0
  102. package/dist/middleware/auth.d.ts +12 -0
  103. package/dist/middleware/auth.d.ts.map +1 -0
  104. package/dist/middleware/auth.js +144 -0
  105. package/dist/middleware/auth.js.map +1 -0
  106. package/dist/middleware/board-mutation-guard.d.ts +3 -0
  107. package/dist/middleware/board-mutation-guard.d.ts.map +1 -0
  108. package/dist/middleware/board-mutation-guard.js +59 -0
  109. package/dist/middleware/board-mutation-guard.js.map +1 -0
  110. package/dist/middleware/error-handler.d.ts +17 -0
  111. package/dist/middleware/error-handler.d.ts.map +1 -0
  112. package/dist/middleware/error-handler.js +37 -0
  113. package/dist/middleware/error-handler.js.map +1 -0
  114. package/dist/middleware/index.d.ts +4 -0
  115. package/dist/middleware/index.d.ts.map +1 -0
  116. package/dist/middleware/index.js +4 -0
  117. package/dist/middleware/index.js.map +1 -0
  118. package/dist/middleware/logger.d.ts +4 -0
  119. package/dist/middleware/logger.d.ts.map +1 -0
  120. package/dist/middleware/logger.js +87 -0
  121. package/dist/middleware/logger.js.map +1 -0
  122. package/dist/middleware/private-hostname-guard.d.ts +11 -0
  123. package/dist/middleware/private-hostname-guard.d.ts.map +1 -0
  124. package/dist/middleware/private-hostname-guard.js +78 -0
  125. package/dist/middleware/private-hostname-guard.js.map +1 -0
  126. package/dist/middleware/validate.d.ts +4 -0
  127. package/dist/middleware/validate.d.ts.map +1 -0
  128. package/dist/middleware/validate.js +7 -0
  129. package/dist/middleware/validate.js.map +1 -0
  130. package/dist/onboarding-assets/ceo/AGENTS.md +54 -0
  131. package/dist/onboarding-assets/ceo/HEARTBEAT.md +72 -0
  132. package/dist/onboarding-assets/ceo/SOUL.md +33 -0
  133. package/dist/onboarding-assets/ceo/TOOLS.md +3 -0
  134. package/dist/onboarding-assets/default/AGENTS.md +3 -0
  135. package/dist/paths.d.ts +3 -0
  136. package/dist/paths.d.ts.map +1 -0
  137. package/dist/paths.js +31 -0
  138. package/dist/paths.js.map +1 -0
  139. package/dist/realtime/live-events-ws.d.ts +28 -0
  140. package/dist/realtime/live-events-ws.d.ts.map +1 -0
  141. package/dist/realtime/live-events-ws.js +187 -0
  142. package/dist/realtime/live-events-ws.js.map +1 -0
  143. package/dist/redaction.d.ts +4 -0
  144. package/dist/redaction.d.ts.map +1 -0
  145. package/dist/redaction.js +63 -0
  146. package/dist/redaction.js.map +1 -0
  147. package/dist/routes/access.d.ts +61 -0
  148. package/dist/routes/access.d.ts.map +1 -0
  149. package/dist/routes/access.js +2265 -0
  150. package/dist/routes/access.js.map +1 -0
  151. package/dist/routes/activity.d.ts +3 -0
  152. package/dist/routes/activity.d.ts.map +1 -0
  153. package/dist/routes/activity.js +78 -0
  154. package/dist/routes/activity.js.map +1 -0
  155. package/dist/routes/agents.d.ts +3 -0
  156. package/dist/routes/agents.d.ts.map +1 -0
  157. package/dist/routes/agents.js +1828 -0
  158. package/dist/routes/agents.js.map +1 -0
  159. package/dist/routes/approvals.d.ts +3 -0
  160. package/dist/routes/approvals.d.ts.map +1 -0
  161. package/dist/routes/approvals.js +275 -0
  162. package/dist/routes/approvals.js.map +1 -0
  163. package/dist/routes/assets.d.ts +4 -0
  164. package/dist/routes/assets.d.ts.map +1 -0
  165. package/dist/routes/assets.js +309 -0
  166. package/dist/routes/assets.js.map +1 -0
  167. package/dist/routes/authz.d.ts +16 -0
  168. package/dist/routes/authz.d.ts.map +1 -0
  169. package/dist/routes/authz.js +47 -0
  170. package/dist/routes/authz.js.map +1 -0
  171. package/dist/routes/companies.d.ts +4 -0
  172. package/dist/routes/companies.d.ts.map +1 -0
  173. package/dist/routes/companies.js +303 -0
  174. package/dist/routes/companies.js.map +1 -0
  175. package/dist/routes/company-skills.d.ts +3 -0
  176. package/dist/routes/company-skills.d.ts.map +1 -0
  177. package/dist/routes/company-skills.js +228 -0
  178. package/dist/routes/company-skills.js.map +1 -0
  179. package/dist/routes/costs.d.ts +3 -0
  180. package/dist/routes/costs.d.ts.map +1 -0
  181. package/dist/routes/costs.js +268 -0
  182. package/dist/routes/costs.js.map +1 -0
  183. package/dist/routes/dashboard.d.ts +3 -0
  184. package/dist/routes/dashboard.d.ts.map +1 -0
  185. package/dist/routes/dashboard.js +15 -0
  186. package/dist/routes/dashboard.js.map +1 -0
  187. package/dist/routes/execution-workspaces.d.ts +3 -0
  188. package/dist/routes/execution-workspaces.d.ts.map +1 -0
  189. package/dist/routes/execution-workspaces.js +165 -0
  190. package/dist/routes/execution-workspaces.js.map +1 -0
  191. package/dist/routes/goals.d.ts +3 -0
  192. package/dist/routes/goals.d.ts.map +1 -0
  193. package/dist/routes/goals.js +95 -0
  194. package/dist/routes/goals.js.map +1 -0
  195. package/dist/routes/health.d.ts +9 -0
  196. package/dist/routes/health.d.ts.map +1 -0
  197. package/dist/routes/health.js +69 -0
  198. package/dist/routes/health.js.map +1 -0
  199. package/dist/routes/index.d.ts +18 -0
  200. package/dist/routes/index.d.ts.map +1 -0
  201. package/dist/routes/index.js +18 -0
  202. package/dist/routes/index.js.map +1 -0
  203. package/dist/routes/instance-settings.d.ts +3 -0
  204. package/dist/routes/instance-settings.d.ts.map +1 -0
  205. package/dist/routes/instance-settings.js +71 -0
  206. package/dist/routes/instance-settings.js.map +1 -0
  207. package/dist/routes/issues-checkout-wakeup.d.ts +9 -0
  208. package/dist/routes/issues-checkout-wakeup.d.ts.map +1 -0
  209. package/dist/routes/issues-checkout-wakeup.js +12 -0
  210. package/dist/routes/issues-checkout-wakeup.js.map +1 -0
  211. package/dist/routes/issues.d.ts +4 -0
  212. package/dist/routes/issues.d.ts.map +1 -0
  213. package/dist/routes/issues.js +1520 -0
  214. package/dist/routes/issues.js.map +1 -0
  215. package/dist/routes/llms.d.ts +3 -0
  216. package/dist/routes/llms.d.ts.map +1 -0
  217. package/dist/routes/llms.js +78 -0
  218. package/dist/routes/llms.js.map +1 -0
  219. package/dist/routes/org-chart-svg.d.ts +25 -0
  220. package/dist/routes/org-chart-svg.d.ts.map +1 -0
  221. package/dist/routes/org-chart-svg.js +657 -0
  222. package/dist/routes/org-chart-svg.js.map +1 -0
  223. package/dist/routes/plugin-ui-static.d.ts +69 -0
  224. package/dist/routes/plugin-ui-static.d.ts.map +1 -0
  225. package/dist/routes/plugin-ui-static.js +411 -0
  226. package/dist/routes/plugin-ui-static.js.map +1 -0
  227. package/dist/routes/plugins.d.ts +120 -0
  228. package/dist/routes/plugins.d.ts.map +1 -0
  229. package/dist/routes/plugins.js +1784 -0
  230. package/dist/routes/plugins.js.map +1 -0
  231. package/dist/routes/projects.d.ts +3 -0
  232. package/dist/routes/projects.d.ts.map +1 -0
  233. package/dist/routes/projects.js +257 -0
  234. package/dist/routes/projects.js.map +1 -0
  235. package/dist/routes/routines.d.ts +3 -0
  236. package/dist/routes/routines.d.ts.map +1 -0
  237. package/dist/routes/routines.js +277 -0
  238. package/dist/routes/routines.js.map +1 -0
  239. package/dist/routes/secrets.d.ts +3 -0
  240. package/dist/routes/secrets.d.ts.map +1 -0
  241. package/dist/routes/secrets.js +128 -0
  242. package/dist/routes/secrets.js.map +1 -0
  243. package/dist/routes/sidebar-badges.d.ts +3 -0
  244. package/dist/routes/sidebar-badges.d.ts.map +1 -0
  245. package/dist/routes/sidebar-badges.js +45 -0
  246. package/dist/routes/sidebar-badges.js.map +1 -0
  247. package/dist/secrets/external-stub-providers.d.ts +5 -0
  248. package/dist/secrets/external-stub-providers.d.ts.map +1 -0
  249. package/dist/secrets/external-stub-providers.js +21 -0
  250. package/dist/secrets/external-stub-providers.js.map +1 -0
  251. package/dist/secrets/local-encrypted-provider.d.ts +3 -0
  252. package/dist/secrets/local-encrypted-provider.d.ts.map +1 -0
  253. package/dist/secrets/local-encrypted-provider.js +116 -0
  254. package/dist/secrets/local-encrypted-provider.js.map +1 -0
  255. package/dist/secrets/provider-registry.d.ts +5 -0
  256. package/dist/secrets/provider-registry.d.ts.map +1 -0
  257. package/dist/secrets/provider-registry.js +20 -0
  258. package/dist/secrets/provider-registry.js.map +1 -0
  259. package/dist/secrets/types.d.ts +21 -0
  260. package/dist/secrets/types.d.ts.map +1 -0
  261. package/dist/secrets/types.js +2 -0
  262. package/dist/secrets/types.js.map +1 -0
  263. package/dist/services/access.d.ts +113 -0
  264. package/dist/services/access.d.ts.map +1 -0
  265. package/dist/services/access.js +247 -0
  266. package/dist/services/access.js.map +1 -0
  267. package/dist/services/activity-log.d.ts +17 -0
  268. package/dist/services/activity-log.d.ts.map +1 -0
  269. package/dist/services/activity-log.js +74 -0
  270. package/dist/services/activity-log.js.map +1 -0
  271. package/dist/services/activity.d.ts +764 -0
  272. package/dist/services/activity.d.ts.map +1 -0
  273. package/dist/services/activity.js +105 -0
  274. package/dist/services/activity.js.map +1 -0
  275. package/dist/services/agent-instructions.d.ts +91 -0
  276. package/dist/services/agent-instructions.d.ts.map +1 -0
  277. package/dist/services/agent-instructions.js +580 -0
  278. package/dist/services/agent-instructions.js.map +1 -0
  279. package/dist/services/agent-permissions.d.ts +6 -0
  280. package/dist/services/agent-permissions.d.ts.map +1 -0
  281. package/dist/services/agent-permissions.js +18 -0
  282. package/dist/services/agent-permissions.js.map +1 -0
  283. package/dist/services/agents.d.ts +1670 -0
  284. package/dist/services/agents.d.ts.map +1 -0
  285. package/dist/services/agents.js +566 -0
  286. package/dist/services/agents.js.map +1 -0
  287. package/dist/services/approvals.d.ts +546 -0
  288. package/dist/services/approvals.d.ts.map +1 -0
  289. package/dist/services/approvals.js +212 -0
  290. package/dist/services/approvals.js.map +1 -0
  291. package/dist/services/assets.d.ts +33 -0
  292. package/dist/services/assets.d.ts.map +1 -0
  293. package/dist/services/assets.js +17 -0
  294. package/dist/services/assets.js.map +1 -0
  295. package/dist/services/board-auth.d.ts +234 -0
  296. package/dist/services/board-auth.d.ts.map +1 -0
  297. package/dist/services/board-auth.js +295 -0
  298. package/dist/services/board-auth.js.map +1 -0
  299. package/dist/services/budgets.d.ts +38 -0
  300. package/dist/services/budgets.d.ts.map +1 -0
  301. package/dist/services/budgets.js +784 -0
  302. package/dist/services/budgets.js.map +1 -0
  303. package/dist/services/companies.d.ts +124 -0
  304. package/dist/services/companies.d.ts.map +1 -0
  305. package/dist/services/companies.js +256 -0
  306. package/dist/services/companies.js.map +1 -0
  307. package/dist/services/company-export-readme.d.ts +17 -0
  308. package/dist/services/company-export-readme.d.ts.map +1 -0
  309. package/dist/services/company-export-readme.js +148 -0
  310. package/dist/services/company-export-readme.js.map +1 -0
  311. package/dist/services/company-portability.d.ts +23 -0
  312. package/dist/services/company-portability.d.ts.map +1 -0
  313. package/dist/services/company-portability.js +3739 -0
  314. package/dist/services/company-portability.js.map +1 -0
  315. package/dist/services/company-skills.d.ts +77 -0
  316. package/dist/services/company-skills.d.ts.map +1 -0
  317. package/dist/services/company-skills.js +2042 -0
  318. package/dist/services/company-skills.js.map +1 -0
  319. package/dist/services/costs.d.ts +114 -0
  320. package/dist/services/costs.d.ts.map +1 -0
  321. package/dist/services/costs.js +294 -0
  322. package/dist/services/costs.js.map +1 -0
  323. package/dist/services/cron.d.ts +80 -0
  324. package/dist/services/cron.d.ts.map +1 -0
  325. package/dist/services/cron.js +300 -0
  326. package/dist/services/cron.js.map +1 -0
  327. package/dist/services/dashboard.d.ts +26 -0
  328. package/dist/services/dashboard.d.ts.map +1 -0
  329. package/dist/services/dashboard.js +98 -0
  330. package/dist/services/dashboard.js.map +1 -0
  331. package/dist/services/default-agent-instructions.d.ts +9 -0
  332. package/dist/services/default-agent-instructions.d.ts.map +1 -0
  333. package/dist/services/default-agent-instructions.js +20 -0
  334. package/dist/services/default-agent-instructions.js.map +1 -0
  335. package/dist/services/documents.d.ts +164 -0
  336. package/dist/services/documents.d.ts.map +1 -0
  337. package/dist/services/documents.js +382 -0
  338. package/dist/services/documents.js.map +1 -0
  339. package/dist/services/execution-workspace-policy.d.ts +21 -0
  340. package/dist/services/execution-workspace-policy.d.ts.map +1 -0
  341. package/dist/services/execution-workspace-policy.js +177 -0
  342. package/dist/services/execution-workspace-policy.js.map +1 -0
  343. package/dist/services/execution-workspaces.d.ts +19 -0
  344. package/dist/services/execution-workspaces.d.ts.map +1 -0
  345. package/dist/services/execution-workspaces.js +87 -0
  346. package/dist/services/execution-workspaces.js.map +1 -0
  347. package/dist/services/finance.d.ts +93 -0
  348. package/dist/services/finance.d.ts.map +1 -0
  349. package/dist/services/finance.js +120 -0
  350. package/dist/services/finance.js.map +1 -0
  351. package/dist/services/goals.d.ts +433 -0
  352. package/dist/services/goals.d.ts.map +1 -0
  353. package/dist/services/goals.js +54 -0
  354. package/dist/services/goals.js.map +1 -0
  355. package/dist/services/heartbeat-run-summary.d.ts +2 -0
  356. package/dist/services/heartbeat-run-summary.d.ts.map +1 -0
  357. package/dist/services/heartbeat-run-summary.js +30 -0
  358. package/dist/services/heartbeat-run-summary.js.map +1 -0
  359. package/dist/services/heartbeat.d.ts +812 -0
  360. package/dist/services/heartbeat.d.ts.map +1 -0
  361. package/dist/services/heartbeat.js +3156 -0
  362. package/dist/services/heartbeat.js.map +1 -0
  363. package/dist/services/hire-hook.d.ts +14 -0
  364. package/dist/services/hire-hook.d.ts.map +1 -0
  365. package/dist/services/hire-hook.js +85 -0
  366. package/dist/services/hire-hook.js.map +1 -0
  367. package/dist/services/index.d.ts +33 -0
  368. package/dist/services/index.d.ts.map +1 -0
  369. package/dist/services/index.js +33 -0
  370. package/dist/services/index.js.map +1 -0
  371. package/dist/services/instance-settings.d.ts +11 -0
  372. package/dist/services/instance-settings.d.ts.map +1 -0
  373. package/dist/services/instance-settings.js +116 -0
  374. package/dist/services/instance-settings.js.map +1 -0
  375. package/dist/services/issue-approvals.d.ts +56 -0
  376. package/dist/services/issue-approvals.d.ts.map +1 -0
  377. package/dist/services/issue-approvals.js +153 -0
  378. package/dist/services/issue-approvals.js.map +1 -0
  379. package/dist/services/issue-assignment-wakeup.d.ts +29 -0
  380. package/dist/services/issue-assignment-wakeup.d.ts.map +1 -0
  381. package/dist/services/issue-assignment-wakeup.js +22 -0
  382. package/dist/services/issue-assignment-wakeup.js.map +1 -0
  383. package/dist/services/issue-goal-fallback.d.ts +18 -0
  384. package/dist/services/issue-goal-fallback.d.ts.map +1 -0
  385. package/dist/services/issue-goal-fallback.js +33 -0
  386. package/dist/services/issue-goal-fallback.js.map +1 -0
  387. package/dist/services/issues.d.ts +560 -0
  388. package/dist/services/issues.d.ts.map +1 -0
  389. package/dist/services/issues.js +1478 -0
  390. package/dist/services/issues.js.map +1 -0
  391. package/dist/services/live-events.d.ts +17 -0
  392. package/dist/services/live-events.d.ts.map +1 -0
  393. package/dist/services/live-events.js +33 -0
  394. package/dist/services/live-events.js.map +1 -0
  395. package/dist/services/plugin-capability-validator.d.ts +108 -0
  396. package/dist/services/plugin-capability-validator.d.ts.map +1 -0
  397. package/dist/services/plugin-capability-validator.js +268 -0
  398. package/dist/services/plugin-capability-validator.js.map +1 -0
  399. package/dist/services/plugin-config-validator.d.ts +26 -0
  400. package/dist/services/plugin-config-validator.d.ts.map +1 -0
  401. package/dist/services/plugin-config-validator.js +41 -0
  402. package/dist/services/plugin-config-validator.js.map +1 -0
  403. package/dist/services/plugin-dev-watcher.d.ts +30 -0
  404. package/dist/services/plugin-dev-watcher.d.ts.map +1 -0
  405. package/dist/services/plugin-dev-watcher.js +241 -0
  406. package/dist/services/plugin-dev-watcher.js.map +1 -0
  407. package/dist/services/plugin-event-bus.d.ts +149 -0
  408. package/dist/services/plugin-event-bus.d.ts.map +1 -0
  409. package/dist/services/plugin-event-bus.js +258 -0
  410. package/dist/services/plugin-event-bus.js.map +1 -0
  411. package/dist/services/plugin-host-service-cleanup.d.ts +14 -0
  412. package/dist/services/plugin-host-service-cleanup.d.ts.map +1 -0
  413. package/dist/services/plugin-host-service-cleanup.js +37 -0
  414. package/dist/services/plugin-host-service-cleanup.js.map +1 -0
  415. package/dist/services/plugin-host-services.d.ts +13 -0
  416. package/dist/services/plugin-host-services.d.ts.map +1 -0
  417. package/dist/services/plugin-host-services.js +969 -0
  418. package/dist/services/plugin-host-services.js.map +1 -0
  419. package/dist/services/plugin-job-coordinator.d.ts +81 -0
  420. package/dist/services/plugin-job-coordinator.d.ts.map +1 -0
  421. package/dist/services/plugin-job-coordinator.js +172 -0
  422. package/dist/services/plugin-job-coordinator.js.map +1 -0
  423. package/dist/services/plugin-job-scheduler.d.ts +163 -0
  424. package/dist/services/plugin-job-scheduler.d.ts.map +1 -0
  425. package/dist/services/plugin-job-scheduler.js +454 -0
  426. package/dist/services/plugin-job-scheduler.js.map +1 -0
  427. package/dist/services/plugin-job-store.d.ts +208 -0
  428. package/dist/services/plugin-job-store.d.ts.map +1 -0
  429. package/dist/services/plugin-job-store.js +350 -0
  430. package/dist/services/plugin-job-store.js.map +1 -0
  431. package/dist/services/plugin-lifecycle.d.ts +203 -0
  432. package/dist/services/plugin-lifecycle.d.ts.map +1 -0
  433. package/dist/services/plugin-lifecycle.js +476 -0
  434. package/dist/services/plugin-lifecycle.js.map +1 -0
  435. package/dist/services/plugin-loader.d.ts +441 -0
  436. package/dist/services/plugin-loader.d.ts.map +1 -0
  437. package/dist/services/plugin-loader.js +1192 -0
  438. package/dist/services/plugin-loader.js.map +1 -0
  439. package/dist/services/plugin-log-retention.d.ts +20 -0
  440. package/dist/services/plugin-log-retention.d.ts.map +1 -0
  441. package/dist/services/plugin-log-retention.js +63 -0
  442. package/dist/services/plugin-log-retention.js.map +1 -0
  443. package/dist/services/plugin-manifest-validator.d.ts +79 -0
  444. package/dist/services/plugin-manifest-validator.d.ts.map +1 -0
  445. package/dist/services/plugin-manifest-validator.js +84 -0
  446. package/dist/services/plugin-manifest-validator.js.map +1 -0
  447. package/dist/services/plugin-registry.d.ts +2542 -0
  448. package/dist/services/plugin-registry.d.ts.map +1 -0
  449. package/dist/services/plugin-registry.js +539 -0
  450. package/dist/services/plugin-registry.js.map +1 -0
  451. package/dist/services/plugin-runtime-sandbox.d.ts +40 -0
  452. package/dist/services/plugin-runtime-sandbox.d.ts.map +1 -0
  453. package/dist/services/plugin-runtime-sandbox.js +154 -0
  454. package/dist/services/plugin-runtime-sandbox.js.map +1 -0
  455. package/dist/services/plugin-secrets-handler.d.ts +81 -0
  456. package/dist/services/plugin-secrets-handler.d.ts.map +1 -0
  457. package/dist/services/plugin-secrets-handler.js +275 -0
  458. package/dist/services/plugin-secrets-handler.js.map +1 -0
  459. package/dist/services/plugin-state-store.d.ts +92 -0
  460. package/dist/services/plugin-state-store.d.ts.map +1 -0
  461. package/dist/services/plugin-state-store.js +190 -0
  462. package/dist/services/plugin-state-store.js.map +1 -0
  463. package/dist/services/plugin-stream-bus.d.ts +29 -0
  464. package/dist/services/plugin-stream-bus.d.ts.map +1 -0
  465. package/dist/services/plugin-stream-bus.js +48 -0
  466. package/dist/services/plugin-stream-bus.js.map +1 -0
  467. package/dist/services/plugin-tool-dispatcher.d.ts +180 -0
  468. package/dist/services/plugin-tool-dispatcher.d.ts.map +1 -0
  469. package/dist/services/plugin-tool-dispatcher.js +224 -0
  470. package/dist/services/plugin-tool-dispatcher.js.map +1 -0
  471. package/dist/services/plugin-tool-registry.d.ts +192 -0
  472. package/dist/services/plugin-tool-registry.d.ts.map +1 -0
  473. package/dist/services/plugin-tool-registry.js +224 -0
  474. package/dist/services/plugin-tool-registry.js.map +1 -0
  475. package/dist/services/plugin-worker-manager.d.ts +260 -0
  476. package/dist/services/plugin-worker-manager.d.ts.map +1 -0
  477. package/dist/services/plugin-worker-manager.js +835 -0
  478. package/dist/services/plugin-worker-manager.js.map +1 -0
  479. package/dist/services/projects.d.ts +87 -0
  480. package/dist/services/projects.d.ts.map +1 -0
  481. package/dist/services/projects.js +656 -0
  482. package/dist/services/projects.js.map +1 -0
  483. package/dist/services/quota-windows.d.ts +9 -0
  484. package/dist/services/quota-windows.d.ts.map +1 -0
  485. package/dist/services/quota-windows.js +56 -0
  486. package/dist/services/quota-windows.js.map +1 -0
  487. package/dist/services/routines.d.ts +135 -0
  488. package/dist/services/routines.d.ts.map +1 -0
  489. package/dist/services/routines.js +1105 -0
  490. package/dist/services/routines.js.map +1 -0
  491. package/dist/services/run-log-store.d.ts +34 -0
  492. package/dist/services/run-log-store.d.ts.map +1 -0
  493. package/dist/services/run-log-store.js +109 -0
  494. package/dist/services/run-log-store.js.map +1 -0
  495. package/dist/services/secrets.d.ts +511 -0
  496. package/dist/services/secrets.d.ts.map +1 -0
  497. package/dist/services/secrets.js +289 -0
  498. package/dist/services/secrets.js.map +1 -0
  499. package/dist/services/sidebar-badges.d.ts +9 -0
  500. package/dist/services/sidebar-badges.d.ts.map +1 -0
  501. package/dist/services/sidebar-badges.js +33 -0
  502. package/dist/services/sidebar-badges.js.map +1 -0
  503. package/dist/services/work-products.d.ts +14 -0
  504. package/dist/services/work-products.d.ts.map +1 -0
  505. package/dist/services/work-products.js +100 -0
  506. package/dist/services/work-products.js.map +1 -0
  507. package/dist/services/workspace-operation-log-store.d.ts +33 -0
  508. package/dist/services/workspace-operation-log-store.d.ts.map +1 -0
  509. package/dist/services/workspace-operation-log-store.js +110 -0
  510. package/dist/services/workspace-operation-log-store.js.map +1 -0
  511. package/dist/services/workspace-operations.d.ts +44 -0
  512. package/dist/services/workspace-operations.d.ts.map +1 -0
  513. package/dist/services/workspace-operations.js +211 -0
  514. package/dist/services/workspace-operations.js.map +1 -0
  515. package/dist/services/workspace-runtime.d.ts +164 -0
  516. package/dist/services/workspace-runtime.d.ts.map +1 -0
  517. package/dist/services/workspace-runtime.js +1235 -0
  518. package/dist/services/workspace-runtime.js.map +1 -0
  519. package/dist/startup-banner.d.ts +31 -0
  520. package/dist/startup-banner.d.ts.map +1 -0
  521. package/dist/startup-banner.js +117 -0
  522. package/dist/startup-banner.js.map +1 -0
  523. package/dist/storage/index.d.ts +6 -0
  524. package/dist/storage/index.d.ts.map +1 -0
  525. package/dist/storage/index.js +29 -0
  526. package/dist/storage/index.js.map +1 -0
  527. package/dist/storage/local-disk-provider.d.ts +3 -0
  528. package/dist/storage/local-disk-provider.d.ts.map +1 -0
  529. package/dist/storage/local-disk-provider.js +79 -0
  530. package/dist/storage/local-disk-provider.js.map +1 -0
  531. package/dist/storage/provider-registry.d.ts +4 -0
  532. package/dist/storage/provider-registry.d.ts.map +1 -0
  533. package/dist/storage/provider-registry.js +15 -0
  534. package/dist/storage/provider-registry.js.map +1 -0
  535. package/dist/storage/s3-provider.d.ts +11 -0
  536. package/dist/storage/s3-provider.d.ts.map +1 -0
  537. package/dist/storage/s3-provider.js +123 -0
  538. package/dist/storage/s3-provider.js.map +1 -0
  539. package/dist/storage/service.d.ts +3 -0
  540. package/dist/storage/service.d.ts.map +1 -0
  541. package/dist/storage/service.js +120 -0
  542. package/dist/storage/service.js.map +1 -0
  543. package/dist/storage/types.d.ts +55 -0
  544. package/dist/storage/types.d.ts.map +1 -0
  545. package/dist/storage/types.js +2 -0
  546. package/dist/storage/types.js.map +1 -0
  547. package/dist/ui-branding.d.ts +13 -0
  548. package/dist/ui-branding.d.ts.map +1 -0
  549. package/dist/ui-branding.js +188 -0
  550. package/dist/ui-branding.js.map +1 -0
  551. package/dist/version.d.ts +2 -0
  552. package/dist/version.d.ts.map +1 -0
  553. package/dist/version.js +5 -0
  554. package/dist/version.js.map +1 -0
  555. package/dist/worktree-config.d.ts +19 -0
  556. package/dist/worktree-config.d.ts.map +1 -0
  557. package/dist/worktree-config.js +365 -0
  558. package/dist/worktree-config.js.map +1 -0
  559. package/package.json +90 -0
  560. package/skills/fidelios/SKILL.md +365 -0
  561. package/skills/fidelios/references/api-reference.md +647 -0
  562. package/skills/fidelios/references/company-skills.md +193 -0
  563. package/skills/fidelios-create-agent/SKILL.md +142 -0
  564. package/skills/fidelios-create-agent/references/api-reference.md +105 -0
  565. package/skills/fidelios-create-plugin/SKILL.md +101 -0
  566. package/skills/para-memory-files/SKILL.md +104 -0
  567. package/skills/para-memory-files/references/schemas.md +35 -0
  568. package/ui-dist/android-chrome-192x192.png +0 -0
  569. package/ui-dist/android-chrome-512x512.png +0 -0
  570. package/ui-dist/apple-touch-icon.png +0 -0
  571. package/ui-dist/assets/_basePickBy-DDS8rFE9.js +1 -0
  572. package/ui-dist/assets/_baseUniq-BTIdqnfJ.js +1 -0
  573. package/ui-dist/assets/apl-B4CMkyY2.js +1 -0
  574. package/ui-dist/assets/arc-CER6ytAf.js +1 -0
  575. package/ui-dist/assets/architectureDiagram-VXUJARFQ-CrJvVSPh.js +36 -0
  576. package/ui-dist/assets/asciiarmor-Df11BRmG.js +1 -0
  577. package/ui-dist/assets/asn1-EdZsLKOL.js +1 -0
  578. package/ui-dist/assets/asterisk-B-8jnY81.js +1 -0
  579. package/ui-dist/assets/blockDiagram-VD42YOAC-p-DB7nkA.js +122 -0
  580. package/ui-dist/assets/brainfuck-C4LP7Hcl.js +1 -0
  581. package/ui-dist/assets/c4Diagram-YG6GDRKO-D1K75fYz.js +10 -0
  582. package/ui-dist/assets/channel-B1viE-VZ.js +1 -0
  583. package/ui-dist/assets/chunk-4BX2VUAB-C1J-fCaK.js +1 -0
  584. package/ui-dist/assets/chunk-55IACEB6-CjEOgVYA.js +1 -0
  585. package/ui-dist/assets/chunk-B4BG7PRW-CGZwFaze.js +165 -0
  586. package/ui-dist/assets/chunk-DI55MBZ5-Dp2ZahPN.js +220 -0
  587. package/ui-dist/assets/chunk-FMBD7UC4-nXC1OkzD.js +15 -0
  588. package/ui-dist/assets/chunk-QN33PNHL-D_uFCkMK.js +1 -0
  589. package/ui-dist/assets/chunk-QZHKN3VN-CG3WK_AN.js +1 -0
  590. package/ui-dist/assets/chunk-TZMSLE5B-COlBSWdP.js +1 -0
  591. package/ui-dist/assets/classDiagram-2ON5EDUG-Cs4NEMXI.js +1 -0
  592. package/ui-dist/assets/classDiagram-v2-WZHVMYZB-Cs4NEMXI.js +1 -0
  593. package/ui-dist/assets/clike-B9uivgTg.js +1 -0
  594. package/ui-dist/assets/clojure-BMjYHr_A.js +1 -0
  595. package/ui-dist/assets/clone-CGwZV8ud.js +1 -0
  596. package/ui-dist/assets/cmake-BQqOBYOt.js +1 -0
  597. package/ui-dist/assets/cobol-CWcv1MsR.js +1 -0
  598. package/ui-dist/assets/coffeescript-S37ZYGWr.js +1 -0
  599. package/ui-dist/assets/commonlisp-DBKNyK5s.js +1 -0
  600. package/ui-dist/assets/cose-bilkent-S5V4N54A-B9XYqCMb.js +1 -0
  601. package/ui-dist/assets/crystal-SjHAIU92.js +1 -0
  602. package/ui-dist/assets/css-BnMrqG3P.js +1 -0
  603. package/ui-dist/assets/cypher-C_CwsFkJ.js +1 -0
  604. package/ui-dist/assets/cytoscape.esm-BQaXIfA_.js +331 -0
  605. package/ui-dist/assets/d-pRatUO7H.js +1 -0
  606. package/ui-dist/assets/dagre-6UL2VRFP-DcCdBLC7.js +4 -0
  607. package/ui-dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  608. package/ui-dist/assets/diagram-PSM6KHXK-np1kLquy.js +24 -0
  609. package/ui-dist/assets/diagram-QEK2KX5R-C-b4qIN1.js +43 -0
  610. package/ui-dist/assets/diagram-S2PKOQOG-Ba-173Ug.js +24 -0
  611. package/ui-dist/assets/diff-DbItnlRl.js +1 -0
  612. package/ui-dist/assets/dockerfile-BKs6k2Af.js +1 -0
  613. package/ui-dist/assets/dtd-DF_7sFjM.js +1 -0
  614. package/ui-dist/assets/dylan-DwRh75JA.js +1 -0
  615. package/ui-dist/assets/ebnf-CDyGwa7X.js +1 -0
  616. package/ui-dist/assets/ecl-Cabwm37j.js +1 -0
  617. package/ui-dist/assets/eiffel-CnydiIhH.js +1 -0
  618. package/ui-dist/assets/elm-vLlmbW-K.js +1 -0
  619. package/ui-dist/assets/erDiagram-Q2GNP2WA-BBmkHiJP.js +60 -0
  620. package/ui-dist/assets/erlang-BNw1qcRV.js +1 -0
  621. package/ui-dist/assets/factor-kuTfRLto.js +1 -0
  622. package/ui-dist/assets/fcl-Kvtd6kyn.js +1 -0
  623. package/ui-dist/assets/flowDiagram-NV44I4VS-Dj_iTDkp.js +162 -0
  624. package/ui-dist/assets/forth-Ffai-XNe.js +1 -0
  625. package/ui-dist/assets/fortran-DYz_wnZ1.js +1 -0
  626. package/ui-dist/assets/ganttDiagram-JELNMOA3-Bn1hanTg.js +267 -0
  627. package/ui-dist/assets/gas-Bneqetm1.js +1 -0
  628. package/ui-dist/assets/gherkin-heZmZLOM.js +1 -0
  629. package/ui-dist/assets/gitGraphDiagram-V2S2FVAM-BjmRpty0.js +65 -0
  630. package/ui-dist/assets/graph-CWBOAGTW.js +1 -0
  631. package/ui-dist/assets/groovy-D9Dt4D0W.js +1 -0
  632. package/ui-dist/assets/haskell-Cw1EW3IL.js +1 -0
  633. package/ui-dist/assets/haxe-H-WmDvRZ.js +1 -0
  634. package/ui-dist/assets/http-DBlCnlav.js +1 -0
  635. package/ui-dist/assets/idl-BEugSyMb.js +1 -0
  636. package/ui-dist/assets/index-B52MtqBm.js +1 -0
  637. package/ui-dist/assets/index-BEBYIFOJ.js +1 -0
  638. package/ui-dist/assets/index-BIvl9YFB.js +1 -0
  639. package/ui-dist/assets/index-BNyP1gwD.js +1 -0
  640. package/ui-dist/assets/index-BRW6bV_B.js +6 -0
  641. package/ui-dist/assets/index-BcQTWaKH.js +1 -0
  642. package/ui-dist/assets/index-BfKYbH5T.js +13 -0
  643. package/ui-dist/assets/index-BhX49pA0.js +1 -0
  644. package/ui-dist/assets/index-BoFaTgOC.js +2 -0
  645. package/ui-dist/assets/index-C-Es83iE.js +7 -0
  646. package/ui-dist/assets/index-C3LG8kvr.js +1 -0
  647. package/ui-dist/assets/index-C5Z9j0rD.js +1 -0
  648. package/ui-dist/assets/index-CFlEF-gp.js +1 -0
  649. package/ui-dist/assets/index-Cjm12V39.js +1 -0
  650. package/ui-dist/assets/index-Cp84QmJD.css +1 -0
  651. package/ui-dist/assets/index-D2t01AH0.js +1 -0
  652. package/ui-dist/assets/index-DEt1jkxJ.js +1 -0
  653. package/ui-dist/assets/index-DeAKBJuz.js +3 -0
  654. package/ui-dist/assets/index-Du65R_Zq.js +1 -0
  655. package/ui-dist/assets/index-WUHteAuP.js +1 -0
  656. package/ui-dist/assets/index-Y_jO6IK_.js +1180 -0
  657. package/ui-dist/assets/index-ZQU9QA5y.js +1 -0
  658. package/ui-dist/assets/index-f6wRGThx.js +1 -0
  659. package/ui-dist/assets/index-hMuLlvYa.js +1 -0
  660. package/ui-dist/assets/infoDiagram-HS3SLOUP-CVMKJlmV.js +2 -0
  661. package/ui-dist/assets/init-Gi6I4Gst.js +1 -0
  662. package/ui-dist/assets/javascript-iXu5QeM3.js +1 -0
  663. package/ui-dist/assets/journeyDiagram-XKPGCS4Q-FrNTHHMi.js +139 -0
  664. package/ui-dist/assets/julia-DuME0IfC.js +1 -0
  665. package/ui-dist/assets/kanban-definition-3W4ZIXB7-BQYKwdVh.js +89 -0
  666. package/ui-dist/assets/katex-O9d3_IXG.js +261 -0
  667. package/ui-dist/assets/layout-BxccZ6zb.js +1 -0
  668. package/ui-dist/assets/linear-Db-Yv5jO.js +1 -0
  669. package/ui-dist/assets/livescript-BwQOo05w.js +1 -0
  670. package/ui-dist/assets/lua-BgMRiT3U.js +1 -0
  671. package/ui-dist/assets/mathematica-DTrFuWx2.js +1 -0
  672. package/ui-dist/assets/mbox-CNhZ1qSd.js +1 -0
  673. package/ui-dist/assets/mermaid.core-BCE9tDOe.js +256 -0
  674. package/ui-dist/assets/mindmap-definition-VGOIOE7T-ZWLuqirD.js +68 -0
  675. package/ui-dist/assets/mirc-CjQqDB4T.js +1 -0
  676. package/ui-dist/assets/mllike-CXdrOF99.js +1 -0
  677. package/ui-dist/assets/modelica-Dc1JOy9r.js +1 -0
  678. package/ui-dist/assets/mscgen-BA5vi2Kp.js +1 -0
  679. package/ui-dist/assets/mumps-BT43cFF4.js +1 -0
  680. package/ui-dist/assets/nginx-DdIZxoE0.js +1 -0
  681. package/ui-dist/assets/nsis-LdVXkNf5.js +1 -0
  682. package/ui-dist/assets/ntriples-BfvgReVJ.js +1 -0
  683. package/ui-dist/assets/octave-Ck1zUtKM.js +1 -0
  684. package/ui-dist/assets/ordinal-Cboi1Yqb.js +1 -0
  685. package/ui-dist/assets/oz-BzwKVEFT.js +1 -0
  686. package/ui-dist/assets/pascal--L3eBynH.js +1 -0
  687. package/ui-dist/assets/perl-CdXCOZ3F.js +1 -0
  688. package/ui-dist/assets/pieDiagram-ADFJNKIX-D01HRHJF.js +30 -0
  689. package/ui-dist/assets/pig-CevX1Tat.js +1 -0
  690. package/ui-dist/assets/powershell-CFHJl5sT.js +1 -0
  691. package/ui-dist/assets/properties-C78fOPTZ.js +1 -0
  692. package/ui-dist/assets/protobuf-ChK-085T.js +1 -0
  693. package/ui-dist/assets/pug-DeIclll2.js +1 -0
  694. package/ui-dist/assets/puppet-DMA9R1ak.js +1 -0
  695. package/ui-dist/assets/python-BuPzkPfP.js +1 -0
  696. package/ui-dist/assets/q-pXgVlZs6.js +1 -0
  697. package/ui-dist/assets/quadrantDiagram-AYHSOK5B-lAmOPnB4.js +7 -0
  698. package/ui-dist/assets/r-B6wPVr8A.js +1 -0
  699. package/ui-dist/assets/requirementDiagram-UZGBJVZJ-ByNWbh-O.js +64 -0
  700. package/ui-dist/assets/rpm-CTu-6PCP.js +1 -0
  701. package/ui-dist/assets/ruby-B2Rjki9n.js +1 -0
  702. package/ui-dist/assets/sankeyDiagram-TZEHDZUN-Cf_Gq84u.js +10 -0
  703. package/ui-dist/assets/sas-B4kiWyti.js +1 -0
  704. package/ui-dist/assets/scheme-C41bIUwD.js +1 -0
  705. package/ui-dist/assets/sequenceDiagram-WL72ISMW-Bx2VZbdr.js +145 -0
  706. package/ui-dist/assets/shell-CjFT_Tl9.js +1 -0
  707. package/ui-dist/assets/sieve-C3Gn_uJK.js +1 -0
  708. package/ui-dist/assets/simple-mode-GW_nhZxv.js +1 -0
  709. package/ui-dist/assets/smalltalk-CnHTOXQT.js +1 -0
  710. package/ui-dist/assets/solr-DehyRSwq.js +1 -0
  711. package/ui-dist/assets/sparql-DkYu6x3z.js +1 -0
  712. package/ui-dist/assets/spreadsheet-BCZA_wO0.js +1 -0
  713. package/ui-dist/assets/sql-D0XecflT.js +1 -0
  714. package/ui-dist/assets/stateDiagram-FKZM4ZOC-vP7G7A65.js +1 -0
  715. package/ui-dist/assets/stateDiagram-v2-4FDKWEC3-C2xpsAAO.js +1 -0
  716. package/ui-dist/assets/stex-C3f8Ysf7.js +1 -0
  717. package/ui-dist/assets/stylus-B533Al4x.js +1 -0
  718. package/ui-dist/assets/swift-BzpIVaGY.js +1 -0
  719. package/ui-dist/assets/tcl-DVfN8rqt.js +1 -0
  720. package/ui-dist/assets/textile-CnDTJFAw.js +1 -0
  721. package/ui-dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  722. package/ui-dist/assets/tiki-DGYXhP31.js +1 -0
  723. package/ui-dist/assets/timeline-definition-IT6M3QCI-BJww-sEp.js +61 -0
  724. package/ui-dist/assets/toml-Bm5Em-hy.js +1 -0
  725. package/ui-dist/assets/treemap-GDKQZRPO-DUux14NY.js +162 -0
  726. package/ui-dist/assets/troff-wAsdV37c.js +1 -0
  727. package/ui-dist/assets/ttcn-CfJYG6tj.js +1 -0
  728. package/ui-dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  729. package/ui-dist/assets/turtle-B1tBg_DP.js +1 -0
  730. package/ui-dist/assets/vb-CmGdzxic.js +1 -0
  731. package/ui-dist/assets/vbscript-BuJXcnF6.js +1 -0
  732. package/ui-dist/assets/velocity-D8B20fx6.js +1 -0
  733. package/ui-dist/assets/verilog-C6RDOZhf.js +1 -0
  734. package/ui-dist/assets/vhdl-lSbBsy5d.js +1 -0
  735. package/ui-dist/assets/webidl-ZXfAyPTL.js +1 -0
  736. package/ui-dist/assets/xquery-DzFWVndE.js +1 -0
  737. package/ui-dist/assets/xychartDiagram-PRI3JC2R-AU5ZOwAw.js +7 -0
  738. package/ui-dist/assets/yacas-BJ4BC0dw.js +1 -0
  739. package/ui-dist/assets/z80-Hz9HOZM7.js +1 -0
  740. package/ui-dist/brands/opencode-logo-dark-square.svg +18 -0
  741. package/ui-dist/brands/opencode-logo-light-square.svg +18 -0
  742. package/ui-dist/favicon-16x16.png +0 -0
  743. package/ui-dist/favicon-32x32.png +0 -0
  744. package/ui-dist/favicon-96x96.png +0 -0
  745. package/ui-dist/favicon.ico +0 -0
  746. package/ui-dist/favicon.svg +3 -0
  747. package/ui-dist/index.html +48 -0
  748. package/ui-dist/site.webmanifest +21 -0
  749. package/ui-dist/sw.js +42 -0
  750. package/ui-dist/worktree-favicon-16x16.png +0 -0
  751. package/ui-dist/worktree-favicon-32x32.png +0 -0
  752. package/ui-dist/worktree-favicon.ico +0 -0
  753. package/ui-dist/worktree-favicon.svg +3 -0
@@ -0,0 +1,1478 @@
1
+ import { and, asc, desc, eq, inArray, isNull, ne, or, sql } from "drizzle-orm";
2
+ import { activityLog, agents, assets, companies, companyMemberships, documents, goals, heartbeatRuns, executionWorkspaces, issueAttachments, issueInboxArchives, issueLabels, issueComments, issueDocuments, issueReadStates, issues, labels, projectWorkspaces, projects, } from "@fideliosai/db";
3
+ import { extractAgentMentionIds, extractProjectMentionIds } from "@fideliosai/shared";
4
+ import { conflict, notFound, unprocessable } from "../errors.js";
5
+ import { defaultIssueExecutionWorkspaceSettingsForProject, gateProjectExecutionWorkspacePolicy, parseProjectExecutionWorkspacePolicy, } from "./execution-workspace-policy.js";
6
+ import { instanceSettingsService } from "./instance-settings.js";
7
+ import { redactCurrentUserText } from "../log-redaction.js";
8
+ import { resolveIssueGoalId, resolveNextIssueGoalId } from "./issue-goal-fallback.js";
9
+ import { getDefaultCompanyGoal } from "./goals.js";
10
+ const ALL_ISSUE_STATUSES = ["backlog", "todo", "in_progress", "in_review", "blocked", "done", "cancelled"];
11
+ const MAX_ISSUE_COMMENT_PAGE_LIMIT = 500;
12
+ function assertTransition(from, to) {
13
+ if (from === to)
14
+ return;
15
+ if (!ALL_ISSUE_STATUSES.includes(to)) {
16
+ throw conflict(`Unknown issue status: ${to}`);
17
+ }
18
+ }
19
+ function applyStatusSideEffects(status, patch) {
20
+ if (!status)
21
+ return patch;
22
+ if (status === "in_progress" && !patch.startedAt) {
23
+ patch.startedAt = new Date();
24
+ }
25
+ if (status === "done") {
26
+ patch.completedAt = new Date();
27
+ }
28
+ if (status === "cancelled") {
29
+ patch.cancelledAt = new Date();
30
+ }
31
+ return patch;
32
+ }
33
+ function sameRunLock(checkoutRunId, actorRunId) {
34
+ if (actorRunId)
35
+ return checkoutRunId === actorRunId;
36
+ return checkoutRunId == null;
37
+ }
38
+ const TERMINAL_HEARTBEAT_RUN_STATUSES = new Set(["succeeded", "failed", "cancelled", "timed_out"]);
39
+ function escapeLikePattern(value) {
40
+ return value.replace(/[\\%_]/g, "\\$&");
41
+ }
42
+ async function getProjectDefaultGoalId(db, companyId, projectId) {
43
+ if (!projectId)
44
+ return null;
45
+ const row = await db
46
+ .select({ goalId: projects.goalId })
47
+ .from(projects)
48
+ .where(and(eq(projects.id, projectId), eq(projects.companyId, companyId)))
49
+ .then((rows) => rows[0] ?? null);
50
+ return row?.goalId ?? null;
51
+ }
52
+ function touchedByUserCondition(companyId, userId) {
53
+ return sql `
54
+ (
55
+ ${issues.createdByUserId} = ${userId}
56
+ OR ${issues.assigneeUserId} = ${userId}
57
+ OR EXISTS (
58
+ SELECT 1
59
+ FROM ${issueReadStates}
60
+ WHERE ${issueReadStates.issueId} = ${issues.id}
61
+ AND ${issueReadStates.companyId} = ${companyId}
62
+ AND ${issueReadStates.userId} = ${userId}
63
+ )
64
+ OR EXISTS (
65
+ SELECT 1
66
+ FROM ${issueComments}
67
+ WHERE ${issueComments.issueId} = ${issues.id}
68
+ AND ${issueComments.companyId} = ${companyId}
69
+ AND ${issueComments.authorUserId} = ${userId}
70
+ )
71
+ )
72
+ `;
73
+ }
74
+ function participatedByAgentCondition(companyId, agentId) {
75
+ return sql `
76
+ (
77
+ ${issues.createdByAgentId} = ${agentId}
78
+ OR ${issues.assigneeAgentId} = ${agentId}
79
+ OR EXISTS (
80
+ SELECT 1
81
+ FROM ${issueComments}
82
+ WHERE ${issueComments.issueId} = ${issues.id}
83
+ AND ${issueComments.companyId} = ${companyId}
84
+ AND ${issueComments.authorAgentId} = ${agentId}
85
+ )
86
+ OR EXISTS (
87
+ SELECT 1
88
+ FROM ${activityLog}
89
+ WHERE ${activityLog.companyId} = ${companyId}
90
+ AND ${activityLog.entityType} = 'issue'
91
+ AND ${activityLog.entityId} = ${issues.id}::text
92
+ AND ${activityLog.agentId} = ${agentId}
93
+ )
94
+ )
95
+ `;
96
+ }
97
+ function myLastCommentAtExpr(companyId, userId) {
98
+ return sql `
99
+ (
100
+ SELECT MAX(${issueComments.createdAt})
101
+ FROM ${issueComments}
102
+ WHERE ${issueComments.issueId} = ${issues.id}
103
+ AND ${issueComments.companyId} = ${companyId}
104
+ AND ${issueComments.authorUserId} = ${userId}
105
+ )
106
+ `;
107
+ }
108
+ function myLastReadAtExpr(companyId, userId) {
109
+ return sql `
110
+ (
111
+ SELECT MAX(${issueReadStates.lastReadAt})
112
+ FROM ${issueReadStates}
113
+ WHERE ${issueReadStates.issueId} = ${issues.id}
114
+ AND ${issueReadStates.companyId} = ${companyId}
115
+ AND ${issueReadStates.userId} = ${userId}
116
+ )
117
+ `;
118
+ }
119
+ function myLastTouchAtExpr(companyId, userId) {
120
+ const myLastCommentAt = myLastCommentAtExpr(companyId, userId);
121
+ const myLastReadAt = myLastReadAtExpr(companyId, userId);
122
+ return sql `
123
+ GREATEST(
124
+ COALESCE(${myLastCommentAt}, to_timestamp(0)),
125
+ COALESCE(${myLastReadAt}, to_timestamp(0)),
126
+ COALESCE(CASE WHEN ${issues.createdByUserId} = ${userId} THEN ${issues.createdAt} ELSE NULL END, to_timestamp(0)),
127
+ COALESCE(CASE WHEN ${issues.assigneeUserId} = ${userId} THEN ${issues.updatedAt} ELSE NULL END, to_timestamp(0))
128
+ )
129
+ `;
130
+ }
131
+ function lastExternalCommentAtExpr(companyId, userId) {
132
+ return sql `
133
+ (
134
+ SELECT MAX(${issueComments.createdAt})
135
+ FROM ${issueComments}
136
+ WHERE ${issueComments.issueId} = ${issues.id}
137
+ AND ${issueComments.companyId} = ${companyId}
138
+ AND (
139
+ ${issueComments.authorUserId} IS NULL
140
+ OR ${issueComments.authorUserId} <> ${userId}
141
+ )
142
+ )
143
+ `;
144
+ }
145
+ function issueLastActivityAtExpr(companyId, userId) {
146
+ const lastExternalCommentAt = lastExternalCommentAtExpr(companyId, userId);
147
+ const myLastTouchAt = myLastTouchAtExpr(companyId, userId);
148
+ return sql `
149
+ COALESCE(
150
+ ${lastExternalCommentAt},
151
+ CASE
152
+ WHEN ${issues.updatedAt} > COALESCE(${myLastTouchAt}, to_timestamp(0))
153
+ THEN ${issues.updatedAt}
154
+ ELSE to_timestamp(0)
155
+ END
156
+ )
157
+ `;
158
+ }
159
+ function unreadForUserCondition(companyId, userId) {
160
+ const touchedCondition = touchedByUserCondition(companyId, userId);
161
+ const myLastTouchAt = myLastTouchAtExpr(companyId, userId);
162
+ return sql `
163
+ (
164
+ ${touchedCondition}
165
+ AND EXISTS (
166
+ SELECT 1
167
+ FROM ${issueComments}
168
+ WHERE ${issueComments.issueId} = ${issues.id}
169
+ AND ${issueComments.companyId} = ${companyId}
170
+ AND (
171
+ ${issueComments.authorUserId} IS NULL
172
+ OR ${issueComments.authorUserId} <> ${userId}
173
+ )
174
+ AND ${issueComments.createdAt} > ${myLastTouchAt}
175
+ )
176
+ )
177
+ `;
178
+ }
179
+ function inboxVisibleForUserCondition(companyId, userId) {
180
+ const issueLastActivityAt = issueLastActivityAtExpr(companyId, userId);
181
+ return sql `
182
+ NOT EXISTS (
183
+ SELECT 1
184
+ FROM ${issueInboxArchives}
185
+ WHERE ${issueInboxArchives.issueId} = ${issues.id}
186
+ AND ${issueInboxArchives.companyId} = ${companyId}
187
+ AND ${issueInboxArchives.userId} = ${userId}
188
+ AND ${issueInboxArchives.archivedAt} >= ${issueLastActivityAt}
189
+ )
190
+ `;
191
+ }
192
+ /** Named entities commonly emitted in saved issue bodies; unknown `&name;` sequences are left unchanged. */
193
+ const WELL_KNOWN_NAMED_HTML_ENTITIES = {
194
+ amp: "&",
195
+ apos: "'",
196
+ copy: "\u00A9",
197
+ gt: ">",
198
+ lt: "<",
199
+ nbsp: "\u00A0",
200
+ quot: '"',
201
+ ensp: "\u2002",
202
+ emsp: "\u2003",
203
+ thinsp: "\u2009",
204
+ };
205
+ function decodeNumericHtmlEntity(digits, radix) {
206
+ const n = Number.parseInt(digits, radix);
207
+ if (Number.isNaN(n) || n < 0 || n > 0x10ffff)
208
+ return null;
209
+ try {
210
+ return String.fromCodePoint(n);
211
+ }
212
+ catch {
213
+ return null;
214
+ }
215
+ }
216
+ /** Decodes HTML character references in a raw @mention capture so UI-encoded bodies match agent names. */
217
+ export function normalizeAgentMentionToken(raw) {
218
+ let s = raw.replace(/&#x([0-9a-fA-F]+);/gi, (full, hex) => decodeNumericHtmlEntity(hex, 16) ?? full);
219
+ s = s.replace(/&#([0-9]+);/g, (full, dec) => decodeNumericHtmlEntity(dec, 10) ?? full);
220
+ s = s.replace(/&([a-z][a-z0-9]*);/gi, (full, name) => {
221
+ const decoded = WELL_KNOWN_NAMED_HTML_ENTITIES[name.toLowerCase()];
222
+ return decoded !== undefined ? decoded : full;
223
+ });
224
+ return s.trim();
225
+ }
226
+ export function deriveIssueUserContext(issue, userId, stats) {
227
+ const normalizeDate = (value) => {
228
+ if (!value)
229
+ return null;
230
+ if (value instanceof Date)
231
+ return Number.isNaN(value.getTime()) ? null : value;
232
+ const parsed = new Date(value);
233
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
234
+ };
235
+ const myLastCommentAt = normalizeDate(stats?.myLastCommentAt);
236
+ const myLastReadAt = normalizeDate(stats?.myLastReadAt);
237
+ const createdTouchAt = issue.createdByUserId === userId ? normalizeDate(issue.createdAt) : null;
238
+ const assignedTouchAt = issue.assigneeUserId === userId ? normalizeDate(issue.updatedAt) : null;
239
+ const myLastTouchAt = [myLastCommentAt, myLastReadAt, createdTouchAt, assignedTouchAt]
240
+ .filter((value) => value instanceof Date)
241
+ .sort((a, b) => b.getTime() - a.getTime())[0] ?? null;
242
+ const lastExternalCommentAt = normalizeDate(stats?.lastExternalCommentAt);
243
+ const isUnreadForMe = Boolean(myLastTouchAt &&
244
+ lastExternalCommentAt &&
245
+ lastExternalCommentAt.getTime() > myLastTouchAt.getTime());
246
+ return {
247
+ myLastTouchAt,
248
+ lastExternalCommentAt,
249
+ isUnreadForMe,
250
+ };
251
+ }
252
+ async function labelMapForIssues(dbOrTx, issueIds) {
253
+ const map = new Map();
254
+ if (issueIds.length === 0)
255
+ return map;
256
+ const rows = await dbOrTx
257
+ .select({
258
+ issueId: issueLabels.issueId,
259
+ label: labels,
260
+ })
261
+ .from(issueLabels)
262
+ .innerJoin(labels, eq(issueLabels.labelId, labels.id))
263
+ .where(inArray(issueLabels.issueId, issueIds))
264
+ .orderBy(asc(labels.name), asc(labels.id));
265
+ for (const row of rows) {
266
+ const existing = map.get(row.issueId);
267
+ if (existing)
268
+ existing.push(row.label);
269
+ else
270
+ map.set(row.issueId, [row.label]);
271
+ }
272
+ return map;
273
+ }
274
+ async function withIssueLabels(dbOrTx, rows) {
275
+ if (rows.length === 0)
276
+ return [];
277
+ const labelsByIssueId = await labelMapForIssues(dbOrTx, rows.map((row) => row.id));
278
+ return rows.map((row) => {
279
+ const issueLabels = labelsByIssueId.get(row.id) ?? [];
280
+ return {
281
+ ...row,
282
+ labels: issueLabels,
283
+ labelIds: issueLabels.map((label) => label.id),
284
+ };
285
+ });
286
+ }
287
+ const ACTIVE_RUN_STATUSES = ["queued", "running"];
288
+ async function activeRunMapForIssues(dbOrTx, issueRows) {
289
+ const map = new Map();
290
+ const runIds = issueRows
291
+ .map((row) => row.executionRunId)
292
+ .filter((id) => id != null);
293
+ if (runIds.length === 0)
294
+ return map;
295
+ const rows = await dbOrTx
296
+ .select({
297
+ id: heartbeatRuns.id,
298
+ status: heartbeatRuns.status,
299
+ agentId: heartbeatRuns.agentId,
300
+ invocationSource: heartbeatRuns.invocationSource,
301
+ triggerDetail: heartbeatRuns.triggerDetail,
302
+ startedAt: heartbeatRuns.startedAt,
303
+ finishedAt: heartbeatRuns.finishedAt,
304
+ createdAt: heartbeatRuns.createdAt,
305
+ })
306
+ .from(heartbeatRuns)
307
+ .where(and(inArray(heartbeatRuns.id, runIds), inArray(heartbeatRuns.status, ACTIVE_RUN_STATUSES)));
308
+ for (const row of rows) {
309
+ map.set(row.id, row);
310
+ }
311
+ return map;
312
+ }
313
+ function withActiveRuns(issueRows, runMap) {
314
+ return issueRows.map((row) => ({
315
+ ...row,
316
+ activeRun: row.executionRunId ? (runMap.get(row.executionRunId) ?? null) : null,
317
+ }));
318
+ }
319
+ export function issueService(db) {
320
+ const instanceSettings = instanceSettingsService(db);
321
+ function redactIssueComment(comment, censorUsernameInLogs) {
322
+ return {
323
+ ...comment,
324
+ body: redactCurrentUserText(comment.body, { enabled: censorUsernameInLogs }),
325
+ };
326
+ }
327
+ async function assertAssignableAgent(companyId, agentId) {
328
+ const assignee = await db
329
+ .select({
330
+ id: agents.id,
331
+ companyId: agents.companyId,
332
+ status: agents.status,
333
+ })
334
+ .from(agents)
335
+ .where(eq(agents.id, agentId))
336
+ .then((rows) => rows[0] ?? null);
337
+ if (!assignee)
338
+ throw notFound("Assignee agent not found");
339
+ if (assignee.companyId !== companyId) {
340
+ throw unprocessable("Assignee must belong to same company");
341
+ }
342
+ if (assignee.status === "pending_approval") {
343
+ throw conflict("Cannot assign work to pending approval agents");
344
+ }
345
+ if (assignee.status === "terminated") {
346
+ throw conflict("Cannot assign work to terminated agents");
347
+ }
348
+ }
349
+ async function assertAssignableUser(companyId, userId) {
350
+ const membership = await db
351
+ .select({ id: companyMemberships.id })
352
+ .from(companyMemberships)
353
+ .where(and(eq(companyMemberships.companyId, companyId), eq(companyMemberships.principalType, "user"), eq(companyMemberships.principalId, userId), eq(companyMemberships.status, "active")))
354
+ .then((rows) => rows[0] ?? null);
355
+ if (!membership) {
356
+ throw notFound("Assignee user not found");
357
+ }
358
+ }
359
+ async function assertValidProjectWorkspace(companyId, projectId, projectWorkspaceId) {
360
+ const workspace = await db
361
+ .select({
362
+ id: projectWorkspaces.id,
363
+ companyId: projectWorkspaces.companyId,
364
+ projectId: projectWorkspaces.projectId,
365
+ })
366
+ .from(projectWorkspaces)
367
+ .where(eq(projectWorkspaces.id, projectWorkspaceId))
368
+ .then((rows) => rows[0] ?? null);
369
+ if (!workspace)
370
+ throw notFound("Project workspace not found");
371
+ if (workspace.companyId !== companyId)
372
+ throw unprocessable("Project workspace must belong to same company");
373
+ if (projectId && workspace.projectId !== projectId) {
374
+ throw unprocessable("Project workspace must belong to the selected project");
375
+ }
376
+ }
377
+ async function assertValidExecutionWorkspace(companyId, projectId, executionWorkspaceId) {
378
+ const workspace = await db
379
+ .select({
380
+ id: executionWorkspaces.id,
381
+ companyId: executionWorkspaces.companyId,
382
+ projectId: executionWorkspaces.projectId,
383
+ })
384
+ .from(executionWorkspaces)
385
+ .where(eq(executionWorkspaces.id, executionWorkspaceId))
386
+ .then((rows) => rows[0] ?? null);
387
+ if (!workspace)
388
+ throw notFound("Execution workspace not found");
389
+ if (workspace.companyId !== companyId)
390
+ throw unprocessable("Execution workspace must belong to same company");
391
+ if (projectId && workspace.projectId !== projectId) {
392
+ throw unprocessable("Execution workspace must belong to the selected project");
393
+ }
394
+ }
395
+ async function assertValidLabelIds(companyId, labelIds, dbOrTx = db) {
396
+ if (labelIds.length === 0)
397
+ return;
398
+ const existing = await dbOrTx
399
+ .select({ id: labels.id })
400
+ .from(labels)
401
+ .where(and(eq(labels.companyId, companyId), inArray(labels.id, labelIds)));
402
+ if (existing.length !== new Set(labelIds).size) {
403
+ throw unprocessable("One or more labels are invalid for this company");
404
+ }
405
+ }
406
+ async function syncIssueLabels(issueId, companyId, labelIds, dbOrTx = db) {
407
+ const deduped = [...new Set(labelIds)];
408
+ await assertValidLabelIds(companyId, deduped, dbOrTx);
409
+ await dbOrTx.delete(issueLabels).where(eq(issueLabels.issueId, issueId));
410
+ if (deduped.length === 0)
411
+ return;
412
+ await dbOrTx.insert(issueLabels).values(deduped.map((labelId) => ({
413
+ issueId,
414
+ labelId,
415
+ companyId,
416
+ })));
417
+ }
418
+ async function isTerminalOrMissingHeartbeatRun(runId) {
419
+ const run = await db
420
+ .select({ status: heartbeatRuns.status })
421
+ .from(heartbeatRuns)
422
+ .where(eq(heartbeatRuns.id, runId))
423
+ .then((rows) => rows[0] ?? null);
424
+ if (!run)
425
+ return true;
426
+ return TERMINAL_HEARTBEAT_RUN_STATUSES.has(run.status);
427
+ }
428
+ async function adoptStaleCheckoutRun(input) {
429
+ const stale = await isTerminalOrMissingHeartbeatRun(input.expectedCheckoutRunId);
430
+ if (!stale)
431
+ return null;
432
+ const now = new Date();
433
+ const adopted = await db
434
+ .update(issues)
435
+ .set({
436
+ checkoutRunId: input.actorRunId,
437
+ executionRunId: input.actorRunId,
438
+ executionLockedAt: now,
439
+ updatedAt: now,
440
+ })
441
+ .where(and(eq(issues.id, input.issueId), eq(issues.status, "in_progress"), eq(issues.assigneeAgentId, input.actorAgentId), eq(issues.checkoutRunId, input.expectedCheckoutRunId)))
442
+ .returning({
443
+ id: issues.id,
444
+ status: issues.status,
445
+ assigneeAgentId: issues.assigneeAgentId,
446
+ checkoutRunId: issues.checkoutRunId,
447
+ executionRunId: issues.executionRunId,
448
+ })
449
+ .then((rows) => rows[0] ?? null);
450
+ return adopted;
451
+ }
452
+ return {
453
+ list: async (companyId, filters) => {
454
+ const conditions = [eq(issues.companyId, companyId)];
455
+ const touchedByUserId = filters?.touchedByUserId?.trim() || undefined;
456
+ const inboxArchivedByUserId = filters?.inboxArchivedByUserId?.trim() || undefined;
457
+ const unreadForUserId = filters?.unreadForUserId?.trim() || undefined;
458
+ const contextUserId = unreadForUserId ?? touchedByUserId ?? inboxArchivedByUserId;
459
+ const rawSearch = filters?.q?.trim() ?? "";
460
+ const hasSearch = rawSearch.length > 0;
461
+ const escapedSearch = hasSearch ? escapeLikePattern(rawSearch) : "";
462
+ const startsWithPattern = `${escapedSearch}%`;
463
+ const containsPattern = `%${escapedSearch}%`;
464
+ const titleStartsWithMatch = sql `${issues.title} ILIKE ${startsWithPattern} ESCAPE '\\'`;
465
+ const titleContainsMatch = sql `${issues.title} ILIKE ${containsPattern} ESCAPE '\\'`;
466
+ const identifierStartsWithMatch = sql `${issues.identifier} ILIKE ${startsWithPattern} ESCAPE '\\'`;
467
+ const identifierContainsMatch = sql `${issues.identifier} ILIKE ${containsPattern} ESCAPE '\\'`;
468
+ const descriptionContainsMatch = sql `${issues.description} ILIKE ${containsPattern} ESCAPE '\\'`;
469
+ const commentContainsMatch = sql `
470
+ EXISTS (
471
+ SELECT 1
472
+ FROM ${issueComments}
473
+ WHERE ${issueComments.issueId} = ${issues.id}
474
+ AND ${issueComments.companyId} = ${companyId}
475
+ AND ${issueComments.body} ILIKE ${containsPattern} ESCAPE '\\'
476
+ )
477
+ `;
478
+ if (filters?.status) {
479
+ const statuses = filters.status.split(",").map((s) => s.trim());
480
+ conditions.push(statuses.length === 1 ? eq(issues.status, statuses[0]) : inArray(issues.status, statuses));
481
+ }
482
+ if (filters?.assigneeAgentId) {
483
+ conditions.push(eq(issues.assigneeAgentId, filters.assigneeAgentId));
484
+ }
485
+ if (filters?.participantAgentId) {
486
+ conditions.push(participatedByAgentCondition(companyId, filters.participantAgentId));
487
+ }
488
+ if (filters?.assigneeUserId) {
489
+ conditions.push(eq(issues.assigneeUserId, filters.assigneeUserId));
490
+ }
491
+ if (touchedByUserId) {
492
+ conditions.push(touchedByUserCondition(companyId, touchedByUserId));
493
+ }
494
+ if (inboxArchivedByUserId) {
495
+ conditions.push(inboxVisibleForUserCondition(companyId, inboxArchivedByUserId));
496
+ }
497
+ if (unreadForUserId) {
498
+ conditions.push(unreadForUserCondition(companyId, unreadForUserId));
499
+ }
500
+ if (filters?.projectId)
501
+ conditions.push(eq(issues.projectId, filters.projectId));
502
+ if (filters?.parentId)
503
+ conditions.push(eq(issues.parentId, filters.parentId));
504
+ if (filters?.originKind)
505
+ conditions.push(eq(issues.originKind, filters.originKind));
506
+ if (filters?.originId)
507
+ conditions.push(eq(issues.originId, filters.originId));
508
+ if (filters?.labelId) {
509
+ const labeledIssueIds = await db
510
+ .select({ issueId: issueLabels.issueId })
511
+ .from(issueLabels)
512
+ .where(and(eq(issueLabels.companyId, companyId), eq(issueLabels.labelId, filters.labelId)));
513
+ if (labeledIssueIds.length === 0)
514
+ return [];
515
+ conditions.push(inArray(issues.id, labeledIssueIds.map((row) => row.issueId)));
516
+ }
517
+ if (hasSearch) {
518
+ conditions.push(or(titleContainsMatch, identifierContainsMatch, descriptionContainsMatch, commentContainsMatch));
519
+ }
520
+ if (!filters?.includeRoutineExecutions && !filters?.originKind && !filters?.originId) {
521
+ conditions.push(ne(issues.originKind, "routine_execution"));
522
+ }
523
+ conditions.push(isNull(issues.hiddenAt));
524
+ const priorityOrder = sql `CASE ${issues.priority} WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END`;
525
+ const searchOrder = sql `
526
+ CASE
527
+ WHEN ${titleStartsWithMatch} THEN 0
528
+ WHEN ${titleContainsMatch} THEN 1
529
+ WHEN ${identifierStartsWithMatch} THEN 2
530
+ WHEN ${identifierContainsMatch} THEN 3
531
+ WHEN ${descriptionContainsMatch} THEN 4
532
+ WHEN ${commentContainsMatch} THEN 5
533
+ ELSE 6
534
+ END
535
+ `;
536
+ const rows = await db
537
+ .select()
538
+ .from(issues)
539
+ .where(and(...conditions))
540
+ .orderBy(hasSearch ? asc(searchOrder) : asc(priorityOrder), asc(priorityOrder), desc(issues.updatedAt));
541
+ const withLabels = await withIssueLabels(db, rows);
542
+ const runMap = await activeRunMapForIssues(db, withLabels);
543
+ const withRuns = withActiveRuns(withLabels, runMap);
544
+ if (!contextUserId || withRuns.length === 0) {
545
+ return withRuns;
546
+ }
547
+ const issueIds = withRuns.map((row) => row.id);
548
+ const statsRows = await db
549
+ .select({
550
+ issueId: issueComments.issueId,
551
+ myLastCommentAt: sql `
552
+ MAX(CASE WHEN ${issueComments.authorUserId} = ${contextUserId} THEN ${issueComments.createdAt} END)
553
+ `,
554
+ lastExternalCommentAt: sql `
555
+ MAX(
556
+ CASE
557
+ WHEN ${issueComments.authorUserId} IS NULL OR ${issueComments.authorUserId} <> ${contextUserId}
558
+ THEN ${issueComments.createdAt}
559
+ END
560
+ )
561
+ `,
562
+ })
563
+ .from(issueComments)
564
+ .where(and(eq(issueComments.companyId, companyId), inArray(issueComments.issueId, issueIds)))
565
+ .groupBy(issueComments.issueId);
566
+ const readRows = await db
567
+ .select({
568
+ issueId: issueReadStates.issueId,
569
+ myLastReadAt: issueReadStates.lastReadAt,
570
+ })
571
+ .from(issueReadStates)
572
+ .where(and(eq(issueReadStates.companyId, companyId), eq(issueReadStates.userId, contextUserId), inArray(issueReadStates.issueId, issueIds)));
573
+ const statsByIssueId = new Map(statsRows.map((row) => [row.issueId, row]));
574
+ const readByIssueId = new Map(readRows.map((row) => [row.issueId, row.myLastReadAt]));
575
+ return withRuns.map((row) => ({
576
+ ...row,
577
+ ...deriveIssueUserContext(row, contextUserId, {
578
+ myLastCommentAt: statsByIssueId.get(row.id)?.myLastCommentAt ?? null,
579
+ myLastReadAt: readByIssueId.get(row.id) ?? null,
580
+ lastExternalCommentAt: statsByIssueId.get(row.id)?.lastExternalCommentAt ?? null,
581
+ }),
582
+ }));
583
+ },
584
+ countUnreadTouchedByUser: async (companyId, userId, status) => {
585
+ const conditions = [
586
+ eq(issues.companyId, companyId),
587
+ isNull(issues.hiddenAt),
588
+ unreadForUserCondition(companyId, userId),
589
+ ne(issues.originKind, "routine_execution"),
590
+ ];
591
+ if (status) {
592
+ const statuses = status.split(",").map((s) => s.trim()).filter(Boolean);
593
+ if (statuses.length === 1) {
594
+ conditions.push(eq(issues.status, statuses[0]));
595
+ }
596
+ else if (statuses.length > 1) {
597
+ conditions.push(inArray(issues.status, statuses));
598
+ }
599
+ }
600
+ const [row] = await db
601
+ .select({ count: sql `count(*)` })
602
+ .from(issues)
603
+ .where(and(...conditions));
604
+ return Number(row?.count ?? 0);
605
+ },
606
+ markRead: async (companyId, issueId, userId, readAt = new Date()) => {
607
+ const now = new Date();
608
+ const [row] = await db
609
+ .insert(issueReadStates)
610
+ .values({
611
+ companyId,
612
+ issueId,
613
+ userId,
614
+ lastReadAt: readAt,
615
+ updatedAt: now,
616
+ })
617
+ .onConflictDoUpdate({
618
+ target: [issueReadStates.companyId, issueReadStates.issueId, issueReadStates.userId],
619
+ set: {
620
+ lastReadAt: readAt,
621
+ updatedAt: now,
622
+ },
623
+ })
624
+ .returning();
625
+ return row;
626
+ },
627
+ archiveInbox: async (companyId, issueId, userId, archivedAt = new Date()) => {
628
+ const now = new Date();
629
+ const [row] = await db
630
+ .insert(issueInboxArchives)
631
+ .values({
632
+ companyId,
633
+ issueId,
634
+ userId,
635
+ archivedAt,
636
+ updatedAt: now,
637
+ })
638
+ .onConflictDoUpdate({
639
+ target: [issueInboxArchives.companyId, issueInboxArchives.issueId, issueInboxArchives.userId],
640
+ set: {
641
+ archivedAt,
642
+ updatedAt: now,
643
+ },
644
+ })
645
+ .returning();
646
+ return row;
647
+ },
648
+ unarchiveInbox: async (companyId, issueId, userId) => {
649
+ const [row] = await db
650
+ .delete(issueInboxArchives)
651
+ .where(and(eq(issueInboxArchives.companyId, companyId), eq(issueInboxArchives.issueId, issueId), eq(issueInboxArchives.userId, userId)))
652
+ .returning();
653
+ return row ?? null;
654
+ },
655
+ getById: async (id) => {
656
+ const row = await db
657
+ .select()
658
+ .from(issues)
659
+ .where(eq(issues.id, id))
660
+ .then((rows) => rows[0] ?? null);
661
+ if (!row)
662
+ return null;
663
+ const [enriched] = await withIssueLabels(db, [row]);
664
+ return enriched;
665
+ },
666
+ getByIdentifier: async (identifier) => {
667
+ const row = await db
668
+ .select()
669
+ .from(issues)
670
+ .where(eq(issues.identifier, identifier.toUpperCase()))
671
+ .then((rows) => rows[0] ?? null);
672
+ if (!row)
673
+ return null;
674
+ const [enriched] = await withIssueLabels(db, [row]);
675
+ return enriched;
676
+ },
677
+ create: async (companyId, data) => {
678
+ const { labelIds: inputLabelIds, ...issueData } = data;
679
+ const isolatedWorkspacesEnabled = (await instanceSettings.getExperimental()).enableIsolatedWorkspaces;
680
+ if (!isolatedWorkspacesEnabled) {
681
+ delete issueData.executionWorkspaceId;
682
+ delete issueData.executionWorkspacePreference;
683
+ delete issueData.executionWorkspaceSettings;
684
+ }
685
+ if (data.assigneeAgentId && data.assigneeUserId) {
686
+ throw unprocessable("Issue can only have one assignee");
687
+ }
688
+ if (data.assigneeAgentId) {
689
+ await assertAssignableAgent(companyId, data.assigneeAgentId);
690
+ }
691
+ if (data.assigneeUserId) {
692
+ await assertAssignableUser(companyId, data.assigneeUserId);
693
+ }
694
+ if (data.projectWorkspaceId) {
695
+ await assertValidProjectWorkspace(companyId, data.projectId, data.projectWorkspaceId);
696
+ }
697
+ if (data.executionWorkspaceId) {
698
+ await assertValidExecutionWorkspace(companyId, data.projectId, data.executionWorkspaceId);
699
+ }
700
+ if (data.status === "in_progress" && !data.assigneeAgentId && !data.assigneeUserId) {
701
+ throw unprocessable("in_progress issues require an assignee");
702
+ }
703
+ return db.transaction(async (tx) => {
704
+ const defaultCompanyGoal = await getDefaultCompanyGoal(tx, companyId);
705
+ const projectGoalId = await getProjectDefaultGoalId(tx, companyId, issueData.projectId);
706
+ let executionWorkspaceSettings = issueData.executionWorkspaceSettings ?? null;
707
+ if (executionWorkspaceSettings == null && issueData.projectId) {
708
+ const project = await tx
709
+ .select({ executionWorkspacePolicy: projects.executionWorkspacePolicy })
710
+ .from(projects)
711
+ .where(and(eq(projects.id, issueData.projectId), eq(projects.companyId, companyId)))
712
+ .then((rows) => rows[0] ?? null);
713
+ executionWorkspaceSettings =
714
+ defaultIssueExecutionWorkspaceSettingsForProject(gateProjectExecutionWorkspacePolicy(parseProjectExecutionWorkspacePolicy(project?.executionWorkspacePolicy), isolatedWorkspacesEnabled));
715
+ }
716
+ let projectWorkspaceId = issueData.projectWorkspaceId ?? null;
717
+ if (!projectWorkspaceId && issueData.projectId) {
718
+ const project = await tx
719
+ .select({
720
+ executionWorkspacePolicy: projects.executionWorkspacePolicy,
721
+ })
722
+ .from(projects)
723
+ .where(and(eq(projects.id, issueData.projectId), eq(projects.companyId, companyId)))
724
+ .then((rows) => rows[0] ?? null);
725
+ const projectPolicy = parseProjectExecutionWorkspacePolicy(project?.executionWorkspacePolicy);
726
+ projectWorkspaceId = projectPolicy?.defaultProjectWorkspaceId ?? null;
727
+ if (!projectWorkspaceId) {
728
+ projectWorkspaceId = await tx
729
+ .select({ id: projectWorkspaces.id })
730
+ .from(projectWorkspaces)
731
+ .where(and(eq(projectWorkspaces.projectId, issueData.projectId), eq(projectWorkspaces.companyId, companyId)))
732
+ .orderBy(desc(projectWorkspaces.isPrimary), asc(projectWorkspaces.createdAt), asc(projectWorkspaces.id))
733
+ .then((rows) => rows[0]?.id ?? null);
734
+ }
735
+ }
736
+ const [company] = await tx
737
+ .update(companies)
738
+ .set({ issueCounter: sql `${companies.issueCounter} + 1` })
739
+ .where(eq(companies.id, companyId))
740
+ .returning({ issueCounter: companies.issueCounter, issuePrefix: companies.issuePrefix });
741
+ const issueNumber = company.issueCounter;
742
+ const identifier = `${company.issuePrefix}-${issueNumber}`;
743
+ const values = {
744
+ ...issueData,
745
+ originKind: issueData.originKind ?? "manual",
746
+ goalId: resolveIssueGoalId({
747
+ projectId: issueData.projectId,
748
+ goalId: issueData.goalId,
749
+ projectGoalId,
750
+ defaultGoalId: defaultCompanyGoal?.id ?? null,
751
+ }),
752
+ ...(projectWorkspaceId ? { projectWorkspaceId } : {}),
753
+ ...(executionWorkspaceSettings ? { executionWorkspaceSettings } : {}),
754
+ companyId,
755
+ issueNumber,
756
+ identifier,
757
+ };
758
+ if (values.status === "in_progress" && !values.startedAt) {
759
+ values.startedAt = new Date();
760
+ }
761
+ if (values.status === "done") {
762
+ values.completedAt = new Date();
763
+ }
764
+ if (values.status === "cancelled") {
765
+ values.cancelledAt = new Date();
766
+ }
767
+ const [issue] = await tx.insert(issues).values(values).returning();
768
+ if (inputLabelIds) {
769
+ await syncIssueLabels(issue.id, companyId, inputLabelIds, tx);
770
+ }
771
+ const [enriched] = await withIssueLabels(tx, [issue]);
772
+ return enriched;
773
+ });
774
+ },
775
+ update: async (id, data) => {
776
+ const existing = await db
777
+ .select()
778
+ .from(issues)
779
+ .where(eq(issues.id, id))
780
+ .then((rows) => rows[0] ?? null);
781
+ if (!existing)
782
+ return null;
783
+ const { labelIds: nextLabelIds, ...issueData } = data;
784
+ const isolatedWorkspacesEnabled = (await instanceSettings.getExperimental()).enableIsolatedWorkspaces;
785
+ if (!isolatedWorkspacesEnabled) {
786
+ delete issueData.executionWorkspaceId;
787
+ delete issueData.executionWorkspacePreference;
788
+ delete issueData.executionWorkspaceSettings;
789
+ }
790
+ if (issueData.status) {
791
+ assertTransition(existing.status, issueData.status);
792
+ }
793
+ const patch = {
794
+ ...issueData,
795
+ updatedAt: new Date(),
796
+ };
797
+ const nextAssigneeAgentId = issueData.assigneeAgentId !== undefined ? issueData.assigneeAgentId : existing.assigneeAgentId;
798
+ const nextAssigneeUserId = issueData.assigneeUserId !== undefined ? issueData.assigneeUserId : existing.assigneeUserId;
799
+ if (nextAssigneeAgentId && nextAssigneeUserId) {
800
+ throw unprocessable("Issue can only have one assignee");
801
+ }
802
+ if (patch.status === "in_progress" && !nextAssigneeAgentId && !nextAssigneeUserId) {
803
+ throw unprocessable("in_progress issues require an assignee");
804
+ }
805
+ if (issueData.assigneeAgentId) {
806
+ await assertAssignableAgent(existing.companyId, issueData.assigneeAgentId);
807
+ }
808
+ if (issueData.assigneeUserId) {
809
+ await assertAssignableUser(existing.companyId, issueData.assigneeUserId);
810
+ }
811
+ const nextProjectId = issueData.projectId !== undefined ? issueData.projectId : existing.projectId;
812
+ const nextProjectWorkspaceId = issueData.projectWorkspaceId !== undefined ? issueData.projectWorkspaceId : existing.projectWorkspaceId;
813
+ const nextExecutionWorkspaceId = issueData.executionWorkspaceId !== undefined ? issueData.executionWorkspaceId : existing.executionWorkspaceId;
814
+ if (nextProjectWorkspaceId) {
815
+ await assertValidProjectWorkspace(existing.companyId, nextProjectId, nextProjectWorkspaceId);
816
+ }
817
+ if (nextExecutionWorkspaceId) {
818
+ await assertValidExecutionWorkspace(existing.companyId, nextProjectId, nextExecutionWorkspaceId);
819
+ }
820
+ applyStatusSideEffects(issueData.status, patch);
821
+ if (issueData.status && issueData.status !== "done") {
822
+ patch.completedAt = null;
823
+ }
824
+ if (issueData.status && issueData.status !== "cancelled") {
825
+ patch.cancelledAt = null;
826
+ }
827
+ if (issueData.status && issueData.status !== "in_progress") {
828
+ patch.checkoutRunId = null;
829
+ }
830
+ if ((issueData.assigneeAgentId !== undefined && issueData.assigneeAgentId !== existing.assigneeAgentId) ||
831
+ (issueData.assigneeUserId !== undefined && issueData.assigneeUserId !== existing.assigneeUserId)) {
832
+ patch.checkoutRunId = null;
833
+ }
834
+ return db.transaction(async (tx) => {
835
+ const defaultCompanyGoal = await getDefaultCompanyGoal(tx, existing.companyId);
836
+ const [currentProjectGoalId, nextProjectGoalId] = await Promise.all([
837
+ getProjectDefaultGoalId(tx, existing.companyId, existing.projectId),
838
+ getProjectDefaultGoalId(tx, existing.companyId, issueData.projectId !== undefined ? issueData.projectId : existing.projectId),
839
+ ]);
840
+ patch.goalId = resolveNextIssueGoalId({
841
+ currentProjectId: existing.projectId,
842
+ currentGoalId: existing.goalId,
843
+ currentProjectGoalId,
844
+ projectId: issueData.projectId,
845
+ goalId: issueData.goalId,
846
+ projectGoalId: nextProjectGoalId,
847
+ defaultGoalId: defaultCompanyGoal?.id ?? null,
848
+ });
849
+ const updated = await tx
850
+ .update(issues)
851
+ .set(patch)
852
+ .where(eq(issues.id, id))
853
+ .returning()
854
+ .then((rows) => rows[0] ?? null);
855
+ if (!updated)
856
+ return null;
857
+ if (nextLabelIds !== undefined) {
858
+ await syncIssueLabels(updated.id, existing.companyId, nextLabelIds, tx);
859
+ }
860
+ const [enriched] = await withIssueLabels(tx, [updated]);
861
+ return enriched;
862
+ });
863
+ },
864
+ remove: (id) => db.transaction(async (tx) => {
865
+ const attachmentAssetIds = await tx
866
+ .select({ assetId: issueAttachments.assetId })
867
+ .from(issueAttachments)
868
+ .where(eq(issueAttachments.issueId, id));
869
+ const issueDocumentIds = await tx
870
+ .select({ documentId: issueDocuments.documentId })
871
+ .from(issueDocuments)
872
+ .where(eq(issueDocuments.issueId, id));
873
+ const removedIssue = await tx
874
+ .delete(issues)
875
+ .where(eq(issues.id, id))
876
+ .returning()
877
+ .then((rows) => rows[0] ?? null);
878
+ if (removedIssue && attachmentAssetIds.length > 0) {
879
+ await tx
880
+ .delete(assets)
881
+ .where(inArray(assets.id, attachmentAssetIds.map((row) => row.assetId)));
882
+ }
883
+ if (removedIssue && issueDocumentIds.length > 0) {
884
+ await tx
885
+ .delete(documents)
886
+ .where(inArray(documents.id, issueDocumentIds.map((row) => row.documentId)));
887
+ }
888
+ if (!removedIssue)
889
+ return null;
890
+ const [enriched] = await withIssueLabels(tx, [removedIssue]);
891
+ return enriched;
892
+ }),
893
+ checkout: async (id, agentId, expectedStatuses, checkoutRunId) => {
894
+ const issueCompany = await db
895
+ .select({ companyId: issues.companyId })
896
+ .from(issues)
897
+ .where(eq(issues.id, id))
898
+ .then((rows) => rows[0] ?? null);
899
+ if (!issueCompany)
900
+ throw notFound("Issue not found");
901
+ await assertAssignableAgent(issueCompany.companyId, agentId);
902
+ const now = new Date();
903
+ const sameRunAssigneeCondition = checkoutRunId
904
+ ? and(eq(issues.assigneeAgentId, agentId), or(isNull(issues.checkoutRunId), eq(issues.checkoutRunId, checkoutRunId)))
905
+ : and(eq(issues.assigneeAgentId, agentId), isNull(issues.checkoutRunId));
906
+ const executionLockCondition = checkoutRunId
907
+ ? or(isNull(issues.executionRunId), eq(issues.executionRunId, checkoutRunId))
908
+ : isNull(issues.executionRunId);
909
+ const updated = await db
910
+ .update(issues)
911
+ .set({
912
+ assigneeAgentId: agentId,
913
+ assigneeUserId: null,
914
+ checkoutRunId,
915
+ executionRunId: checkoutRunId,
916
+ status: "in_progress",
917
+ startedAt: now,
918
+ updatedAt: now,
919
+ })
920
+ .where(and(eq(issues.id, id), inArray(issues.status, expectedStatuses), or(isNull(issues.assigneeAgentId), sameRunAssigneeCondition), executionLockCondition))
921
+ .returning()
922
+ .then((rows) => rows[0] ?? null);
923
+ if (updated) {
924
+ const [enriched] = await withIssueLabels(db, [updated]);
925
+ return enriched;
926
+ }
927
+ const current = await db
928
+ .select({
929
+ id: issues.id,
930
+ status: issues.status,
931
+ assigneeAgentId: issues.assigneeAgentId,
932
+ checkoutRunId: issues.checkoutRunId,
933
+ executionRunId: issues.executionRunId,
934
+ })
935
+ .from(issues)
936
+ .where(eq(issues.id, id))
937
+ .then((rows) => rows[0] ?? null);
938
+ if (!current)
939
+ throw notFound("Issue not found");
940
+ if (current.assigneeAgentId === agentId &&
941
+ current.status === "in_progress" &&
942
+ current.checkoutRunId == null &&
943
+ (current.executionRunId == null || current.executionRunId === checkoutRunId) &&
944
+ checkoutRunId) {
945
+ const adopted = await db
946
+ .update(issues)
947
+ .set({
948
+ checkoutRunId,
949
+ executionRunId: checkoutRunId,
950
+ updatedAt: new Date(),
951
+ })
952
+ .where(and(eq(issues.id, id), eq(issues.status, "in_progress"), eq(issues.assigneeAgentId, agentId), isNull(issues.checkoutRunId), or(isNull(issues.executionRunId), eq(issues.executionRunId, checkoutRunId))))
953
+ .returning()
954
+ .then((rows) => rows[0] ?? null);
955
+ if (adopted)
956
+ return adopted;
957
+ }
958
+ if (checkoutRunId &&
959
+ current.assigneeAgentId === agentId &&
960
+ current.status === "in_progress" &&
961
+ current.checkoutRunId &&
962
+ current.checkoutRunId !== checkoutRunId) {
963
+ const adopted = await adoptStaleCheckoutRun({
964
+ issueId: id,
965
+ actorAgentId: agentId,
966
+ actorRunId: checkoutRunId,
967
+ expectedCheckoutRunId: current.checkoutRunId,
968
+ });
969
+ if (adopted) {
970
+ const row = await db.select().from(issues).where(eq(issues.id, id)).then((rows) => rows[0]);
971
+ const [enriched] = await withIssueLabels(db, [row]);
972
+ return enriched;
973
+ }
974
+ }
975
+ // If this run already owns it and it's in_progress, return it (no self-409)
976
+ if (current.assigneeAgentId === agentId &&
977
+ current.status === "in_progress" &&
978
+ sameRunLock(current.checkoutRunId, checkoutRunId)) {
979
+ const row = await db.select().from(issues).where(eq(issues.id, id)).then((rows) => rows[0]);
980
+ const [enriched] = await withIssueLabels(db, [row]);
981
+ return enriched;
982
+ }
983
+ throw conflict("Issue checkout conflict", {
984
+ issueId: current.id,
985
+ status: current.status,
986
+ assigneeAgentId: current.assigneeAgentId,
987
+ checkoutRunId: current.checkoutRunId,
988
+ executionRunId: current.executionRunId,
989
+ });
990
+ },
991
+ assertCheckoutOwner: async (id, actorAgentId, actorRunId) => {
992
+ const current = await db
993
+ .select({
994
+ id: issues.id,
995
+ status: issues.status,
996
+ assigneeAgentId: issues.assigneeAgentId,
997
+ checkoutRunId: issues.checkoutRunId,
998
+ })
999
+ .from(issues)
1000
+ .where(eq(issues.id, id))
1001
+ .then((rows) => rows[0] ?? null);
1002
+ if (!current)
1003
+ throw notFound("Issue not found");
1004
+ if (current.status === "in_progress" &&
1005
+ current.assigneeAgentId === actorAgentId &&
1006
+ sameRunLock(current.checkoutRunId, actorRunId)) {
1007
+ return { ...current, adoptedFromRunId: null };
1008
+ }
1009
+ if (actorRunId &&
1010
+ current.status === "in_progress" &&
1011
+ current.assigneeAgentId === actorAgentId &&
1012
+ current.checkoutRunId &&
1013
+ current.checkoutRunId !== actorRunId) {
1014
+ const adopted = await adoptStaleCheckoutRun({
1015
+ issueId: id,
1016
+ actorAgentId,
1017
+ actorRunId,
1018
+ expectedCheckoutRunId: current.checkoutRunId,
1019
+ });
1020
+ if (adopted) {
1021
+ return {
1022
+ ...adopted,
1023
+ adoptedFromRunId: current.checkoutRunId,
1024
+ };
1025
+ }
1026
+ }
1027
+ throw conflict("Issue run ownership conflict", {
1028
+ issueId: current.id,
1029
+ status: current.status,
1030
+ assigneeAgentId: current.assigneeAgentId,
1031
+ checkoutRunId: current.checkoutRunId,
1032
+ actorAgentId,
1033
+ actorRunId,
1034
+ });
1035
+ },
1036
+ release: async (id, actorAgentId, actorRunId) => {
1037
+ const existing = await db
1038
+ .select()
1039
+ .from(issues)
1040
+ .where(eq(issues.id, id))
1041
+ .then((rows) => rows[0] ?? null);
1042
+ if (!existing)
1043
+ return null;
1044
+ if (actorAgentId && existing.assigneeAgentId && existing.assigneeAgentId !== actorAgentId) {
1045
+ throw conflict("Only assignee can release issue");
1046
+ }
1047
+ if (actorAgentId &&
1048
+ existing.status === "in_progress" &&
1049
+ existing.assigneeAgentId === actorAgentId &&
1050
+ existing.checkoutRunId &&
1051
+ !sameRunLock(existing.checkoutRunId, actorRunId ?? null)) {
1052
+ throw conflict("Only checkout run can release issue", {
1053
+ issueId: existing.id,
1054
+ assigneeAgentId: existing.assigneeAgentId,
1055
+ checkoutRunId: existing.checkoutRunId,
1056
+ actorRunId: actorRunId ?? null,
1057
+ });
1058
+ }
1059
+ const updated = await db
1060
+ .update(issues)
1061
+ .set({
1062
+ status: "todo",
1063
+ assigneeAgentId: null,
1064
+ checkoutRunId: null,
1065
+ updatedAt: new Date(),
1066
+ })
1067
+ .where(eq(issues.id, id))
1068
+ .returning()
1069
+ .then((rows) => rows[0] ?? null);
1070
+ if (!updated)
1071
+ return null;
1072
+ const [enriched] = await withIssueLabels(db, [updated]);
1073
+ return enriched;
1074
+ },
1075
+ listLabels: (companyId) => db.select().from(labels).where(eq(labels.companyId, companyId)).orderBy(asc(labels.name), asc(labels.id)),
1076
+ getLabelById: (id) => db
1077
+ .select()
1078
+ .from(labels)
1079
+ .where(eq(labels.id, id))
1080
+ .then((rows) => rows[0] ?? null),
1081
+ createLabel: async (companyId, data) => {
1082
+ const [created] = await db
1083
+ .insert(labels)
1084
+ .values({
1085
+ companyId,
1086
+ name: data.name.trim(),
1087
+ color: data.color,
1088
+ })
1089
+ .returning();
1090
+ return created;
1091
+ },
1092
+ deleteLabel: async (id) => db
1093
+ .delete(labels)
1094
+ .where(eq(labels.id, id))
1095
+ .returning()
1096
+ .then((rows) => rows[0] ?? null),
1097
+ listComments: async (issueId, opts) => {
1098
+ const order = opts?.order === "asc" ? "asc" : "desc";
1099
+ const afterCommentId = opts?.afterCommentId?.trim() || null;
1100
+ const limit = opts?.limit && opts.limit > 0
1101
+ ? Math.min(Math.floor(opts.limit), MAX_ISSUE_COMMENT_PAGE_LIMIT)
1102
+ : null;
1103
+ const conditions = [eq(issueComments.issueId, issueId)];
1104
+ if (afterCommentId) {
1105
+ const anchor = await db
1106
+ .select({
1107
+ id: issueComments.id,
1108
+ createdAt: issueComments.createdAt,
1109
+ })
1110
+ .from(issueComments)
1111
+ .where(and(eq(issueComments.issueId, issueId), eq(issueComments.id, afterCommentId)))
1112
+ .then((rows) => rows[0] ?? null);
1113
+ if (!anchor)
1114
+ return [];
1115
+ conditions.push(order === "asc"
1116
+ ? sql `(
1117
+ ${issueComments.createdAt} > ${anchor.createdAt}
1118
+ OR (${issueComments.createdAt} = ${anchor.createdAt} AND ${issueComments.id} > ${anchor.id})
1119
+ )`
1120
+ : sql `(
1121
+ ${issueComments.createdAt} < ${anchor.createdAt}
1122
+ OR (${issueComments.createdAt} = ${anchor.createdAt} AND ${issueComments.id} < ${anchor.id})
1123
+ )`);
1124
+ }
1125
+ const query = db
1126
+ .select()
1127
+ .from(issueComments)
1128
+ .where(and(...conditions))
1129
+ .orderBy(order === "asc" ? asc(issueComments.createdAt) : desc(issueComments.createdAt), order === "asc" ? asc(issueComments.id) : desc(issueComments.id));
1130
+ const comments = limit ? await query.limit(limit) : await query;
1131
+ const { censorUsernameInLogs } = await instanceSettings.getGeneral();
1132
+ return comments.map((comment) => redactIssueComment(comment, censorUsernameInLogs));
1133
+ },
1134
+ getCommentCursor: async (issueId) => {
1135
+ const [latest, countRow] = await Promise.all([
1136
+ db
1137
+ .select({
1138
+ latestCommentId: issueComments.id,
1139
+ latestCommentAt: issueComments.createdAt,
1140
+ })
1141
+ .from(issueComments)
1142
+ .where(eq(issueComments.issueId, issueId))
1143
+ .orderBy(desc(issueComments.createdAt), desc(issueComments.id))
1144
+ .limit(1)
1145
+ .then((rows) => rows[0] ?? null),
1146
+ db
1147
+ .select({
1148
+ totalComments: sql `count(*)::int`,
1149
+ })
1150
+ .from(issueComments)
1151
+ .where(eq(issueComments.issueId, issueId))
1152
+ .then((rows) => rows[0] ?? null),
1153
+ ]);
1154
+ return {
1155
+ totalComments: Number(countRow?.totalComments ?? 0),
1156
+ latestCommentId: latest?.latestCommentId ?? null,
1157
+ latestCommentAt: latest?.latestCommentAt ?? null,
1158
+ };
1159
+ },
1160
+ getComment: (commentId) => instanceSettings.getGeneral().then(({ censorUsernameInLogs }) => db
1161
+ .select()
1162
+ .from(issueComments)
1163
+ .where(eq(issueComments.id, commentId))
1164
+ .then((rows) => {
1165
+ const comment = rows[0] ?? null;
1166
+ return comment ? redactIssueComment(comment, censorUsernameInLogs) : null;
1167
+ })),
1168
+ addComment: async (issueId, body, actor) => {
1169
+ const issue = await db
1170
+ .select({ companyId: issues.companyId })
1171
+ .from(issues)
1172
+ .where(eq(issues.id, issueId))
1173
+ .then((rows) => rows[0] ?? null);
1174
+ if (!issue)
1175
+ throw notFound("Issue not found");
1176
+ const currentUserRedactionOptions = {
1177
+ enabled: (await instanceSettings.getGeneral()).censorUsernameInLogs,
1178
+ };
1179
+ const redactedBody = redactCurrentUserText(body, currentUserRedactionOptions);
1180
+ const [comment] = await db
1181
+ .insert(issueComments)
1182
+ .values({
1183
+ companyId: issue.companyId,
1184
+ issueId,
1185
+ authorAgentId: actor.agentId ?? null,
1186
+ authorUserId: actor.userId ?? null,
1187
+ body: redactedBody,
1188
+ })
1189
+ .returning();
1190
+ // Update issue's updatedAt so comment activity is reflected in recency sorting
1191
+ await db
1192
+ .update(issues)
1193
+ .set({ updatedAt: new Date() })
1194
+ .where(eq(issues.id, issueId));
1195
+ return redactIssueComment(comment, currentUserRedactionOptions.enabled);
1196
+ },
1197
+ createAttachment: async (input) => {
1198
+ const issue = await db
1199
+ .select({ id: issues.id, companyId: issues.companyId })
1200
+ .from(issues)
1201
+ .where(eq(issues.id, input.issueId))
1202
+ .then((rows) => rows[0] ?? null);
1203
+ if (!issue)
1204
+ throw notFound("Issue not found");
1205
+ if (input.issueCommentId) {
1206
+ const comment = await db
1207
+ .select({ id: issueComments.id, companyId: issueComments.companyId, issueId: issueComments.issueId })
1208
+ .from(issueComments)
1209
+ .where(eq(issueComments.id, input.issueCommentId))
1210
+ .then((rows) => rows[0] ?? null);
1211
+ if (!comment)
1212
+ throw notFound("Issue comment not found");
1213
+ if (comment.companyId !== issue.companyId || comment.issueId !== issue.id) {
1214
+ throw unprocessable("Attachment comment must belong to same issue and company");
1215
+ }
1216
+ }
1217
+ return db.transaction(async (tx) => {
1218
+ const [asset] = await tx
1219
+ .insert(assets)
1220
+ .values({
1221
+ companyId: issue.companyId,
1222
+ provider: input.provider,
1223
+ objectKey: input.objectKey,
1224
+ contentType: input.contentType,
1225
+ byteSize: input.byteSize,
1226
+ sha256: input.sha256,
1227
+ originalFilename: input.originalFilename ?? null,
1228
+ createdByAgentId: input.createdByAgentId ?? null,
1229
+ createdByUserId: input.createdByUserId ?? null,
1230
+ })
1231
+ .returning();
1232
+ const [attachment] = await tx
1233
+ .insert(issueAttachments)
1234
+ .values({
1235
+ companyId: issue.companyId,
1236
+ issueId: issue.id,
1237
+ assetId: asset.id,
1238
+ issueCommentId: input.issueCommentId ?? null,
1239
+ })
1240
+ .returning();
1241
+ return {
1242
+ id: attachment.id,
1243
+ companyId: attachment.companyId,
1244
+ issueId: attachment.issueId,
1245
+ issueCommentId: attachment.issueCommentId,
1246
+ assetId: attachment.assetId,
1247
+ provider: asset.provider,
1248
+ objectKey: asset.objectKey,
1249
+ contentType: asset.contentType,
1250
+ byteSize: asset.byteSize,
1251
+ sha256: asset.sha256,
1252
+ originalFilename: asset.originalFilename,
1253
+ createdByAgentId: asset.createdByAgentId,
1254
+ createdByUserId: asset.createdByUserId,
1255
+ createdAt: attachment.createdAt,
1256
+ updatedAt: attachment.updatedAt,
1257
+ };
1258
+ });
1259
+ },
1260
+ listAttachments: async (issueId) => db
1261
+ .select({
1262
+ id: issueAttachments.id,
1263
+ companyId: issueAttachments.companyId,
1264
+ issueId: issueAttachments.issueId,
1265
+ issueCommentId: issueAttachments.issueCommentId,
1266
+ assetId: issueAttachments.assetId,
1267
+ provider: assets.provider,
1268
+ objectKey: assets.objectKey,
1269
+ contentType: assets.contentType,
1270
+ byteSize: assets.byteSize,
1271
+ sha256: assets.sha256,
1272
+ originalFilename: assets.originalFilename,
1273
+ createdByAgentId: assets.createdByAgentId,
1274
+ createdByUserId: assets.createdByUserId,
1275
+ createdAt: issueAttachments.createdAt,
1276
+ updatedAt: issueAttachments.updatedAt,
1277
+ })
1278
+ .from(issueAttachments)
1279
+ .innerJoin(assets, eq(issueAttachments.assetId, assets.id))
1280
+ .where(eq(issueAttachments.issueId, issueId))
1281
+ .orderBy(desc(issueAttachments.createdAt)),
1282
+ getAttachmentById: async (id) => db
1283
+ .select({
1284
+ id: issueAttachments.id,
1285
+ companyId: issueAttachments.companyId,
1286
+ issueId: issueAttachments.issueId,
1287
+ issueCommentId: issueAttachments.issueCommentId,
1288
+ assetId: issueAttachments.assetId,
1289
+ provider: assets.provider,
1290
+ objectKey: assets.objectKey,
1291
+ contentType: assets.contentType,
1292
+ byteSize: assets.byteSize,
1293
+ sha256: assets.sha256,
1294
+ originalFilename: assets.originalFilename,
1295
+ createdByAgentId: assets.createdByAgentId,
1296
+ createdByUserId: assets.createdByUserId,
1297
+ createdAt: issueAttachments.createdAt,
1298
+ updatedAt: issueAttachments.updatedAt,
1299
+ })
1300
+ .from(issueAttachments)
1301
+ .innerJoin(assets, eq(issueAttachments.assetId, assets.id))
1302
+ .where(eq(issueAttachments.id, id))
1303
+ .then((rows) => rows[0] ?? null),
1304
+ removeAttachment: async (id) => db.transaction(async (tx) => {
1305
+ const existing = await tx
1306
+ .select({
1307
+ id: issueAttachments.id,
1308
+ companyId: issueAttachments.companyId,
1309
+ issueId: issueAttachments.issueId,
1310
+ issueCommentId: issueAttachments.issueCommentId,
1311
+ assetId: issueAttachments.assetId,
1312
+ provider: assets.provider,
1313
+ objectKey: assets.objectKey,
1314
+ contentType: assets.contentType,
1315
+ byteSize: assets.byteSize,
1316
+ sha256: assets.sha256,
1317
+ originalFilename: assets.originalFilename,
1318
+ createdByAgentId: assets.createdByAgentId,
1319
+ createdByUserId: assets.createdByUserId,
1320
+ createdAt: issueAttachments.createdAt,
1321
+ updatedAt: issueAttachments.updatedAt,
1322
+ })
1323
+ .from(issueAttachments)
1324
+ .innerJoin(assets, eq(issueAttachments.assetId, assets.id))
1325
+ .where(eq(issueAttachments.id, id))
1326
+ .then((rows) => rows[0] ?? null);
1327
+ if (!existing)
1328
+ return null;
1329
+ await tx.delete(issueAttachments).where(eq(issueAttachments.id, id));
1330
+ await tx.delete(assets).where(eq(assets.id, existing.assetId));
1331
+ return existing;
1332
+ }),
1333
+ findMentionedAgents: async (companyId, body) => {
1334
+ const re = /\B@([^\s@,!?.]+)/g;
1335
+ const tokens = new Set();
1336
+ let m;
1337
+ while ((m = re.exec(body)) !== null) {
1338
+ const normalized = normalizeAgentMentionToken(m[1]);
1339
+ if (normalized)
1340
+ tokens.add(normalized.toLowerCase());
1341
+ }
1342
+ const explicitAgentMentionIds = extractAgentMentionIds(body);
1343
+ if (tokens.size === 0 && explicitAgentMentionIds.length === 0)
1344
+ return [];
1345
+ const rows = await db.select({ id: agents.id, name: agents.name })
1346
+ .from(agents).where(eq(agents.companyId, companyId));
1347
+ const resolved = new Set(explicitAgentMentionIds);
1348
+ for (const agent of rows) {
1349
+ if (tokens.has(agent.name.toLowerCase())) {
1350
+ resolved.add(agent.id);
1351
+ }
1352
+ }
1353
+ return [...resolved];
1354
+ },
1355
+ findMentionedProjectIds: async (issueId) => {
1356
+ const issue = await db
1357
+ .select({
1358
+ companyId: issues.companyId,
1359
+ title: issues.title,
1360
+ description: issues.description,
1361
+ })
1362
+ .from(issues)
1363
+ .where(eq(issues.id, issueId))
1364
+ .then((rows) => rows[0] ?? null);
1365
+ if (!issue)
1366
+ return [];
1367
+ const comments = await db
1368
+ .select({ body: issueComments.body })
1369
+ .from(issueComments)
1370
+ .where(eq(issueComments.issueId, issueId));
1371
+ const mentionedIds = new Set();
1372
+ for (const source of [
1373
+ issue.title,
1374
+ issue.description ?? "",
1375
+ ...comments.map((comment) => comment.body),
1376
+ ]) {
1377
+ for (const projectId of extractProjectMentionIds(source)) {
1378
+ mentionedIds.add(projectId);
1379
+ }
1380
+ }
1381
+ if (mentionedIds.size === 0)
1382
+ return [];
1383
+ const rows = await db
1384
+ .select({ id: projects.id })
1385
+ .from(projects)
1386
+ .where(and(eq(projects.companyId, issue.companyId), inArray(projects.id, [...mentionedIds])));
1387
+ const valid = new Set(rows.map((row) => row.id));
1388
+ return [...mentionedIds].filter((projectId) => valid.has(projectId));
1389
+ },
1390
+ getAncestors: async (issueId) => {
1391
+ const raw = [];
1392
+ const visited = new Set([issueId]);
1393
+ const start = await db.select().from(issues).where(eq(issues.id, issueId)).then(r => r[0] ?? null);
1394
+ let currentId = start?.parentId ?? null;
1395
+ while (currentId && !visited.has(currentId) && raw.length < 50) {
1396
+ visited.add(currentId);
1397
+ const parent = await db.select({
1398
+ id: issues.id, identifier: issues.identifier, title: issues.title, description: issues.description,
1399
+ status: issues.status, priority: issues.priority,
1400
+ assigneeAgentId: issues.assigneeAgentId, projectId: issues.projectId,
1401
+ goalId: issues.goalId, parentId: issues.parentId,
1402
+ }).from(issues).where(eq(issues.id, currentId)).then(r => r[0] ?? null);
1403
+ if (!parent)
1404
+ break;
1405
+ raw.push({
1406
+ id: parent.id, identifier: parent.identifier ?? null, title: parent.title, description: parent.description ?? null,
1407
+ status: parent.status, priority: parent.priority,
1408
+ assigneeAgentId: parent.assigneeAgentId ?? null,
1409
+ projectId: parent.projectId ?? null, goalId: parent.goalId ?? null,
1410
+ });
1411
+ currentId = parent.parentId ?? null;
1412
+ }
1413
+ // Batch-fetch referenced projects and goals
1414
+ const projectIds = [...new Set(raw.map(a => a.projectId).filter((id) => id != null))];
1415
+ const goalIds = [...new Set(raw.map(a => a.goalId).filter((id) => id != null))];
1416
+ const projectMap = new Map();
1417
+ const goalMap = new Map();
1418
+ if (projectIds.length > 0) {
1419
+ const workspaceRows = await db
1420
+ .select()
1421
+ .from(projectWorkspaces)
1422
+ .where(inArray(projectWorkspaces.projectId, projectIds))
1423
+ .orderBy(desc(projectWorkspaces.isPrimary), asc(projectWorkspaces.createdAt), asc(projectWorkspaces.id));
1424
+ const workspaceMap = new Map();
1425
+ for (const workspace of workspaceRows) {
1426
+ const existing = workspaceMap.get(workspace.projectId);
1427
+ if (existing)
1428
+ existing.push(workspace);
1429
+ else
1430
+ workspaceMap.set(workspace.projectId, [workspace]);
1431
+ }
1432
+ const rows = await db.select({
1433
+ id: projects.id, name: projects.name, description: projects.description,
1434
+ status: projects.status, goalId: projects.goalId,
1435
+ }).from(projects).where(inArray(projects.id, projectIds));
1436
+ for (const r of rows) {
1437
+ const projectWorkspaceRows = workspaceMap.get(r.id) ?? [];
1438
+ const workspaces = projectWorkspaceRows.map((workspace) => ({
1439
+ id: workspace.id,
1440
+ companyId: workspace.companyId,
1441
+ projectId: workspace.projectId,
1442
+ name: workspace.name,
1443
+ cwd: workspace.cwd,
1444
+ repoUrl: workspace.repoUrl ?? null,
1445
+ repoRef: workspace.repoRef ?? null,
1446
+ metadata: workspace.metadata ?? null,
1447
+ isPrimary: workspace.isPrimary,
1448
+ createdAt: workspace.createdAt,
1449
+ updatedAt: workspace.updatedAt,
1450
+ }));
1451
+ const primaryWorkspace = workspaces.find((workspace) => workspace.isPrimary) ?? workspaces[0] ?? null;
1452
+ projectMap.set(r.id, {
1453
+ ...r,
1454
+ workspaces,
1455
+ primaryWorkspace,
1456
+ });
1457
+ // Also collect goalIds from projects
1458
+ if (r.goalId && !goalIds.includes(r.goalId))
1459
+ goalIds.push(r.goalId);
1460
+ }
1461
+ }
1462
+ if (goalIds.length > 0) {
1463
+ const rows = await db.select({
1464
+ id: goals.id, title: goals.title, description: goals.description,
1465
+ level: goals.level, status: goals.status,
1466
+ }).from(goals).where(inArray(goals.id, goalIds));
1467
+ for (const r of rows)
1468
+ goalMap.set(r.id, r);
1469
+ }
1470
+ return raw.map(a => ({
1471
+ ...a,
1472
+ project: a.projectId ? projectMap.get(a.projectId) ?? null : null,
1473
+ goal: a.goalId ? goalMap.get(a.goalId) ?? null : null,
1474
+ }));
1475
+ },
1476
+ };
1477
+ }
1478
+ //# sourceMappingURL=issues.js.map