@capybara-hq/kernel 0.0.0-stage → 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +20 -2
  4. package/bootstrap.json +26 -0
  5. package/dist/admin/admin.controller.d.ts +139 -0
  6. package/dist/admin/admin.controller.js +238 -0
  7. package/dist/admin/extensions.controller.d.ts +100 -0
  8. package/dist/admin/extensions.controller.js +226 -0
  9. package/dist/admin/setup.controller.d.ts +36 -0
  10. package/dist/admin/setup.controller.js +106 -0
  11. package/dist/admin/setup.service.d.ts +47 -0
  12. package/dist/admin/setup.service.js +90 -0
  13. package/dist/agents/agents.controller.d.ts +205 -0
  14. package/dist/agents/agents.controller.js +144 -0
  15. package/dist/agents/agents.service.d.ts +177 -0
  16. package/dist/agents/agents.service.js +677 -0
  17. package/dist/agents/definition.d.ts +198 -0
  18. package/dist/agents/definition.js +152 -0
  19. package/dist/agents/models.controller.d.ts +13 -0
  20. package/dist/agents/models.controller.js +31 -0
  21. package/dist/agents/templates.controller.d.ts +15 -0
  22. package/dist/agents/templates.controller.js +37 -0
  23. package/dist/agents/templates.d.ts +83 -0
  24. package/dist/agents/templates.js +173 -0
  25. package/dist/catalog/admin-catalog.controller.d.ts +143 -0
  26. package/dist/catalog/admin-catalog.controller.js +245 -0
  27. package/dist/catalog/catalog.service.d.ts +430 -0
  28. package/dist/catalog/catalog.service.js +882 -0
  29. package/dist/catalog/claude/agents.d.ts +27 -0
  30. package/dist/catalog/claude/agents.js +270 -0
  31. package/dist/catalog/claude/commands.d.ts +50 -0
  32. package/dist/catalog/claude/commands.js +179 -0
  33. package/dist/catalog/claude/manifest.d.ts +69 -0
  34. package/dist/catalog/claude/manifest.js +134 -0
  35. package/dist/catalog/claude/marketplace.d.ts +35 -0
  36. package/dist/catalog/claude/marketplace.js +194 -0
  37. package/dist/catalog/claude/mcp.d.ts +33 -0
  38. package/dist/catalog/claude/mcp.js +226 -0
  39. package/dist/catalog/claude/report.d.ts +86 -0
  40. package/dist/catalog/claude/report.js +121 -0
  41. package/dist/catalog/claude/translate.d.ts +56 -0
  42. package/dist/catalog/claude/translate.js +857 -0
  43. package/dist/catalog/cli.d.ts +46 -0
  44. package/dist/catalog/cli.js +211 -0
  45. package/dist/catalog/git-source.d.ts +127 -0
  46. package/dist/catalog/git-source.js +520 -0
  47. package/dist/catalog/marketplace-fetch.d.ts +99 -0
  48. package/dist/catalog/marketplace-fetch.js +203 -0
  49. package/dist/catalog/marketplaces.controller.d.ts +97 -0
  50. package/dist/catalog/marketplaces.controller.js +197 -0
  51. package/dist/catalog/marketplaces.service.d.ts +340 -0
  52. package/dist/catalog/marketplaces.service.js +1217 -0
  53. package/dist/catalog/org-catalog.controller.d.ts +128 -0
  54. package/dist/catalog/org-catalog.controller.js +277 -0
  55. package/dist/catalog/org-catalog.service.d.ts +246 -0
  56. package/dist/catalog/org-catalog.service.js +625 -0
  57. package/dist/catalog/plugin-import.d.ts +436 -0
  58. package/dist/catalog/plugin-import.js +1069 -0
  59. package/dist/catalog/plugin-install.d.ts +447 -0
  60. package/dist/catalog/plugin-install.js +1333 -0
  61. package/dist/catalog/plugin-package.d.ts +143 -0
  62. package/dist/catalog/plugin-package.js +382 -0
  63. package/dist/catalog/plugin-upgrade.d.ts +222 -0
  64. package/dist/catalog/plugin-upgrade.js +1219 -0
  65. package/dist/catalog/requests.service.d.ts +162 -0
  66. package/dist/catalog/requests.service.js +504 -0
  67. package/dist/catalog/schema-path.d.ts +7 -0
  68. package/dist/catalog/schema-path.js +63 -0
  69. package/dist/catalog/upgrade-targets.d.ts +59 -0
  70. package/dist/catalog/upgrade-targets.js +90 -0
  71. package/dist/catalog/versions.d.ts +31 -0
  72. package/dist/catalog/versions.js +44 -0
  73. package/dist/channels/actions.d.ts +37 -0
  74. package/dist/channels/actions.js +121 -0
  75. package/dist/channels/cards.d.ts +44 -0
  76. package/dist/channels/cards.js +156 -0
  77. package/dist/channels/connections.controller.d.ts +59 -0
  78. package/dist/channels/connections.controller.js +115 -0
  79. package/dist/channels/connections.service.d.ts +187 -0
  80. package/dist/channels/connections.service.js +534 -0
  81. package/dist/channels/features.d.ts +12 -0
  82. package/dist/channels/features.js +22 -0
  83. package/dist/channels/inbound.d.ts +120 -0
  84. package/dist/channels/inbound.js +332 -0
  85. package/dist/channels/outbound.d.ts +140 -0
  86. package/dist/channels/outbound.js +1126 -0
  87. package/dist/channels/phrases.d.ts +100 -0
  88. package/dist/channels/phrases.js +81 -0
  89. package/dist/channels/supervisor.d.ts +182 -0
  90. package/dist/channels/supervisor.js +625 -0
  91. package/dist/channels/threads.d.ts +29 -0
  92. package/dist/channels/threads.js +104 -0
  93. package/dist/channels/webhook-url.d.ts +16 -0
  94. package/dist/channels/webhook-url.js +34 -0
  95. package/dist/channels/webhook.controller.d.ts +19 -0
  96. package/dist/channels/webhook.controller.js +72 -0
  97. package/dist/channels/webhook.d.ts +73 -0
  98. package/dist/channels/webhook.js +274 -0
  99. package/dist/config/docs.d.ts +9 -0
  100. package/dist/config/docs.js +85 -0
  101. package/dist/config/env.d.ts +6 -0
  102. package/dist/config/env.js +73 -0
  103. package/dist/config/fields.d.ts +42 -0
  104. package/dist/config/fields.js +214 -0
  105. package/dist/config/file-source.d.ts +3 -0
  106. package/dist/config/file-source.js +31 -0
  107. package/dist/config/load.d.ts +20 -0
  108. package/dist/config/load.js +98 -0
  109. package/dist/config/nacos-source.d.ts +31 -0
  110. package/dist/config/nacos-source.js +229 -0
  111. package/dist/config/schema.d.ts +237 -0
  112. package/dist/config/schema.js +1192 -0
  113. package/dist/config/sources.d.ts +18 -0
  114. package/dist/config/sources.js +59 -0
  115. package/dist/config/types.d.ts +9 -0
  116. package/dist/config/types.js +7 -0
  117. package/dist/conversations/artifacts.d.ts +52 -0
  118. package/dist/conversations/artifacts.js +137 -0
  119. package/dist/conversations/attachments.controller.d.ts +28 -0
  120. package/dist/conversations/attachments.controller.js +96 -0
  121. package/dist/conversations/attachments.service.d.ts +180 -0
  122. package/dist/conversations/attachments.service.js +578 -0
  123. package/dist/conversations/conversations.controller.d.ts +288 -0
  124. package/dist/conversations/conversations.controller.js +607 -0
  125. package/dist/conversations/conversations.service.d.ts +321 -0
  126. package/dist/conversations/conversations.service.js +754 -0
  127. package/dist/conversations/event-log.d.ts +122 -0
  128. package/dist/conversations/event-log.js +259 -0
  129. package/dist/conversations/events.d.ts +856 -0
  130. package/dist/conversations/events.js +639 -0
  131. package/dist/conversations/files.d.ts +92 -0
  132. package/dist/conversations/files.js +213 -0
  133. package/dist/conversations/outputs-read.d.ts +34 -0
  134. package/dist/conversations/outputs-read.js +37 -0
  135. package/dist/conversations/queue.d.ts +169 -0
  136. package/dist/conversations/queue.js +527 -0
  137. package/dist/conversations/sandbox-status.d.ts +21 -0
  138. package/dist/conversations/sandbox-status.js +24 -0
  139. package/dist/conversations/selection.d.ts +46 -0
  140. package/dist/conversations/selection.js +75 -0
  141. package/dist/conversations/titles.d.ts +93 -0
  142. package/dist/conversations/titles.js +423 -0
  143. package/dist/ctx/bus.d.ts +16 -0
  144. package/dist/ctx/bus.js +101 -0
  145. package/dist/ctx/create-ctx.d.ts +109 -0
  146. package/dist/ctx/create-ctx.js +592 -0
  147. package/dist/ctx/kv.d.ts +4 -0
  148. package/dist/ctx/kv.js +31 -0
  149. package/dist/ctx/lock.d.ts +4 -0
  150. package/dist/ctx/lock.js +39 -0
  151. package/dist/ctx/namespace.d.ts +6 -0
  152. package/dist/ctx/namespace.js +12 -0
  153. package/dist/ctx/queue.d.ts +25 -0
  154. package/dist/ctx/queue.js +151 -0
  155. package/dist/ctx/secrets.d.ts +45 -0
  156. package/dist/ctx/secrets.js +175 -0
  157. package/dist/db/kernel-schema.d.ts +1122 -0
  158. package/dist/db/kernel-schema.js +5 -0
  159. package/dist/db/migrator.d.ts +28 -0
  160. package/dist/db/migrator.js +140 -0
  161. package/dist/db/pool.d.ts +21 -0
  162. package/dist/db/pool.js +28 -0
  163. package/dist/db/sql-statements.d.ts +34 -0
  164. package/dist/db/sql-statements.js +168 -0
  165. package/dist/errors.d.ts +211 -0
  166. package/dist/errors.js +213 -0
  167. package/dist/evals/budget.d.ts +61 -0
  168. package/dist/evals/budget.js +181 -0
  169. package/dist/evals/diff.d.ts +55 -0
  170. package/dist/evals/diff.js +133 -0
  171. package/dist/evals/judge.d.ts +53 -0
  172. package/dist/evals/judge.js +149 -0
  173. package/dist/evals/plan.d.ts +47 -0
  174. package/dist/evals/plan.js +77 -0
  175. package/dist/evals/reconstruct.d.ts +137 -0
  176. package/dist/evals/reconstruct.js +322 -0
  177. package/dist/evals/recorded-tools.d.ts +54 -0
  178. package/dist/evals/recorded-tools.js +167 -0
  179. package/dist/evals/run-replay.d.ts +86 -0
  180. package/dist/evals/run-replay.js +502 -0
  181. package/dist/evals/runs.controller.d.ts +100 -0
  182. package/dist/evals/runs.controller.js +199 -0
  183. package/dist/evals/runs.service.d.ts +275 -0
  184. package/dist/evals/runs.service.js +836 -0
  185. package/dist/evals/sets.controller.d.ts +61 -0
  186. package/dist/evals/sets.controller.js +183 -0
  187. package/dist/evals/sets.service.d.ts +128 -0
  188. package/dist/evals/sets.service.js +558 -0
  189. package/dist/evals/snapshot.d.ts +76 -0
  190. package/dist/evals/snapshot.js +207 -0
  191. package/dist/evals/step-replay.d.ts +113 -0
  192. package/dist/evals/step-replay.js +181 -0
  193. package/dist/evals/trajectory.controller.d.ts +41 -0
  194. package/dist/evals/trajectory.controller.js +88 -0
  195. package/dist/evals/trajectory.d.ts +144 -0
  196. package/dist/evals/trajectory.js +338 -0
  197. package/dist/evals/trajectory.service.d.ts +108 -0
  198. package/dist/evals/trajectory.service.js +323 -0
  199. package/dist/evals/worker.d.ts +101 -0
  200. package/dist/evals/worker.js +790 -0
  201. package/dist/extensions/admin-ops.d.ts +105 -0
  202. package/dist/extensions/admin-ops.js +353 -0
  203. package/dist/extensions/admin-view.d.ts +79 -0
  204. package/dist/extensions/admin-view.js +327 -0
  205. package/dist/extensions/approvals.d.ts +119 -0
  206. package/dist/extensions/approvals.js +205 -0
  207. package/dist/extensions/blobs.d.ts +45 -0
  208. package/dist/extensions/blobs.js +160 -0
  209. package/dist/extensions/bootstrap.d.ts +176 -0
  210. package/dist/extensions/bootstrap.js +535 -0
  211. package/dist/extensions/cli.d.ts +61 -0
  212. package/dist/extensions/cli.js +165 -0
  213. package/dist/extensions/config-json-schema.d.ts +9 -0
  214. package/dist/extensions/config-json-schema.js +73 -0
  215. package/dist/extensions/deployment-config.d.ts +138 -0
  216. package/dist/extensions/deployment-config.js +394 -0
  217. package/dist/extensions/enabled.d.ts +31 -0
  218. package/dist/extensions/enabled.js +55 -0
  219. package/dist/extensions/hooks.d.ts +161 -0
  220. package/dist/extensions/hooks.js +425 -0
  221. package/dist/extensions/host.d.ts +577 -0
  222. package/dist/extensions/host.js +2071 -0
  223. package/dist/extensions/inflight.d.ts +69 -0
  224. package/dist/extensions/inflight.js +277 -0
  225. package/dist/extensions/installs.d.ts +166 -0
  226. package/dist/extensions/installs.js +253 -0
  227. package/dist/extensions/instance.d.ts +167 -0
  228. package/dist/extensions/instance.js +329 -0
  229. package/dist/extensions/ledger.d.ts +30 -0
  230. package/dist/extensions/ledger.js +50 -0
  231. package/dist/extensions/lifecycle.d.ts +80 -0
  232. package/dist/extensions/lifecycle.js +152 -0
  233. package/dist/extensions/migrate-lock.d.ts +51 -0
  234. package/dist/extensions/migrate-lock.js +100 -0
  235. package/dist/extensions/org-config.controller.d.ts +24 -0
  236. package/dist/extensions/org-config.controller.js +59 -0
  237. package/dist/extensions/org-config.d.ts +169 -0
  238. package/dist/extensions/org-config.js +520 -0
  239. package/dist/extensions/package.d.ts +115 -0
  240. package/dist/extensions/package.js +246 -0
  241. package/dist/extensions/permission-set.d.ts +117 -0
  242. package/dist/extensions/permission-set.js +184 -0
  243. package/dist/extensions/permission-view.d.ts +194 -0
  244. package/dist/extensions/permission-view.js +284 -0
  245. package/dist/extensions/registry.d.ts +24 -0
  246. package/dist/extensions/registry.js +56 -0
  247. package/dist/extensions/resolve.d.ts +12 -0
  248. package/dist/extensions/resolve.js +71 -0
  249. package/dist/extensions/sources.d.ts +69 -0
  250. package/dist/extensions/sources.js +120 -0
  251. package/dist/extensions/sync.d.ts +40 -0
  252. package/dist/extensions/sync.js +242 -0
  253. package/dist/files/previewers.controller.d.ts +46 -0
  254. package/dist/files/previewers.controller.js +105 -0
  255. package/dist/files/previewers.d.ts +100 -0
  256. package/dist/files/previewers.js +250 -0
  257. package/dist/http/api.module.d.ts +114 -0
  258. package/dist/http/api.module.js +448 -0
  259. package/dist/http/app.d.ts +77 -0
  260. package/dist/http/app.js +220 -0
  261. package/dist/http/error.filter.d.ts +21 -0
  262. package/dist/http/error.filter.js +85 -0
  263. package/dist/http/gateway.module.d.ts +15 -0
  264. package/dist/http/gateway.module.js +13 -0
  265. package/dist/http/health.controller.d.ts +26 -0
  266. package/dist/http/health.controller.js +79 -0
  267. package/dist/http/nest-logger.d.ts +20 -0
  268. package/dist/http/nest-logger.js +28 -0
  269. package/dist/http/plugin-dispatch.d.ts +68 -0
  270. package/dist/http/plugin-dispatch.js +200 -0
  271. package/dist/http/tokens.d.ts +131 -0
  272. package/dist/http/tokens.js +131 -0
  273. package/dist/http/zod.pipe.d.ts +8 -0
  274. package/dist/http/zod.pipe.js +14 -0
  275. package/dist/identity/accounts.d.ts +93 -0
  276. package/dist/identity/accounts.js +367 -0
  277. package/dist/identity/api-tokens.d.ts +73 -0
  278. package/dist/identity/api-tokens.js +197 -0
  279. package/dist/identity/audit.d.ts +23 -0
  280. package/dist/identity/audit.js +41 -0
  281. package/dist/identity/auth.controller.d.ts +40 -0
  282. package/dist/identity/auth.controller.js +130 -0
  283. package/dist/identity/auth.guard.d.ts +41 -0
  284. package/dist/identity/auth.guard.js +162 -0
  285. package/dist/identity/binding.d.ts +47 -0
  286. package/dist/identity/binding.js +84 -0
  287. package/dist/identity/cookies.d.ts +16 -0
  288. package/dist/identity/cookies.js +32 -0
  289. package/dist/identity/credential-check.d.ts +17 -0
  290. package/dist/identity/credential-check.js +24 -0
  291. package/dist/identity/enterprise-admin.d.ts +14 -0
  292. package/dist/identity/enterprise-admin.js +27 -0
  293. package/dist/identity/external.d.ts +106 -0
  294. package/dist/identity/external.js +337 -0
  295. package/dist/identity/hash.d.ts +2 -0
  296. package/dist/identity/hash.js +3 -0
  297. package/dist/identity/login.d.ts +6 -0
  298. package/dist/identity/login.js +20 -0
  299. package/dist/identity/me.controller.d.ts +61 -0
  300. package/dist/identity/me.controller.js +159 -0
  301. package/dist/identity/passwords.d.ts +6 -0
  302. package/dist/identity/passwords.js +37 -0
  303. package/dist/identity/principal.d.ts +56 -0
  304. package/dist/identity/principal.js +38 -0
  305. package/dist/identity/rate-limit.d.ts +55 -0
  306. package/dist/identity/rate-limit.js +121 -0
  307. package/dist/identity/sessions.d.ts +84 -0
  308. package/dist/identity/sessions.js +306 -0
  309. package/dist/identity/settings.d.ts +121 -0
  310. package/dist/identity/settings.js +248 -0
  311. package/dist/identity/sso.controller.d.ts +59 -0
  312. package/dist/identity/sso.controller.js +192 -0
  313. package/dist/identity/sso.d.ts +83 -0
  314. package/dist/identity/sso.js +202 -0
  315. package/dist/inbox/inbox.service.d.ts +43 -0
  316. package/dist/inbox/inbox.service.js +57 -0
  317. package/dist/index.d.ts +69 -0
  318. package/dist/index.js +67 -0
  319. package/dist/kernel.d.ts +259 -0
  320. package/dist/kernel.js +1326 -0
  321. package/dist/log-config.d.ts +9 -0
  322. package/dist/log-config.js +27 -0
  323. package/dist/log-context.d.ts +32 -0
  324. package/dist/log-context.js +40 -0
  325. package/dist/log-loki.d.ts +34 -0
  326. package/dist/log-loki.js +145 -0
  327. package/dist/log.d.ts +79 -0
  328. package/dist/log.js +303 -0
  329. package/dist/models/prices.d.ts +53 -0
  330. package/dist/models/prices.js +121 -0
  331. package/dist/models/purposes.controller.d.ts +19 -0
  332. package/dist/models/purposes.controller.js +56 -0
  333. package/dist/models/purposes.d.ts +140 -0
  334. package/dist/models/purposes.js +267 -0
  335. package/dist/net/proxy.d.ts +44 -0
  336. package/dist/net/proxy.js +162 -0
  337. package/dist/net/public-address.d.ts +60 -0
  338. package/dist/net/public-address.js +272 -0
  339. package/dist/net/safe-fetch.d.ts +38 -0
  340. package/dist/net/safe-fetch.js +140 -0
  341. package/dist/orgs/directory-sync.controller.d.ts +14 -0
  342. package/dist/orgs/directory-sync.controller.js +40 -0
  343. package/dist/orgs/directory-sync.d.ts +166 -0
  344. package/dist/orgs/directory-sync.js +558 -0
  345. package/dist/orgs/invitations.controller.d.ts +58 -0
  346. package/dist/orgs/invitations.controller.js +137 -0
  347. package/dist/orgs/invitations.service.d.ts +80 -0
  348. package/dist/orgs/invitations.service.js +217 -0
  349. package/dist/orgs/members.service.d.ts +63 -0
  350. package/dist/orgs/members.service.js +234 -0
  351. package/dist/orgs/offboarding.d.ts +141 -0
  352. package/dist/orgs/offboarding.js +398 -0
  353. package/dist/orgs/org-lock.d.ts +32 -0
  354. package/dist/orgs/org-lock.js +46 -0
  355. package/dist/orgs/org.guard.d.ts +35 -0
  356. package/dist/orgs/org.guard.js +95 -0
  357. package/dist/orgs/orgs.controller.d.ts +78 -0
  358. package/dist/orgs/orgs.controller.js +192 -0
  359. package/dist/orgs/orgs.service.d.ts +61 -0
  360. package/dist/orgs/orgs.service.js +209 -0
  361. package/dist/orgs/roles.d.ts +13 -0
  362. package/dist/orgs/roles.js +58 -0
  363. package/dist/orgs/settings.controller.d.ts +20 -0
  364. package/dist/orgs/settings.controller.js +53 -0
  365. package/dist/orgs/settings.service.d.ts +120 -0
  366. package/dist/orgs/settings.service.js +178 -0
  367. package/dist/packages/npm.d.ts +50 -0
  368. package/dist/packages/npm.js +218 -0
  369. package/dist/packages/provenance.d.ts +47 -0
  370. package/dist/packages/provenance.js +147 -0
  371. package/dist/packages/tgz.d.ts +76 -0
  372. package/dist/packages/tgz.js +225 -0
  373. package/dist/runtime/abort.d.ts +32 -0
  374. package/dist/runtime/abort.js +71 -0
  375. package/dist/runtime/checkpointer.d.ts +32 -0
  376. package/dist/runtime/checkpointer.js +243 -0
  377. package/dist/runtime/context/build.d.ts +254 -0
  378. package/dist/runtime/context/build.js +693 -0
  379. package/dist/runtime/context/claude-tools.d.ts +11 -0
  380. package/dist/runtime/context/claude-tools.js +24 -0
  381. package/dist/runtime/context/compaction.d.ts +26 -0
  382. package/dist/runtime/context/compaction.js +195 -0
  383. package/dist/runtime/context/pairing.d.ts +11 -0
  384. package/dist/runtime/context/pairing.js +82 -0
  385. package/dist/runtime/context/reminders.d.ts +5 -0
  386. package/dist/runtime/context/reminders.js +11 -0
  387. package/dist/runtime/context/skills.d.ts +105 -0
  388. package/dist/runtime/context/skills.js +283 -0
  389. package/dist/runtime/context/tokens.d.ts +19 -0
  390. package/dist/runtime/context/tokens.js +104 -0
  391. package/dist/runtime/conversation-lock.d.ts +40 -0
  392. package/dist/runtime/conversation-lock.js +97 -0
  393. package/dist/runtime/hook-calls.d.ts +84 -0
  394. package/dist/runtime/hook-calls.js +136 -0
  395. package/dist/runtime/langgraph-loop.d.ts +52 -0
  396. package/dist/runtime/langgraph-loop.js +247 -0
  397. package/dist/runtime/loop.d.ts +93 -0
  398. package/dist/runtime/loop.js +7 -0
  399. package/dist/runtime/maintenance.d.ts +80 -0
  400. package/dist/runtime/maintenance.js +148 -0
  401. package/dist/runtime/media-cache.d.ts +21 -0
  402. package/dist/runtime/media-cache.js +51 -0
  403. package/dist/runtime/model-call.d.ts +176 -0
  404. package/dist/runtime/model-call.js +1049 -0
  405. package/dist/runtime/providers.d.ts +86 -0
  406. package/dist/runtime/providers.js +224 -0
  407. package/dist/runtime/quota.d.ts +29 -0
  408. package/dist/runtime/quota.js +70 -0
  409. package/dist/runtime/run-finish.d.ts +45 -0
  410. package/dist/runtime/run-finish.js +69 -0
  411. package/dist/runtime/run-queue.d.ts +121 -0
  412. package/dist/runtime/run-queue.js +493 -0
  413. package/dist/runtime/run-worker.d.ts +138 -0
  414. package/dist/runtime/run-worker.js +806 -0
  415. package/dist/runtime/stream.controller.d.ts +34 -0
  416. package/dist/runtime/stream.controller.js +122 -0
  417. package/dist/runtime/stream.d.ts +63 -0
  418. package/dist/runtime/stream.js +262 -0
  419. package/dist/runtime/subagents/child.d.ts +80 -0
  420. package/dist/runtime/subagents/child.js +225 -0
  421. package/dist/runtime/subagents/definition.d.ts +103 -0
  422. package/dist/runtime/subagents/definition.js +392 -0
  423. package/dist/runtime/subagents/dispatch.d.ts +69 -0
  424. package/dist/runtime/subagents/dispatch.js +502 -0
  425. package/dist/runtime/subagents/limits.d.ts +23 -0
  426. package/dist/runtime/subagents/limits.js +34 -0
  427. package/dist/runtime/subagents/org-agents.d.ts +50 -0
  428. package/dist/runtime/subagents/org-agents.js +70 -0
  429. package/dist/runtime/subagents/preamble.d.ts +7 -0
  430. package/dist/runtime/subagents/preamble.js +11 -0
  431. package/dist/runtime/subagents/progress.d.ts +26 -0
  432. package/dist/runtime/subagents/progress.js +36 -0
  433. package/dist/runtime/subagents/roster.d.ts +55 -0
  434. package/dist/runtime/subagents/roster.js +111 -0
  435. package/dist/runtime/subagents/skill-fork.d.ts +123 -0
  436. package/dist/runtime/subagents/skill-fork.js +259 -0
  437. package/dist/runtime/usage-report.d.ts +163 -0
  438. package/dist/runtime/usage-report.js +551 -0
  439. package/dist/runtime/waits.d.ts +233 -0
  440. package/dist/runtime/waits.js +883 -0
  441. package/dist/sandbox/leases.d.ts +169 -0
  442. package/dist/sandbox/leases.js +515 -0
  443. package/dist/sandbox/lifecycle.d.ts +21 -0
  444. package/dist/sandbox/lifecycle.js +68 -0
  445. package/dist/sandbox/sandbox.service.d.ts +249 -0
  446. package/dist/sandbox/sandbox.service.js +908 -0
  447. package/dist/skills/catalog.d.ts +149 -0
  448. package/dist/skills/catalog.js +405 -0
  449. package/dist/skills/changes.controller.d.ts +56 -0
  450. package/dist/skills/changes.controller.js +136 -0
  451. package/dist/skills/changes.service.d.ts +175 -0
  452. package/dist/skills/changes.service.js +805 -0
  453. package/dist/skills/invocable.controller.d.ts +23 -0
  454. package/dist/skills/invocable.controller.js +50 -0
  455. package/dist/skills/invocation-keys.d.ts +23 -0
  456. package/dist/skills/invocation-keys.js +44 -0
  457. package/dist/skills/invoke.d.ts +135 -0
  458. package/dist/skills/invoke.js +286 -0
  459. package/dist/skills/package.d.ts +87 -0
  460. package/dist/skills/package.js +227 -0
  461. package/dist/skills/skills.controller.d.ts +40 -0
  462. package/dist/skills/skills.controller.js +110 -0
  463. package/dist/skills/skills.service.d.ts +192 -0
  464. package/dist/skills/skills.service.js +567 -0
  465. package/dist/storage/prefix.d.ts +36 -0
  466. package/dist/storage/prefix.js +104 -0
  467. package/dist/storage/purge.d.ts +27 -0
  468. package/dist/storage/purge.js +75 -0
  469. package/dist/storage/storage.service.d.ts +44 -0
  470. package/dist/storage/storage.service.js +145 -0
  471. package/dist/text.d.ts +13 -0
  472. package/dist/text.js +13 -0
  473. package/dist/tools/approvals.controller.d.ts +53 -0
  474. package/dist/tools/approvals.controller.js +128 -0
  475. package/dist/tools/approvals.service.d.ts +172 -0
  476. package/dist/tools/approvals.service.js +568 -0
  477. package/dist/tools/breaker.d.ts +28 -0
  478. package/dist/tools/breaker.js +72 -0
  479. package/dist/tools/builtins/agent.d.ts +81 -0
  480. package/dist/tools/builtins/agent.js +223 -0
  481. package/dist/tools/builtins/ask-user.d.ts +28 -0
  482. package/dist/tools/builtins/ask-user.js +139 -0
  483. package/dist/tools/builtins/read-tool-output.d.ts +18 -0
  484. package/dist/tools/builtins/read-tool-output.js +108 -0
  485. package/dist/tools/builtins/sandbox/bash.d.ts +16 -0
  486. package/dist/tools/builtins/sandbox/bash.js +137 -0
  487. package/dist/tools/builtins/sandbox/common.d.ts +116 -0
  488. package/dist/tools/builtins/sandbox/common.js +306 -0
  489. package/dist/tools/builtins/sandbox/deliver.d.ts +5 -0
  490. package/dist/tools/builtins/sandbox/deliver.js +180 -0
  491. package/dist/tools/builtins/sandbox/edit.d.ts +4 -0
  492. package/dist/tools/builtins/sandbox/edit.js +98 -0
  493. package/dist/tools/builtins/sandbox/glob-match.d.ts +25 -0
  494. package/dist/tools/builtins/sandbox/glob-match.js +240 -0
  495. package/dist/tools/builtins/sandbox/glob.d.ts +4 -0
  496. package/dist/tools/builtins/sandbox/glob.js +104 -0
  497. package/dist/tools/builtins/sandbox/grep.d.ts +9 -0
  498. package/dist/tools/builtins/sandbox/grep.js +133 -0
  499. package/dist/tools/builtins/sandbox/index.d.ts +12 -0
  500. package/dist/tools/builtins/sandbox/index.js +27 -0
  501. package/dist/tools/builtins/sandbox/names.d.ts +7 -0
  502. package/dist/tools/builtins/sandbox/names.js +20 -0
  503. package/dist/tools/builtins/sandbox/read.d.ts +8 -0
  504. package/dist/tools/builtins/sandbox/read.js +121 -0
  505. package/dist/tools/builtins/sandbox/write.d.ts +4 -0
  506. package/dist/tools/builtins/sandbox/write.js +88 -0
  507. package/dist/tools/builtins/skill-load.d.ts +53 -0
  508. package/dist/tools/builtins/skill-load.js +446 -0
  509. package/dist/tools/builtins/skill-write.d.ts +59 -0
  510. package/dist/tools/builtins/skill-write.js +244 -0
  511. package/dist/tools/builtins/tool-search.d.ts +31 -0
  512. package/dist/tools/builtins/tool-search.js +171 -0
  513. package/dist/tools/connector-content.controller.d.ts +34 -0
  514. package/dist/tools/connector-content.controller.js +78 -0
  515. package/dist/tools/connector-content.d.ts +104 -0
  516. package/dist/tools/connector-content.js +267 -0
  517. package/dist/tools/connectors.controller.d.ts +210 -0
  518. package/dist/tools/connectors.controller.js +234 -0
  519. package/dist/tools/connectors.service.d.ts +303 -0
  520. package/dist/tools/connectors.service.js +1102 -0
  521. package/dist/tools/credentials.d.ts +139 -0
  522. package/dist/tools/credentials.js +351 -0
  523. package/dist/tools/drift.d.ts +141 -0
  524. package/dist/tools/drift.js +539 -0
  525. package/dist/tools/elicitation.d.ts +81 -0
  526. package/dist/tools/elicitation.js +266 -0
  527. package/dist/tools/endpoint.d.ts +18 -0
  528. package/dist/tools/endpoint.js +115 -0
  529. package/dist/tools/info.d.ts +67 -0
  530. package/dist/tools/info.js +113 -0
  531. package/dist/tools/naming.d.ts +27 -0
  532. package/dist/tools/naming.js +47 -0
  533. package/dist/tools/oauth/discovery.d.ts +65 -0
  534. package/dist/tools/oauth/discovery.js +307 -0
  535. package/dist/tools/oauth/flow.d.ts +63 -0
  536. package/dist/tools/oauth/flow.js +237 -0
  537. package/dist/tools/oauth/oauth.controller.d.ts +31 -0
  538. package/dist/tools/oauth/oauth.controller.js +95 -0
  539. package/dist/tools/oauth/tokens.d.ts +111 -0
  540. package/dist/tools/oauth/tokens.js +258 -0
  541. package/dist/tools/outputs.d.ts +61 -0
  542. package/dist/tools/outputs.js +156 -0
  543. package/dist/tools/pipeline.d.ts +322 -0
  544. package/dist/tools/pipeline.js +1236 -0
  545. package/dist/tools/policy.d.ts +60 -0
  546. package/dist/tools/policy.js +236 -0
  547. package/dist/tools/questions.controller.d.ts +24 -0
  548. package/dist/tools/questions.controller.js +58 -0
  549. package/dist/tools/questions.service.d.ts +103 -0
  550. package/dist/tools/questions.service.js +295 -0
  551. package/dist/tools/redact.d.ts +20 -0
  552. package/dist/tools/redact.js +60 -0
  553. package/dist/tools/registry.d.ts +246 -0
  554. package/dist/tools/registry.js +481 -0
  555. package/dist/tools/resources.d.ts +16 -0
  556. package/dist/tools/resources.js +76 -0
  557. package/dist/tools/specs.d.ts +14 -0
  558. package/dist/tools/specs.js +31 -0
  559. package/dist/tools/validate.d.ts +20 -0
  560. package/dist/tools/validate.js +183 -0
  561. package/dist/tools/view.d.ts +43 -0
  562. package/dist/tools/view.js +225 -0
  563. package/dist/ui/embed-token.d.ts +31 -0
  564. package/dist/ui/embed-token.js +132 -0
  565. package/dist/ui/registry.d.ts +58 -0
  566. package/dist/ui/registry.js +90 -0
  567. package/dist/ui/ui-stream.d.ts +37 -0
  568. package/dist/ui/ui-stream.js +162 -0
  569. package/dist/ui/views.controller.d.ts +81 -0
  570. package/dist/ui/views.controller.js +261 -0
  571. package/dist/ui/views.d.ts +155 -0
  572. package/dist/ui/views.js +306 -0
  573. package/dist/version.d.ts +5 -0
  574. package/dist/version.js +6 -0
  575. package/package.json +69 -3
  576. package/src/migrations/0001_init.sql +8 -0
  577. package/src/migrations/0002_secrets.sql +8 -0
  578. package/src/migrations/0003_identity.sql +117 -0
  579. package/src/migrations/0004_plugin_org_config_nullable.sql +3 -0
  580. package/src/migrations/0005_agents.sql +27 -0
  581. package/src/migrations/0006_conversations.sql +37 -0
  582. package/src/migrations/0007_checkpoints.sql +26 -0
  583. package/src/migrations/0008_runs_trigger_seq.sql +3 -0
  584. package/src/migrations/0009_runs_active_unique.sql +4 -0
  585. package/src/migrations/0010_tools.sql +125 -0
  586. package/src/migrations/0011_approvals_spec.sql +10 -0
  587. package/src/migrations/0012_run_waits.sql +24 -0
  588. package/src/migrations/0013_app_tools_source.sql +4 -0
  589. package/src/migrations/0014_tool_specs.sql +8 -0
  590. package/src/migrations/0015_tool_drift.sql +20 -0
  591. package/src/migrations/0016_plugin_permissions.sql +11 -0
  592. package/src/migrations/0017_identity_sources.sql +6 -0
  593. package/src/migrations/0018_channels.sql +74 -0
  594. package/src/migrations/0019_identity_trust.sql +17 -0
  595. package/src/migrations/0020_channel_card_lookup.sql +10 -0
  596. package/src/migrations/0021_org_storage_purge.sql +9 -0
  597. package/src/migrations/0022_attachments.sql +29 -0
  598. package/src/migrations/0023_sandboxes.sql +37 -0
  599. package/src/migrations/0024_skills.sql +46 -0
  600. package/src/migrations/0025_skills_catalog_idx.sql +6 -0
  601. package/src/migrations/0026_skill_changes.sql +34 -0
  602. package/src/migrations/0027_model_prices.sql +18 -0
  603. package/src/migrations/0028_evals.sql +105 -0
  604. package/src/migrations/0029_model_purposes.sql +18 -0
  605. package/src/migrations/0030_plugin_installs.sql +73 -0
  606. package/src/migrations/0031_plugin_snapshot_source.sql +6 -0
  607. package/src/migrations/0032_plugin_deployment_configs.sql +10 -0
  608. package/src/migrations/0033_rename_apps_to_connectors.sql +25 -0
  609. package/src/migrations/0034_directory.sql +49 -0
  610. package/src/migrations/0035_catalogs.sql +40 -0
  611. package/src/migrations/0036_app_import_staging.sql +17 -0
  612. package/src/migrations/0037_directory_installs.sql +92 -0
  613. package/src/migrations/0038_channel_inbound_mode.sql +6 -0
  614. package/src/migrations/0039_channel_card_pending.sql +8 -0
  615. package/src/migrations/0040_usage_report_sweep.sql +10 -0
  616. package/src/migrations/0041_rename_plugins_to_extensions.sql +38 -0
  617. package/src/migrations/0042_rename_directory_to_catalog.sql +80 -0
  618. package/src/migrations/0043_rename_app_installs_to_plugin_installs.sql +20 -0
  619. package/src/migrations/0044_catalog_one_kind.sql +90 -0
  620. package/src/migrations/0045_plugin_dependencies.sql +9 -0
  621. package/src/migrations/0046_git_sources.sql +25 -0
  622. package/src/migrations/0047_marketplace_entry_heads.sql +7 -0
  623. package/src/migrations/0048_marketplace_entry_trees.sql +8 -0
  624. package/src/migrations/0049_plugin_upgrades.sql +37 -0
  625. package/src/migrations/0050_bootstrap.sql +53 -0
  626. package/src/migrations/0051_claude_compat.sql +26 -0
  627. package/src/migrations/0052_conversations_account_agent_idx.sql +5 -0
  628. package/src/migrations/0053_subagents.sql +73 -0
  629. package/src/migrations/0054_subagent_wait_expiry.sql +7 -0
  630. package/src/migrations/0055_subagent_parent_indexes.sql +10 -0
  631. package/src/migrations/0056_approval_reason.sql +3 -0
  632. package/src/migrations/0057_conversation_titles.sql +11 -0
  633. package/src/migrations/0058_conversation_selection.sql +4 -0
  634. package/src/migrations/0059_conversation_queue.sql +22 -0
  635. package/src/migrations/0060_file_previewers.sql +10 -0
  636. package/src/migrations/0061_queue_selection.sql +5 -0
  637. package/src/migrations/0062_queued_skill.sql +8 -0
