@slaw-ai/server 2026.611.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 (1198) hide show
  1. package/LICENSE +26 -0
  2. package/dist/adapters/builtin-adapter-types.d.ts +5 -0
  3. package/dist/adapters/builtin-adapter-types.d.ts.map +1 -0
  4. package/dist/adapters/builtin-adapter-types.js +18 -0
  5. package/dist/adapters/builtin-adapter-types.js.map +1 -0
  6. package/dist/adapters/codex-models.d.ts +5 -0
  7. package/dist/adapters/codex-models.d.ts.map +1 -0
  8. package/dist/adapters/codex-models.js +105 -0
  9. package/dist/adapters/codex-models.js.map +1 -0
  10. package/dist/adapters/cursor-models.d.ts +13 -0
  11. package/dist/adapters/cursor-models.d.ts.map +1 -0
  12. package/dist/adapters/cursor-models.js +148 -0
  13. package/dist/adapters/cursor-models.js.map +1 -0
  14. package/dist/adapters/http/execute.d.ts +3 -0
  15. package/dist/adapters/http/execute.d.ts.map +1 -0
  16. package/dist/adapters/http/execute.js +51 -0
  17. package/dist/adapters/http/execute.js.map +1 -0
  18. package/dist/adapters/http/execute.test.d.ts +2 -0
  19. package/dist/adapters/http/execute.test.d.ts.map +1 -0
  20. package/dist/adapters/http/execute.test.js +40 -0
  21. package/dist/adapters/http/execute.test.js.map +1 -0
  22. package/dist/adapters/http/index.d.ts +3 -0
  23. package/dist/adapters/http/index.d.ts.map +1 -0
  24. package/dist/adapters/http/index.js +20 -0
  25. package/dist/adapters/http/index.js.map +1 -0
  26. package/dist/adapters/http/test.d.ts +3 -0
  27. package/dist/adapters/http/test.d.ts.map +1 -0
  28. package/dist/adapters/http/test.js +106 -0
  29. package/dist/adapters/http/test.js.map +1 -0
  30. package/dist/adapters/index.d.ts +4 -0
  31. package/dist/adapters/index.d.ts.map +1 -0
  32. package/dist/adapters/index.js +3 -0
  33. package/dist/adapters/index.js.map +1 -0
  34. package/dist/adapters/plugin-loader.d.ts +28 -0
  35. package/dist/adapters/plugin-loader.d.ts.map +1 -0
  36. package/dist/adapters/plugin-loader.js +196 -0
  37. package/dist/adapters/plugin-loader.js.map +1 -0
  38. package/dist/adapters/process/execute.d.ts +3 -0
  39. package/dist/adapters/process/execute.d.ts.map +1 -0
  40. package/dist/adapters/process/execute.js +70 -0
  41. package/dist/adapters/process/execute.js.map +1 -0
  42. package/dist/adapters/process/index.d.ts +3 -0
  43. package/dist/adapters/process/index.d.ts.map +1 -0
  44. package/dist/adapters/process/index.js +23 -0
  45. package/dist/adapters/process/index.js.map +1 -0
  46. package/dist/adapters/process/test.d.ts +3 -0
  47. package/dist/adapters/process/test.d.ts.map +1 -0
  48. package/dist/adapters/process/test.js +77 -0
  49. package/dist/adapters/process/test.js.map +1 -0
  50. package/dist/adapters/registry.d.ts +69 -0
  51. package/dist/adapters/registry.d.ts.map +1 -0
  52. package/dist/adapters/registry.js +598 -0
  53. package/dist/adapters/registry.js.map +1 -0
  54. package/dist/adapters/types.d.ts +2 -0
  55. package/dist/adapters/types.d.ts.map +1 -0
  56. package/dist/adapters/types.js +2 -0
  57. package/dist/adapters/types.js.map +1 -0
  58. package/dist/adapters/utils.d.ts +43 -0
  59. package/dist/adapters/utils.d.ts.map +1 -0
  60. package/dist/adapters/utils.js +52 -0
  61. package/dist/adapters/utils.js.map +1 -0
  62. package/dist/agent-auth-jwt.d.ts +14 -0
  63. package/dist/agent-auth-jwt.d.ts.map +1 -0
  64. package/dist/agent-auth-jwt.js +117 -0
  65. package/dist/agent-auth-jwt.js.map +1 -0
  66. package/dist/app.d.ts +39 -0
  67. package/dist/app.d.ts.map +1 -0
  68. package/dist/app.js +386 -0
  69. package/dist/app.js.map +1 -0
  70. package/dist/attachment-types.d.ts +23 -0
  71. package/dist/attachment-types.d.ts.map +1 -0
  72. package/dist/attachment-types.js +98 -0
  73. package/dist/attachment-types.js.map +1 -0
  74. package/dist/auth/better-auth.d.ts +40 -0
  75. package/dist/auth/better-auth.d.ts.map +1 -0
  76. package/dist/auth/better-auth.js +148 -0
  77. package/dist/auth/better-auth.js.map +1 -0
  78. package/dist/config-file.d.ts +24 -0
  79. package/dist/config-file.d.ts.map +1 -0
  80. package/dist/config-file.js +73 -0
  81. package/dist/config-file.js.map +1 -0
  82. package/dist/config.d.ts +44 -0
  83. package/dist/config.d.ts.map +1 -0
  84. package/dist/config.js +247 -0
  85. package/dist/config.js.map +1 -0
  86. package/dist/dev-runner-worktree.d.ts +15 -0
  87. package/dist/dev-runner-worktree.d.ts.map +1 -0
  88. package/dist/dev-runner-worktree.js +101 -0
  89. package/dist/dev-runner-worktree.js.map +1 -0
  90. package/dist/dev-server-status.d.ts +33 -0
  91. package/dist/dev-server-status.d.ts.map +1 -0
  92. package/dist/dev-server-status.js +89 -0
  93. package/dist/dev-server-status.js.map +1 -0
  94. package/dist/dev-watch-ignore.d.ts +2 -0
  95. package/dist/dev-watch-ignore.d.ts.map +1 -0
  96. package/dist/dev-watch-ignore.js +36 -0
  97. package/dist/dev-watch-ignore.js.map +1 -0
  98. package/dist/errors.d.ts +12 -0
  99. package/dist/errors.d.ts.map +1 -0
  100. package/dist/errors.js +28 -0
  101. package/dist/errors.js.map +1 -0
  102. package/dist/first-admin-claim.d.ts +17 -0
  103. package/dist/first-admin-claim.d.ts.map +1 -0
  104. package/dist/first-admin-claim.js +30 -0
  105. package/dist/first-admin-claim.js.map +1 -0
  106. package/dist/home-paths.d.ts +15 -0
  107. package/dist/home-paths.d.ts.map +1 -0
  108. package/dist/home-paths.js +48 -0
  109. package/dist/home-paths.js.map +1 -0
  110. package/dist/http/body-limits.d.ts +4 -0
  111. package/dist/http/body-limits.d.ts.map +1 -0
  112. package/dist/http/body-limits.js +4 -0
  113. package/dist/http/body-limits.js.map +1 -0
  114. package/dist/index.d.ts +10 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.js +786 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/instance-claim.d.ts +23 -0
  119. package/dist/instance-claim.d.ts.map +1 -0
  120. package/dist/instance-claim.js +126 -0
  121. package/dist/instance-claim.js.map +1 -0
  122. package/dist/lib/join-request-dedupe.d.ts +11 -0
  123. package/dist/lib/join-request-dedupe.d.ts.map +1 -0
  124. package/dist/lib/join-request-dedupe.js +49 -0
  125. package/dist/lib/join-request-dedupe.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 +122 -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 +302 -0
  133. package/dist/middleware/auth.js.map +1 -0
  134. package/dist/middleware/error-handler.d.ts +17 -0
  135. package/dist/middleware/error-handler.d.ts.map +1 -0
  136. package/dist/middleware/error-handler.js +46 -0
  137. package/dist/middleware/error-handler.js.map +1 -0
  138. package/dist/middleware/http-log-policy.d.ts +2 -0
  139. package/dist/middleware/http-log-policy.d.ts.map +1 -0
  140. package/dist/middleware/http-log-policy.js +52 -0
  141. package/dist/middleware/http-log-policy.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 +92 -0
  149. package/dist/middleware/logger.js.map +1 -0
  150. package/dist/middleware/operator-mutation-guard.d.ts +3 -0
  151. package/dist/middleware/operator-mutation-guard.d.ts.map +1 -0
  152. package/dist/middleware/operator-mutation-guard.js +70 -0
  153. package/dist/middleware/operator-mutation-guard.js.map +1 -0
  154. package/dist/middleware/private-hostname-guard.d.ts +11 -0
  155. package/dist/middleware/private-hostname-guard.d.ts.map +1 -0
  156. package/dist/middleware/private-hostname-guard.js +78 -0
  157. package/dist/middleware/private-hostname-guard.js.map +1 -0
  158. package/dist/middleware/validate.d.ts +4 -0
  159. package/dist/middleware/validate.d.ts.map +1 -0
  160. package/dist/middleware/validate.js +7 -0
  161. package/dist/middleware/validate.js.map +1 -0
  162. package/dist/onboarding-assets/default/AGENTS.md +18 -0
  163. package/dist/onboarding-assets/squad_lead/AGENTS.md +61 -0
  164. package/dist/onboarding-assets/squad_lead/HEARTBEAT.md +85 -0
  165. package/dist/onboarding-assets/squad_lead/SOUL.md +33 -0
  166. package/dist/onboarding-assets/squad_lead/TOOLS.md +3 -0
  167. package/dist/paths.d.ts +3 -0
  168. package/dist/paths.d.ts.map +1 -0
  169. package/dist/paths.js +31 -0
  170. package/dist/paths.js.map +1 -0
  171. package/dist/realtime/live-events-ws.d.ts +28 -0
  172. package/dist/realtime/live-events-ws.d.ts.map +1 -0
  173. package/dist/realtime/live-events-ws.js +187 -0
  174. package/dist/realtime/live-events-ws.js.map +1 -0
  175. package/dist/redaction.d.ts +5 -0
  176. package/dist/redaction.d.ts.map +1 -0
  177. package/dist/redaction.js +125 -0
  178. package/dist/redaction.js.map +1 -0
  179. package/dist/routes/access.d.ts +75 -0
  180. package/dist/routes/access.d.ts.map +1 -0
  181. package/dist/routes/access.js +3070 -0
  182. package/dist/routes/access.js.map +1 -0
  183. package/dist/routes/activity.d.ts +3 -0
  184. package/dist/routes/activity.d.ts.map +1 -0
  185. package/dist/routes/activity.js +90 -0
  186. package/dist/routes/activity.js.map +1 -0
  187. package/dist/routes/adapters.d.ts +16 -0
  188. package/dist/routes/adapters.d.ts.map +1 -0
  189. package/dist/routes/adapters.js +539 -0
  190. package/dist/routes/adapters.js.map +1 -0
  191. package/dist/routes/agents.d.ts +6 -0
  192. package/dist/routes/agents.d.ts.map +1 -0
  193. package/dist/routes/agents.js +2733 -0
  194. package/dist/routes/agents.js.map +1 -0
  195. package/dist/routes/approvals.d.ts +6 -0
  196. package/dist/routes/approvals.d.ts.map +1 -0
  197. package/dist/routes/approvals.js +300 -0
  198. package/dist/routes/approvals.js.map +1 -0
  199. package/dist/routes/assets.d.ts +4 -0
  200. package/dist/routes/assets.d.ts.map +1 -0
  201. package/dist/routes/assets.js +309 -0
  202. package/dist/routes/assets.js.map +1 -0
  203. package/dist/routes/auth.d.ts +3 -0
  204. package/dist/routes/auth.d.ts.map +1 -0
  205. package/dist/routes/auth.js +82 -0
  206. package/dist/routes/auth.js.map +1 -0
  207. package/dist/routes/authz.d.ts +19 -0
  208. package/dist/routes/authz.d.ts.map +1 -0
  209. package/dist/routes/authz.js +75 -0
  210. package/dist/routes/authz.js.map +1 -0
  211. package/dist/routes/botfather.d.ts +9 -0
  212. package/dist/routes/botfather.d.ts.map +1 -0
  213. package/dist/routes/botfather.js +127 -0
  214. package/dist/routes/botfather.js.map +1 -0
  215. package/dist/routes/cloud-upstreams.d.ts +5 -0
  216. package/dist/routes/cloud-upstreams.d.ts.map +1 -0
  217. package/dist/routes/cloud-upstreams.js +103 -0
  218. package/dist/routes/cloud-upstreams.js.map +1 -0
  219. package/dist/routes/costs.d.ts +11 -0
  220. package/dist/routes/costs.d.ts.map +1 -0
  221. package/dist/routes/costs.js +285 -0
  222. package/dist/routes/costs.js.map +1 -0
  223. package/dist/routes/dashboard.d.ts +3 -0
  224. package/dist/routes/dashboard.d.ts.map +1 -0
  225. package/dist/routes/dashboard.js +15 -0
  226. package/dist/routes/dashboard.js.map +1 -0
  227. package/dist/routes/environment-selection.d.ts +13 -0
  228. package/dist/routes/environment-selection.d.ts.map +1 -0
  229. package/dist/routes/environment-selection.js +30 -0
  230. package/dist/routes/environment-selection.js.map +1 -0
  231. package/dist/routes/environments.d.ts +6 -0
  232. package/dist/routes/environments.d.ts.map +1 -0
  233. package/dist/routes/environments.js +414 -0
  234. package/dist/routes/environments.js.map +1 -0
  235. package/dist/routes/execution-workspaces.d.ts +3 -0
  236. package/dist/routes/execution-workspaces.d.ts.map +1 -0
  237. package/dist/routes/execution-workspaces.js +537 -0
  238. package/dist/routes/execution-workspaces.js.map +1 -0
  239. package/dist/routes/goals.d.ts +3 -0
  240. package/dist/routes/goals.d.ts.map +1 -0
  241. package/dist/routes/goals.js +95 -0
  242. package/dist/routes/goals.js.map +1 -0
  243. package/dist/routes/health.d.ts +9 -0
  244. package/dist/routes/health.d.ts.map +1 -0
  245. package/dist/routes/health.js +143 -0
  246. package/dist/routes/health.js.map +1 -0
  247. package/dist/routes/inbox-dismissals.d.ts +3 -0
  248. package/dist/routes/inbox-dismissals.d.ts.map +1 -0
  249. package/dist/routes/inbox-dismissals.js +58 -0
  250. package/dist/routes/inbox-dismissals.js.map +1 -0
  251. package/dist/routes/index.d.ts +24 -0
  252. package/dist/routes/index.d.ts.map +1 -0
  253. package/dist/routes/index.js +24 -0
  254. package/dist/routes/index.js.map +1 -0
  255. package/dist/routes/instance-database-backups.d.ts +15 -0
  256. package/dist/routes/instance-database-backups.d.ts.map +1 -0
  257. package/dist/routes/instance-database-backups.js +12 -0
  258. package/dist/routes/instance-database-backups.js.map +1 -0
  259. package/dist/routes/instance-settings.d.ts +3 -0
  260. package/dist/routes/instance-settings.d.ts.map +1 -0
  261. package/dist/routes/instance-settings.js +110 -0
  262. package/dist/routes/instance-settings.js.map +1 -0
  263. package/dist/routes/issue-tree-control.d.ts +3 -0
  264. package/dist/routes/issue-tree-control.d.ts.map +1 -0
  265. package/dist/routes/issue-tree-control.js +373 -0
  266. package/dist/routes/issue-tree-control.js.map +1 -0
  267. package/dist/routes/issues-checkout-wakeup.d.ts +9 -0
  268. package/dist/routes/issues-checkout-wakeup.d.ts.map +1 -0
  269. package/dist/routes/issues-checkout-wakeup.js +12 -0
  270. package/dist/routes/issues-checkout-wakeup.js.map +1 -0
  271. package/dist/routes/issues.d.ts +15 -0
  272. package/dist/routes/issues.d.ts.map +1 -0
  273. package/dist/routes/issues.js +5276 -0
  274. package/dist/routes/issues.js.map +1 -0
  275. package/dist/routes/llms.d.ts +3 -0
  276. package/dist/routes/llms.d.ts.map +1 -0
  277. package/dist/routes/llms.js +80 -0
  278. package/dist/routes/llms.js.map +1 -0
  279. package/dist/routes/openapi.d.ts +4 -0
  280. package/dist/routes/openapi.d.ts.map +1 -0
  281. package/dist/routes/openapi.js +3284 -0
  282. package/dist/routes/openapi.js.map +1 -0
  283. package/dist/routes/org-chart-svg.d.ts +25 -0
  284. package/dist/routes/org-chart-svg.d.ts.map +1 -0
  285. package/dist/routes/org-chart-svg.js +656 -0
  286. package/dist/routes/org-chart-svg.js.map +1 -0
  287. package/dist/routes/plugin-ui-static.d.ts +69 -0
  288. package/dist/routes/plugin-ui-static.d.ts.map +1 -0
  289. package/dist/routes/plugin-ui-static.js +411 -0
  290. package/dist/routes/plugin-ui-static.js.map +1 -0
  291. package/dist/routes/plugins.d.ts +121 -0
  292. package/dist/routes/plugins.d.ts.map +1 -0
  293. package/dist/routes/plugins.js +2390 -0
  294. package/dist/routes/plugins.js.map +1 -0
  295. package/dist/routes/projects.d.ts +3 -0
  296. package/dist/routes/projects.d.ts.map +1 -0
  297. package/dist/routes/projects.js +566 -0
  298. package/dist/routes/projects.js.map +1 -0
  299. package/dist/routes/resource-memberships.d.ts +3 -0
  300. package/dist/routes/resource-memberships.d.ts.map +1 -0
  301. package/dist/routes/resource-memberships.js +97 -0
  302. package/dist/routes/resource-memberships.js.map +1 -0
  303. package/dist/routes/routines.d.ts +6 -0
  304. package/dist/routes/routines.d.ts.map +1 -0
  305. package/dist/routes/routines.js +411 -0
  306. package/dist/routes/routines.js.map +1 -0
  307. package/dist/routes/secrets.d.ts +3 -0
  308. package/dist/routes/secrets.d.ts.map +1 -0
  309. package/dist/routes/secrets.js +419 -0
  310. package/dist/routes/secrets.js.map +1 -0
  311. package/dist/routes/sidebar-badges.d.ts +3 -0
  312. package/dist/routes/sidebar-badges.d.ts.map +1 -0
  313. package/dist/routes/sidebar-badges.js +68 -0
  314. package/dist/routes/sidebar-badges.js.map +1 -0
  315. package/dist/routes/sidebar-preferences.d.ts +3 -0
  316. package/dist/routes/sidebar-preferences.d.ts.map +1 -0
  317. package/dist/routes/sidebar-preferences.js +63 -0
  318. package/dist/routes/sidebar-preferences.js.map +1 -0
  319. package/dist/routes/squad-import-paths.d.ts +3 -0
  320. package/dist/routes/squad-import-paths.d.ts.map +1 -0
  321. package/dist/routes/squad-import-paths.js +3 -0
  322. package/dist/routes/squad-import-paths.js.map +1 -0
  323. package/dist/routes/squad-skills.d.ts +3 -0
  324. package/dist/routes/squad-skills.d.ts.map +1 -0
  325. package/dist/routes/squad-skills.js +366 -0
  326. package/dist/routes/squad-skills.js.map +1 -0
  327. package/dist/routes/squads.d.ts +4 -0
  328. package/dist/routes/squads.d.ts.map +1 -0
  329. package/dist/routes/squads.js +450 -0
  330. package/dist/routes/squads.js.map +1 -0
  331. package/dist/routes/user-profiles.d.ts +3 -0
  332. package/dist/routes/user-profiles.d.ts.map +1 -0
  333. package/dist/routes/user-profiles.js +337 -0
  334. package/dist/routes/user-profiles.js.map +1 -0
  335. package/dist/routes/workspace-command-authz.d.ts +14 -0
  336. package/dist/routes/workspace-command-authz.d.ts.map +1 -0
  337. package/dist/routes/workspace-command-authz.js +83 -0
  338. package/dist/routes/workspace-command-authz.js.map +1 -0
  339. package/dist/routes/workspace-runtime-service-authz.d.ts +12 -0
  340. package/dist/routes/workspace-runtime-service-authz.d.ts.map +1 -0
  341. package/dist/routes/workspace-runtime-service-authz.js +96 -0
  342. package/dist/routes/workspace-runtime-service-authz.js.map +1 -0
  343. package/dist/runtime-api.d.ts +19 -0
  344. package/dist/runtime-api.d.ts.map +1 -0
  345. package/dist/runtime-api.js +137 -0
  346. package/dist/runtime-api.js.map +1 -0
  347. package/dist/secrets/aws-secrets-manager-provider.d.ts +87 -0
  348. package/dist/secrets/aws-secrets-manager-provider.d.ts.map +1 -0
  349. package/dist/secrets/aws-secrets-manager-provider.js +964 -0
  350. package/dist/secrets/aws-secrets-manager-provider.js.map +1 -0
  351. package/dist/secrets/configured-provider.d.ts +3 -0
  352. package/dist/secrets/configured-provider.d.ts.map +1 -0
  353. package/dist/secrets/configured-provider.js +8 -0
  354. package/dist/secrets/configured-provider.js.map +1 -0
  355. package/dist/secrets/external-stub-providers.d.ts +5 -0
  356. package/dist/secrets/external-stub-providers.d.ts.map +1 -0
  357. package/dist/secrets/external-stub-providers.js +71 -0
  358. package/dist/secrets/external-stub-providers.js.map +1 -0
  359. package/dist/secrets/local-encrypted-provider.d.ts +3 -0
  360. package/dist/secrets/local-encrypted-provider.d.ts.map +1 -0
  361. package/dist/secrets/local-encrypted-provider.js +244 -0
  362. package/dist/secrets/local-encrypted-provider.js.map +1 -0
  363. package/dist/secrets/provider-registry.d.ts +6 -0
  364. package/dist/secrets/provider-registry.d.ts.map +1 -0
  365. package/dist/secrets/provider-registry.js +24 -0
  366. package/dist/secrets/provider-registry.js.map +1 -0
  367. package/dist/secrets/types.d.ts +138 -0
  368. package/dist/secrets/types.d.ts.map +1 -0
  369. package/dist/secrets/types.js +36 -0
  370. package/dist/secrets/types.js.map +1 -0
  371. package/dist/services/access.d.ts +184 -0
  372. package/dist/services/access.d.ts.map +1 -0
  373. package/dist/services/access.js +542 -0
  374. package/dist/services/access.js.map +1 -0
  375. package/dist/services/activity-log.d.ts +19 -0
  376. package/dist/services/activity-log.d.ts.map +1 -0
  377. package/dist/services/activity-log.js +99 -0
  378. package/dist/services/activity-log.js.map +1 -0
  379. package/dist/services/activity.d.ts +462 -0
  380. package/dist/services/activity.d.ts.map +1 -0
  381. package/dist/services/activity.js +443 -0
  382. package/dist/services/activity.js.map +1 -0
  383. package/dist/services/adapter-plugin-store.d.ts +36 -0
  384. package/dist/services/adapter-plugin-store.d.ts.map +1 -0
  385. package/dist/services/adapter-plugin-store.js +154 -0
  386. package/dist/services/adapter-plugin-store.js.map +1 -0
  387. package/dist/services/agent-instructions.d.ts +91 -0
  388. package/dist/services/agent-instructions.d.ts.map +1 -0
  389. package/dist/services/agent-instructions.js +580 -0
  390. package/dist/services/agent-instructions.js.map +1 -0
  391. package/dist/services/agent-permissions.d.ts +6 -0
  392. package/dist/services/agent-permissions.d.ts.map +1 -0
  393. package/dist/services/agent-permissions.js +20 -0
  394. package/dist/services/agent-permissions.js.map +1 -0
  395. package/dist/services/agent-start-lock.d.ts +2 -0
  396. package/dist/services/agent-start-lock.d.ts.map +1 -0
  397. package/dist/services/agent-start-lock.js +43 -0
  398. package/dist/services/agent-start-lock.js.map +1 -0
  399. package/dist/services/agents.d.ts +2253 -0
  400. package/dist/services/agents.d.ts.map +1 -0
  401. package/dist/services/agents.js +609 -0
  402. package/dist/services/agents.js.map +1 -0
  403. package/dist/services/approvals.d.ts +546 -0
  404. package/dist/services/approvals.d.ts.map +1 -0
  405. package/dist/services/approvals.js +212 -0
  406. package/dist/services/approvals.js.map +1 -0
  407. package/dist/services/assets.d.ts +33 -0
  408. package/dist/services/assets.d.ts.map +1 -0
  409. package/dist/services/assets.js +17 -0
  410. package/dist/services/assets.js.map +1 -0
  411. package/dist/services/authorization.d.ts +67 -0
  412. package/dist/services/authorization.d.ts.map +1 -0
  413. package/dist/services/authorization.js +608 -0
  414. package/dist/services/authorization.js.map +1 -0
  415. package/dist/services/botfather/authoring-lock.d.ts +17 -0
  416. package/dist/services/botfather/authoring-lock.d.ts.map +1 -0
  417. package/dist/services/botfather/authoring-lock.js +23 -0
  418. package/dist/services/botfather/authoring-lock.js.map +1 -0
  419. package/dist/services/botfather/authoring-lock.test.d.ts +2 -0
  420. package/dist/services/botfather/authoring-lock.test.d.ts.map +1 -0
  421. package/dist/services/botfather/authoring-lock.test.js +25 -0
  422. package/dist/services/botfather/authoring-lock.test.js.map +1 -0
  423. package/dist/services/botfather/client.d.ts +26 -0
  424. package/dist/services/botfather/client.d.ts.map +1 -0
  425. package/dist/services/botfather/client.js +113 -0
  426. package/dist/services/botfather/client.js.map +1 -0
  427. package/dist/services/botfather/credentials.d.ts +15 -0
  428. package/dist/services/botfather/credentials.d.ts.map +1 -0
  429. package/dist/services/botfather/credentials.js +39 -0
  430. package/dist/services/botfather/credentials.js.map +1 -0
  431. package/dist/services/botfather/enrollment.d.ts +49 -0
  432. package/dist/services/botfather/enrollment.d.ts.map +1 -0
  433. package/dist/services/botfather/enrollment.js +145 -0
  434. package/dist/services/botfather/enrollment.js.map +1 -0
  435. package/dist/services/botfather/instance-limit-enforcement.d.ts +44 -0
  436. package/dist/services/botfather/instance-limit-enforcement.d.ts.map +1 -0
  437. package/dist/services/botfather/instance-limit-enforcement.js +83 -0
  438. package/dist/services/botfather/instance-limit-enforcement.js.map +1 -0
  439. package/dist/services/botfather/instance-limit-enforcement.test.d.ts +2 -0
  440. package/dist/services/botfather/instance-limit-enforcement.test.d.ts.map +1 -0
  441. package/dist/services/botfather/instance-limit-enforcement.test.js +66 -0
  442. package/dist/services/botfather/instance-limit-enforcement.test.js.map +1 -0
  443. package/dist/services/botfather/limits-store.d.ts +36 -0
  444. package/dist/services/botfather/limits-store.d.ts.map +1 -0
  445. package/dist/services/botfather/limits-store.js +94 -0
  446. package/dist/services/botfather/limits-store.js.map +1 -0
  447. package/dist/services/botfather/limits-store.test.d.ts +2 -0
  448. package/dist/services/botfather/limits-store.test.d.ts.map +1 -0
  449. package/dist/services/botfather/limits-store.test.js +70 -0
  450. package/dist/services/botfather/limits-store.test.js.map +1 -0
  451. package/dist/services/botfather/reporter.d.ts +41 -0
  452. package/dist/services/botfather/reporter.d.ts.map +1 -0
  453. package/dist/services/botfather/reporter.js +448 -0
  454. package/dist/services/botfather/reporter.js.map +1 -0
  455. package/dist/services/botfather/service.d.ts +84 -0
  456. package/dist/services/botfather/service.d.ts.map +1 -0
  457. package/dist/services/botfather/service.js +229 -0
  458. package/dist/services/botfather/service.js.map +1 -0
  459. package/dist/services/botfather/service.test.d.ts +2 -0
  460. package/dist/services/botfather/service.test.d.ts.map +1 -0
  461. package/dist/services/botfather/service.test.js +120 -0
  462. package/dist/services/botfather/service.test.js.map +1 -0
  463. package/dist/services/botfather/skill-catalog.d.ts +28 -0
  464. package/dist/services/botfather/skill-catalog.d.ts.map +1 -0
  465. package/dist/services/botfather/skill-catalog.js +101 -0
  466. package/dist/services/botfather/skill-catalog.js.map +1 -0
  467. package/dist/services/botfather/skill-catalog.test.d.ts +2 -0
  468. package/dist/services/botfather/skill-catalog.test.d.ts.map +1 -0
  469. package/dist/services/botfather/skill-catalog.test.js +151 -0
  470. package/dist/services/botfather/skill-catalog.test.js.map +1 -0
  471. package/dist/services/budgets.d.ts +38 -0
  472. package/dist/services/budgets.d.ts.map +1 -0
  473. package/dist/services/budgets.js +833 -0
  474. package/dist/services/budgets.js.map +1 -0
  475. package/dist/services/catalog-provenance.d.ts +7 -0
  476. package/dist/services/catalog-provenance.d.ts.map +1 -0
  477. package/dist/services/catalog-provenance.js +64 -0
  478. package/dist/services/catalog-provenance.js.map +1 -0
  479. package/dist/services/cloud-upstreams.d.ts +42 -0
  480. package/dist/services/cloud-upstreams.d.ts.map +1 -0
  481. package/dist/services/cloud-upstreams.js +1071 -0
  482. package/dist/services/cloud-upstreams.js.map +1 -0
  483. package/dist/services/costs.d.ts +127 -0
  484. package/dist/services/costs.d.ts.map +1 -0
  485. package/dist/services/costs.js +409 -0
  486. package/dist/services/costs.js.map +1 -0
  487. package/dist/services/cron.d.ts +80 -0
  488. package/dist/services/cron.d.ts.map +1 -0
  489. package/dist/services/cron.js +300 -0
  490. package/dist/services/cron.js.map +1 -0
  491. package/dist/services/dashboard.d.ts +34 -0
  492. package/dist/services/dashboard.d.ts.map +1 -0
  493. package/dist/services/dashboard.js +142 -0
  494. package/dist/services/dashboard.js.map +1 -0
  495. package/dist/services/default-agent-instructions.d.ts +9 -0
  496. package/dist/services/default-agent-instructions.d.ts.map +1 -0
  497. package/dist/services/default-agent-instructions.js +20 -0
  498. package/dist/services/default-agent-instructions.js.map +1 -0
  499. package/dist/services/document-annotations.d.ts +160 -0
  500. package/dist/services/document-annotations.d.ts.map +1 -0
  501. package/dist/services/document-annotations.js +324 -0
  502. package/dist/services/document-annotations.js.map +1 -0
  503. package/dist/services/documents.d.ts +347 -0
  504. package/dist/services/documents.d.ts.map +1 -0
  505. package/dist/services/documents.js +638 -0
  506. package/dist/services/documents.js.map +1 -0
  507. package/dist/services/environment-config.d.ts +55 -0
  508. package/dist/services/environment-config.d.ts.map +1 -0
  509. package/dist/services/environment-config.js +441 -0
  510. package/dist/services/environment-config.js.map +1 -0
  511. package/dist/services/environment-execution-target.d.ts +21 -0
  512. package/dist/services/environment-execution-target.d.ts.map +1 -0
  513. package/dist/services/environment-execution-target.js +121 -0
  514. package/dist/services/environment-execution-target.js.map +1 -0
  515. package/dist/services/environment-probe.d.ts +9 -0
  516. package/dist/services/environment-probe.d.ts.map +1 -0
  517. package/dist/services/environment-probe.js +106 -0
  518. package/dist/services/environment-probe.js.map +1 -0
  519. package/dist/services/environment-run-orchestrator.d.ts +124 -0
  520. package/dist/services/environment-run-orchestrator.d.ts.map +1 -0
  521. package/dist/services/environment-run-orchestrator.js +392 -0
  522. package/dist/services/environment-run-orchestrator.js.map +1 -0
  523. package/dist/services/environment-runtime.d.ts +90 -0
  524. package/dist/services/environment-runtime.d.ts.map +1 -0
  525. package/dist/services/environment-runtime.js +968 -0
  526. package/dist/services/environment-runtime.js.map +1 -0
  527. package/dist/services/environments.d.ts +36 -0
  528. package/dist/services/environments.d.ts.map +1 -0
  529. package/dist/services/environments.js +260 -0
  530. package/dist/services/environments.js.map +1 -0
  531. package/dist/services/execution-workspace-policy.d.ts +42 -0
  532. package/dist/services/execution-workspace-policy.d.ts.map +1 -0
  533. package/dist/services/execution-workspace-policy.js +262 -0
  534. package/dist/services/execution-workspace-policy.js.map +1 -0
  535. package/dist/services/execution-workspaces.d.ts +30 -0
  536. package/dist/services/execution-workspaces.d.ts.map +1 -0
  537. package/dist/services/execution-workspaces.js +645 -0
  538. package/dist/services/execution-workspaces.js.map +1 -0
  539. package/dist/services/finance.d.ts +93 -0
  540. package/dist/services/finance.d.ts.map +1 -0
  541. package/dist/services/finance.js +120 -0
  542. package/dist/services/finance.js.map +1 -0
  543. package/dist/services/github-fetch.d.ts +4 -0
  544. package/dist/services/github-fetch.d.ts.map +1 -0
  545. package/dist/services/github-fetch.js +23 -0
  546. package/dist/services/github-fetch.js.map +1 -0
  547. package/dist/services/goals.d.ts +433 -0
  548. package/dist/services/goals.d.ts.map +1 -0
  549. package/dist/services/goals.js +54 -0
  550. package/dist/services/goals.js.map +1 -0
  551. package/dist/services/heartbeat-circuit-breaker.d.ts +89 -0
  552. package/dist/services/heartbeat-circuit-breaker.d.ts.map +1 -0
  553. package/dist/services/heartbeat-circuit-breaker.js +156 -0
  554. package/dist/services/heartbeat-circuit-breaker.js.map +1 -0
  555. package/dist/services/heartbeat-circuit-breaker.test.d.ts +2 -0
  556. package/dist/services/heartbeat-circuit-breaker.test.d.ts.map +1 -0
  557. package/dist/services/heartbeat-circuit-breaker.test.js +97 -0
  558. package/dist/services/heartbeat-circuit-breaker.test.js.map +1 -0
  559. package/dist/services/heartbeat-run-summary.d.ts +7 -0
  560. package/dist/services/heartbeat-run-summary.d.ts.map +1 -0
  561. package/dist/services/heartbeat-run-summary.js +84 -0
  562. package/dist/services/heartbeat-run-summary.js.map +1 -0
  563. package/dist/services/heartbeat-stop-metadata.d.ts +28 -0
  564. package/dist/services/heartbeat-stop-metadata.d.ts.map +1 -0
  565. package/dist/services/heartbeat-stop-metadata.js +86 -0
  566. package/dist/services/heartbeat-stop-metadata.js.map +1 -0
  567. package/dist/services/heartbeat-stop-metadata.test.d.ts +2 -0
  568. package/dist/services/heartbeat-stop-metadata.test.d.ts.map +1 -0
  569. package/dist/services/heartbeat-stop-metadata.test.js +93 -0
  570. package/dist/services/heartbeat-stop-metadata.test.js.map +1 -0
  571. package/dist/services/heartbeat.d.ts +1578 -0
  572. package/dist/services/heartbeat.d.ts.map +1 -0
  573. package/dist/services/heartbeat.js +8274 -0
  574. package/dist/services/heartbeat.js.map +1 -0
  575. package/dist/services/hire-hook.d.ts +14 -0
  576. package/dist/services/hire-hook.d.ts.map +1 -0
  577. package/dist/services/hire-hook.js +85 -0
  578. package/dist/services/hire-hook.js.map +1 -0
  579. package/dist/services/inbox-dismissals.d.ts +22 -0
  580. package/dist/services/inbox-dismissals.d.ts.map +1 -0
  581. package/dist/services/inbox-dismissals.js +33 -0
  582. package/dist/services/inbox-dismissals.js.map +1 -0
  583. package/dist/services/index.d.ts +50 -0
  584. package/dist/services/index.d.ts.map +1 -0
  585. package/dist/services/index.js +49 -0
  586. package/dist/services/index.js.map +1 -0
  587. package/dist/services/instance-settings.d.ts +12 -0
  588. package/dist/services/instance-settings.d.ts.map +1 -0
  589. package/dist/services/instance-settings.js +142 -0
  590. package/dist/services/instance-settings.js.map +1 -0
  591. package/dist/services/invite-grants.d.ts +15 -0
  592. package/dist/services/invite-grants.d.ts.map +1 -0
  593. package/dist/services/invite-grants.js +50 -0
  594. package/dist/services/invite-grants.js.map +1 -0
  595. package/dist/services/issue-approvals.d.ts +56 -0
  596. package/dist/services/issue-approvals.d.ts.map +1 -0
  597. package/dist/services/issue-approvals.js +153 -0
  598. package/dist/services/issue-approvals.js.map +1 -0
  599. package/dist/services/issue-assignment-wakeup.d.ts +29 -0
  600. package/dist/services/issue-assignment-wakeup.d.ts.map +1 -0
  601. package/dist/services/issue-assignment-wakeup.js +22 -0
  602. package/dist/services/issue-assignment-wakeup.js.map +1 -0
  603. package/dist/services/issue-continuation-summary.d.ts +71 -0
  604. package/dist/services/issue-continuation-summary.d.ts.map +1 -0
  605. package/dist/services/issue-continuation-summary.js +222 -0
  606. package/dist/services/issue-continuation-summary.js.map +1 -0
  607. package/dist/services/issue-execution-policy.d.ts +93 -0
  608. package/dist/services/issue-execution-policy.d.ts.map +1 -0
  609. package/dist/services/issue-execution-policy.js +838 -0
  610. package/dist/services/issue-execution-policy.js.map +1 -0
  611. package/dist/services/issue-goal-fallback.d.ts +18 -0
  612. package/dist/services/issue-goal-fallback.d.ts.map +1 -0
  613. package/dist/services/issue-goal-fallback.js +33 -0
  614. package/dist/services/issue-goal-fallback.js.map +1 -0
  615. package/dist/services/issue-liveness.d.ts +3 -0
  616. package/dist/services/issue-liveness.d.ts.map +1 -0
  617. package/dist/services/issue-liveness.js +2 -0
  618. package/dist/services/issue-liveness.js.map +1 -0
  619. package/dist/services/issue-recovery-actions.d.ts +40 -0
  620. package/dist/services/issue-recovery-actions.d.ts.map +1 -0
  621. package/dist/services/issue-recovery-actions.js +204 -0
  622. package/dist/services/issue-recovery-actions.js.map +1 -0
  623. package/dist/services/issue-references.d.ts +22 -0
  624. package/dist/services/issue-references.d.ts.map +1 -0
  625. package/dist/services/issue-references.js +341 -0
  626. package/dist/services/issue-references.js.map +1 -0
  627. package/dist/services/issue-thread-interactions.d.ts +81 -0
  628. package/dist/services/issue-thread-interactions.d.ts.map +1 -0
  629. package/dist/services/issue-thread-interactions.js +1017 -0
  630. package/dist/services/issue-thread-interactions.js.map +1 -0
  631. package/dist/services/issue-thread-interactions.test.d.ts +2 -0
  632. package/dist/services/issue-thread-interactions.test.d.ts.map +1 -0
  633. package/dist/services/issue-thread-interactions.test.js +195 -0
  634. package/dist/services/issue-thread-interactions.test.js.map +1 -0
  635. package/dist/services/issue-tree-control.d.ts +89 -0
  636. package/dist/services/issue-tree-control.d.ts.map +1 -0
  637. package/dist/services/issue-tree-control.js +933 -0
  638. package/dist/services/issue-tree-control.js.map +1 -0
  639. package/dist/services/issues.d.ts +898 -0
  640. package/dist/services/issues.d.ts.map +1 -0
  641. package/dist/services/issues.js +4705 -0
  642. package/dist/services/issues.js.map +1 -0
  643. package/dist/services/json-schema-secret-refs.d.ts +5 -0
  644. package/dist/services/json-schema-secret-refs.d.ts.map +1 -0
  645. package/dist/services/json-schema-secret-refs.js +67 -0
  646. package/dist/services/json-schema-secret-refs.js.map +1 -0
  647. package/dist/services/live-events.d.ts +17 -0
  648. package/dist/services/live-events.d.ts.map +1 -0
  649. package/dist/services/live-events.js +33 -0
  650. package/dist/services/live-events.js.map +1 -0
  651. package/dist/services/local-service-supervisor.d.ts +56 -0
  652. package/dist/services/local-service-supervisor.d.ts.map +1 -0
  653. package/dist/services/local-service-supervisor.js +284 -0
  654. package/dist/services/local-service-supervisor.js.map +1 -0
  655. package/dist/services/operator-auth.d.ts +271 -0
  656. package/dist/services/operator-auth.d.ts.map +1 -0
  657. package/dist/services/operator-auth.js +361 -0
  658. package/dist/services/operator-auth.js.map +1 -0
  659. package/dist/services/plugin-capability-validator.d.ts +108 -0
  660. package/dist/services/plugin-capability-validator.d.ts.map +1 -0
  661. package/dist/services/plugin-capability-validator.js +314 -0
  662. package/dist/services/plugin-capability-validator.js.map +1 -0
  663. package/dist/services/plugin-config-validator.d.ts +26 -0
  664. package/dist/services/plugin-config-validator.d.ts.map +1 -0
  665. package/dist/services/plugin-config-validator.js +41 -0
  666. package/dist/services/plugin-config-validator.js.map +1 -0
  667. package/dist/services/plugin-database.d.ts +49 -0
  668. package/dist/services/plugin-database.d.ts.map +1 -0
  669. package/dist/services/plugin-database.js +475 -0
  670. package/dist/services/plugin-database.js.map +1 -0
  671. package/dist/services/plugin-dev-watcher.d.ts +30 -0
  672. package/dist/services/plugin-dev-watcher.d.ts.map +1 -0
  673. package/dist/services/plugin-dev-watcher.js +246 -0
  674. package/dist/services/plugin-dev-watcher.js.map +1 -0
  675. package/dist/services/plugin-environment-driver.d.ts +126 -0
  676. package/dist/services/plugin-environment-driver.d.ts.map +1 -0
  677. package/dist/services/plugin-environment-driver.js +226 -0
  678. package/dist/services/plugin-environment-driver.js.map +1 -0
  679. package/dist/services/plugin-event-bus.d.ts +149 -0
  680. package/dist/services/plugin-event-bus.d.ts.map +1 -0
  681. package/dist/services/plugin-event-bus.js +258 -0
  682. package/dist/services/plugin-event-bus.js.map +1 -0
  683. package/dist/services/plugin-host-service-cleanup.d.ts +14 -0
  684. package/dist/services/plugin-host-service-cleanup.d.ts.map +1 -0
  685. package/dist/services/plugin-host-service-cleanup.js +37 -0
  686. package/dist/services/plugin-host-service-cleanup.js.map +1 -0
  687. package/dist/services/plugin-host-services.d.ts +17 -0
  688. package/dist/services/plugin-host-services.d.ts.map +1 -0
  689. package/dist/services/plugin-host-services.js +2460 -0
  690. package/dist/services/plugin-host-services.js.map +1 -0
  691. package/dist/services/plugin-job-coordinator.d.ts +81 -0
  692. package/dist/services/plugin-job-coordinator.d.ts.map +1 -0
  693. package/dist/services/plugin-job-coordinator.js +172 -0
  694. package/dist/services/plugin-job-coordinator.js.map +1 -0
  695. package/dist/services/plugin-job-scheduler.d.ts +163 -0
  696. package/dist/services/plugin-job-scheduler.d.ts.map +1 -0
  697. package/dist/services/plugin-job-scheduler.js +454 -0
  698. package/dist/services/plugin-job-scheduler.js.map +1 -0
  699. package/dist/services/plugin-job-store.d.ts +208 -0
  700. package/dist/services/plugin-job-store.d.ts.map +1 -0
  701. package/dist/services/plugin-job-store.js +350 -0
  702. package/dist/services/plugin-job-store.js.map +1 -0
  703. package/dist/services/plugin-lifecycle.d.ts +203 -0
  704. package/dist/services/plugin-lifecycle.d.ts.map +1 -0
  705. package/dist/services/plugin-lifecycle.js +501 -0
  706. package/dist/services/plugin-lifecycle.js.map +1 -0
  707. package/dist/services/plugin-loader.d.ts +453 -0
  708. package/dist/services/plugin-loader.d.ts.map +1 -0
  709. package/dist/services/plugin-loader.js +1295 -0
  710. package/dist/services/plugin-loader.js.map +1 -0
  711. package/dist/services/plugin-local-folders.d.ts +49 -0
  712. package/dist/services/plugin-local-folders.d.ts.map +1 -0
  713. package/dist/services/plugin-local-folders.js +510 -0
  714. package/dist/services/plugin-local-folders.js.map +1 -0
  715. package/dist/services/plugin-log-retention.d.ts +20 -0
  716. package/dist/services/plugin-log-retention.d.ts.map +1 -0
  717. package/dist/services/plugin-log-retention.js +63 -0
  718. package/dist/services/plugin-log-retention.js.map +1 -0
  719. package/dist/services/plugin-managed-agents.d.ts +15 -0
  720. package/dist/services/plugin-managed-agents.d.ts.map +1 -0
  721. package/dist/services/plugin-managed-agents.js +457 -0
  722. package/dist/services/plugin-managed-agents.js.map +1 -0
  723. package/dist/services/plugin-managed-routines.d.ts +42 -0
  724. package/dist/services/plugin-managed-routines.d.ts.map +1 -0
  725. package/dist/services/plugin-managed-routines.js +416 -0
  726. package/dist/services/plugin-managed-routines.js.map +1 -0
  727. package/dist/services/plugin-managed-skills.d.ts +14 -0
  728. package/dist/services/plugin-managed-skills.d.ts.map +1 -0
  729. package/dist/services/plugin-managed-skills.js +264 -0
  730. package/dist/services/plugin-managed-skills.js.map +1 -0
  731. package/dist/services/plugin-manifest-validator.d.ts +79 -0
  732. package/dist/services/plugin-manifest-validator.d.ts.map +1 -0
  733. package/dist/services/plugin-manifest-validator.js +84 -0
  734. package/dist/services/plugin-manifest-validator.js.map +1 -0
  735. package/dist/services/plugin-registry.d.ts +2550 -0
  736. package/dist/services/plugin-registry.d.ts.map +1 -0
  737. package/dist/services/plugin-registry.js +581 -0
  738. package/dist/services/plugin-registry.js.map +1 -0
  739. package/dist/services/plugin-runtime-sandbox.d.ts +40 -0
  740. package/dist/services/plugin-runtime-sandbox.d.ts.map +1 -0
  741. package/dist/services/plugin-runtime-sandbox.js +154 -0
  742. package/dist/services/plugin-runtime-sandbox.js.map +1 -0
  743. package/dist/services/plugin-secrets-handler.d.ts +83 -0
  744. package/dist/services/plugin-secrets-handler.d.ts.map +1 -0
  745. package/dist/services/plugin-secrets-handler.js +168 -0
  746. package/dist/services/plugin-secrets-handler.js.map +1 -0
  747. package/dist/services/plugin-state-store.d.ts +92 -0
  748. package/dist/services/plugin-state-store.d.ts.map +1 -0
  749. package/dist/services/plugin-state-store.js +190 -0
  750. package/dist/services/plugin-state-store.js.map +1 -0
  751. package/dist/services/plugin-stream-bus.d.ts +29 -0
  752. package/dist/services/plugin-stream-bus.d.ts.map +1 -0
  753. package/dist/services/plugin-stream-bus.js +48 -0
  754. package/dist/services/plugin-stream-bus.js.map +1 -0
  755. package/dist/services/plugin-tool-dispatcher.d.ts +181 -0
  756. package/dist/services/plugin-tool-dispatcher.d.ts.map +1 -0
  757. package/dist/services/plugin-tool-dispatcher.js +224 -0
  758. package/dist/services/plugin-tool-dispatcher.js.map +1 -0
  759. package/dist/services/plugin-tool-registry.d.ts +192 -0
  760. package/dist/services/plugin-tool-registry.d.ts.map +1 -0
  761. package/dist/services/plugin-tool-registry.js +224 -0
  762. package/dist/services/plugin-tool-registry.js.map +1 -0
  763. package/dist/services/plugin-worker-manager.d.ts +262 -0
  764. package/dist/services/plugin-worker-manager.d.ts.map +1 -0
  765. package/dist/services/plugin-worker-manager.js +942 -0
  766. package/dist/services/plugin-worker-manager.js.map +1 -0
  767. package/dist/services/portable-path.d.ts +2 -0
  768. package/dist/services/portable-path.d.ts.map +1 -0
  769. package/dist/services/portable-path.js +15 -0
  770. package/dist/services/portable-path.js.map +1 -0
  771. package/dist/services/principal-access-compatibility.d.ts +26 -0
  772. package/dist/services/principal-access-compatibility.d.ts.map +1 -0
  773. package/dist/services/principal-access-compatibility.js +94 -0
  774. package/dist/services/principal-access-compatibility.js.map +1 -0
  775. package/dist/services/productivity-review.d.ts +83 -0
  776. package/dist/services/productivity-review.d.ts.map +1 -0
  777. package/dist/services/productivity-review.js +652 -0
  778. package/dist/services/productivity-review.js.map +1 -0
  779. package/dist/services/project-workspace-runtime-config.d.ts +4 -0
  780. package/dist/services/project-workspace-runtime-config.d.ts.map +1 -0
  781. package/dist/services/project-workspace-runtime-config.js +54 -0
  782. package/dist/services/project-workspace-runtime-config.js.map +1 -0
  783. package/dist/services/projects.d.ts +99 -0
  784. package/dist/services/projects.d.ts.map +1 -0
  785. package/dist/services/projects.js +879 -0
  786. package/dist/services/projects.js.map +1 -0
  787. package/dist/services/quota-windows.d.ts +9 -0
  788. package/dist/services/quota-windows.d.ts.map +1 -0
  789. package/dist/services/quota-windows.js +56 -0
  790. package/dist/services/quota-windows.js.map +1 -0
  791. package/dist/services/recovery/index.d.ts +10 -0
  792. package/dist/services/recovery/index.d.ts.map +1 -0
  793. package/dist/services/recovery/index.js +6 -0
  794. package/dist/services/recovery/index.js.map +1 -0
  795. package/dist/services/recovery/issue-graph-liveness.d.ts +85 -0
  796. package/dist/services/recovery/issue-graph-liveness.d.ts.map +1 -0
  797. package/dist/services/recovery/issue-graph-liveness.js +356 -0
  798. package/dist/services/recovery/issue-graph-liveness.js.map +1 -0
  799. package/dist/services/recovery/model-profile-hint.d.ts +21 -0
  800. package/dist/services/recovery/model-profile-hint.d.ts.map +1 -0
  801. package/dist/services/recovery/model-profile-hint.js +36 -0
  802. package/dist/services/recovery/model-profile-hint.js.map +1 -0
  803. package/dist/services/recovery/model-profile-hint.test.d.ts +2 -0
  804. package/dist/services/recovery/model-profile-hint.test.d.ts.map +1 -0
  805. package/dist/services/recovery/model-profile-hint.test.js +38 -0
  806. package/dist/services/recovery/model-profile-hint.test.js.map +1 -0
  807. package/dist/services/recovery/origins.d.ts +36 -0
  808. package/dist/services/recovery/origins.d.ts.map +1 -0
  809. package/dist/services/recovery/origins.js +45 -0
  810. package/dist/services/recovery/origins.js.map +1 -0
  811. package/dist/services/recovery/pause-hold-guard.d.ts +6 -0
  812. package/dist/services/recovery/pause-hold-guard.d.ts.map +1 -0
  813. package/dist/services/recovery/pause-hold-guard.js +6 -0
  814. package/dist/services/recovery/pause-hold-guard.js.map +1 -0
  815. package/dist/services/recovery/run-liveness-continuations.d.ts +50 -0
  816. package/dist/services/recovery/run-liveness-continuations.d.ts.map +1 -0
  817. package/dist/services/recovery/run-liveness-continuations.js +117 -0
  818. package/dist/services/recovery/run-liveness-continuations.js.map +1 -0
  819. package/dist/services/recovery/service.d.ts +258 -0
  820. package/dist/services/recovery/service.d.ts.map +1 -0
  821. package/dist/services/recovery/service.js +2892 -0
  822. package/dist/services/recovery/service.js.map +1 -0
  823. package/dist/services/recovery/successful-run-handoff.d.ts +89 -0
  824. package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -0
  825. package/dist/services/recovery/successful-run-handoff.js +304 -0
  826. package/dist/services/recovery/successful-run-handoff.js.map +1 -0
  827. package/dist/services/recovery/successful-run-handoff.test.d.ts +2 -0
  828. package/dist/services/recovery/successful-run-handoff.test.d.ts.map +1 -0
  829. package/dist/services/recovery/successful-run-handoff.test.js +276 -0
  830. package/dist/services/recovery/successful-run-handoff.test.js.map +1 -0
  831. package/dist/services/resource-memberships.d.ts +55 -0
  832. package/dist/services/resource-memberships.d.ts.map +1 -0
  833. package/dist/services/resource-memberships.js +213 -0
  834. package/dist/services/resource-memberships.js.map +1 -0
  835. package/dist/services/routines.d.ts +170 -0
  836. package/dist/services/routines.d.ts.map +1 -0
  837. package/dist/services/routines.js +2015 -0
  838. package/dist/services/routines.js.map +1 -0
  839. package/dist/services/run-continuations.d.ts +3 -0
  840. package/dist/services/run-continuations.d.ts.map +1 -0
  841. package/dist/services/run-continuations.js +2 -0
  842. package/dist/services/run-continuations.js.map +1 -0
  843. package/dist/services/run-liveness.d.ts +46 -0
  844. package/dist/services/run-liveness.d.ts.map +1 -0
  845. package/dist/services/run-liveness.js +275 -0
  846. package/dist/services/run-liveness.js.map +1 -0
  847. package/dist/services/run-log-store.d.ts +34 -0
  848. package/dist/services/run-log-store.d.ts.map +1 -0
  849. package/dist/services/run-log-store.js +111 -0
  850. package/dist/services/run-log-store.js.map +1 -0
  851. package/dist/services/sandbox-provider-runtime.d.ts +132 -0
  852. package/dist/services/sandbox-provider-runtime.d.ts.map +1 -0
  853. package/dist/services/sandbox-provider-runtime.js +216 -0
  854. package/dist/services/sandbox-provider-runtime.js.map +1 -0
  855. package/dist/services/secrets.d.ts +1991 -0
  856. package/dist/services/secrets.d.ts.map +1 -0
  857. package/dist/services/secrets.js +1781 -0
  858. package/dist/services/secrets.js.map +1 -0
  859. package/dist/services/session-workspace-cwd.d.ts +2 -0
  860. package/dist/services/session-workspace-cwd.d.ts.map +1 -0
  861. package/dist/services/session-workspace-cwd.js +24 -0
  862. package/dist/services/session-workspace-cwd.js.map +1 -0
  863. package/dist/services/session-workspace-cwd.test.d.ts +2 -0
  864. package/dist/services/session-workspace-cwd.test.d.ts.map +1 -0
  865. package/dist/services/session-workspace-cwd.test.js +25 -0
  866. package/dist/services/session-workspace-cwd.test.js.map +1 -0
  867. package/dist/services/sidebar-badges.d.ts +14 -0
  868. package/dist/services/sidebar-badges.d.ts.map +1 -0
  869. package/dist/services/sidebar-badges.js +48 -0
  870. package/dist/services/sidebar-badges.js.map +1 -0
  871. package/dist/services/sidebar-preferences.d.ts +9 -0
  872. package/dist/services/sidebar-preferences.d.ts.map +1 -0
  873. package/dist/services/sidebar-preferences.js +82 -0
  874. package/dist/services/sidebar-preferences.js.map +1 -0
  875. package/dist/services/skills-catalog.d.ts +14 -0
  876. package/dist/services/skills-catalog.d.ts.map +1 -0
  877. package/dist/services/skills-catalog.js +171 -0
  878. package/dist/services/skills-catalog.js.map +1 -0
  879. package/dist/services/squad-export-readme.d.ts +17 -0
  880. package/dist/services/squad-export-readme.d.ts.map +1 -0
  881. package/dist/services/squad-export-readme.js +148 -0
  882. package/dist/services/squad-export-readme.js.map +1 -0
  883. package/dist/services/squad-member-roles.d.ts +9 -0
  884. package/dist/services/squad-member-roles.d.ts.map +1 -0
  885. package/dist/services/squad-member-roles.js +48 -0
  886. package/dist/services/squad-member-roles.js.map +1 -0
  887. package/dist/services/squad-portability.d.ts +24 -0
  888. package/dist/services/squad-portability.d.ts.map +1 -0
  889. package/dist/services/squad-portability.js +4093 -0
  890. package/dist/services/squad-portability.js.map +1 -0
  891. package/dist/services/squad-search-rate-limit.d.ts +22 -0
  892. package/dist/services/squad-search-rate-limit.d.ts.map +1 -0
  893. package/dist/services/squad-search-rate-limit.js +38 -0
  894. package/dist/services/squad-search-rate-limit.js.map +1 -0
  895. package/dist/services/squad-search.d.ts +8 -0
  896. package/dist/services/squad-search.d.ts.map +1 -0
  897. package/dist/services/squad-search.js +626 -0
  898. package/dist/services/squad-search.js.map +1 -0
  899. package/dist/services/squad-skills.d.ts +107 -0
  900. package/dist/services/squad-skills.d.ts.map +1 -0
  901. package/dist/services/squad-skills.js +3044 -0
  902. package/dist/services/squad-skills.js.map +1 -0
  903. package/dist/services/squads.d.ts +154 -0
  904. package/dist/services/squads.d.ts.map +1 -0
  905. package/dist/services/squads.js +278 -0
  906. package/dist/services/squads.js.map +1 -0
  907. package/dist/services/wake-cycle-guard.d.ts +44 -0
  908. package/dist/services/wake-cycle-guard.d.ts.map +1 -0
  909. package/dist/services/wake-cycle-guard.js +79 -0
  910. package/dist/services/wake-cycle-guard.js.map +1 -0
  911. package/dist/services/wake-cycle-guard.test.d.ts +2 -0
  912. package/dist/services/wake-cycle-guard.test.d.ts.map +1 -0
  913. package/dist/services/wake-cycle-guard.test.js +67 -0
  914. package/dist/services/wake-cycle-guard.test.js.map +1 -0
  915. package/dist/services/work-products.d.ts +14 -0
  916. package/dist/services/work-products.d.ts.map +1 -0
  917. package/dist/services/work-products.js +100 -0
  918. package/dist/services/work-products.js.map +1 -0
  919. package/dist/services/workspace-operation-log-store.d.ts +33 -0
  920. package/dist/services/workspace-operation-log-store.d.ts.map +1 -0
  921. package/dist/services/workspace-operation-log-store.js +110 -0
  922. package/dist/services/workspace-operation-log-store.js.map +1 -0
  923. package/dist/services/workspace-operations.d.ts +44 -0
  924. package/dist/services/workspace-operations.d.ts.map +1 -0
  925. package/dist/services/workspace-operations.js +211 -0
  926. package/dist/services/workspace-operations.js.map +1 -0
  927. package/dist/services/workspace-realization.d.ts +33 -0
  928. package/dist/services/workspace-realization.d.ts.map +1 -0
  929. package/dist/services/workspace-realization.js +221 -0
  930. package/dist/services/workspace-realization.js.map +1 -0
  931. package/dist/services/workspace-runtime-read-model.d.ts +92 -0
  932. package/dist/services/workspace-runtime-read-model.d.ts.map +1 -0
  933. package/dist/services/workspace-runtime-read-model.js +67 -0
  934. package/dist/services/workspace-runtime-read-model.js.map +1 -0
  935. package/dist/services/workspace-runtime.d.ts +252 -0
  936. package/dist/services/workspace-runtime.d.ts.map +1 -0
  937. package/dist/services/workspace-runtime.js +2519 -0
  938. package/dist/services/workspace-runtime.js.map +1 -0
  939. package/dist/startup-banner.d.ts +32 -0
  940. package/dist/startup-banner.d.ts.map +1 -0
  941. package/dist/startup-banner.js +118 -0
  942. package/dist/startup-banner.js.map +1 -0
  943. package/dist/static-index-html.d.ts +2 -0
  944. package/dist/static-index-html.d.ts.map +1 -0
  945. package/dist/static-index-html.js +7 -0
  946. package/dist/static-index-html.js.map +1 -0
  947. package/dist/storage/index.d.ts +6 -0
  948. package/dist/storage/index.d.ts.map +1 -0
  949. package/dist/storage/index.js +29 -0
  950. package/dist/storage/index.js.map +1 -0
  951. package/dist/storage/local-disk-provider.d.ts +3 -0
  952. package/dist/storage/local-disk-provider.d.ts.map +1 -0
  953. package/dist/storage/local-disk-provider.js +85 -0
  954. package/dist/storage/local-disk-provider.js.map +1 -0
  955. package/dist/storage/provider-registry.d.ts +4 -0
  956. package/dist/storage/provider-registry.d.ts.map +1 -0
  957. package/dist/storage/provider-registry.js +15 -0
  958. package/dist/storage/provider-registry.js.map +1 -0
  959. package/dist/storage/s3-provider.d.ts +11 -0
  960. package/dist/storage/s3-provider.d.ts.map +1 -0
  961. package/dist/storage/s3-provider.js +124 -0
  962. package/dist/storage/s3-provider.js.map +1 -0
  963. package/dist/storage/service.d.ts +3 -0
  964. package/dist/storage/service.d.ts.map +1 -0
  965. package/dist/storage/service.js +120 -0
  966. package/dist/storage/service.js.map +1 -0
  967. package/dist/storage/types.d.ts +59 -0
  968. package/dist/storage/types.d.ts.map +1 -0
  969. package/dist/storage/types.js +2 -0
  970. package/dist/storage/types.js.map +1 -0
  971. package/dist/ui-branding.d.ts +13 -0
  972. package/dist/ui-branding.d.ts.map +1 -0
  973. package/dist/ui-branding.js +187 -0
  974. package/dist/ui-branding.js.map +1 -0
  975. package/dist/version.d.ts +2 -0
  976. package/dist/version.d.ts.map +1 -0
  977. package/dist/version.js +5 -0
  978. package/dist/version.js.map +1 -0
  979. package/dist/vite-html-renderer.d.ts +18 -0
  980. package/dist/vite-html-renderer.d.ts.map +1 -0
  981. package/dist/vite-html-renderer.js +61 -0
  982. package/dist/vite-html-renderer.js.map +1 -0
  983. package/dist/worktree-config.d.ts +19 -0
  984. package/dist/worktree-config.d.ts.map +1 -0
  985. package/dist/worktree-config.js +373 -0
  986. package/dist/worktree-config.js.map +1 -0
  987. package/package.json +92 -0
  988. package/skills/diagnose-why-work-stopped/SKILL.md +161 -0
  989. package/skills/para-memory-files/SKILL.md +104 -0
  990. package/skills/para-memory-files/references/schemas.md +35 -0
  991. package/skills/slaw/SKILL.md +371 -0
  992. package/skills/slaw/references/api-reference.md +879 -0
  993. package/skills/slaw/references/artifacts.md +44 -0
  994. package/skills/slaw/references/issue-workspaces.md +80 -0
  995. package/skills/slaw/references/routines.md +187 -0
  996. package/skills/slaw/references/squad-skills.md +258 -0
  997. package/skills/slaw/references/workflows.md +113 -0
  998. package/skills/slaw/scripts/slaw-upload-artifact.sh +371 -0
  999. package/skills/slaw-converting-plans-to-tasks/SKILL.md +42 -0
  1000. package/skills/slaw-create-agent/SKILL.md +163 -0
  1001. package/skills/slaw-create-agent/references/agent-instruction-templates.md +123 -0
  1002. package/skills/slaw-create-agent/references/agents/coder.md +64 -0
  1003. package/skills/slaw-create-agent/references/agents/qa.md +88 -0
  1004. package/skills/slaw-create-agent/references/agents/securityengineer.md +135 -0
  1005. package/skills/slaw-create-agent/references/agents/uxdesigner.md +115 -0
  1006. package/skills/slaw-create-agent/references/api-reference.md +110 -0
  1007. package/skills/slaw-create-agent/references/baseline-role-guide.md +168 -0
  1008. package/skills/slaw-create-agent/references/draft-review-checklist.md +95 -0
  1009. package/skills/slaw-create-plugin/SKILL.md +154 -0
  1010. package/skills/slaw-dev/SKILL.md +267 -0
  1011. package/skills/terminal-bench-loop/SKILL.md +236 -0
  1012. package/ui-dist/android-chrome-192x192.png +0 -0
  1013. package/ui-dist/android-chrome-512x512.png +0 -0
  1014. package/ui-dist/apple-touch-icon.png +0 -0
  1015. package/ui-dist/assets/apl-B4CMkyY2.js +1 -0
  1016. package/ui-dist/assets/arc-xbLjL0VN.js +1 -0
  1017. package/ui-dist/assets/architectureDiagram-3BPJPVTR-KcFd4B-U.js +36 -0
  1018. package/ui-dist/assets/asciiarmor-Df11BRmG.js +1 -0
  1019. package/ui-dist/assets/asn1-EdZsLKOL.js +1 -0
  1020. package/ui-dist/assets/asterisk-B-8jnY81.js +1 -0
  1021. package/ui-dist/assets/blockDiagram-GPEHLZMM-CSD4otEL.js +132 -0
  1022. package/ui-dist/assets/brainfuck-C4LP7Hcl.js +1 -0
  1023. package/ui-dist/assets/c4Diagram-AAUBKEIU-Cre_NEHp.js +10 -0
  1024. package/ui-dist/assets/channel-BFN8obi8.js +1 -0
  1025. package/ui-dist/assets/chunk-2J33WTMH-CssLBsbh.js +1 -0
  1026. package/ui-dist/assets/chunk-4BX2VUAB-DjiavNFv.js +1 -0
  1027. package/ui-dist/assets/chunk-55IACEB6-C_F0yeYq.js +1 -0
  1028. package/ui-dist/assets/chunk-727SXJPM-B1FAOW4a.js +206 -0
  1029. package/ui-dist/assets/chunk-AQP2D5EJ-Do1241W-.js +231 -0
  1030. package/ui-dist/assets/chunk-FMBD7UC4-BQRrOMZD.js +15 -0
  1031. package/ui-dist/assets/chunk-ND2GUHAM-BPSt3kZ1.js +1 -0
  1032. package/ui-dist/assets/chunk-QZHKN3VN-BSpmhWDD.js +1 -0
  1033. package/ui-dist/assets/classDiagram-4FO5ZUOK-1Ay0zFCU.js +1 -0
  1034. package/ui-dist/assets/classDiagram-v2-Q7XG4LA2-1Ay0zFCU.js +1 -0
  1035. package/ui-dist/assets/clike-B9uivgTg.js +1 -0
  1036. package/ui-dist/assets/clojure-BMjYHr_A.js +1 -0
  1037. package/ui-dist/assets/cmake-BQqOBYOt.js +1 -0
  1038. package/ui-dist/assets/cobol-CWcv1MsR.js +1 -0
  1039. package/ui-dist/assets/coffeescript-S37ZYGWr.js +1 -0
  1040. package/ui-dist/assets/commonlisp-DBKNyK5s.js +1 -0
  1041. package/ui-dist/assets/cose-bilkent-S5V4N54A-CK2f2Te4.js +1 -0
  1042. package/ui-dist/assets/crystal-SjHAIU92.js +1 -0
  1043. package/ui-dist/assets/css-BnMrqG3P.js +1 -0
  1044. package/ui-dist/assets/cypher-C_CwsFkJ.js +1 -0
  1045. package/ui-dist/assets/cytoscape.esm-D8joxN9f.js +321 -0
  1046. package/ui-dist/assets/d-pRatUO7H.js +1 -0
  1047. package/ui-dist/assets/dagre-BM42HDAG-DaOXTN9-.js +4 -0
  1048. package/ui-dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  1049. package/ui-dist/assets/diagram-2AECGRRQ-D0ScQUGy.js +43 -0
  1050. package/ui-dist/assets/diagram-5GNKFQAL-7mH4Cncd.js +10 -0
  1051. package/ui-dist/assets/diagram-KO2AKTUF-aA9kuK-7.js +3 -0
  1052. package/ui-dist/assets/diagram-LMA3HP47-C9UXfmdK.js +24 -0
  1053. package/ui-dist/assets/diagram-OG6HWLK6-Ba3U-x1r.js +24 -0
  1054. package/ui-dist/assets/diff-DbItnlRl.js +1 -0
  1055. package/ui-dist/assets/dockerfile-BKs6k2Af.js +1 -0
  1056. package/ui-dist/assets/dtd-DF_7sFjM.js +1 -0
  1057. package/ui-dist/assets/dylan-DwRh75JA.js +1 -0
  1058. package/ui-dist/assets/ebnf-CDyGwa7X.js +1 -0
  1059. package/ui-dist/assets/ecl-Cabwm37j.js +1 -0
  1060. package/ui-dist/assets/eiffel-CnydiIhH.js +1 -0
  1061. package/ui-dist/assets/elm-vLlmbW-K.js +1 -0
  1062. package/ui-dist/assets/erDiagram-TEJ5UH35-CmskPKH1.js +85 -0
  1063. package/ui-dist/assets/erlang-BNw1qcRV.js +1 -0
  1064. package/ui-dist/assets/factor-kuTfRLto.js +1 -0
  1065. package/ui-dist/assets/fcl-Kvtd6kyn.js +1 -0
  1066. package/ui-dist/assets/flowDiagram-I6XJVG4X-B0iEPqGd.js +162 -0
  1067. package/ui-dist/assets/forth-Ffai-XNe.js +1 -0
  1068. package/ui-dist/assets/fortran-DYz_wnZ1.js +1 -0
  1069. package/ui-dist/assets/ganttDiagram-6RSMTGT7-DtpxlgWQ.js +292 -0
  1070. package/ui-dist/assets/gas-Bneqetm1.js +1 -0
  1071. package/ui-dist/assets/gherkin-heZmZLOM.js +1 -0
  1072. package/ui-dist/assets/gitGraphDiagram-PVQCEYII-VefBjqya.js +106 -0
  1073. package/ui-dist/assets/graph-CAnANduQ.js +1 -0
  1074. package/ui-dist/assets/groovy-D9Dt4D0W.js +1 -0
  1075. package/ui-dist/assets/haskell-Cw1EW3IL.js +1 -0
  1076. package/ui-dist/assets/haxe-H-WmDvRZ.js +1 -0
  1077. package/ui-dist/assets/http-DBlCnlav.js +1 -0
  1078. package/ui-dist/assets/idl-BEugSyMb.js +1 -0
  1079. package/ui-dist/assets/index-B9KxOFt-.js +1 -0
  1080. package/ui-dist/assets/index-BMPCuc-W.js +1 -0
  1081. package/ui-dist/assets/index-Bbfs2D7R.js +1 -0
  1082. package/ui-dist/assets/index-BrgHE5Lg.js +1 -0
  1083. package/ui-dist/assets/index-C5q-Cwlp.js +7 -0
  1084. package/ui-dist/assets/index-C6LpKpr3.js +1 -0
  1085. package/ui-dist/assets/index-CIzt5DFV.js +1 -0
  1086. package/ui-dist/assets/index-CRwAuYPj.js +1 -0
  1087. package/ui-dist/assets/index-CTEnIXsJ.js +1 -0
  1088. package/ui-dist/assets/index-CXGemv2V.js +1 -0
  1089. package/ui-dist/assets/index-ClDiS51u.js +1 -0
  1090. package/ui-dist/assets/index-CvKYfvpz.js +1 -0
  1091. package/ui-dist/assets/index-D2IqxlXD.js +1 -0
  1092. package/ui-dist/assets/index-D97fJMFR.js +522 -0
  1093. package/ui-dist/assets/index-DDHdUa2f.js +1 -0
  1094. package/ui-dist/assets/index-DMZ0QXqi.js +1 -0
  1095. package/ui-dist/assets/index-DMi4KpxO.js +6 -0
  1096. package/ui-dist/assets/index-DZB48Gve.js +1 -0
  1097. package/ui-dist/assets/index-Drr9zRdK.css +1 -0
  1098. package/ui-dist/assets/index-DtGqpE43.js +1 -0
  1099. package/ui-dist/assets/index-Du18kURt.js +2 -0
  1100. package/ui-dist/assets/index-KaLXuTqA.js +1 -0
  1101. package/ui-dist/assets/index-j5NgiILm.js +13 -0
  1102. package/ui-dist/assets/index-u0SfLZ3g.js +3 -0
  1103. package/ui-dist/assets/infoDiagram-5YYISTIA-D2OGH-dO.js +2 -0
  1104. package/ui-dist/assets/init-Gi6I4Gst.js +1 -0
  1105. package/ui-dist/assets/ishikawaDiagram-YF4QCWOH-CnMf3BJj.js +70 -0
  1106. package/ui-dist/assets/javascript-iXu5QeM3.js +1 -0
  1107. package/ui-dist/assets/journeyDiagram-JHISSGLW-BaXdD53T.js +139 -0
  1108. package/ui-dist/assets/julia-DuME0IfC.js +1 -0
  1109. package/ui-dist/assets/kanban-definition-UN3LZRKU-Brt7LjHm.js +89 -0
  1110. package/ui-dist/assets/katex-yT8l5JNH.js +257 -0
  1111. package/ui-dist/assets/layout-DGIYPm2g.js +1 -0
  1112. package/ui-dist/assets/linear-536T6Mkh.js +1 -0
  1113. package/ui-dist/assets/livescript-BwQOo05w.js +1 -0
  1114. package/ui-dist/assets/lua-VAEuO923.js +1 -0
  1115. package/ui-dist/assets/mathematica-DTrFuWx2.js +1 -0
  1116. package/ui-dist/assets/mbox-CNhZ1qSd.js +1 -0
  1117. package/ui-dist/assets/mermaid.core-CURTLVBm.js +303 -0
  1118. package/ui-dist/assets/mindmap-definition-RKZ34NQL-S2tDCU-U.js +96 -0
  1119. package/ui-dist/assets/mirc-CjQqDB4T.js +1 -0
  1120. package/ui-dist/assets/mllike-CXdrOF99.js +1 -0
  1121. package/ui-dist/assets/modelica-Dc1JOy9r.js +1 -0
  1122. package/ui-dist/assets/mscgen-BA5vi2Kp.js +1 -0
  1123. package/ui-dist/assets/mumps-BT43cFF4.js +1 -0
  1124. package/ui-dist/assets/nginx-DdIZxoE0.js +1 -0
  1125. package/ui-dist/assets/nsis-LdVXkNf5.js +1 -0
  1126. package/ui-dist/assets/ntriples-BfvgReVJ.js +1 -0
  1127. package/ui-dist/assets/octave-Ck1zUtKM.js +1 -0
  1128. package/ui-dist/assets/ordinal-Cboi1Yqb.js +1 -0
  1129. package/ui-dist/assets/oz-BzwKVEFT.js +1 -0
  1130. package/ui-dist/assets/pascal--L3eBynH.js +1 -0
  1131. package/ui-dist/assets/perl-CdXCOZ3F.js +1 -0
  1132. package/ui-dist/assets/pieDiagram-4H26LBE5-DD_Ih32z.js +30 -0
  1133. package/ui-dist/assets/pig-CevX1Tat.js +1 -0
  1134. package/ui-dist/assets/powershell-CFHJl5sT.js +1 -0
  1135. package/ui-dist/assets/properties-C78fOPTZ.js +1 -0
  1136. package/ui-dist/assets/protobuf-ChK-085T.js +1 -0
  1137. package/ui-dist/assets/pug-DeIclll2.js +1 -0
  1138. package/ui-dist/assets/puppet-DMA9R1ak.js +1 -0
  1139. package/ui-dist/assets/python-BuPzkPfP.js +1 -0
  1140. package/ui-dist/assets/q-pXgVlZs6.js +1 -0
  1141. package/ui-dist/assets/quadrantDiagram-W4KKPZXB-DA5BPBIK.js +7 -0
  1142. package/ui-dist/assets/r-B6wPVr8A.js +1 -0
  1143. package/ui-dist/assets/requirementDiagram-4Y6WPE33-Em8SPCro.js +84 -0
  1144. package/ui-dist/assets/rpm-CTu-6PCP.js +1 -0
  1145. package/ui-dist/assets/ruby-B2Rjki9n.js +1 -0
  1146. package/ui-dist/assets/sankeyDiagram-5OEKKPKP-BJVC4haY.js +40 -0
  1147. package/ui-dist/assets/sas-B4kiWyti.js +1 -0
  1148. package/ui-dist/assets/scheme-C41bIUwD.js +1 -0
  1149. package/ui-dist/assets/sequenceDiagram-3UESZ5HK-Cskntadf.js +162 -0
  1150. package/ui-dist/assets/shell-CjFT_Tl9.js +1 -0
  1151. package/ui-dist/assets/sieve-C3Gn_uJK.js +1 -0
  1152. package/ui-dist/assets/simple-mode-GW_nhZxv.js +1 -0
  1153. package/ui-dist/assets/smalltalk-CnHTOXQT.js +1 -0
  1154. package/ui-dist/assets/solr-DehyRSwq.js +1 -0
  1155. package/ui-dist/assets/sparql-DkYu6x3z.js +1 -0
  1156. package/ui-dist/assets/spreadsheet-BCZA_wO0.js +1 -0
  1157. package/ui-dist/assets/sql-D0XecflT.js +1 -0
  1158. package/ui-dist/assets/stateDiagram-AJRCARHV-CxlfdaOi.js +1 -0
  1159. package/ui-dist/assets/stateDiagram-v2-BHNVJYJU-eTgftUjW.js +1 -0
  1160. package/ui-dist/assets/stex-C3f8Ysf7.js +1 -0
  1161. package/ui-dist/assets/stylus-B533Al4x.js +1 -0
  1162. package/ui-dist/assets/swift-BzpIVaGY.js +1 -0
  1163. package/ui-dist/assets/tcl-DVfN8rqt.js +1 -0
  1164. package/ui-dist/assets/textile-CnDTJFAw.js +1 -0
  1165. package/ui-dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  1166. package/ui-dist/assets/tiki-DGYXhP31.js +1 -0
  1167. package/ui-dist/assets/timeline-definition-PNZ67QCA-LOdaWSSa.js +120 -0
  1168. package/ui-dist/assets/toml-Bm5Em-hy.js +1 -0
  1169. package/ui-dist/assets/troff-wAsdV37c.js +1 -0
  1170. package/ui-dist/assets/ttcn-CfJYG6tj.js +1 -0
  1171. package/ui-dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  1172. package/ui-dist/assets/turtle-B1tBg_DP.js +1 -0
  1173. package/ui-dist/assets/vb-CmGdzxic.js +1 -0
  1174. package/ui-dist/assets/vbscript-BuJXcnF6.js +1 -0
  1175. package/ui-dist/assets/velocity-D8B20fx6.js +1 -0
  1176. package/ui-dist/assets/vennDiagram-CIIHVFJN-CJ4ji6B3.js +34 -0
  1177. package/ui-dist/assets/verilog-C6RDOZhf.js +1 -0
  1178. package/ui-dist/assets/vhdl-lSbBsy5d.js +1 -0
  1179. package/ui-dist/assets/wardley-L42UT6IY-CxnVdUVH.js +153 -0
  1180. package/ui-dist/assets/wardleyDiagram-YWT4CUSO-CgGDttpl.js +78 -0
  1181. package/ui-dist/assets/webidl-ZXfAyPTL.js +1 -0
  1182. package/ui-dist/assets/xquery-DzFWVndE.js +1 -0
  1183. package/ui-dist/assets/xychartDiagram-2RQKCTM6-zuQa7bqx.js +7 -0
  1184. package/ui-dist/assets/yacas-BJ4BC0dw.js +1 -0
  1185. package/ui-dist/assets/z80-Hz9HOZM7.js +1 -0
  1186. package/ui-dist/brands/opencode-logo-dark-square.svg +18 -0
  1187. package/ui-dist/brands/opencode-logo-light-square.svg +18 -0
  1188. package/ui-dist/favicon-16x16.png +0 -0
  1189. package/ui-dist/favicon-32x32.png +0 -0
  1190. package/ui-dist/favicon.ico +0 -0
  1191. package/ui-dist/favicon.svg +8 -0
  1192. package/ui-dist/index.html +46 -0
  1193. package/ui-dist/site.webmanifest +30 -0
  1194. package/ui-dist/sw.js +42 -0
  1195. package/ui-dist/worktree-favicon-16x16.png +0 -0
  1196. package/ui-dist/worktree-favicon-32x32.png +0 -0
  1197. package/ui-dist/worktree-favicon.ico +0 -0
  1198. package/ui-dist/worktree-favicon.svg +9 -0
