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