@@ -0,0 +1,551 @@
1
+ import { DelayedError, Job, Queue, UnrecoverableError, Worker } from "bullmq";
2
+ import { sql } from "kysely";
3
+ import { enabledExtensionsQuery } from "../extensions/enabled.js";
4
+ import { deepFreeze, errMsg } from "../extensions/hooks.js";
5
+ import { withJobContext } from "../log-context.js";
6
+ import { bullConnection } from "./run-queue.js";
7
+ /** Queue of `usage.report` deliveries (no `:` in the name). */
8
+ export const USAGE_REPORT_QUEUE = "cap-kernel-usage-report";
9
+ /** One job per `usage` event (no `:`: conversation ids are UUIDs, seq is a number). */
10
+ export const usageReportJobId = (conversationId, seq) => `usage-${conversationId}-${seq}`;
11
+ /** First attempt plus 5 retries (F11). */
12
+ export const USAGE_REPORT_ATTEMPTS = 6;
13
+ /** Retry backoff: 2 s, doubling (2, 4, 8, 16, 32 s). */
14
+ export const USAGE_REPORT_BACKOFF_MS = 2000;
15
+ /** Failed jobs (given up) are kept for inspection, at most {@link KEEP_FAILED_MAX} of them. */
16
+ const KEEP_FAILED_S = 7 * 86_400;
17
+ /** Upper bound on kept failed jobs (I-2): a long outage of a billing endpoint cannot grow Redis. */
18
+ const KEEP_FAILED_MAX = 100_000;
19
+ /** Warnings about a plugin that cannot take deliveries are logged at most once per this window. */
20
+ const WARN_WINDOW_MS = 60_000;
21
+ /**
22
+ * Upper bound on kept finished jobs (Redis memory). At the default retention it only bites above
23
+ * ~1.1 usage events per second sustained for a day; dedupe needs the jobs only for the sweeper overlap.
24
+ */
25
+ const KEEP_COMPLETED_MAX = 100_000;
26
+ /** Maintenance job of the sweeper (no `:`), its scheduler id and period. */
27
+ export const USAGE_SWEEP_JOB = "usage-report-sweep";
28
+ export const USAGE_SWEEP_SCHEDULER_ID = "usage-report-sweep-every";
29
+ export const USAGE_SWEEP_EVERY_MS = 60_000;
30
+ /** The sweep leaves the newest events to the fast path (and to transactions still committing). */
31
+ export const USAGE_SWEEP_LAG_MS = 30_000;
32
+ /**
33
+ * Each sweep re-scans this far behind the watermark: events whose transaction committed after a
34
+ * previous sweep passed their `created_at` are still found. Far inside the dedupe window
35
+ * (`hooks.usageReportKeepHours` ≥ 1 h), so re-enqueued events dedupe on the kept job.
36
+ */
37
+ export const USAGE_SWEEP_OVERLAP_MS = 10 * 60_000;
38
+ const SWEEP_PAGE = 500;
39
+ const JOB = "usage-report";
40
+ /**
41
+ * Plugins that subscribe to `usage.report` according to deployment state: an approved permission
42
+ * snapshot that declares the `usage.report` hook, for a plugin the deployment still knows: an enabled
43
+ * install, or a config-declared plugin with a replica status row that is not `unloaded`. With `orgId`, only plugins
44
+ * the organization enabled (org config rows and required bootstrap plugins).
45
+ */
46
+ export async function queryUsageSubscribers(db, orgId) {
47
+ let q = db
48
+ .selectFrom("extension_permission_snapshots as s")
49
+ .select("s.plugin")
50
+ .where(sql `s.permissions -> 'permissions' -> 'hooks' ? 'usage.report'`)
51
+ .where((eb) => eb.or([
52
+ eb.exists(eb
53
+ .selectFrom("extension_installs as i")
54
+ .select(sql `1`.as("one"))
55
+ .whereRef("i.name", "=", "s.plugin")
56
+ .where("i.desired_state", "=", "enabled")),
57
+ // config-declared plugins still declared (and not unloaded) on some replica; installs are
58
+ // covered by desired_state above (their replica rows linger as `unloaded` when disabled)
59
+ eb.exists(eb
60
+ .selectFrom("extension_replica_status as r")
61
+ .select(sql `1`.as("one"))
62
+ .whereRef("r.plugin", "=", "s.plugin")
63
+ .where("r.source", "=", "config")
64
+ .where("r.state", "<>", "unloaded")),
65
+ ]));
66
+ if (orgId !== undefined) {
67
+ q = q.where("s.plugin", "in", enabledExtensionsQuery(db, orgId));
68
+ }
69
+ return new Set((await q.execute()).map((r) => r.plugin));
70
+ }
71
+ /**
72
+ * Of `plugins`, those that are **definitely** unservable right now (I-2, N-3): live replicas report
73
+ * them (a `extension_replica_status` row with a heartbeat newer than `staleSeconds`), no live row is
74
+ * `loaded` or still serves an older version (`serving_version`, e.g. an upgrade pending approval), and
75
+ * the rows are not all `unloaded` (that is the state right after a re-enable, before the replicas
76
+ * reconcile). A plugin with no live row at all is unknown too (slow to load, or a host without a
77
+ * status store). Unknown plugins are never listed.
78
+ */
79
+ export async function queryUnservable(db, plugins, staleSeconds) {
80
+ if (plugins.length === 0)
81
+ return new Set();
82
+ const rows = await db
83
+ .selectFrom("extension_replica_status")
84
+ .select("plugin")
85
+ .where("plugin", "in", [...plugins])
86
+ .where("heartbeat_at", ">", sql `now() - make_interval(secs => ${staleSeconds})`)
87
+ .groupBy("plugin")
88
+ .having(sql `bool_or(state = 'loaded' OR serving_version IS NOT NULL)`, "=", false)
89
+ .having(sql `bool_and(state = 'unloaded')`, "=", false)
90
+ .execute();
91
+ return new Set(rows.map((r) => r.plugin));
92
+ }
93
+ /** `" dropped: x (why), y (why)"`, or empty. */
94
+ const droppedNote = (dropped) => dropped.size === 0
95
+ ? ""
96
+ : ` dropped: ${[...dropped].map(([p, why]) => `${p} (${why})`).join(", ")}`;
97
+ /** A target this replica cannot deliver to: not loaded here, or loaded without a handler. */
98
+ class Undeliverable extends Error {
99
+ plugin;
100
+ why;
101
+ constructor(plugin, why) {
102
+ super(why === "no_handler"
103
+ ? `plugin ${plugin} is loaded on this replica but registered no usage.report handler`
104
+ : `plugin ${plugin} has no usage.report handler on this replica`);
105
+ this.plugin = plugin;
106
+ this.why = why;
107
+ this.name = "Undeliverable";
108
+ }
109
+ }
110
+ /**
111
+ * The next `pending` set (m-2 fence): plugins that failed now, narrowed to what the stored job data
112
+ * still lists. A plugin another (stalled-over) execution already delivered never comes back.
113
+ */
114
+ export function narrowPending(stored, failed) {
115
+ return stored === undefined ? [...failed] : failed.filter((p) => stored.includes(p));
116
+ }
117
+ /**
118
+ * Reliable `usage.report` delivery (F11, P-17, R13). Every `usage` event written to the event log (chat
119
+ * runs and full-run eval replays) is delivered at least once to every subscribing plugin.
120
+ * - **Fast path:** `model-call` enqueues job `usage-<conversationId>-<seq>` right after writing the event
121
+ * (never awaited; an enqueue failure only logs). Skipped without I/O when this replica has no
122
+ * `usage.report` handler (M-2); the sweeper then offers the event.
123
+ * - **Sweeper (R13):** a maintenance job (once across replicas, every minute) re-enqueues the `usage`
124
+ * events in `[watermark - 10 min, now - 30 s]` with the same job ids, so a lost fast-path enqueue is
125
+ * caught up and duplicates dedupe on the kept job (`hooks.usageReportKeepHours`).
126
+ * - **Worker** (worker role, `hooks.usageReportConcurrency` per replica): reads the payload from the log
127
+ * at execution time (the `usage` event, the conversation with `kind`, the run). On the first attempt
128
+ * the targets are the deployment's subscribers the organization enabled (I-2: not this replica's
129
+ * handlers), written into `pending`; plugins run concurrently (`allSettled`); failed ones stay in
130
+ * `pending` and are retried (5 retries, 2 s doubling). A plugin not loaded on this replica (or
131
+ * between generations) is a failure, so another replica or a later attempt delivers it. On the
132
+ * last attempt it is dropped only when it is definitely unservable ({@link queryUnservable});
133
+ * otherwise the job fails as usual. A plugin loaded here that registered no handler is dropped at
134
+ * once (I-2). A drop (N-3) is never silent: after delivering to the other targets the job ends
135
+ * failed with an `UnrecoverableError` whose failedReason names the dropped plugins, plus a
136
+ * throttled warning. Plugins the organization disabled by delivery time are dropped silently (not
137
+ * targets any more). The final failure logs an error (no audit); failed jobs are kept 7 days, at
138
+ * most 100 000. Each call runs through the instance's `inflight.run`, limited by `hooks.timeoutMs`;
139
+ * when this replica stops, in-flight calls are aborted and the job goes back to the queue without
140
+ * using up an attempt.
141
+ * Handlers must be idempotent by `eventId` (`<conversationId>/<seq>`). Nothing is written to the event
142
+ * log (never model-visible). Compaction calls log usage too (`purpose: "compaction"`) and are reported,
143
+ * as are conversation title calls (`purpose: "title"`, no run: `runId` is "").
144
+ * Single-step eval replays and judge requests log no usage: not reported (M7).
145
+ */
146
+ export class UsageReporter {
147
+ d;
148
+ queue;
149
+ queueConn;
150
+ worker;
151
+ workerConn;
152
+ closed = false;
153
+ stopping = new AbortController();
154
+ constructor(d) {
155
+ this.d = d;
156
+ }
157
+ jobOpts(conversationId, seq) {
158
+ return {
159
+ jobId: usageReportJobId(conversationId, seq),
160
+ attempts: this.d.retry?.attempts ?? USAGE_REPORT_ATTEMPTS,
161
+ backoff: { type: "exponential", delay: this.d.retry?.backoffMs ?? USAGE_REPORT_BACKOFF_MS },
162
+ removeOnComplete: {
163
+ age: this.d.config().hooks.usageReportKeepHours * 3600,
164
+ count: KEEP_COMPLETED_MAX,
165
+ },
166
+ removeOnFail: { age: KEEP_FAILED_S, count: KEEP_FAILED_MAX },
167
+ };
168
+ }
169
+ /**
170
+ * Enqueues the delivery of one `usage` event. Returns without a job when no plugin subscribes.
171
+ * Never throws: an enqueue failure (e.g. a Redis hiccup) only logs a warning; the sweeper catches up.
172
+ */
173
+ async enqueue(conversationId, seq) {
174
+ if (this.closed)
175
+ return;
176
+ // M-2: no usage.report handler on this replica → no I/O at all. A plugin loaded only on other
177
+ // replicas still gets the event: the sweeper re-offers it within about a minute and a half.
178
+ if (!this.d.hooks.has("usage.report"))
179
+ return;
180
+ try {
181
+ if ((await this.d.subscribers()).size === 0)
182
+ return;
183
+ await this.getQueue().add(JOB, { conversationId, seq }, this.jobOpts(conversationId, seq));
184
+ }
185
+ catch (err) {
186
+ this.d.log.warn("cannot enqueue usage report", { conversationId, seq, err });
187
+ }
188
+ }
189
+ /**
190
+ * One sweep (R13): re-enqueues the `usage` events created in `[watermark - overlap, now - lag]` in
191
+ * pages, then advances the watermark to `now - lag`. With no subscriber it only advances. The first
192
+ * sweep starts at `now - lag - overlap`. Returns the number of events offered to the queue.
193
+ */
194
+ async sweep(opts = {}) {
195
+ // bounds and keyset as full-precision timestamp text (microseconds), computed with the DB clock
196
+ // unless a test fixes "now" (m-a, m-c)
197
+ const to = opts.now !== undefined
198
+ ? new Date(opts.now - USAGE_SWEEP_LAG_MS).toISOString()
199
+ : (await sql `SELECT (now() - make_interval(secs => ${USAGE_SWEEP_LAG_MS / 1000}))::text AS to`.execute(this.d.db)).rows[0]?.to;
200
+ if (to === undefined)
201
+ return 0;
202
+ const row = await this.d.db
203
+ .selectFrom("usage_report_sweep")
204
+ .select(sql `watermark::text`.as("watermark"))
205
+ .where("id", "=", 1)
206
+ .executeTakeFirst();
207
+ const watermark = row?.watermark ?? to;
208
+ let offered = 0;
209
+ if ((await this.d.subscribers()).size > 0) {
210
+ let after;
211
+ for (;;) {
212
+ let q = this.d.db
213
+ .selectFrom("conversation_events")
214
+ .select(["conversation_id", "seq", sql `created_at::text`.as("at")])
215
+ .where("type", "=", "usage")
216
+ .where(sql `created_at >= ${watermark}::timestamptz - make_interval(secs => ${USAGE_SWEEP_OVERLAP_MS / 1000})`)
217
+ .where(sql `created_at <= ${to}::timestamptz`);
218
+ if (after) {
219
+ q = q.where(sql `(created_at, conversation_id, seq) > (${after.at}::timestamptz, ${after.conv}, ${after.seq}::bigint)`);
220
+ }
221
+ const page = await q
222
+ .orderBy("created_at")
223
+ .orderBy("conversation_id")
224
+ .orderBy("seq")
225
+ .limit(SWEEP_PAGE)
226
+ .execute();
227
+ if (page.length > 0) {
228
+ await this.getQueue().addBulk(page.map((r) => ({
229
+ name: JOB,
230
+ data: { conversationId: r.conversation_id, seq: Number(r.seq) },
231
+ opts: this.jobOpts(r.conversation_id, Number(r.seq)),
232
+ })));
233
+ offered += page.length;
234
+ }
235
+ const last = page.at(-1);
236
+ if (!last || page.length < SWEEP_PAGE)
237
+ break;
238
+ after = { at: last.at, conv: last.conversation_id, seq: String(last.seq) };
239
+ }
240
+ }
241
+ await this.d.db
242
+ .insertInto("usage_report_sweep")
243
+ .values({ id: 1, watermark: sql `${to}::timestamptz` })
244
+ .onConflict((oc) => oc.column("id").doUpdateSet({
245
+ watermark: sql `GREATEST(usage_report_sweep.watermark, excluded.watermark)`,
246
+ updated_at: sql `now()`,
247
+ }))
248
+ .execute();
249
+ return offered;
250
+ }
251
+ /** Starts the worker (worker role only). Job lock and stalled detection follow the run queue. */
252
+ startWorker() {
253
+ if (this.worker || this.closed)
254
+ return;
255
+ const { jobLockMs, stalledIntervalMs } = this.d.config().runtime;
256
+ // the queue exists before any job runs: in-flight jobs fence and requeue through it, even on a
257
+ // replica that never enqueued (m-b)
258
+ this.getQueue();
259
+ this.workerConn = bullConnection(this.d.redisUrl, this.d.log);
260
+ this.worker = new Worker(USAGE_REPORT_QUEUE, (j, t) => withJobContext(USAGE_REPORT_QUEUE, j, () => this.process(j, t)), {
261
+ connection: this.workerConn,
262
+ concurrency: this.d.config().hooks.usageReportConcurrency,
263
+ lockDuration: jobLockMs,
264
+ stalledInterval: stalledIntervalMs,
265
+ maxStalledCount: 3,
266
+ });
267
+ this.worker.on("error", (err) => this.d.log.error("usage report worker error", { err }));
268
+ this.worker.on("failed", (j, err) => {
269
+ if (!j || err instanceof DelayedError || err.name === "DelayedError")
270
+ return;
271
+ // a definite drop (N-3) was already warned about (throttled); the failed job is the trace
272
+ if (err instanceof UnrecoverableError || err.name === "UnrecoverableError")
273
+ return;
274
+ const final = j.attemptsMade >= (j.opts.attempts ?? 1);
275
+ const fields = {
276
+ jobId: j.id,
277
+ conversationId: j.data.conversationId,
278
+ seq: j.data.seq,
279
+ pending: j.data.pending,
280
+ attempt: j.attemptsMade,
281
+ error: err.message,
282
+ };
283
+ if (final)
284
+ this.d.log.error("usage report given up after retries", fields);
285
+ else
286
+ this.d.log.warn("usage report attempt failed; retrying", fields);
287
+ });
288
+ }
289
+ /** Stops the worker (in-flight calls are aborted, their jobs requeued) and the queue. */
290
+ async stop() {
291
+ this.closed = true;
292
+ this.stopping.abort();
293
+ const w = this.worker;
294
+ this.worker = undefined;
295
+ // the worker first: its in-flight jobs still use the queue to fence and requeue
296
+ await w?.close().catch(() => { });
297
+ const q = this.queue;
298
+ this.queue = undefined;
299
+ await q?.close().catch(() => { });
300
+ for (const c of [this.workerConn, this.queueConn]) {
301
+ if (c)
302
+ await c.quit().catch(() => c.disconnect());
303
+ }
304
+ this.workerConn = undefined;
305
+ this.queueConn = undefined;
306
+ }
307
+ getQueue() {
308
+ if (!this.queue) {
309
+ if (this.closed)
310
+ throw new Error("usage report queue is closed");
311
+ this.queueConn = bullConnection(this.d.redisUrl, this.d.log);
312
+ this.queue = new Queue(USAGE_REPORT_QUEUE, { connection: this.queueConn });
313
+ this.queue.on("error", (err) => this.d.log.error("usage report queue error", { err }));
314
+ }
315
+ return this.queue;
316
+ }
317
+ /** The payload of one usage event, read from the log; null when the event no longer exists. */
318
+ async payloadOf(conversationId, seq) {
319
+ const row = await this.d.db
320
+ .selectFrom("conversation_events as e")
321
+ .innerJoin("conversations as c", "c.id", "e.conversation_id")
322
+ .leftJoin("runs as r", "r.id", "e.run_id")
323
+ // a sub-agent's run: its dispatch says where it was dispatched from (spec §11)
324
+ .leftJoin("subagent_dispatches as sd", "sd.child_run_id", "e.run_id")
325
+ .select([
326
+ "e.payload",
327
+ "e.run_id",
328
+ "e.created_at",
329
+ "e.type",
330
+ "c.org_id",
331
+ "c.agent_id",
332
+ "c.account_id",
333
+ "c.kind",
334
+ "r.trigger_account_id",
335
+ "sd.parent_conversation_id",
336
+ "sd.parent_run_id",
337
+ "sd.parent_call_id",
338
+ ])
339
+ .where("e.conversation_id", "=", conversationId)
340
+ .where("e.seq", "=", String(seq))
341
+ .executeTakeFirst();
342
+ if (row?.type !== "usage")
343
+ return null;
344
+ const p = row.payload;
345
+ return {
346
+ eventId: `${conversationId}/${seq}`,
347
+ purpose: p.purpose ?? "step",
348
+ orgId: row.org_id,
349
+ accountId: row.trigger_account_id ?? row.account_id,
350
+ agentId: row.agent_id,
351
+ conversationId,
352
+ // a sub-agent's calls report "chat" (spec §11: the SDK union is not widened)
353
+ conversationKind: row.kind === "eval" ? "eval" : "chat",
354
+ runId: row.run_id ?? "",
355
+ ...(row.parent_conversation_id !== null &&
356
+ row.parent_run_id !== null &&
357
+ row.parent_call_id !== null && {
358
+ parent: {
359
+ conversationId: row.parent_conversation_id,
360
+ runId: row.parent_run_id,
361
+ callId: row.parent_call_id,
362
+ },
363
+ }),
364
+ provider: p.provider,
365
+ model: p.model,
366
+ usage: {
367
+ inputTokens: p.inputTokens,
368
+ outputTokens: p.outputTokens,
369
+ cacheReadTokens: p.cacheReadTokens,
370
+ cacheWriteTokens: p.cacheWriteTokens,
371
+ },
372
+ occurredAt: new Date(row.created_at).toISOString(),
373
+ };
374
+ }
375
+ /**
376
+ * Writes the next `pending` set and the accumulated drops, fenced against a concurrent
377
+ * (stalled-over) execution (m-2 fence): only plugins the stored data still lists as pending or
378
+ * dropped can stay, so a plugin another execution delivered never comes back.
379
+ */
380
+ async writePending(j, next, dropped) {
381
+ const fresh = j.id === undefined ? undefined : await Job.fromId(this.getQueue(), j.id);
382
+ const data = fresh?.data;
383
+ const stored = data?.pending ?? j.data.pending;
384
+ const storedDropped = data?.dropped ?? j.data.dropped ?? {};
385
+ const allowed = stored === undefined ? undefined : [...stored, ...Object.keys(storedDropped)];
386
+ const keep = [...dropped].filter(([p]) => allowed === undefined || allowed.includes(p));
387
+ const out = {
388
+ conversationId: j.data.conversationId,
389
+ seq: j.data.seq,
390
+ pending: narrowPending(allowed, next),
391
+ ...(keep.length > 0 && { dropped: Object.fromEntries(keep) }),
392
+ };
393
+ await j.updateData(out);
394
+ j.data = out;
395
+ }
396
+ async process(j, token) {
397
+ const { conversationId, seq } = j.data;
398
+ const payload = await this.payloadOf(conversationId, seq);
399
+ if (payload === null)
400
+ return; // conversation deleted meanwhile: nothing to report
401
+ const subscribers = await this.d.subscribers(payload.orgId);
402
+ if (j.data.pending === undefined) {
403
+ // first attempt: the targets come from deployment state, recorded so later attempts (on any
404
+ // replica) deliver exactly the plugins that have not succeeded yet
405
+ const targets = [...subscribers];
406
+ await j.updateData({ conversationId, seq, pending: targets });
407
+ j.data.pending = targets;
408
+ }
409
+ // plugins the organization disabled meanwhile are dropped (not a failure)
410
+ const targets = (j.data.pending ?? []).filter((p) => subscribers.has(p));
411
+ if (targets.length === 0)
412
+ return;
413
+ const byPlugin = new Map();
414
+ for (const h of this.d.hooks.handlers("usage.report")) {
415
+ byPlugin.set(h.plugin, [...(byPlugin.get(h.plugin) ?? []), h.handler]);
416
+ }
417
+ const frozen = deepFreeze(structuredClone(payload));
418
+ const timeoutMs = this.d.config().hooks.timeoutMs;
419
+ const results = await Promise.allSettled(targets.map(async (plugin) => {
420
+ const handlers = byPlugin.get(plugin);
421
+ if (!handlers || handlers.length === 0) {
422
+ throw new Undeliverable(plugin, this.d.isActive?.(plugin) ? "no_handler" : "not_loaded");
423
+ }
424
+ for (const h of handlers)
425
+ await this.call(h, frozen, timeoutMs);
426
+ }));
427
+ const failed = [];
428
+ const notHere = [];
429
+ /** Definite drops (N-3): plugin → why; they end the job as failed, with no further retries. */
430
+ const dropped = new Map();
431
+ results.forEach((r, i) => {
432
+ if (r.status === "fulfilled")
433
+ return;
434
+ const plugin = targets[i];
435
+ if (r.reason instanceof Undeliverable) {
436
+ // I-2: loaded here without a handler: not a subscriber (declared but never registered, or
437
+ // a downgrade); dropped, not retried
438
+ if (r.reason.why === "no_handler")
439
+ dropped.set(plugin, "registered no usage.report handler");
440
+ else
441
+ notHere.push(plugin);
442
+ return;
443
+ }
444
+ failed.push(plugin);
445
+ if (!this.stopping.signal.aborted) {
446
+ this.d.log.warn("usage.report delivery to a plugin failed", {
447
+ plugin,
448
+ eventId: payload.eventId,
449
+ error: errMsg(r.reason),
450
+ });
451
+ }
452
+ });
453
+ // not loaded here: another replica or a later attempt may serve it (retry). On the last attempt a
454
+ // target is dropped only when it is definitely unservable; unknown ones fail the job as before.
455
+ const final = j.attemptsMade + 1 >= (j.opts.attempts ?? 1);
456
+ const gone = final && notHere.length > 0 && !this.stopping.signal.aborted
457
+ ? await this.unservable(notHere)
458
+ : new Set();
459
+ for (const plugin of notHere) {
460
+ if (gone.has(plugin))
461
+ dropped.set(plugin, "no replica has it loaded");
462
+ else
463
+ failed.push(plugin);
464
+ }
465
+ // m-2: drops accumulate across attempts (minus plugins delivered now), so a drop on an attempt
466
+ // that also had a transient failure still fails the job once the rest succeeds
467
+ const delivered = new Set(targets.filter((_, i) => results[i]?.status === "fulfilled"));
468
+ const allDropped = new Map(
469
+ // (a plugin the organization disabled meanwhile is no target any more: not traced)
470
+ Object.entries(j.data.dropped ?? {}).filter(([p]) => !delivered.has(p) && subscribers.has(p)));
471
+ for (const [p, why] of dropped)
472
+ allDropped.set(p, why);
473
+ if (failed.length > 0) {
474
+ await this.writePending(j, failed, allDropped);
475
+ if (this.stopping.signal.aborted) {
476
+ // shutdown is not the plugin's fault: back to the queue without using up an attempt (m-3)
477
+ await j.moveToDelayed(Date.now(), token);
478
+ throw new DelayedError();
479
+ }
480
+ throw new Error(`usage.report failed for: ${failed.join(", ")}${droppedNote(dropped)}`);
481
+ }
482
+ // m-1: pending = the dropped plugins only, so a manual retry reaches them and never the
483
+ // plugins already served
484
+ await this.writePending(j, [...allDropped.keys()], allDropped);
485
+ const traced = new Map([...allDropped].filter(([p]) => j.data.dropped?.[p] !== undefined));
486
+ if (traced.size === 0)
487
+ return;
488
+ // N-3: a definite drop leaves a durable trace: the job ends failed (kept under the failed-job
489
+ // cap, visible in queue tooling) with the dropped plugins in failedReason; no more retries
490
+ for (const [plugin, reason] of dropped) {
491
+ void this.warnOnce(plugin, "dropped", "usage.report target dropped", {
492
+ plugin,
493
+ eventId: payload.eventId,
494
+ reason,
495
+ });
496
+ }
497
+ throw new UnrecoverableError(`usage.report delivered to the rest;${droppedNote(traced)}`);
498
+ }
499
+ /** {@link UsageReporterDeps.unservable}; a lookup failure counts as "unknown" (keep retrying). */
500
+ async unservable(plugins) {
501
+ if (!this.d.unservable)
502
+ return new Set();
503
+ try {
504
+ return await this.d.unservable(plugins);
505
+ }
506
+ catch (err) {
507
+ this.d.log.warn("cannot read plugin replica status for usage.report", { err });
508
+ return new Set();
509
+ }
510
+ }
511
+ /** Logs a warning at most once per plugin and kind per minute (Redis key with a TTL). */
512
+ async warnOnce(plugin, kind, msg, fields) {
513
+ let first = true;
514
+ try {
515
+ this.getQueue();
516
+ const key = `capk:usage-warn:${plugin}:${kind}`;
517
+ first = (await this.queueConn?.set(key, "1", "PX", WARN_WINDOW_MS, "NX")) !== null;
518
+ }
519
+ catch {
520
+ // Redis unavailable: log anyway rather than hiding it
521
+ }
522
+ if (first)
523
+ this.d.log.warn(msg, fields);
524
+ }
525
+ /** One handler call with its own signal (timeout or replica stop aborts it); rejects on either. */
526
+ async call(h, payload, timeoutMs) {
527
+ const ac = new AbortController();
528
+ const onStop = () => ac.abort(new Error("replica stopping"));
529
+ if (this.stopping.signal.aborted)
530
+ onStop();
531
+ else
532
+ this.stopping.signal.addEventListener("abort", onStop, { once: true });
533
+ let timer;
534
+ try {
535
+ await Promise.race([
536
+ Promise.resolve().then(() => h(payload, ac.signal)),
537
+ new Promise((_, reject) => {
538
+ timer = setTimeout(() => {
539
+ ac.abort(new Error(`timed out after ${timeoutMs} ms`));
540
+ reject(new Error(`timed out after ${timeoutMs} ms`));
541
+ }, timeoutMs);
542
+ ac.signal.addEventListener("abort", () => reject(ac.signal.reason), { once: true });
543
+ }),
544
+ ]);
545
+ }
546
+ finally {
547
+ clearTimeout(timer);
548
+ this.stopping.signal.removeEventListener("abort", onStop);
549
+ }
550
+ }
551
+ }