@@ -0,0 +1,2460 @@
1
+ import { activityLog, agentTaskSessions as agentTaskSessionsTable, agents as agentsTable, budgetIncidents, costEvents, heartbeatRuns, invites, issues as issuesTable, pluginLogs, principalPermissionGrants, projects as projectsTable, } from "@slaw-ai/db";
2
+ import { eq, and, like, desc, inArray, sql, isNull, isNotNull, gt, lte } from "drizzle-orm";
3
+ import { pluginOperationIssueOriginKind } from "@slaw-ai/shared";
4
+ import { squadService } from "./squads.js";
5
+ import { agentService } from "./agents.js";
6
+ import { projectService } from "./projects.js";
7
+ import { executionWorkspaceService } from "./execution-workspaces.js";
8
+ import { issueService } from "./issues.js";
9
+ import { issueThreadInteractionService } from "./issue-thread-interactions.js";
10
+ import { goalService } from "./goals.js";
11
+ import { documentService } from "./documents.js";
12
+ import { heartbeatService } from "./heartbeat.js";
13
+ import { budgetService } from "./budgets.js";
14
+ import { issueApprovalService } from "./issue-approvals.js";
15
+ import { subscribeSquadLiveEvents } from "./live-events.js";
16
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
17
+ import path from "node:path";
18
+ import { pluginRegistryService } from "./plugin-registry.js";
19
+ import { pluginStateStore } from "./plugin-state-store.js";
20
+ import { pluginDatabaseService } from "./plugin-database.js";
21
+ import { pluginManagedAgentService } from "./plugin-managed-agents.js";
22
+ import { pluginManagedRoutineService } from "./plugin-managed-routines.js";
23
+ import { pluginManagedSkillService } from "./plugin-managed-skills.js";
24
+ import { assertConfiguredLocalFolder, assertWritableConfiguredLocalFolder, getStoredLocalFolders, deletePluginLocalFolderFile, inspectPluginLocalFolder, listPluginLocalFolderEntries, preparePluginLocalFolder, readPluginLocalFolderText, requireLocalFolderDeclaration, setStoredLocalFolder, writePluginLocalFolderTextAtomic, } from "./plugin-local-folders.js";
25
+ import { createPluginSecretsHandler } from "./plugin-secrets-handler.js";
26
+ import { logActivity } from "./activity-log.js";
27
+ import { lookup as dnsLookup } from "node:dns/promises";
28
+ import { request as httpRequest } from "node:http";
29
+ import { request as httpsRequest } from "node:https";
30
+ import { isIP } from "node:net";
31
+ import { logger } from "../middleware/logger.js";
32
+ import { accessService } from "./access.js";
33
+ import { authorizationService } from "./authorization.js";
34
+ import { sanitizeRecord } from "../redaction.js";
35
+ // ---------------------------------------------------------------------------
36
+ // SSRF protection for plugin HTTP fetch
37
+ // ---------------------------------------------------------------------------
38
+ /** Maximum time (ms) a plugin fetch request may take before being aborted. */
39
+ const PLUGIN_FETCH_TIMEOUT_MS = 30_000;
40
+ /** Maximum time (ms) to wait for a DNS lookup before aborting. */
41
+ const DNS_LOOKUP_TIMEOUT_MS = 5_000;
42
+ /** Only these protocols are allowed for plugin HTTP requests. */
43
+ const ALLOWED_PROTOCOLS = new Set(["http:", "https:"]);
44
+ /**
45
+ * Check if an IP address is in a private/reserved range (RFC 1918, loopback,
46
+ * link-local, etc.) that plugins should never be able to reach.
47
+ *
48
+ * Handles IPv4-mapped IPv6 addresses (e.g. ::ffff:127.0.0.1) which Node's
49
+ * dns.lookup may return depending on OS configuration.
50
+ */
51
+ function isPrivateIP(ip) {
52
+ const lower = ip.toLowerCase();
53
+ // Unwrap IPv4-mapped IPv6 addresses (::ffff:x.x.x.x) and re-check as IPv4
54
+ const v4MappedMatch = lower.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
55
+ if (v4MappedMatch && v4MappedMatch[1])
56
+ return isPrivateIP(v4MappedMatch[1]);
57
+ // IPv4 patterns
58
+ if (ip.startsWith("10."))
59
+ return true;
60
+ if (ip.startsWith("172.")) {
61
+ const second = parseInt(ip.split(".")[1], 10);
62
+ if (second >= 16 && second <= 31)
63
+ return true;
64
+ }
65
+ if (ip.startsWith("192.168."))
66
+ return true;
67
+ if (ip.startsWith("127."))
68
+ return true; // loopback
69
+ if (ip.startsWith("169.254."))
70
+ return true; // link-local
71
+ if (ip === "0.0.0.0")
72
+ return true;
73
+ // IPv6 patterns
74
+ if (lower === "::1")
75
+ return true; // loopback
76
+ if (lower.startsWith("fc") || lower.startsWith("fd"))
77
+ return true; // ULA
78
+ if (lower.startsWith("fe80"))
79
+ return true; // link-local
80
+ if (lower === "::")
81
+ return true;
82
+ return false;
83
+ }
84
+ async function validateAndResolveFetchUrl(urlString) {
85
+ let parsed;
86
+ try {
87
+ parsed = new URL(urlString);
88
+ }
89
+ catch {
90
+ throw new Error(`Invalid URL: ${urlString}`);
91
+ }
92
+ if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) {
93
+ throw new Error(`Disallowed protocol "${parsed.protocol}" — only http: and https: are permitted`);
94
+ }
95
+ // Resolve the hostname to an IP and check for private ranges.
96
+ // We pin the resolved IP into the URL to eliminate the TOCTOU window
97
+ // between DNS resolution here and the second resolution fetch() would do.
98
+ const originalHostname = parsed.hostname.replace(/^\[|\]$/g, ""); // strip IPv6 brackets
99
+ const hostHeader = parsed.host; // includes port if non-default
100
+ // Race the DNS lookup against a timeout to prevent indefinite hangs
101
+ // when DNS is misconfigured or unresponsive.
102
+ const dnsPromise = dnsLookup(originalHostname, { all: true });
103
+ const timeoutPromise = new Promise((_, reject) => {
104
+ setTimeout(() => reject(new Error(`DNS lookup timed out after ${DNS_LOOKUP_TIMEOUT_MS}ms for ${originalHostname}`)), DNS_LOOKUP_TIMEOUT_MS);
105
+ });
106
+ try {
107
+ const results = await Promise.race([dnsPromise, timeoutPromise]);
108
+ if (results.length === 0) {
109
+ throw new Error(`DNS resolution returned no results for ${originalHostname}`);
110
+ }
111
+ // Filter to only non-private IPs instead of rejecting the entire request
112
+ // when some IPs are private. This handles multi-homed hosts that resolve
113
+ // to both private and public addresses.
114
+ const safeResults = results.filter((entry) => !isPrivateIP(entry.address));
115
+ if (safeResults.length === 0) {
116
+ throw new Error(`All resolved IPs for ${originalHostname} are in private/reserved ranges`);
117
+ }
118
+ const resolved = safeResults[0];
119
+ return {
120
+ parsedUrl: parsed,
121
+ resolvedAddress: resolved.address,
122
+ hostHeader,
123
+ tlsServername: parsed.protocol === "https:" && isIP(originalHostname) === 0
124
+ ? originalHostname
125
+ : undefined,
126
+ useTls: parsed.protocol === "https:",
127
+ };
128
+ }
129
+ catch (err) {
130
+ // Re-throw our own errors; wrap DNS failures
131
+ if (err instanceof Error && (err.message.startsWith("All resolved IPs") ||
132
+ err.message.startsWith("DNS resolution returned") ||
133
+ err.message.startsWith("DNS lookup timed out")))
134
+ throw err;
135
+ throw new Error(`DNS resolution failed for ${originalHostname}: ${err.message}`);
136
+ }
137
+ }
138
+ function buildPinnedRequestOptions(target, init) {
139
+ const headers = new Headers(init?.headers);
140
+ const method = init?.method ?? "GET";
141
+ const body = init?.body === undefined || init?.body === null
142
+ ? undefined
143
+ : typeof init.body === "string"
144
+ ? init.body
145
+ : String(init.body);
146
+ headers.set("Host", target.hostHeader);
147
+ if (body !== undefined && !headers.has("content-length") && !headers.has("transfer-encoding")) {
148
+ headers.set("content-length", String(Buffer.byteLength(body)));
149
+ }
150
+ const pathname = `${target.parsedUrl.pathname}${target.parsedUrl.search}`;
151
+ const auth = target.parsedUrl.username || target.parsedUrl.password
152
+ ? `${decodeURIComponent(target.parsedUrl.username)}:${decodeURIComponent(target.parsedUrl.password)}`
153
+ : undefined;
154
+ return {
155
+ options: {
156
+ protocol: target.parsedUrl.protocol,
157
+ host: target.resolvedAddress,
158
+ port: target.parsedUrl.port
159
+ ? Number(target.parsedUrl.port)
160
+ : target.useTls
161
+ ? 443
162
+ : 80,
163
+ path: pathname,
164
+ method,
165
+ headers: Object.fromEntries(headers.entries()),
166
+ auth,
167
+ servername: target.tlsServername,
168
+ },
169
+ body,
170
+ };
171
+ }
172
+ async function executePinnedHttpRequest(target, init, signal) {
173
+ const { options, body } = buildPinnedRequestOptions(target, init);
174
+ const response = await new Promise((resolve, reject) => {
175
+ const requestFn = target.useTls ? httpsRequest : httpRequest;
176
+ const req = requestFn({ ...options, signal }, resolve);
177
+ req.on("error", reject);
178
+ if (body !== undefined) {
179
+ req.write(body);
180
+ }
181
+ req.end();
182
+ });
183
+ const MAX_RESPONSE_BODY_BYTES = 200 * 1024 * 1024; // 200 MB
184
+ const chunks = [];
185
+ let totalBytes = 0;
186
+ await new Promise((resolve, reject) => {
187
+ response.on("data", (chunk) => {
188
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
189
+ totalBytes += buf.length;
190
+ if (totalBytes > MAX_RESPONSE_BODY_BYTES) {
191
+ chunks.length = 0;
192
+ response.destroy(new Error(`Response body exceeded ${MAX_RESPONSE_BODY_BYTES} bytes`));
193
+ return;
194
+ }
195
+ chunks.push(buf);
196
+ });
197
+ response.on("end", resolve);
198
+ response.on("error", reject);
199
+ });
200
+ const headers = {};
201
+ for (const [key, value] of Object.entries(response.headers)) {
202
+ if (Array.isArray(value)) {
203
+ headers[key] = value.join(", ");
204
+ }
205
+ else if (value !== undefined) {
206
+ headers[key] = value;
207
+ }
208
+ }
209
+ return {
210
+ status: response.statusCode ?? 500,
211
+ statusText: response.statusMessage ?? "",
212
+ headers,
213
+ body: Buffer.concat(chunks).toString("utf8"),
214
+ };
215
+ }
216
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
217
+ const PATH_LIKE_PATTERN = /[\\/]/;
218
+ const WINDOWS_DRIVE_PATH_PATTERN = /^[A-Za-z]:[\\/]/;
219
+ function looksLikePath(value) {
220
+ const normalized = value.trim();
221
+ return (PATH_LIKE_PATTERN.test(normalized)
222
+ || WINDOWS_DRIVE_PATH_PATTERN.test(normalized)) && !UUID_PATTERN.test(normalized);
223
+ }
224
+ function sanitizeWorkspaceText(value) {
225
+ const trimmed = value.trim();
226
+ if (!trimmed || UUID_PATTERN.test(trimmed))
227
+ return "";
228
+ return trimmed;
229
+ }
230
+ function sanitizeWorkspacePath(cwd) {
231
+ if (!cwd)
232
+ return "";
233
+ return looksLikePath(cwd) ? cwd.trim() : "";
234
+ }
235
+ function sanitizeWorkspaceName(name, fallbackPath) {
236
+ const safeName = sanitizeWorkspaceText(name);
237
+ if (safeName && !looksLikePath(safeName)) {
238
+ return safeName;
239
+ }
240
+ const normalized = fallbackPath.trim().replace(/[\\/]+$/, "");
241
+ const segments = normalized.split(/[\\/]/).filter(Boolean);
242
+ return segments[segments.length - 1] ?? "Workspace";
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // Buffered plugin log writes
246
+ // ---------------------------------------------------------------------------
247
+ /** How many buffered log entries trigger an immediate flush. */
248
+ const LOG_BUFFER_FLUSH_SIZE = 100;
249
+ /** How often (ms) the buffer is flushed regardless of size. */
250
+ const LOG_BUFFER_FLUSH_INTERVAL_MS = 5_000;
251
+ /** Max length for a single plugin log message (bytes/chars). */
252
+ const MAX_LOG_MESSAGE_LENGTH = 10_000;
253
+ /** Max serialised JSON size for plugin log meta objects. */
254
+ const MAX_LOG_META_JSON_LENGTH = 50_000;
255
+ /** Max length for a metric name. */
256
+ const MAX_METRIC_NAME_LENGTH = 500;
257
+ /** Pino reserved field names that plugins must not overwrite. */
258
+ const PINO_RESERVED_KEYS = new Set([
259
+ "level",
260
+ "time",
261
+ "pid",
262
+ "hostname",
263
+ "msg",
264
+ "v",
265
+ ]);
266
+ /** Truncate a string to `max` characters, appending a marker if truncated. */
267
+ function truncStr(s, max) {
268
+ if (s.length <= max)
269
+ return s;
270
+ return s.slice(0, max) + "...[truncated]";
271
+ }
272
+ /** Sanitise a plugin-supplied meta object: enforce size limit and strip reserved keys. */
273
+ function sanitiseMeta(meta) {
274
+ if (meta == null)
275
+ return null;
276
+ // Strip pino reserved keys
277
+ const cleaned = {};
278
+ for (const [k, v] of Object.entries(meta)) {
279
+ if (!PINO_RESERVED_KEYS.has(k)) {
280
+ cleaned[k] = v;
281
+ }
282
+ }
283
+ // Enforce total serialised size
284
+ let json;
285
+ try {
286
+ json = JSON.stringify(cleaned);
287
+ }
288
+ catch {
289
+ return { _sanitised: true, _error: "meta was not JSON-serialisable" };
290
+ }
291
+ if (json.length > MAX_LOG_META_JSON_LENGTH) {
292
+ return { _sanitised: true, _error: `meta exceeded ${MAX_LOG_META_JSON_LENGTH} chars` };
293
+ }
294
+ return cleaned;
295
+ }
296
+ const _logBuffer = [];
297
+ /**
298
+ * Flush all buffered log entries to the database in a single batch insert per
299
+ * unique db instance. Errors are swallowed with a console.error fallback so
300
+ * flushing never crashes the process.
301
+ */
302
+ export async function flushPluginLogBuffer() {
303
+ if (_logBuffer.length === 0)
304
+ return;
305
+ // Drain the buffer atomically so concurrent flushes don't double-insert.
306
+ const entries = _logBuffer.splice(0, _logBuffer.length);
307
+ // Group entries by db identity so multi-db scenarios are handled correctly.
308
+ const byDb = new Map();
309
+ for (const entry of entries) {
310
+ const group = byDb.get(entry.db);
311
+ if (group) {
312
+ group.push(entry);
313
+ }
314
+ else {
315
+ byDb.set(entry.db, [entry]);
316
+ }
317
+ }
318
+ for (const [dbInstance, group] of byDb) {
319
+ const values = group.map((e) => ({
320
+ pluginId: e.pluginId,
321
+ level: e.level,
322
+ message: e.message,
323
+ meta: e.meta,
324
+ }));
325
+ try {
326
+ await dbInstance.insert(pluginLogs).values(values);
327
+ }
328
+ catch (err) {
329
+ try {
330
+ logger.warn({ err, count: values.length }, "Failed to batch-persist plugin logs to DB");
331
+ }
332
+ catch {
333
+ console.error("[plugin-host-services] Batch log flush failed:", err);
334
+ }
335
+ }
336
+ }
337
+ }
338
+ /** Interval handle for the periodic log flush. */
339
+ const _logFlushInterval = setInterval(() => {
340
+ flushPluginLogBuffer().catch((err) => {
341
+ console.error("[plugin-host-services] Periodic log flush error:", err);
342
+ });
343
+ }, LOG_BUFFER_FLUSH_INTERVAL_MS);
344
+ // Allow the interval to be unref'd so it doesn't keep the process alive in tests.
345
+ if (_logFlushInterval.unref)
346
+ _logFlushInterval.unref();
347
+ /**
348
+ * buildHostServices — creates a concrete implementation of the `HostServices`
349
+ * interface for a specific plugin.
350
+ *
351
+ * This implementation delegates to the core Slaw domain services,
352
+ * providing the bridge between the plugin worker's SDK and the host platform.
353
+ *
354
+ * @param db - Database connection instance.
355
+ * @param pluginId - The UUID of the plugin installation record.
356
+ * @param pluginKey - The unique identifier from the plugin manifest (e.g., "acme.linear").
357
+ * @param eventBus - The system-wide event bus for publishing plugin events.
358
+ * @returns An object implementing the HostServices interface for the plugin SDK.
359
+ */
360
+ /** Maximum time (ms) to keep a session event subscription alive before forcing cleanup. */
361
+ const SESSION_EVENT_SUBSCRIPTION_TIMEOUT_MS = 30 * 60 * 1_000; // 30 minutes
362
+ export function buildHostServices(db, pluginId, pluginKey, eventBus, notifyWorker, options = {}) {
363
+ const registry = pluginRegistryService(db);
364
+ const stateStore = pluginStateStore(db);
365
+ const pluginDb = pluginDatabaseService(db);
366
+ const secretsHandler = createPluginSecretsHandler({ db, pluginId });
367
+ const squads = squadService(db);
368
+ const agents = agentService(db);
369
+ const managedAgents = pluginManagedAgentService(db, {
370
+ pluginId,
371
+ pluginKey,
372
+ manifest: options.manifest,
373
+ instructionTemplateVariables: async (squadId) => {
374
+ const variables = {};
375
+ for (const declaration of options.manifest?.localFolders ?? []) {
376
+ const status = await inspectPluginLocalFolder({
377
+ folderKey: declaration.folderKey,
378
+ declaration,
379
+ storedConfig: await getStoredLocalFolderConfig(squadId, declaration.folderKey),
380
+ });
381
+ const prefix = `localFolders.${declaration.folderKey}`;
382
+ variables[`${prefix}.path`] = status.realPath ?? status.path ?? null;
383
+ variables[`${prefix}.agentsPath`] = status.realPath ? path.join(status.realPath, "AGENTS.md") : null;
384
+ }
385
+ return variables;
386
+ },
387
+ });
388
+ const managedRoutines = pluginManagedRoutineService(db, {
389
+ pluginId,
390
+ pluginKey,
391
+ manifest: options.manifest,
392
+ pluginWorkerManager: options.pluginWorkerManager,
393
+ });
394
+ const managedSkills = pluginManagedSkillService(db, {
395
+ pluginId,
396
+ pluginKey,
397
+ manifest: options.manifest,
398
+ });
399
+ const heartbeat = heartbeatService(db, {
400
+ pluginWorkerManager: options.pluginWorkerManager,
401
+ });
402
+ const projects = projectService(db);
403
+ const executionWorkspaces = executionWorkspaceService(db);
404
+ const issues = issueService(db);
405
+ const documents = documentService(db);
406
+ const goals = goalService(db);
407
+ const access = accessService(db);
408
+ const authorization = authorizationService(db);
409
+ const budgets = budgetService(db);
410
+ const issueApprovals = issueApprovalService(db);
411
+ const scopedBus = eventBus.forPlugin(pluginKey);
412
+ // Track active session event subscriptions for cleanup
413
+ const activeSubscriptions = new Set();
414
+ let disposed = false;
415
+ const ensureSquadId = (squadId) => {
416
+ if (!squadId)
417
+ throw new Error("squadId is required for this operation");
418
+ return squadId;
419
+ };
420
+ const parseWindowValue = (value) => {
421
+ if (typeof value === "number" && Number.isFinite(value)) {
422
+ return Math.max(0, Math.floor(value));
423
+ }
424
+ if (typeof value === "string" && value.trim().length > 0) {
425
+ const parsed = Number(value);
426
+ if (Number.isFinite(parsed)) {
427
+ return Math.max(0, Math.floor(parsed));
428
+ }
429
+ }
430
+ return null;
431
+ };
432
+ const applyWindow = (rows, params) => {
433
+ const offset = parseWindowValue(params?.offset) ?? 0;
434
+ const limit = parseWindowValue(params?.limit);
435
+ if (limit == null)
436
+ return rows.slice(offset);
437
+ return rows.slice(offset, offset + limit);
438
+ };
439
+ const authorizationAuditDecisionCondition = (decisionFilter) => {
440
+ const conditions = [
441
+ sql `lower(${activityLog.details}->>'decision') = ${decisionFilter}`,
442
+ decisionFilter === "allow" ? sql `left(coalesce(${activityLog.details}->>'reason', ''), 6) = 'allow_'` : undefined,
443
+ decisionFilter === "deny" ? sql `left(coalesce(${activityLog.details}->>'reason', ''), 5) = 'deny_'` : undefined,
444
+ decisionFilter === "allow" ? sql `${activityLog.details}->>'allowed' = 'true'` : undefined,
445
+ decisionFilter === "deny" ? sql `${activityLog.details}->>'allowed' = 'false'` : undefined,
446
+ ].filter((condition) => Boolean(condition));
447
+ return sql `(${sql.join(conditions, sql ` OR `)})`;
448
+ };
449
+ /**
450
+ * Plugins are instance-wide in the current runtime. Squad IDs are still
451
+ * required for squad-scoped data access, but there is no per-squad
452
+ * availability gate to enforce here.
453
+ */
454
+ const ensurePluginAvailableForSquad = async (_squadId) => { };
455
+ const getLocalFolderDeclaration = (folderKey) => requireLocalFolderDeclaration(options.manifest?.localFolders, folderKey);
456
+ const getStoredLocalFolderConfig = async (squadId, folderKey) => {
457
+ ensureSquadId(squadId);
458
+ await ensurePluginAvailableForSquad(squadId);
459
+ const settings = await registry.getSquadSettings(pluginId, squadId);
460
+ return getStoredLocalFolders(settings?.settingsJson)[folderKey] ?? null;
461
+ };
462
+ const inspectStoredLocalFolder = async (squadId, folderKey) => inspectPluginLocalFolder({
463
+ folderKey,
464
+ declaration: getLocalFolderDeclaration(folderKey),
465
+ storedConfig: await getStoredLocalFolderConfig(squadId, folderKey),
466
+ });
467
+ const inSquad = (record, squadId) => Boolean(record && record.squadId === squadId);
468
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
469
+ const readProviderMetadata = (metadata) => {
470
+ if (!isRecord(metadata))
471
+ return null;
472
+ if (isRecord(metadata.providerMetadata))
473
+ return { ...metadata.providerMetadata };
474
+ const rebuild = metadata.rebuild;
475
+ if (!isRecord(rebuild))
476
+ return null;
477
+ const rebuildMetadata = rebuild.metadata;
478
+ if (!isRecord(rebuildMetadata) || !isRecord(rebuildMetadata.providerMetadata))
479
+ return null;
480
+ return { ...rebuildMetadata.providerMetadata };
481
+ };
482
+ const toPluginExecutionWorkspaceMetadata = (workspace) => ({
483
+ id: workspace.id,
484
+ squadId: workspace.squadId,
485
+ projectId: workspace.projectId,
486
+ projectWorkspaceId: workspace.projectWorkspaceId,
487
+ path: workspace.cwd ?? workspace.providerRef,
488
+ cwd: workspace.cwd,
489
+ repoUrl: workspace.repoUrl,
490
+ baseRef: workspace.baseRef,
491
+ branchName: workspace.branchName,
492
+ providerType: workspace.providerType,
493
+ providerMetadata: readProviderMetadata(workspace.metadata),
494
+ });
495
+ const requireInSquad = (entityName, record, squadId) => {
496
+ if (!inSquad(record, squadId)) {
497
+ throw new Error(`${entityName} not found`);
498
+ }
499
+ return record;
500
+ };
501
+ const pluginActivityDetails = (details, actor) => {
502
+ const initiatingActorType = actor?.actorAgentId ? "agent" : actor?.actorUserId ? "user" : null;
503
+ const initiatingActorId = actor?.actorAgentId ?? actor?.actorUserId ?? null;
504
+ return {
505
+ ...(details ?? {}),
506
+ sourcePluginId: pluginId,
507
+ sourcePluginKey: pluginKey,
508
+ initiatingActorType,
509
+ initiatingActorId,
510
+ initiatingAgentId: actor?.actorAgentId ?? null,
511
+ initiatingUserId: actor?.actorUserId ?? null,
512
+ initiatingRunId: actor?.actorRunId ?? null,
513
+ pluginId,
514
+ pluginKey,
515
+ };
516
+ };
517
+ const defaultPluginOriginKind = `plugin:${pluginKey}`;
518
+ const normalizePluginOriginKind = (originKind = defaultPluginOriginKind) => {
519
+ if (originKind == null || originKind === "")
520
+ return defaultPluginOriginKind;
521
+ if (typeof originKind !== "string") {
522
+ throw new Error("Plugin issue originKind must be a string");
523
+ }
524
+ if (originKind === defaultPluginOriginKind || originKind.startsWith(`${defaultPluginOriginKind}:`)) {
525
+ return originKind;
526
+ }
527
+ throw new Error(`Plugin may only use originKind values under ${defaultPluginOriginKind}`);
528
+ };
529
+ const assertReadableOriginFilter = (originKind) => {
530
+ if (typeof originKind !== "string" || !originKind.startsWith("plugin:"))
531
+ return;
532
+ normalizePluginOriginKind(originKind);
533
+ };
534
+ const logPluginActivity = async (input) => {
535
+ await logActivity(db, {
536
+ squadId: input.squadId,
537
+ actorType: "plugin",
538
+ actorId: pluginId,
539
+ agentId: input.actor?.actorAgentId ?? null,
540
+ runId: input.actor?.actorRunId ?? null,
541
+ action: input.action,
542
+ entityType: input.entityType,
543
+ entityId: input.entityId,
544
+ details: pluginActivityDetails(input.details, input.actor),
545
+ });
546
+ };
547
+ const collectIssueSubtreeIds = async (squadId, rootIssueId) => {
548
+ const seen = new Set([rootIssueId]);
549
+ let frontier = [rootIssueId];
550
+ while (frontier.length > 0) {
551
+ const children = await db
552
+ .select({ id: issuesTable.id })
553
+ .from(issuesTable)
554
+ .where(and(eq(issuesTable.squadId, squadId), inArray(issuesTable.parentId, frontier)));
555
+ frontier = children.map((child) => child.id).filter((id) => !seen.has(id));
556
+ for (const id of frontier)
557
+ seen.add(id);
558
+ }
559
+ return [...seen];
560
+ };
561
+ const getIssueRunSummaries = async (squadId, issueIds, options = {}) => {
562
+ if (issueIds.length === 0)
563
+ return [];
564
+ const issueIdExpr = sql `${heartbeatRuns.contextSnapshot} ->> 'issueId'`;
565
+ const statusCondition = options.activeOnly
566
+ ? inArray(heartbeatRuns.status, ["queued", "running"])
567
+ : undefined;
568
+ const rows = await db
569
+ .select({
570
+ id: heartbeatRuns.id,
571
+ issueId: issueIdExpr,
572
+ agentId: heartbeatRuns.agentId,
573
+ status: heartbeatRuns.status,
574
+ invocationSource: heartbeatRuns.invocationSource,
575
+ triggerDetail: heartbeatRuns.triggerDetail,
576
+ startedAt: heartbeatRuns.startedAt,
577
+ finishedAt: heartbeatRuns.finishedAt,
578
+ error: heartbeatRuns.error,
579
+ createdAt: heartbeatRuns.createdAt,
580
+ })
581
+ .from(heartbeatRuns)
582
+ .where(and(eq(heartbeatRuns.squadId, squadId), inArray(issueIdExpr, issueIds), statusCondition))
583
+ .orderBy(desc(heartbeatRuns.createdAt))
584
+ .limit(100);
585
+ return rows.map((row) => ({
586
+ ...row,
587
+ startedAt: row.startedAt?.toISOString() ?? null,
588
+ finishedAt: row.finishedAt?.toISOString() ?? null,
589
+ createdAt: row.createdAt.toISOString(),
590
+ }));
591
+ };
592
+ const setBlockedByWithActivity = async (params) => {
593
+ const existing = requireInSquad("Issue", await issues.getById(params.issueId), params.squadId);
594
+ const previous = await issues.getRelationSummaries(params.issueId);
595
+ await issues.update(params.issueId, {
596
+ blockedByIssueIds: params.blockedByIssueIds,
597
+ actorAgentId: params.actorAgentId ?? null,
598
+ actorUserId: params.actorUserId ?? null,
599
+ });
600
+ const relations = await issues.getRelationSummaries(params.issueId);
601
+ await logPluginActivity({
602
+ squadId: params.squadId,
603
+ action: "issue.relations.updated",
604
+ entityType: "issue",
605
+ entityId: params.issueId,
606
+ actor: {
607
+ actorAgentId: params.actorAgentId,
608
+ actorUserId: params.actorUserId,
609
+ actorRunId: params.actorRunId,
610
+ },
611
+ details: {
612
+ identifier: existing.identifier,
613
+ mutation: params.mutation,
614
+ blockedByIssueIds: params.blockedByIssueIds,
615
+ previousBlockedByIssueIds: previous.blockedBy.map((relation) => relation.id),
616
+ },
617
+ });
618
+ return relations;
619
+ };
620
+ const getIssueCostSummary = async (squadId, issueIds, billingCode) => {
621
+ const scopeConditions = [
622
+ issueIds.length > 0 ? inArray(costEvents.issueId, issueIds) : undefined,
623
+ billingCode ? eq(costEvents.billingCode, billingCode) : undefined,
624
+ ].filter((condition) => Boolean(condition));
625
+ if (scopeConditions.length === 0) {
626
+ return {
627
+ costCents: 0,
628
+ inputTokens: 0,
629
+ cachedInputTokens: 0,
630
+ outputTokens: 0,
631
+ billingCode: billingCode ?? null,
632
+ };
633
+ }
634
+ const scopeCondition = scopeConditions.length === 1 ? scopeConditions[0] : and(...scopeConditions);
635
+ const [row] = await db
636
+ .select({
637
+ costCents: sql `coalesce(sum(${costEvents.costCents}), 0)::double precision`,
638
+ inputTokens: sql `coalesce(sum(${costEvents.inputTokens}), 0)::double precision`,
639
+ cachedInputTokens: sql `coalesce(sum(${costEvents.cachedInputTokens}), 0)::double precision`,
640
+ outputTokens: sql `coalesce(sum(${costEvents.outputTokens}), 0)::double precision`,
641
+ })
642
+ .from(costEvents)
643
+ .where(and(eq(costEvents.squadId, squadId), scopeCondition));
644
+ return {
645
+ costCents: Number(row?.costCents ?? 0),
646
+ inputTokens: Number(row?.inputTokens ?? 0),
647
+ cachedInputTokens: Number(row?.cachedInputTokens ?? 0),
648
+ outputTokens: Number(row?.outputTokens ?? 0),
649
+ billingCode: billingCode ?? null,
650
+ };
651
+ };
652
+ const getOpenBudgetIncidents = async (squadId) => {
653
+ const rows = await db
654
+ .select({
655
+ id: budgetIncidents.id,
656
+ scopeType: budgetIncidents.scopeType,
657
+ scopeId: budgetIncidents.scopeId,
658
+ metric: budgetIncidents.metric,
659
+ windowKind: budgetIncidents.windowKind,
660
+ thresholdType: budgetIncidents.thresholdType,
661
+ amountLimit: budgetIncidents.amountLimit,
662
+ amountObserved: budgetIncidents.amountObserved,
663
+ status: budgetIncidents.status,
664
+ approvalId: budgetIncidents.approvalId,
665
+ createdAt: budgetIncidents.createdAt,
666
+ })
667
+ .from(budgetIncidents)
668
+ .where(and(eq(budgetIncidents.squadId, squadId), eq(budgetIncidents.status, "open")))
669
+ .orderBy(desc(budgetIncidents.createdAt));
670
+ return rows.map((row) => ({
671
+ ...row,
672
+ createdAt: row.createdAt.toISOString(),
673
+ }));
674
+ };
675
+ const INVITE_TOKEN_PREFIX = "pcp_invite_";
676
+ const INVITE_TOKEN_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
677
+ const INVITE_TOKEN_SUFFIX_LENGTH = 8;
678
+ const INVITE_TOKEN_MAX_RETRIES = 5;
679
+ const SQUAD_INVITE_TTL_MS = 72 * 60 * 60 * 1000;
680
+ const hashToken = (token) => createHash("sha256").update(token).digest("hex");
681
+ const createInviteToken = () => {
682
+ const bytes = randomBytes(INVITE_TOKEN_SUFFIX_LENGTH);
683
+ let suffix = "";
684
+ for (let idx = 0; idx < INVITE_TOKEN_SUFFIX_LENGTH; idx += 1) {
685
+ suffix += INVITE_TOKEN_ALPHABET[bytes[idx] % INVITE_TOKEN_ALPHABET.length];
686
+ }
687
+ return `${INVITE_TOKEN_PREFIX}${suffix}`;
688
+ };
689
+ const isInviteTokenHashCollisionError = (error) => {
690
+ const candidates = [
691
+ error,
692
+ error?.cause ?? null,
693
+ ];
694
+ for (const candidate of candidates) {
695
+ if (!candidate || typeof candidate !== "object")
696
+ continue;
697
+ const code = "code" in candidate && typeof candidate.code === "string" ? candidate.code : null;
698
+ const message = "message" in candidate && typeof candidate.message === "string" ? candidate.message : "";
699
+ const constraint = "constraint" in candidate && typeof candidate.constraint === "string" ? candidate.constraint : null;
700
+ if (code !== "23505")
701
+ continue;
702
+ if (constraint === "invites_token_hash_unique_idx")
703
+ return true;
704
+ if (message.includes("invites_token_hash_unique_idx"))
705
+ return true;
706
+ }
707
+ return false;
708
+ };
709
+ const inviteState = (invite) => {
710
+ if (invite.revokedAt)
711
+ return "revoked";
712
+ if (invite.acceptedAt)
713
+ return "accepted";
714
+ if (invite.expiresAt <= new Date())
715
+ return "expired";
716
+ return "active";
717
+ };
718
+ const redactInvite = (invite) => {
719
+ const { tokenHash: _tokenHash, defaultsPayload, ...safeInvite } = invite;
720
+ return {
721
+ ...safeInvite,
722
+ allowedJoinTypes: safeInvite.allowedJoinTypes,
723
+ defaultsPayload: defaultsPayload && typeof defaultsPayload === "object"
724
+ ? sanitizeRecord(defaultsPayload)
725
+ : defaultsPayload ?? null,
726
+ state: inviteState(invite),
727
+ };
728
+ };
729
+ const inviteStateWhereClause = (state) => {
730
+ const now = new Date();
731
+ switch (state) {
732
+ case "active":
733
+ return and(isNull(invites.revokedAt), isNull(invites.acceptedAt), gt(invites.expiresAt, now));
734
+ case "accepted":
735
+ return isNotNull(invites.acceptedAt);
736
+ case "expired":
737
+ return and(isNull(invites.revokedAt), isNull(invites.acceptedAt), lte(invites.expiresAt, now));
738
+ case "revoked":
739
+ return isNotNull(invites.revokedAt);
740
+ default:
741
+ return undefined;
742
+ }
743
+ };
744
+ const mergeInviteDefaults = (defaultsPayload, agentMessage, humanRole) => {
745
+ const defaults = defaultsPayload && typeof defaultsPayload === "object"
746
+ ? { ...defaultsPayload }
747
+ : {};
748
+ if (humanRole) {
749
+ defaults.human = {
750
+ ...(typeof defaults.human === "object" && defaults.human !== null ? defaults.human : {}),
751
+ role: humanRole,
752
+ };
753
+ }
754
+ if (agentMessage) {
755
+ defaults.agent = {
756
+ ...(typeof defaults.agent === "object" && defaults.agent !== null ? defaults.agent : {}),
757
+ message: agentMessage,
758
+ };
759
+ }
760
+ return sanitizeRecord(defaults);
761
+ };
762
+ const redactGrant = (grant) => ({
763
+ ...grant,
764
+ principalType: grant.principalType,
765
+ permissionKey: grant.permissionKey,
766
+ scope: grant.scope && typeof grant.scope === "object" ? sanitizeRecord(grant.scope) : grant.scope ?? null,
767
+ });
768
+ const loadPluginMember = async (squadId, memberId) => {
769
+ const member = await access.getMemberById(squadId, memberId);
770
+ if (!member)
771
+ return null;
772
+ const grants = await access.listPrincipalGrants(squadId, member.principalType, member.principalId);
773
+ return {
774
+ ...member,
775
+ principalType: member.principalType,
776
+ status: member.status,
777
+ grants: grants.map(redactGrant),
778
+ };
779
+ };
780
+ const pluginAssignmentActor = (actor) => {
781
+ if (actor.type === "agent") {
782
+ return {
783
+ type: "agent",
784
+ agentId: actor.agentId ?? null,
785
+ squadId: actor.squadId ?? null,
786
+ source: "agent_key",
787
+ };
788
+ }
789
+ return {
790
+ type: "operator",
791
+ userId: actor.userId ?? null,
792
+ squadIds: Array.isArray(actor.squadIds) ? actor.squadIds : [],
793
+ source: "session",
794
+ };
795
+ };
796
+ const policyPathForResource = (resourceType) => {
797
+ switch (resourceType) {
798
+ case "agent":
799
+ return { table: "agent" };
800
+ case "project":
801
+ return { table: "project" };
802
+ case "issue":
803
+ return { table: "issue" };
804
+ case "squad":
805
+ return { table: "squad" };
806
+ }
807
+ };
808
+ const readAuthorizationPolicy = async (squadId, resourceType, resourceId) => {
809
+ const pathInfo = policyPathForResource(resourceType);
810
+ if (pathInfo.table === "agent") {
811
+ const agent = await agents.getById(resourceId);
812
+ if (!inSquad(agent, squadId))
813
+ return null;
814
+ const permissions = agent.permissions && typeof agent.permissions === "object" ? agent.permissions : {};
815
+ return {
816
+ resourceType,
817
+ resourceId,
818
+ squadId,
819
+ policy: permissions.authorizationPolicy && typeof permissions.authorizationPolicy === "object"
820
+ ? sanitizeRecord(permissions.authorizationPolicy)
821
+ : null,
822
+ updatedAt: agent.updatedAt,
823
+ };
824
+ }
825
+ if (pathInfo.table === "project") {
826
+ const project = await projects.getById(resourceId);
827
+ if (!inSquad(project, squadId))
828
+ return null;
829
+ const policy = project.executionWorkspacePolicy && typeof project.executionWorkspacePolicy === "object"
830
+ ? project.executionWorkspacePolicy.authorizationPolicy
831
+ : null;
832
+ return {
833
+ resourceType,
834
+ resourceId,
835
+ squadId,
836
+ policy: policy && typeof policy === "object" ? sanitizeRecord(policy) : null,
837
+ updatedAt: project.updatedAt,
838
+ };
839
+ }
840
+ if (pathInfo.table === "issue") {
841
+ const issue = await issues.getById(resourceId);
842
+ if (!inSquad(issue, squadId))
843
+ return null;
844
+ const policy = issue.executionPolicy && typeof issue.executionPolicy === "object"
845
+ ? issue.executionPolicy.authorizationPolicy
846
+ : null;
847
+ return {
848
+ resourceType,
849
+ resourceId,
850
+ squadId,
851
+ policy: policy && typeof policy === "object" ? sanitizeRecord(policy) : null,
852
+ updatedAt: issue.updatedAt,
853
+ };
854
+ }
855
+ const squad = await squads.getById(resourceId);
856
+ if (!squad || squad.id !== squadId)
857
+ return null;
858
+ return { resourceType, resourceId, squadId, policy: null, updatedAt: squad.updatedAt };
859
+ };
860
+ return {
861
+ config: {
862
+ async get() {
863
+ const configRow = await registry.getConfig(pluginId);
864
+ return configRow?.configJson ?? {};
865
+ },
866
+ },
867
+ localFolders: {
868
+ async declarations() {
869
+ return options.manifest?.localFolders ?? [];
870
+ },
871
+ async configure(params) {
872
+ const squadId = ensureSquadId(params.squadId);
873
+ await ensurePluginAvailableForSquad(squadId);
874
+ const declaration = getLocalFolderDeclaration(params.folderKey);
875
+ const existing = await registry.getSquadSettings(pluginId, squadId);
876
+ const existingConfig = getStoredLocalFolders(existing?.settingsJson)[params.folderKey] ?? null;
877
+ await preparePluginLocalFolder({
878
+ folderKey: params.folderKey,
879
+ declaration,
880
+ storedConfig: existingConfig,
881
+ overrideConfig: {
882
+ path: params.path,
883
+ },
884
+ });
885
+ const status = await inspectPluginLocalFolder({
886
+ folderKey: params.folderKey,
887
+ declaration,
888
+ storedConfig: existingConfig,
889
+ overrideConfig: {
890
+ path: params.path,
891
+ },
892
+ });
893
+ const nextSettings = setStoredLocalFolder(existing?.settingsJson, params.folderKey, {
894
+ path: params.path,
895
+ access: status.access,
896
+ requiredDirectories: status.requiredDirectories,
897
+ requiredFiles: status.requiredFiles,
898
+ });
899
+ await registry.upsertSquadSettings(pluginId, squadId, {
900
+ enabled: existing?.enabled ?? true,
901
+ settingsJson: nextSettings,
902
+ lastError: status.healthy ? null : status.problems.map((item) => item.message).join("; "),
903
+ });
904
+ return status;
905
+ },
906
+ async status(params) {
907
+ return inspectStoredLocalFolder(params.squadId, params.folderKey);
908
+ },
909
+ async list(params) {
910
+ const status = await inspectStoredLocalFolder(params.squadId, params.folderKey);
911
+ assertConfiguredLocalFolder(status);
912
+ const listing = await listPluginLocalFolderEntries(status.realPath, {
913
+ relativePath: params.relativePath,
914
+ recursive: params.recursive,
915
+ maxEntries: params.maxEntries,
916
+ });
917
+ return { ...listing, folderKey: params.folderKey };
918
+ },
919
+ async readText(params) {
920
+ const status = await inspectStoredLocalFolder(params.squadId, params.folderKey);
921
+ assertConfiguredLocalFolder(status);
922
+ return readPluginLocalFolderText(status.realPath, params.relativePath);
923
+ },
924
+ async writeTextAtomic(params) {
925
+ const squadId = ensureSquadId(params.squadId);
926
+ await preparePluginLocalFolder({
927
+ folderKey: params.folderKey,
928
+ declaration: getLocalFolderDeclaration(params.folderKey),
929
+ storedConfig: await getStoredLocalFolderConfig(squadId, params.folderKey),
930
+ });
931
+ const status = await inspectStoredLocalFolder(squadId, params.folderKey);
932
+ assertWritableConfiguredLocalFolder(status);
933
+ await writePluginLocalFolderTextAtomic(status.realPath, params.relativePath, params.contents);
934
+ return inspectStoredLocalFolder(squadId, params.folderKey);
935
+ },
936
+ async deleteFile(params) {
937
+ const squadId = ensureSquadId(params.squadId);
938
+ const status = await inspectStoredLocalFolder(squadId, params.folderKey);
939
+ assertWritableConfiguredLocalFolder(status);
940
+ await deletePluginLocalFolderFile(status.realPath, params.relativePath, params.folderKey);
941
+ return inspectStoredLocalFolder(squadId, params.folderKey);
942
+ },
943
+ },
944
+ state: {
945
+ async get(params) {
946
+ return stateStore.get(pluginId, params.scopeKind, params.stateKey, {
947
+ scopeId: params.scopeId,
948
+ namespace: params.namespace,
949
+ });
950
+ },
951
+ async set(params) {
952
+ await stateStore.set(pluginId, {
953
+ scopeKind: params.scopeKind,
954
+ scopeId: params.scopeId,
955
+ namespace: params.namespace,
956
+ stateKey: params.stateKey,
957
+ value: params.value,
958
+ });
959
+ },
960
+ async delete(params) {
961
+ await stateStore.delete(pluginId, params.scopeKind, params.stateKey, {
962
+ scopeId: params.scopeId,
963
+ namespace: params.namespace,
964
+ });
965
+ },
966
+ },
967
+ db: {
968
+ async namespace() {
969
+ return pluginDb.getRuntimeNamespace(pluginId);
970
+ },
971
+ async query(params) {
972
+ return pluginDb.query(pluginId, params.sql, params.params);
973
+ },
974
+ async execute(params) {
975
+ return pluginDb.execute(pluginId, params.sql, params.params);
976
+ },
977
+ },
978
+ entities: {
979
+ async upsert(params) {
980
+ return registry.upsertEntity(pluginId, params);
981
+ },
982
+ async list(params) {
983
+ return registry.listEntities(pluginId, params);
984
+ },
985
+ },
986
+ events: {
987
+ async emit(params) {
988
+ if (params.squadId) {
989
+ await ensurePluginAvailableForSquad(params.squadId);
990
+ }
991
+ await scopedBus.emit(params.name, params.squadId, params.payload);
992
+ },
993
+ async subscribe(params) {
994
+ const handler = async (event) => {
995
+ if (notifyWorker) {
996
+ notifyWorker("onEvent", { event });
997
+ }
998
+ };
999
+ if (params.filter) {
1000
+ scopedBus.subscribe(params.eventPattern, params.filter, handler);
1001
+ }
1002
+ else {
1003
+ scopedBus.subscribe(params.eventPattern, handler);
1004
+ }
1005
+ },
1006
+ },
1007
+ http: {
1008
+ async fetch(params) {
1009
+ // SSRF protection: validate protocol whitelist + block private IPs.
1010
+ // Resolve once, then connect directly to that IP to prevent DNS rebinding.
1011
+ const target = await validateAndResolveFetchUrl(params.url);
1012
+ const controller = new AbortController();
1013
+ const timeout = setTimeout(() => controller.abort(), PLUGIN_FETCH_TIMEOUT_MS);
1014
+ try {
1015
+ const init = params.init;
1016
+ return await executePinnedHttpRequest(target, init, controller.signal);
1017
+ }
1018
+ finally {
1019
+ clearTimeout(timeout);
1020
+ }
1021
+ },
1022
+ },
1023
+ secrets: {
1024
+ async resolve(params) {
1025
+ return secretsHandler.resolve(params);
1026
+ },
1027
+ },
1028
+ activity: {
1029
+ async log(params) {
1030
+ const squadId = ensureSquadId(params.squadId);
1031
+ await ensurePluginAvailableForSquad(squadId);
1032
+ await logActivity(db, {
1033
+ squadId,
1034
+ actorType: "plugin",
1035
+ actorId: pluginId,
1036
+ action: params.message,
1037
+ entityType: params.entityType ?? "plugin",
1038
+ entityId: params.entityId ?? pluginId,
1039
+ details: pluginActivityDetails(params.metadata),
1040
+ });
1041
+ },
1042
+ },
1043
+ metrics: {
1044
+ async write(params) {
1045
+ const safeName = truncStr(String(params.name ?? ""), MAX_METRIC_NAME_LENGTH);
1046
+ logger.debug({ pluginId, name: safeName, value: params.value, tags: params.tags }, "Plugin metric write");
1047
+ // Persist metrics to plugin_logs via the batch buffer (same path as
1048
+ // logger.log) so they benefit from batched writes and are flushed
1049
+ // reliably on shutdown. Using level "metric" makes them queryable
1050
+ // alongside regular logs via the same API (§26).
1051
+ _logBuffer.push({
1052
+ db,
1053
+ pluginId,
1054
+ level: "metric",
1055
+ message: safeName,
1056
+ meta: sanitiseMeta({ value: params.value, tags: params.tags ?? null }),
1057
+ });
1058
+ if (_logBuffer.length >= LOG_BUFFER_FLUSH_SIZE) {
1059
+ flushPluginLogBuffer().catch((err) => {
1060
+ console.error("[plugin-host-services] Triggered metric flush failed:", err);
1061
+ });
1062
+ }
1063
+ },
1064
+ },
1065
+ logger: {
1066
+ async log(params) {
1067
+ const { level, meta } = params;
1068
+ const safeMessage = truncStr(String(params.message ?? ""), MAX_LOG_MESSAGE_LENGTH);
1069
+ const safeMeta = sanitiseMeta(meta);
1070
+ const pluginLogger = logger.child({ service: "plugin-worker", pluginId });
1071
+ const logFields = {
1072
+ ...safeMeta,
1073
+ pluginLogLevel: level,
1074
+ pluginTimestamp: new Date().toISOString(),
1075
+ };
1076
+ if (level === "error")
1077
+ pluginLogger.error(logFields, `[plugin] ${safeMessage}`);
1078
+ else if (level === "warn")
1079
+ pluginLogger.warn(logFields, `[plugin] ${safeMessage}`);
1080
+ else if (level === "debug")
1081
+ pluginLogger.debug(logFields, `[plugin] ${safeMessage}`);
1082
+ else
1083
+ pluginLogger.info(logFields, `[plugin] ${safeMessage}`);
1084
+ // Persist to plugin_logs table via the module-level batch buffer (§26.1).
1085
+ // Fire-and-forget — logging should never block the worker.
1086
+ _logBuffer.push({
1087
+ db,
1088
+ pluginId,
1089
+ level: level ?? "info",
1090
+ message: safeMessage,
1091
+ meta: safeMeta,
1092
+ });
1093
+ if (_logBuffer.length >= LOG_BUFFER_FLUSH_SIZE) {
1094
+ flushPluginLogBuffer().catch((err) => {
1095
+ console.error("[plugin-host-services] Triggered log flush failed:", err);
1096
+ });
1097
+ }
1098
+ },
1099
+ },
1100
+ squads: {
1101
+ async list(params) {
1102
+ return applyWindow((await squads.list()), params);
1103
+ },
1104
+ async get(params) {
1105
+ await ensurePluginAvailableForSquad(params.squadId);
1106
+ return (await squads.getById(params.squadId));
1107
+ },
1108
+ },
1109
+ projects: {
1110
+ async list(params) {
1111
+ const squadId = ensureSquadId(params.squadId);
1112
+ await ensurePluginAvailableForSquad(squadId);
1113
+ return applyWindow((await projects.list(squadId)), params);
1114
+ },
1115
+ async get(params) {
1116
+ const squadId = ensureSquadId(params.squadId);
1117
+ await ensurePluginAvailableForSquad(squadId);
1118
+ const project = await projects.getById(params.projectId);
1119
+ return (inSquad(project, squadId) ? project : null);
1120
+ },
1121
+ async listWorkspaces(params) {
1122
+ const squadId = ensureSquadId(params.squadId);
1123
+ await ensurePluginAvailableForSquad(squadId);
1124
+ const project = await projects.getById(params.projectId);
1125
+ if (!inSquad(project, squadId))
1126
+ return [];
1127
+ const rows = await projects.listWorkspaces(params.projectId);
1128
+ return rows.map((row) => {
1129
+ const path = sanitizeWorkspacePath(row.cwd);
1130
+ const name = sanitizeWorkspaceName(row.name, path);
1131
+ return {
1132
+ id: row.id,
1133
+ projectId: row.projectId,
1134
+ name,
1135
+ path,
1136
+ repoUrl: row.repoUrl,
1137
+ repoRef: row.repoRef,
1138
+ defaultRef: row.defaultRef,
1139
+ isPrimary: row.isPrimary,
1140
+ createdAt: row.createdAt.toISOString(),
1141
+ updatedAt: row.updatedAt.toISOString(),
1142
+ };
1143
+ });
1144
+ },
1145
+ async getPrimaryWorkspace(params) {
1146
+ const squadId = ensureSquadId(params.squadId);
1147
+ await ensurePluginAvailableForSquad(squadId);
1148
+ const project = await projects.getById(params.projectId);
1149
+ if (!inSquad(project, squadId))
1150
+ return null;
1151
+ const row = project.primaryWorkspace;
1152
+ const path = sanitizeWorkspacePath(project.codebase.effectiveLocalFolder);
1153
+ const name = sanitizeWorkspaceName(row?.name ?? project.name, path);
1154
+ return {
1155
+ id: row?.id ?? `${project.id}:managed`,
1156
+ projectId: project.id,
1157
+ name,
1158
+ path,
1159
+ repoUrl: row?.repoUrl ?? project.codebase.repoUrl,
1160
+ repoRef: row?.repoRef ?? project.codebase.repoRef,
1161
+ defaultRef: row?.defaultRef ?? project.codebase.defaultRef,
1162
+ isPrimary: true,
1163
+ createdAt: (row?.createdAt ?? project.createdAt).toISOString(),
1164
+ updatedAt: (row?.updatedAt ?? project.updatedAt).toISOString(),
1165
+ };
1166
+ },
1167
+ async getWorkspaceForIssue(params) {
1168
+ const squadId = ensureSquadId(params.squadId);
1169
+ await ensurePluginAvailableForSquad(squadId);
1170
+ const issue = await issues.getById(params.issueId);
1171
+ if (!inSquad(issue, squadId))
1172
+ return null;
1173
+ const projectId = issue.projectId;
1174
+ if (!projectId)
1175
+ return null;
1176
+ const project = await projects.getById(projectId);
1177
+ if (!inSquad(project, squadId))
1178
+ return null;
1179
+ const row = project.primaryWorkspace;
1180
+ const path = sanitizeWorkspacePath(project.codebase.effectiveLocalFolder);
1181
+ const name = sanitizeWorkspaceName(row?.name ?? project.name, path);
1182
+ return {
1183
+ id: row?.id ?? `${project.id}:managed`,
1184
+ projectId: project.id,
1185
+ name,
1186
+ path,
1187
+ repoUrl: row?.repoUrl ?? project.codebase.repoUrl,
1188
+ repoRef: row?.repoRef ?? project.codebase.repoRef,
1189
+ defaultRef: row?.defaultRef ?? project.codebase.defaultRef,
1190
+ isPrimary: true,
1191
+ createdAt: (row?.createdAt ?? project.createdAt).toISOString(),
1192
+ updatedAt: (row?.updatedAt ?? project.updatedAt).toISOString(),
1193
+ };
1194
+ },
1195
+ async getManaged(params) {
1196
+ const squadId = ensureSquadId(params.squadId);
1197
+ await ensurePluginAvailableForSquad(squadId);
1198
+ return projects.resolveManagedProject({
1199
+ squadId,
1200
+ pluginId,
1201
+ pluginKey,
1202
+ projectKey: params.projectKey,
1203
+ createIfMissing: false,
1204
+ });
1205
+ },
1206
+ async reconcileManaged(params) {
1207
+ const squadId = ensureSquadId(params.squadId);
1208
+ await ensurePluginAvailableForSquad(squadId);
1209
+ return projects.resolveManagedProject({
1210
+ squadId,
1211
+ pluginId,
1212
+ pluginKey,
1213
+ projectKey: params.projectKey,
1214
+ });
1215
+ },
1216
+ async resetManaged(params) {
1217
+ const squadId = ensureSquadId(params.squadId);
1218
+ await ensurePluginAvailableForSquad(squadId);
1219
+ return projects.resolveManagedProject({
1220
+ squadId,
1221
+ pluginId,
1222
+ pluginKey,
1223
+ projectKey: params.projectKey,
1224
+ reset: true,
1225
+ });
1226
+ },
1227
+ },
1228
+ executionWorkspaces: {
1229
+ async get(params) {
1230
+ const squadId = ensureSquadId(params.squadId);
1231
+ await ensurePluginAvailableForSquad(squadId);
1232
+ const workspace = await executionWorkspaces.getById(params.workspaceId);
1233
+ if (inSquad(workspace, squadId)) {
1234
+ return toPluginExecutionWorkspaceMetadata(workspace);
1235
+ }
1236
+ return null;
1237
+ },
1238
+ },
1239
+ routines: {
1240
+ async managedGet(params) {
1241
+ const squadId = ensureSquadId(params.squadId);
1242
+ await ensurePluginAvailableForSquad(squadId);
1243
+ return managedRoutines.get(params.routineKey, squadId);
1244
+ },
1245
+ async managedReconcile(params) {
1246
+ const squadId = ensureSquadId(params.squadId);
1247
+ await ensurePluginAvailableForSquad(squadId);
1248
+ return managedRoutines.reconcile(params.routineKey, squadId, {
1249
+ assigneeAgentId: params.assigneeAgentId,
1250
+ projectId: params.projectId,
1251
+ });
1252
+ },
1253
+ async managedReset(params) {
1254
+ const squadId = ensureSquadId(params.squadId);
1255
+ await ensurePluginAvailableForSquad(squadId);
1256
+ return managedRoutines.reset(params.routineKey, squadId, {
1257
+ assigneeAgentId: params.assigneeAgentId,
1258
+ projectId: params.projectId,
1259
+ });
1260
+ },
1261
+ async managedUpdate(params) {
1262
+ const squadId = ensureSquadId(params.squadId);
1263
+ await ensurePluginAvailableForSquad(squadId);
1264
+ return managedRoutines.update(params.routineKey, squadId, {
1265
+ status: params.status,
1266
+ });
1267
+ },
1268
+ async managedRun(params) {
1269
+ const squadId = ensureSquadId(params.squadId);
1270
+ await ensurePluginAvailableForSquad(squadId);
1271
+ return managedRoutines.run(params.routineKey, squadId, {
1272
+ assigneeAgentId: params.assigneeAgentId,
1273
+ projectId: params.projectId,
1274
+ });
1275
+ },
1276
+ },
1277
+ skills: {
1278
+ async managedGet(params) {
1279
+ const squadId = ensureSquadId(params.squadId);
1280
+ await ensurePluginAvailableForSquad(squadId);
1281
+ return managedSkills.get(params.skillKey, squadId);
1282
+ },
1283
+ async managedReconcile(params) {
1284
+ const squadId = ensureSquadId(params.squadId);
1285
+ await ensurePluginAvailableForSquad(squadId);
1286
+ return managedSkills.reconcile(params.skillKey, squadId);
1287
+ },
1288
+ async managedReset(params) {
1289
+ const squadId = ensureSquadId(params.squadId);
1290
+ await ensurePluginAvailableForSquad(squadId);
1291
+ return managedSkills.reset(params.skillKey, squadId);
1292
+ },
1293
+ },
1294
+ issues: {
1295
+ async list(params) {
1296
+ const squadId = ensureSquadId(params.squadId);
1297
+ await ensurePluginAvailableForSquad(squadId);
1298
+ assertReadableOriginFilter(params.originKind);
1299
+ return applyWindow((await issues.list(squadId, params)), params);
1300
+ },
1301
+ async get(params) {
1302
+ const squadId = ensureSquadId(params.squadId);
1303
+ await ensurePluginAvailableForSquad(squadId);
1304
+ const issue = await issues.getById(params.issueId);
1305
+ return (inSquad(issue, squadId) ? issue : null);
1306
+ },
1307
+ async create(params) {
1308
+ const squadId = ensureSquadId(params.squadId);
1309
+ await ensurePluginAvailableForSquad(squadId);
1310
+ const { actorAgentId, actorUserId, actorRunId, originKind, surfaceVisibility, ...issueInput } = params;
1311
+ const normalizedOriginKind = normalizePluginOriginKind(surfaceVisibility === "plugin_operation" && !originKind
1312
+ ? pluginOperationIssueOriginKind(pluginKey)
1313
+ : originKind);
1314
+ const issue = (await issues.create(squadId, {
1315
+ ...issueInput,
1316
+ originKind: normalizedOriginKind,
1317
+ originId: params.originId ?? null,
1318
+ originRunId: params.originRunId ?? actorRunId ?? null,
1319
+ createdByAgentId: actorAgentId ?? null,
1320
+ createdByUserId: actorUserId ?? null,
1321
+ }));
1322
+ await logPluginActivity({
1323
+ squadId,
1324
+ action: "issue.created",
1325
+ entityType: "issue",
1326
+ entityId: issue.id,
1327
+ actor: { actorAgentId, actorUserId, actorRunId },
1328
+ details: {
1329
+ title: issue.title,
1330
+ identifier: issue.identifier,
1331
+ originKind: normalizedOriginKind,
1332
+ originId: issue.originId,
1333
+ billingCode: issue.billingCode,
1334
+ blockedByIssueIds: params.blockedByIssueIds ?? [],
1335
+ },
1336
+ });
1337
+ return issue;
1338
+ },
1339
+ async update(params) {
1340
+ const squadId = ensureSquadId(params.squadId);
1341
+ await ensurePluginAvailableForSquad(squadId);
1342
+ const existing = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1343
+ const patch = { ...params.patch };
1344
+ const actorAgentId = typeof patch.actorAgentId === "string" ? patch.actorAgentId : null;
1345
+ const actorUserId = typeof patch.actorUserId === "string" ? patch.actorUserId : null;
1346
+ const actorRunId = typeof patch.actorRunId === "string" ? patch.actorRunId : null;
1347
+ delete patch.actorAgentId;
1348
+ delete patch.actorUserId;
1349
+ delete patch.actorRunId;
1350
+ if (patch.originKind !== undefined) {
1351
+ patch.originKind = normalizePluginOriginKind(patch.originKind);
1352
+ }
1353
+ const updated = (await issues.update(params.issueId, {
1354
+ ...patch,
1355
+ actorAgentId,
1356
+ actorUserId,
1357
+ }));
1358
+ await logPluginActivity({
1359
+ squadId,
1360
+ action: "issue.updated",
1361
+ entityType: "issue",
1362
+ entityId: updated.id,
1363
+ actor: { actorAgentId, actorUserId, actorRunId },
1364
+ details: {
1365
+ identifier: updated.identifier,
1366
+ patch,
1367
+ _previous: {
1368
+ status: existing.status,
1369
+ assigneeAgentId: existing.assigneeAgentId,
1370
+ assigneeUserId: existing.assigneeUserId,
1371
+ },
1372
+ },
1373
+ });
1374
+ return updated;
1375
+ },
1376
+ async getRelations(params) {
1377
+ const squadId = ensureSquadId(params.squadId);
1378
+ await ensurePluginAvailableForSquad(squadId);
1379
+ requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1380
+ return await issues.getRelationSummaries(params.issueId);
1381
+ },
1382
+ async setBlockedBy(params) {
1383
+ const squadId = ensureSquadId(params.squadId);
1384
+ await ensurePluginAvailableForSquad(squadId);
1385
+ return setBlockedByWithActivity({
1386
+ squadId,
1387
+ issueId: params.issueId,
1388
+ blockedByIssueIds: params.blockedByIssueIds,
1389
+ mutation: "set",
1390
+ actorAgentId: params.actorAgentId,
1391
+ actorUserId: params.actorUserId,
1392
+ actorRunId: params.actorRunId,
1393
+ });
1394
+ },
1395
+ async addBlockers(params) {
1396
+ const squadId = ensureSquadId(params.squadId);
1397
+ await ensurePluginAvailableForSquad(squadId);
1398
+ requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1399
+ const previous = await issues.getRelationSummaries(params.issueId);
1400
+ const nextBlockedByIssueIds = [
1401
+ ...new Set([
1402
+ ...previous.blockedBy.map((relation) => relation.id),
1403
+ ...params.blockerIssueIds,
1404
+ ]),
1405
+ ];
1406
+ return setBlockedByWithActivity({
1407
+ squadId,
1408
+ issueId: params.issueId,
1409
+ blockedByIssueIds: nextBlockedByIssueIds,
1410
+ mutation: "add",
1411
+ actorAgentId: params.actorAgentId,
1412
+ actorUserId: params.actorUserId,
1413
+ actorRunId: params.actorRunId,
1414
+ });
1415
+ },
1416
+ async removeBlockers(params) {
1417
+ const squadId = ensureSquadId(params.squadId);
1418
+ await ensurePluginAvailableForSquad(squadId);
1419
+ requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1420
+ const previous = await issues.getRelationSummaries(params.issueId);
1421
+ const removals = new Set(params.blockerIssueIds);
1422
+ const nextBlockedByIssueIds = previous.blockedBy
1423
+ .map((relation) => relation.id)
1424
+ .filter((issueId) => !removals.has(issueId));
1425
+ return setBlockedByWithActivity({
1426
+ squadId,
1427
+ issueId: params.issueId,
1428
+ blockedByIssueIds: nextBlockedByIssueIds,
1429
+ mutation: "remove",
1430
+ actorAgentId: params.actorAgentId,
1431
+ actorUserId: params.actorUserId,
1432
+ actorRunId: params.actorRunId,
1433
+ });
1434
+ },
1435
+ async assertCheckoutOwner(params) {
1436
+ const squadId = ensureSquadId(params.squadId);
1437
+ await ensurePluginAvailableForSquad(squadId);
1438
+ requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1439
+ const ownership = await issues.assertCheckoutOwner(params.issueId, params.actorAgentId, params.actorRunId);
1440
+ if (ownership.adoptedFromRunId) {
1441
+ await logPluginActivity({
1442
+ squadId,
1443
+ action: "issue.checkout_lock_adopted",
1444
+ entityType: "issue",
1445
+ entityId: params.issueId,
1446
+ actor: {
1447
+ actorAgentId: params.actorAgentId,
1448
+ actorRunId: params.actorRunId,
1449
+ },
1450
+ details: {
1451
+ previousCheckoutRunId: ownership.adoptedFromRunId,
1452
+ checkoutRunId: params.actorRunId,
1453
+ reason: "stale_checkout_run",
1454
+ },
1455
+ });
1456
+ }
1457
+ return {
1458
+ issueId: ownership.id,
1459
+ status: ownership.status,
1460
+ assigneeAgentId: ownership.assigneeAgentId,
1461
+ checkoutRunId: ownership.checkoutRunId,
1462
+ adoptedFromRunId: ownership.adoptedFromRunId,
1463
+ };
1464
+ },
1465
+ async getSubtree(params) {
1466
+ const squadId = ensureSquadId(params.squadId);
1467
+ await ensurePluginAvailableForSquad(squadId);
1468
+ const rootIssue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1469
+ const includeRoot = params.includeRoot !== false;
1470
+ const subtreeIssueIds = await collectIssueSubtreeIds(squadId, rootIssue.id);
1471
+ const issueIds = includeRoot ? subtreeIssueIds : subtreeIssueIds.filter((issueId) => issueId !== rootIssue.id);
1472
+ const issueRows = issueIds.length > 0
1473
+ ? await db
1474
+ .select()
1475
+ .from(issuesTable)
1476
+ .where(and(eq(issuesTable.squadId, squadId), inArray(issuesTable.id, issueIds)))
1477
+ : [];
1478
+ const issuesById = new Map(issueRows.map((issue) => [issue.id, issue]));
1479
+ const outputIssues = issueIds
1480
+ .map((issueId) => issuesById.get(issueId))
1481
+ .filter((issue) => Boolean(issue));
1482
+ const assigneeAgentIds = [
1483
+ ...new Set(outputIssues.map((issue) => issue.assigneeAgentId).filter((id) => Boolean(id))),
1484
+ ];
1485
+ const [relationPairs, documentPairs, activeRunRows, assigneeRows] = await Promise.all([
1486
+ params.includeRelations
1487
+ ? Promise.all(issueIds.map(async (issueId) => [issueId, await issues.getRelationSummaries(issueId)]))
1488
+ : Promise.resolve(null),
1489
+ params.includeDocuments
1490
+ ? Promise.all(issueIds.map(async (issueId) => {
1491
+ const docs = await documents.listIssueDocuments(issueId);
1492
+ const summaries = docs.map((document) => {
1493
+ const { body: _body, ...summary } = document;
1494
+ return { ...summary, format: "markdown" };
1495
+ });
1496
+ return [
1497
+ issueId,
1498
+ summaries,
1499
+ ];
1500
+ }))
1501
+ : Promise.resolve(null),
1502
+ params.includeActiveRuns
1503
+ ? getIssueRunSummaries(squadId, issueIds, { activeOnly: true })
1504
+ : Promise.resolve(null),
1505
+ params.includeAssignees && assigneeAgentIds.length > 0
1506
+ ? db
1507
+ .select({
1508
+ id: agentsTable.id,
1509
+ name: agentsTable.name,
1510
+ role: agentsTable.role,
1511
+ title: agentsTable.title,
1512
+ status: agentsTable.status,
1513
+ })
1514
+ .from(agentsTable)
1515
+ .where(and(eq(agentsTable.squadId, squadId), inArray(agentsTable.id, assigneeAgentIds)))
1516
+ : Promise.resolve(params.includeAssignees ? [] : null),
1517
+ ]);
1518
+ const activeRuns = activeRunRows
1519
+ ? Object.fromEntries(issueIds.map((issueId) => [
1520
+ issueId,
1521
+ activeRunRows.filter((run) => run.issueId === issueId),
1522
+ ]))
1523
+ : undefined;
1524
+ return {
1525
+ rootIssueId: rootIssue.id,
1526
+ squadId,
1527
+ issueIds,
1528
+ issues: outputIssues,
1529
+ ...(relationPairs ? { relations: Object.fromEntries(relationPairs) } : {}),
1530
+ ...(documentPairs ? { documents: Object.fromEntries(documentPairs) } : {}),
1531
+ ...(activeRuns ? { activeRuns } : {}),
1532
+ ...(assigneeRows
1533
+ ? {
1534
+ assignees: Object.fromEntries(assigneeRows.map((agent) => [
1535
+ agent.id,
1536
+ { ...agent, status: agent.status },
1537
+ ])),
1538
+ }
1539
+ : {}),
1540
+ };
1541
+ },
1542
+ async requestWakeup(params) {
1543
+ const squadId = ensureSquadId(params.squadId);
1544
+ await ensurePluginAvailableForSquad(squadId);
1545
+ const issue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1546
+ if (!issue.assigneeAgentId) {
1547
+ throw new Error("Issue has no assigned agent to wake");
1548
+ }
1549
+ if (["backlog", "done", "cancelled"].includes(issue.status)) {
1550
+ throw new Error(`Issue is not wakeable in status: ${issue.status}`);
1551
+ }
1552
+ const relations = await issues.getRelationSummaries(issue.id);
1553
+ const unresolvedBlockers = relations.blockedBy.filter((blocker) => blocker.status !== "done");
1554
+ if (unresolvedBlockers.length > 0) {
1555
+ throw new Error("Issue is blocked by unresolved blockers");
1556
+ }
1557
+ const budgetBlock = await budgets.getInvocationBlock(squadId, issue.assigneeAgentId, {
1558
+ issueId: issue.id,
1559
+ projectId: issue.projectId,
1560
+ });
1561
+ if (budgetBlock) {
1562
+ throw new Error(budgetBlock.reason);
1563
+ }
1564
+ const contextSource = params.contextSource ?? "plugin.issue.requestWakeup";
1565
+ const run = await heartbeat.wakeup(issue.assigneeAgentId, {
1566
+ source: "assignment",
1567
+ triggerDetail: "system",
1568
+ reason: params.reason ?? "plugin_issue_wakeup_requested",
1569
+ payload: {
1570
+ issueId: issue.id,
1571
+ mutation: "plugin_wakeup",
1572
+ pluginId,
1573
+ pluginKey,
1574
+ contextSource,
1575
+ },
1576
+ idempotencyKey: params.idempotencyKey ?? null,
1577
+ requestedByActorType: "system",
1578
+ requestedByActorId: pluginId,
1579
+ contextSnapshot: {
1580
+ issueId: issue.id,
1581
+ taskId: issue.id,
1582
+ wakeReason: params.reason ?? "plugin_issue_wakeup_requested",
1583
+ source: contextSource,
1584
+ pluginId,
1585
+ pluginKey,
1586
+ },
1587
+ });
1588
+ await logPluginActivity({
1589
+ squadId,
1590
+ action: "issue.assignment_wakeup_requested",
1591
+ entityType: "issue",
1592
+ entityId: issue.id,
1593
+ actor: {
1594
+ actorAgentId: params.actorAgentId,
1595
+ actorUserId: params.actorUserId,
1596
+ actorRunId: params.actorRunId,
1597
+ },
1598
+ details: {
1599
+ identifier: issue.identifier,
1600
+ assigneeAgentId: issue.assigneeAgentId,
1601
+ runId: run?.id ?? null,
1602
+ reason: params.reason ?? "plugin_issue_wakeup_requested",
1603
+ contextSource,
1604
+ },
1605
+ });
1606
+ return { queued: Boolean(run), runId: run?.id ?? null };
1607
+ },
1608
+ async requestWakeups(params) {
1609
+ const squadId = ensureSquadId(params.squadId);
1610
+ await ensurePluginAvailableForSquad(squadId);
1611
+ const results = [];
1612
+ for (const issueId of [...new Set(params.issueIds)]) {
1613
+ const issue = requireInSquad("Issue", await issues.getById(issueId), squadId);
1614
+ if (!issue.assigneeAgentId) {
1615
+ throw new Error("Issue has no assigned agent to wake");
1616
+ }
1617
+ if (["backlog", "done", "cancelled"].includes(issue.status)) {
1618
+ throw new Error(`Issue is not wakeable in status: ${issue.status}`);
1619
+ }
1620
+ const relations = await issues.getRelationSummaries(issue.id);
1621
+ const unresolvedBlockers = relations.blockedBy.filter((blocker) => blocker.status !== "done");
1622
+ if (unresolvedBlockers.length > 0) {
1623
+ throw new Error("Issue is blocked by unresolved blockers");
1624
+ }
1625
+ const budgetBlock = await budgets.getInvocationBlock(squadId, issue.assigneeAgentId, {
1626
+ issueId: issue.id,
1627
+ projectId: issue.projectId,
1628
+ });
1629
+ if (budgetBlock) {
1630
+ throw new Error(budgetBlock.reason);
1631
+ }
1632
+ const contextSource = params.contextSource ?? "plugin.issue.requestWakeups";
1633
+ const run = await heartbeat.wakeup(issue.assigneeAgentId, {
1634
+ source: "assignment",
1635
+ triggerDetail: "system",
1636
+ reason: params.reason ?? "plugin_issue_wakeup_requested",
1637
+ payload: {
1638
+ issueId: issue.id,
1639
+ mutation: "plugin_wakeup",
1640
+ pluginId,
1641
+ pluginKey,
1642
+ contextSource,
1643
+ },
1644
+ idempotencyKey: params.idempotencyKeyPrefix ? `${params.idempotencyKeyPrefix}:${issue.id}` : null,
1645
+ requestedByActorType: "system",
1646
+ requestedByActorId: pluginId,
1647
+ contextSnapshot: {
1648
+ issueId: issue.id,
1649
+ taskId: issue.id,
1650
+ wakeReason: params.reason ?? "plugin_issue_wakeup_requested",
1651
+ source: contextSource,
1652
+ pluginId,
1653
+ pluginKey,
1654
+ },
1655
+ });
1656
+ await logPluginActivity({
1657
+ squadId,
1658
+ action: "issue.assignment_wakeup_requested",
1659
+ entityType: "issue",
1660
+ entityId: issue.id,
1661
+ actor: {
1662
+ actorAgentId: params.actorAgentId,
1663
+ actorUserId: params.actorUserId,
1664
+ actorRunId: params.actorRunId,
1665
+ },
1666
+ details: {
1667
+ identifier: issue.identifier,
1668
+ assigneeAgentId: issue.assigneeAgentId,
1669
+ runId: run?.id ?? null,
1670
+ reason: params.reason ?? "plugin_issue_wakeup_requested",
1671
+ contextSource,
1672
+ },
1673
+ });
1674
+ results.push({ issueId: issue.id, queued: Boolean(run), runId: run?.id ?? null });
1675
+ }
1676
+ return results;
1677
+ },
1678
+ async getOrchestrationSummary(params) {
1679
+ const squadId = ensureSquadId(params.squadId);
1680
+ await ensurePluginAvailableForSquad(squadId);
1681
+ const rootIssue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1682
+ const subtreeIssueIds = params.includeSubtree
1683
+ ? await collectIssueSubtreeIds(squadId, rootIssue.id)
1684
+ : [rootIssue.id];
1685
+ const relationPairs = await Promise.all(subtreeIssueIds.map(async (issueId) => [issueId, await issues.getRelationSummaries(issueId)]));
1686
+ const approvalRows = (await Promise.all(subtreeIssueIds.map(async (issueId) => {
1687
+ const rows = await issueApprovals.listApprovalsForIssue(issueId);
1688
+ return rows.map((approval) => ({
1689
+ issueId,
1690
+ id: approval.id,
1691
+ type: approval.type,
1692
+ status: approval.status,
1693
+ requestedByAgentId: approval.requestedByAgentId,
1694
+ requestedByUserId: approval.requestedByUserId,
1695
+ decidedByUserId: approval.decidedByUserId,
1696
+ decidedAt: approval.decidedAt?.toISOString() ?? null,
1697
+ createdAt: approval.createdAt.toISOString(),
1698
+ }));
1699
+ }))).flat();
1700
+ const [runs, costsSummary, openBudgetIncidents] = await Promise.all([
1701
+ getIssueRunSummaries(squadId, subtreeIssueIds),
1702
+ getIssueCostSummary(squadId, subtreeIssueIds, params.billingCode ?? rootIssue.billingCode ?? null),
1703
+ getOpenBudgetIncidents(squadId),
1704
+ ]);
1705
+ const issueRows = await db
1706
+ .select({
1707
+ id: issuesTable.id,
1708
+ assigneeAgentId: issuesTable.assigneeAgentId,
1709
+ projectId: issuesTable.projectId,
1710
+ })
1711
+ .from(issuesTable)
1712
+ .where(and(eq(issuesTable.squadId, squadId), inArray(issuesTable.id, subtreeIssueIds)));
1713
+ const invocationBlocks = (await Promise.all(issueRows
1714
+ .filter((issueRow) => issueRow.assigneeAgentId)
1715
+ .map(async (issueRow) => {
1716
+ const block = await budgets.getInvocationBlock(squadId, issueRow.assigneeAgentId, {
1717
+ issueId: issueRow.id,
1718
+ projectId: issueRow.projectId,
1719
+ });
1720
+ return block
1721
+ ? {
1722
+ issueId: issueRow.id,
1723
+ agentId: issueRow.assigneeAgentId,
1724
+ scopeType: block.scopeType,
1725
+ scopeId: block.scopeId,
1726
+ scopeName: block.scopeName,
1727
+ reason: block.reason,
1728
+ }
1729
+ : null;
1730
+ }))).filter((block) => block !== null);
1731
+ return {
1732
+ issueId: rootIssue.id,
1733
+ squadId,
1734
+ subtreeIssueIds,
1735
+ relations: Object.fromEntries(relationPairs),
1736
+ approvals: approvalRows,
1737
+ runs,
1738
+ costs: costsSummary,
1739
+ openBudgetIncidents,
1740
+ invocationBlocks,
1741
+ };
1742
+ },
1743
+ async listComments(params) {
1744
+ const squadId = ensureSquadId(params.squadId);
1745
+ await ensurePluginAvailableForSquad(squadId);
1746
+ if (!inSquad(await issues.getById(params.issueId), squadId))
1747
+ return [];
1748
+ return (await issues.listComments(params.issueId));
1749
+ },
1750
+ async createComment(params) {
1751
+ const squadId = ensureSquadId(params.squadId);
1752
+ await ensurePluginAvailableForSquad(squadId);
1753
+ const issue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1754
+ const comment = (await issues.addComment(params.issueId, params.body, { agentId: params.authorAgentId }));
1755
+ await logPluginActivity({
1756
+ squadId,
1757
+ action: "issue.comment.created",
1758
+ entityType: "issue",
1759
+ entityId: issue.id,
1760
+ actor: { actorAgentId: params.authorAgentId ?? null },
1761
+ details: {
1762
+ identifier: issue.identifier,
1763
+ commentId: comment.id,
1764
+ bodySnippet: comment.body.slice(0, 120),
1765
+ },
1766
+ });
1767
+ return comment;
1768
+ },
1769
+ async createInteraction(params) {
1770
+ const squadId = ensureSquadId(params.squadId);
1771
+ await ensurePluginAvailableForSquad(squadId);
1772
+ const issue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1773
+ const interaction = await issueThreadInteractionService(db).create(issue, params.interaction, {
1774
+ agentId: params.authorAgentId ?? null,
1775
+ });
1776
+ await logPluginActivity({
1777
+ squadId,
1778
+ action: "issue.thread_interaction_created",
1779
+ entityType: "issue",
1780
+ entityId: issue.id,
1781
+ actor: { actorAgentId: params.authorAgentId ?? null },
1782
+ details: {
1783
+ identifier: issue.identifier,
1784
+ interactionId: interaction.id,
1785
+ interactionKind: interaction.kind,
1786
+ interactionStatus: interaction.status,
1787
+ continuationPolicy: interaction.continuationPolicy,
1788
+ },
1789
+ });
1790
+ return interaction;
1791
+ },
1792
+ },
1793
+ issueDocuments: {
1794
+ async list(params) {
1795
+ const squadId = ensureSquadId(params.squadId);
1796
+ await ensurePluginAvailableForSquad(squadId);
1797
+ requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1798
+ const rows = await documents.listIssueDocuments(params.issueId);
1799
+ return rows;
1800
+ },
1801
+ async get(params) {
1802
+ const squadId = ensureSquadId(params.squadId);
1803
+ await ensurePluginAvailableForSquad(squadId);
1804
+ requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1805
+ const doc = await documents.getIssueDocumentByKey(params.issueId, params.key);
1806
+ return (doc ?? null);
1807
+ },
1808
+ async upsert(params) {
1809
+ const squadId = ensureSquadId(params.squadId);
1810
+ await ensurePluginAvailableForSquad(squadId);
1811
+ const issue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1812
+ const result = await documents.upsertIssueDocument({
1813
+ issueId: params.issueId,
1814
+ key: params.key,
1815
+ body: params.body,
1816
+ title: params.title ?? null,
1817
+ format: params.format ?? "markdown",
1818
+ changeSummary: params.changeSummary ?? null,
1819
+ });
1820
+ await logPluginActivity({
1821
+ squadId,
1822
+ action: "issue.document_upserted",
1823
+ entityType: "issue",
1824
+ entityId: issue.id,
1825
+ details: {
1826
+ identifier: issue.identifier,
1827
+ documentKey: params.key,
1828
+ title: params.title ?? null,
1829
+ format: params.format ?? "markdown",
1830
+ },
1831
+ });
1832
+ return result.document;
1833
+ },
1834
+ async delete(params) {
1835
+ const squadId = ensureSquadId(params.squadId);
1836
+ await ensurePluginAvailableForSquad(squadId);
1837
+ const issue = requireInSquad("Issue", await issues.getById(params.issueId), squadId);
1838
+ await documents.deleteIssueDocument(params.issueId, params.key);
1839
+ await logPluginActivity({
1840
+ squadId,
1841
+ action: "issue.document_deleted",
1842
+ entityType: "issue",
1843
+ entityId: issue.id,
1844
+ details: {
1845
+ identifier: issue.identifier,
1846
+ documentKey: params.key,
1847
+ },
1848
+ });
1849
+ },
1850
+ },
1851
+ agents: {
1852
+ async list(params) {
1853
+ const squadId = ensureSquadId(params.squadId);
1854
+ await ensurePluginAvailableForSquad(squadId);
1855
+ const rows = await agents.list(squadId);
1856
+ return applyWindow(rows.filter((agent) => !params.status || agent.status === params.status), params);
1857
+ },
1858
+ async get(params) {
1859
+ const squadId = ensureSquadId(params.squadId);
1860
+ await ensurePluginAvailableForSquad(squadId);
1861
+ const agent = await agents.getById(params.agentId);
1862
+ return (inSquad(agent, squadId) ? agent : null);
1863
+ },
1864
+ async pause(params) {
1865
+ const squadId = ensureSquadId(params.squadId);
1866
+ await ensurePluginAvailableForSquad(squadId);
1867
+ const agent = await agents.getById(params.agentId);
1868
+ requireInSquad("Agent", agent, squadId);
1869
+ return (await agents.pause(params.agentId));
1870
+ },
1871
+ async resume(params) {
1872
+ const squadId = ensureSquadId(params.squadId);
1873
+ await ensurePluginAvailableForSquad(squadId);
1874
+ const agent = await agents.getById(params.agentId);
1875
+ requireInSquad("Agent", agent, squadId);
1876
+ return (await agents.resume(params.agentId));
1877
+ },
1878
+ async invoke(params) {
1879
+ const squadId = ensureSquadId(params.squadId);
1880
+ await ensurePluginAvailableForSquad(squadId);
1881
+ const agent = await agents.getById(params.agentId);
1882
+ requireInSquad("Agent", agent, squadId);
1883
+ const run = await heartbeat.wakeup(params.agentId, {
1884
+ source: "automation",
1885
+ triggerDetail: "system",
1886
+ reason: params.reason ?? null,
1887
+ payload: { prompt: params.prompt },
1888
+ requestedByActorType: "system",
1889
+ requestedByActorId: pluginId,
1890
+ });
1891
+ if (!run)
1892
+ throw new Error("Agent wakeup was skipped by heartbeat policy");
1893
+ return { runId: run.id };
1894
+ },
1895
+ async managedGet(params) {
1896
+ const squadId = ensureSquadId(params.squadId);
1897
+ await ensurePluginAvailableForSquad(squadId);
1898
+ return managedAgents.get(params.agentKey, squadId);
1899
+ },
1900
+ async managedReconcile(params) {
1901
+ const squadId = ensureSquadId(params.squadId);
1902
+ await ensurePluginAvailableForSquad(squadId);
1903
+ return managedAgents.reconcile(params.agentKey, squadId);
1904
+ },
1905
+ async managedReset(params) {
1906
+ const squadId = ensureSquadId(params.squadId);
1907
+ await ensurePluginAvailableForSquad(squadId);
1908
+ return managedAgents.reset(params.agentKey, squadId);
1909
+ },
1910
+ },
1911
+ goals: {
1912
+ async list(params) {
1913
+ const squadId = ensureSquadId(params.squadId);
1914
+ await ensurePluginAvailableForSquad(squadId);
1915
+ const rows = await goals.list(squadId);
1916
+ return applyWindow(rows.filter((goal) => (!params.level || goal.level === params.level) &&
1917
+ (!params.status || goal.status === params.status)), params);
1918
+ },
1919
+ async get(params) {
1920
+ const squadId = ensureSquadId(params.squadId);
1921
+ await ensurePluginAvailableForSquad(squadId);
1922
+ const goal = await goals.getById(params.goalId);
1923
+ return (inSquad(goal, squadId) ? goal : null);
1924
+ },
1925
+ async create(params) {
1926
+ const squadId = ensureSquadId(params.squadId);
1927
+ await ensurePluginAvailableForSquad(squadId);
1928
+ return (await goals.create(squadId, {
1929
+ title: params.title,
1930
+ description: params.description,
1931
+ level: params.level,
1932
+ status: params.status,
1933
+ parentId: params.parentId,
1934
+ ownerAgentId: params.ownerAgentId,
1935
+ }));
1936
+ },
1937
+ async update(params) {
1938
+ const squadId = ensureSquadId(params.squadId);
1939
+ await ensurePluginAvailableForSquad(squadId);
1940
+ requireInSquad("Goal", await goals.getById(params.goalId), squadId);
1941
+ return (await goals.update(params.goalId, params.patch));
1942
+ },
1943
+ },
1944
+ access: {
1945
+ async listMembers(params) {
1946
+ const squadId = ensureSquadId(params.squadId);
1947
+ await ensurePluginAvailableForSquad(squadId);
1948
+ const rows = await access.listMembers(squadId);
1949
+ const visibleRows = params.includeArchived ? rows : rows.filter((row) => row.status !== "archived");
1950
+ const grants = await db
1951
+ .select()
1952
+ .from(principalPermissionGrants)
1953
+ .where(eq(principalPermissionGrants.squadId, squadId));
1954
+ const grantsByPrincipal = new Map();
1955
+ for (const grant of grants) {
1956
+ const key = `${grant.principalType}:${grant.principalId}`;
1957
+ const existing = grantsByPrincipal.get(key) ?? [];
1958
+ existing.push(grant);
1959
+ grantsByPrincipal.set(key, existing);
1960
+ }
1961
+ return visibleRows.map((member) => ({
1962
+ ...member,
1963
+ principalType: member.principalType,
1964
+ status: member.status,
1965
+ grants: (grantsByPrincipal.get(`${member.principalType}:${member.principalId}`) ?? []).map(redactGrant),
1966
+ }));
1967
+ },
1968
+ async getMember(params) {
1969
+ const squadId = ensureSquadId(params.squadId);
1970
+ await ensurePluginAvailableForSquad(squadId);
1971
+ return loadPluginMember(squadId, params.memberId);
1972
+ },
1973
+ async updateMember(params) {
1974
+ const squadId = ensureSquadId(params.squadId);
1975
+ await ensurePluginAvailableForSquad(squadId);
1976
+ const updated = await access.updateMember(squadId, params.memberId, params.patch);
1977
+ if (!updated)
1978
+ throw new Error("Member not found");
1979
+ await logPluginActivity({
1980
+ squadId,
1981
+ action: "squad_member.updated_by_plugin",
1982
+ entityType: "squad_membership",
1983
+ entityId: params.memberId,
1984
+ details: {
1985
+ patch: sanitizeRecord(params.patch),
1986
+ },
1987
+ });
1988
+ return (await loadPluginMember(squadId, params.memberId));
1989
+ },
1990
+ async listInvites(params) {
1991
+ const squadId = ensureSquadId(params.squadId);
1992
+ await ensurePluginAvailableForSquad(squadId);
1993
+ const limit = Math.min(Math.max(Number(params.limit ?? 20), 1), 100);
1994
+ const offset = Math.max(Number(params.offset ?? 0), 0);
1995
+ const stateClause = inviteStateWhereClause(params.state);
1996
+ const rows = await db
1997
+ .select()
1998
+ .from(invites)
1999
+ .where(stateClause ? and(eq(invites.squadId, squadId), stateClause) : eq(invites.squadId, squadId))
2000
+ .orderBy(desc(invites.createdAt))
2001
+ .limit(limit + 1)
2002
+ .offset(offset);
2003
+ const hasMore = rows.length > limit;
2004
+ return {
2005
+ invites: rows.slice(0, limit).map(redactInvite),
2006
+ nextOffset: hasMore ? offset + limit : null,
2007
+ };
2008
+ },
2009
+ async createInvite(params) {
2010
+ const squadId = ensureSquadId(params.squadId);
2011
+ await ensurePluginAvailableForSquad(squadId);
2012
+ const normalizedAgentMessage = typeof params.agentMessage === "string"
2013
+ ? params.agentMessage.trim() || null
2014
+ : null;
2015
+ const allowedJoinTypes = params.allowedJoinTypes ?? "both";
2016
+ const humanRole = allowedJoinTypes === "agent" ? null : params.humanRole ?? "operator";
2017
+ const insertValues = {
2018
+ squadId,
2019
+ inviteType: "squad_join",
2020
+ allowedJoinTypes,
2021
+ defaultsPayload: mergeInviteDefaults(params.defaultsPayload ?? null, normalizedAgentMessage, humanRole),
2022
+ expiresAt: new Date(Date.now() + SQUAD_INVITE_TTL_MS),
2023
+ invitedByUserId: null,
2024
+ };
2025
+ let token = null;
2026
+ let created = null;
2027
+ for (let attempt = 0; attempt < INVITE_TOKEN_MAX_RETRIES; attempt += 1) {
2028
+ const candidateToken = createInviteToken();
2029
+ try {
2030
+ created = await db
2031
+ .insert(invites)
2032
+ .values({
2033
+ ...insertValues,
2034
+ tokenHash: hashToken(candidateToken),
2035
+ })
2036
+ .returning()
2037
+ .then((rows) => rows[0] ?? null);
2038
+ token = candidateToken;
2039
+ break;
2040
+ }
2041
+ catch (error) {
2042
+ if (!isInviteTokenHashCollisionError(error))
2043
+ throw error;
2044
+ }
2045
+ }
2046
+ if (!token || !created)
2047
+ throw new Error("Failed to generate a unique invite token");
2048
+ await logPluginActivity({
2049
+ squadId,
2050
+ action: "invite.created_by_plugin",
2051
+ entityType: "invite",
2052
+ entityId: created.id,
2053
+ details: {
2054
+ allowedJoinTypes: created.allowedJoinTypes,
2055
+ expiresAt: created.expiresAt.toISOString(),
2056
+ hasAgentMessage: Boolean(normalizedAgentMessage),
2057
+ },
2058
+ });
2059
+ return { ...redactInvite(created), token };
2060
+ },
2061
+ async revokeInvite(params) {
2062
+ const squadId = ensureSquadId(params.squadId);
2063
+ await ensurePluginAvailableForSquad(squadId);
2064
+ const invite = await db
2065
+ .select()
2066
+ .from(invites)
2067
+ .where(and(eq(invites.id, params.inviteId), eq(invites.squadId, squadId)))
2068
+ .then((rows) => rows[0] ?? null);
2069
+ if (!invite)
2070
+ throw new Error("Invite not found");
2071
+ if (invite.acceptedAt)
2072
+ throw new Error("Invite already consumed");
2073
+ if (invite.revokedAt)
2074
+ return redactInvite(invite);
2075
+ const revoked = await db
2076
+ .update(invites)
2077
+ .set({ revokedAt: new Date(), updatedAt: new Date() })
2078
+ .where(eq(invites.id, invite.id))
2079
+ .returning()
2080
+ .then((rows) => rows[0] ?? invite);
2081
+ await logPluginActivity({
2082
+ squadId,
2083
+ action: "invite.revoked_by_plugin",
2084
+ entityType: "invite",
2085
+ entityId: invite.id,
2086
+ });
2087
+ return redactInvite(revoked);
2088
+ },
2089
+ },
2090
+ authorization: {
2091
+ async listGrants(params) {
2092
+ const squadId = ensureSquadId(params.squadId);
2093
+ await ensurePluginAvailableForSquad(squadId);
2094
+ const conditions = [
2095
+ eq(principalPermissionGrants.squadId, squadId),
2096
+ params.principalType ? eq(principalPermissionGrants.principalType, params.principalType) : undefined,
2097
+ params.principalId ? eq(principalPermissionGrants.principalId, params.principalId) : undefined,
2098
+ ].filter((condition) => Boolean(condition));
2099
+ const rows = await db
2100
+ .select()
2101
+ .from(principalPermissionGrants)
2102
+ .where(and(...conditions))
2103
+ .orderBy(principalPermissionGrants.principalType, principalPermissionGrants.principalId, principalPermissionGrants.permissionKey);
2104
+ return rows.map(redactGrant);
2105
+ },
2106
+ async setGrants(params) {
2107
+ const squadId = ensureSquadId(params.squadId);
2108
+ await ensurePluginAvailableForSquad(squadId);
2109
+ if (params.principalType !== "agent" && params.principalType !== "user") {
2110
+ throw new Error("principalType must be 'agent' or 'user'");
2111
+ }
2112
+ if (params.principalType === "agent") {
2113
+ requireInSquad("Agent", await agents.getById(params.principalId), squadId);
2114
+ }
2115
+ else {
2116
+ const membership = await access.getMembership(squadId, params.principalType, params.principalId);
2117
+ if (!membership)
2118
+ throw new Error("Principal is not a member of this squad");
2119
+ }
2120
+ await access.setPrincipalGrants(squadId, params.principalType, params.principalId, params.grants.map((grant) => ({
2121
+ permissionKey: grant.permissionKey,
2122
+ scope: grant.scope ? sanitizeRecord(grant.scope) : null,
2123
+ })), params.grantedByUserId ?? null);
2124
+ await logPluginActivity({
2125
+ squadId,
2126
+ action: "authorization.grants_updated_by_plugin",
2127
+ entityType: "principal_permission_grants",
2128
+ entityId: `${params.principalType}:${params.principalId}`,
2129
+ details: { grantCount: params.grants.length },
2130
+ });
2131
+ return access
2132
+ .listPrincipalGrants(squadId, params.principalType, params.principalId)
2133
+ .then((rows) => rows.map(redactGrant));
2134
+ },
2135
+ async policySummary(params) {
2136
+ const squadId = ensureSquadId(params.squadId);
2137
+ await ensurePluginAvailableForSquad(squadId);
2138
+ const [members, grants] = await Promise.all([
2139
+ access.listMembers(squadId),
2140
+ db
2141
+ .select({ id: principalPermissionGrants.id })
2142
+ .from(principalPermissionGrants)
2143
+ .where(eq(principalPermissionGrants.squadId, squadId)),
2144
+ ]);
2145
+ return {
2146
+ squadId,
2147
+ permissionsMode: "simple",
2148
+ memberCount: members.length,
2149
+ activeMemberCount: members.filter((member) => member.status === "active").length,
2150
+ grantCount: grants.length,
2151
+ advancedPolicyAvailable: false,
2152
+ };
2153
+ },
2154
+ async getPolicy(params) {
2155
+ const squadId = ensureSquadId(params.squadId);
2156
+ await ensurePluginAvailableForSquad(squadId);
2157
+ return readAuthorizationPolicy(squadId, params.resourceType, params.resourceId);
2158
+ },
2159
+ async updatePolicy(params) {
2160
+ const squadId = ensureSquadId(params.squadId);
2161
+ await ensurePluginAvailableForSquad(squadId);
2162
+ const policy = params.policy ? sanitizeRecord(params.policy) : null;
2163
+ if (params.resourceType === "agent") {
2164
+ const agent = requireInSquad("Agent", await agents.getById(params.resourceId), squadId);
2165
+ const permissions = agent.permissions && typeof agent.permissions === "object"
2166
+ ? { ...agent.permissions }
2167
+ : {};
2168
+ if (policy)
2169
+ permissions.authorizationPolicy = policy;
2170
+ else
2171
+ delete permissions.authorizationPolicy;
2172
+ await db
2173
+ .update(agentsTable)
2174
+ .set({ permissions, updatedAt: new Date() })
2175
+ .where(eq(agentsTable.id, agent.id));
2176
+ }
2177
+ else if (params.resourceType === "project") {
2178
+ const project = requireInSquad("Project", await projects.getById(params.resourceId), squadId);
2179
+ const executionWorkspacePolicy = project.executionWorkspacePolicy && typeof project.executionWorkspacePolicy === "object"
2180
+ ? { ...project.executionWorkspacePolicy }
2181
+ : {};
2182
+ if (policy)
2183
+ executionWorkspacePolicy.authorizationPolicy = policy;
2184
+ else
2185
+ delete executionWorkspacePolicy.authorizationPolicy;
2186
+ await db
2187
+ .update(projectsTable)
2188
+ .set({ executionWorkspacePolicy, updatedAt: new Date() })
2189
+ .where(eq(projectsTable.id, project.id));
2190
+ }
2191
+ else if (params.resourceType === "issue") {
2192
+ const issue = requireInSquad("Issue", await issues.getById(params.resourceId), squadId);
2193
+ const executionPolicy = issue.executionPolicy && typeof issue.executionPolicy === "object"
2194
+ ? { ...issue.executionPolicy }
2195
+ : {};
2196
+ if (policy)
2197
+ executionPolicy.authorizationPolicy = policy;
2198
+ else
2199
+ delete executionPolicy.authorizationPolicy;
2200
+ await db
2201
+ .update(issuesTable)
2202
+ .set({ executionPolicy, updatedAt: new Date() })
2203
+ .where(eq(issuesTable.id, issue.id));
2204
+ }
2205
+ else {
2206
+ const squad = await squads.getById(params.resourceId);
2207
+ if (!squad || squad.id !== squadId)
2208
+ throw new Error("Squad not found");
2209
+ throw new Error("Squad authorization policy updates are not supported by the current core schema");
2210
+ }
2211
+ await logPluginActivity({
2212
+ squadId,
2213
+ action: "authorization.policy_updated_by_plugin",
2214
+ entityType: params.resourceType,
2215
+ entityId: params.resourceId,
2216
+ details: { hasPolicy: Boolean(policy) },
2217
+ });
2218
+ const updated = await readAuthorizationPolicy(squadId, params.resourceType, params.resourceId);
2219
+ if (!updated)
2220
+ throw new Error("Policy resource not found");
2221
+ return updated;
2222
+ },
2223
+ async previewAssignment(params) {
2224
+ const squadId = ensureSquadId(params.squadId);
2225
+ await ensurePluginAvailableForSquad(squadId);
2226
+ return authorization.decide({
2227
+ actor: pluginAssignmentActor(params.actor),
2228
+ action: "tasks:assign",
2229
+ resource: { type: "issue", squadId, ...params.target },
2230
+ scope: {
2231
+ issueId: params.target.issueId ?? null,
2232
+ projectId: params.target.projectId ?? null,
2233
+ parentIssueId: params.target.parentIssueId ?? null,
2234
+ assigneeAgentId: params.target.assigneeAgentId ?? null,
2235
+ assigneeUserId: params.target.assigneeUserId ?? null,
2236
+ },
2237
+ });
2238
+ },
2239
+ async explainAssignment(params) {
2240
+ const squadId = ensureSquadId(params.squadId);
2241
+ await ensurePluginAvailableForSquad(squadId);
2242
+ return authorization.decide({
2243
+ actor: pluginAssignmentActor(params.actor),
2244
+ action: "tasks:assign",
2245
+ resource: { type: "issue", squadId, ...params.target },
2246
+ scope: {
2247
+ issueId: params.target.issueId ?? null,
2248
+ projectId: params.target.projectId ?? null,
2249
+ parentIssueId: params.target.parentIssueId ?? null,
2250
+ assigneeAgentId: params.target.assigneeAgentId ?? null,
2251
+ assigneeUserId: params.target.assigneeUserId ?? null,
2252
+ },
2253
+ });
2254
+ },
2255
+ async searchAudit(params) {
2256
+ const squadId = ensureSquadId(params.squadId);
2257
+ await ensurePluginAvailableForSquad(squadId);
2258
+ const limit = Math.min(Math.max(Number(params.limit ?? 50), 1), 100);
2259
+ const offset = Math.max(Number(params.offset ?? 0), 0);
2260
+ const decisionFilter = typeof params.decision === "string" && params.decision.trim()
2261
+ ? params.decision.trim().toLowerCase()
2262
+ : null;
2263
+ const conditions = [
2264
+ eq(activityLog.squadId, squadId),
2265
+ params.action ? eq(activityLog.action, params.action) : undefined,
2266
+ params.actorType ? eq(activityLog.actorType, params.actorType) : undefined,
2267
+ params.actorId ? eq(activityLog.actorId, params.actorId) : undefined,
2268
+ params.entityType ? eq(activityLog.entityType, params.entityType) : undefined,
2269
+ params.entityId ? eq(activityLog.entityId, params.entityId) : undefined,
2270
+ decisionFilter ? authorizationAuditDecisionCondition(decisionFilter) : undefined,
2271
+ ].filter((condition) => Boolean(condition));
2272
+ const rows = await db
2273
+ .select()
2274
+ .from(activityLog)
2275
+ .where(and(...conditions))
2276
+ .orderBy(desc(activityLog.createdAt))
2277
+ .limit(limit)
2278
+ .offset(offset);
2279
+ return rows.map((row) => ({
2280
+ ...row,
2281
+ details: row.details && typeof row.details === "object"
2282
+ ? sanitizeRecord(row.details)
2283
+ : row.details ?? null,
2284
+ }));
2285
+ },
2286
+ },
2287
+ agentSessions: {
2288
+ async create(params) {
2289
+ const squadId = ensureSquadId(params.squadId);
2290
+ await ensurePluginAvailableForSquad(squadId);
2291
+ const agent = await agents.getById(params.agentId);
2292
+ requireInSquad("Agent", agent, squadId);
2293
+ const taskKey = params.taskKey ?? `plugin:${pluginKey}:session:${randomUUID()}`;
2294
+ const row = await db
2295
+ .insert(agentTaskSessionsTable)
2296
+ .values({
2297
+ squadId,
2298
+ agentId: params.agentId,
2299
+ adapterType: agent.adapterType,
2300
+ taskKey,
2301
+ sessionParamsJson: null,
2302
+ sessionDisplayId: null,
2303
+ lastRunId: null,
2304
+ lastError: null,
2305
+ })
2306
+ .returning()
2307
+ .then((rows) => rows[0]);
2308
+ return {
2309
+ sessionId: row.id,
2310
+ agentId: params.agentId,
2311
+ squadId,
2312
+ status: "active",
2313
+ createdAt: row.createdAt.toISOString(),
2314
+ };
2315
+ },
2316
+ async list(params) {
2317
+ const squadId = ensureSquadId(params.squadId);
2318
+ await ensurePluginAvailableForSquad(squadId);
2319
+ const rows = await db
2320
+ .select()
2321
+ .from(agentTaskSessionsTable)
2322
+ .where(and(eq(agentTaskSessionsTable.agentId, params.agentId), eq(agentTaskSessionsTable.squadId, squadId), like(agentTaskSessionsTable.taskKey, `plugin:${pluginKey}:session:%`)))
2323
+ .orderBy(desc(agentTaskSessionsTable.createdAt));
2324
+ return rows.map((row) => ({
2325
+ sessionId: row.id,
2326
+ agentId: row.agentId,
2327
+ squadId: row.squadId,
2328
+ status: "active",
2329
+ createdAt: row.createdAt.toISOString(),
2330
+ }));
2331
+ },
2332
+ async sendMessage(params) {
2333
+ if (disposed) {
2334
+ throw new Error("Host services have been disposed");
2335
+ }
2336
+ const squadId = ensureSquadId(params.squadId);
2337
+ await ensurePluginAvailableForSquad(squadId);
2338
+ // Verify session exists and belongs to this plugin
2339
+ const session = await db
2340
+ .select()
2341
+ .from(agentTaskSessionsTable)
2342
+ .where(and(eq(agentTaskSessionsTable.id, params.sessionId), eq(agentTaskSessionsTable.squadId, squadId), like(agentTaskSessionsTable.taskKey, `plugin:${pluginKey}:session:%`)))
2343
+ .then((rows) => rows[0] ?? null);
2344
+ if (!session)
2345
+ throw new Error(`Session not found: ${params.sessionId}`);
2346
+ const run = await heartbeat.wakeup(session.agentId, {
2347
+ source: "automation",
2348
+ triggerDetail: "system",
2349
+ reason: params.reason ?? null,
2350
+ payload: { prompt: params.prompt },
2351
+ contextSnapshot: {
2352
+ taskKey: session.taskKey,
2353
+ wakeSource: "automation",
2354
+ wakeTriggerDetail: "system",
2355
+ },
2356
+ requestedByActorType: "system",
2357
+ requestedByActorId: pluginId,
2358
+ });
2359
+ if (!run)
2360
+ throw new Error("Agent wakeup was skipped by heartbeat policy");
2361
+ // Subscribe to live events and forward to the plugin worker as notifications.
2362
+ // Track the subscription so it can be cleaned up on dispose() if the run
2363
+ // never reaches a terminal status (hang, crash, network partition).
2364
+ if (notifyWorker) {
2365
+ const TERMINAL_STATUSES = new Set(["succeeded", "failed", "cancelled", "timed_out"]);
2366
+ const cleanup = () => {
2367
+ unsubscribe();
2368
+ clearTimeout(timeoutTimer);
2369
+ activeSubscriptions.delete(entry);
2370
+ };
2371
+ const unsubscribe = subscribeSquadLiveEvents(squadId, (event) => {
2372
+ const payload = event.payload;
2373
+ if (!payload || payload.runId !== run.id)
2374
+ return;
2375
+ if (event.type === "heartbeat.run.log" || event.type === "heartbeat.run.event") {
2376
+ notifyWorker("agents.sessions.event", {
2377
+ sessionId: params.sessionId,
2378
+ runId: run.id,
2379
+ seq: payload.seq ?? 0,
2380
+ eventType: "chunk",
2381
+ stream: payload.stream ?? null,
2382
+ message: payload.chunk ?? payload.message ?? null,
2383
+ payload: payload,
2384
+ });
2385
+ }
2386
+ else if (event.type === "heartbeat.run.status") {
2387
+ const status = payload.status;
2388
+ if (TERMINAL_STATUSES.has(status)) {
2389
+ notifyWorker("agents.sessions.event", {
2390
+ sessionId: params.sessionId,
2391
+ runId: run.id,
2392
+ seq: 0,
2393
+ eventType: status === "succeeded" ? "done" : "error",
2394
+ stream: "system",
2395
+ message: status === "succeeded" ? "Run completed" : `Run ${status}`,
2396
+ payload: payload,
2397
+ });
2398
+ cleanup();
2399
+ }
2400
+ else {
2401
+ notifyWorker("agents.sessions.event", {
2402
+ sessionId: params.sessionId,
2403
+ runId: run.id,
2404
+ seq: 0,
2405
+ eventType: "status",
2406
+ stream: "system",
2407
+ message: `Run status: ${status}`,
2408
+ payload: payload,
2409
+ });
2410
+ }
2411
+ }
2412
+ });
2413
+ // Safety-net timeout: if the run never reaches a terminal status,
2414
+ // force-cleanup the subscription to prevent unbounded leaks.
2415
+ const timeoutTimer = setTimeout(() => {
2416
+ logger.warn({ pluginId, pluginKey, runId: run.id }, "session event subscription timed out — forcing cleanup");
2417
+ cleanup();
2418
+ }, SESSION_EVENT_SUBSCRIPTION_TIMEOUT_MS);
2419
+ const entry = { unsubscribe, timer: timeoutTimer };
2420
+ activeSubscriptions.add(entry);
2421
+ }
2422
+ return { runId: run.id };
2423
+ },
2424
+ async close(params) {
2425
+ const squadId = ensureSquadId(params.squadId);
2426
+ await ensurePluginAvailableForSquad(squadId);
2427
+ const deleted = await db
2428
+ .delete(agentTaskSessionsTable)
2429
+ .where(and(eq(agentTaskSessionsTable.id, params.sessionId), eq(agentTaskSessionsTable.squadId, squadId), like(agentTaskSessionsTable.taskKey, `plugin:${pluginKey}:session:%`)))
2430
+ .returning()
2431
+ .then((rows) => rows.length);
2432
+ if (deleted === 0)
2433
+ throw new Error(`Session not found: ${params.sessionId}`);
2434
+ },
2435
+ },
2436
+ /**
2437
+ * Clean up all active session event subscriptions and flush any buffered
2438
+ * log entries. Must be called when the plugin worker is stopped, crashed,
2439
+ * or unloaded to prevent leaked listeners and lost log entries.
2440
+ */
2441
+ dispose() {
2442
+ disposed = true;
2443
+ // Clear event bus subscriptions to prevent accumulation on worker restart.
2444
+ // Without this, each crash/restart cycle adds duplicate subscriptions.
2445
+ scopedBus.clear();
2446
+ // Snapshot to avoid iterator invalidation from concurrent sendMessage() calls
2447
+ const snapshot = Array.from(activeSubscriptions);
2448
+ activeSubscriptions.clear();
2449
+ for (const entry of snapshot) {
2450
+ clearTimeout(entry.timer);
2451
+ entry.unsubscribe();
2452
+ }
2453
+ // Flush any buffered log entries synchronously-as-possible on dispose.
2454
+ flushPluginLogBuffer().catch((err) => {
2455
+ console.error("[plugin-host-services] dispose() log flush failed:", err);
2456
+ });
2457
+ },
2458
+ };
2459
+ }
2460
+ //# sourceMappingURL=plugin-host-services.js.map