@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,104 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { sql } from "kysely";
3
+ import { audit } from "../identity/audit.js";
4
+ /** 匿名访客账号的显示名。 */
5
+ const ANONYMOUS_DISPLAY_NAME = "Anonymous guest";
6
+ /** 匿名访客成员关系的来源标记(通讯录同步只撤销 `directory:*`,不会碰它)。 */
7
+ const ANONYMOUS_MEMBERSHIP_SOURCE = "anonymous";
8
+ /**
9
+ * 该组织唯一的匿名访客账号 id;首次使用时创建(`accounts.status = active`、没有任何登录方式、组织角色 guest)。
10
+ * 每次都确保成员关系存在(被移出后再次使用会补回 guest):运行的兜底扫描会中止「发起人已不是该组织成员」的运行。
11
+ * 跨副本并发首次创建用事务级咨询锁串行化,只建一个账号。
12
+ */
13
+ export async function ensureAnonymousGuest(db, orgId) {
14
+ return db.transaction().execute(async (t) => {
15
+ await sql `SELECT pg_advisory_xact_lock(hashtext(${`capybara.anonymous:${orgId}`}))`.execute(t);
16
+ const existing = await t
17
+ .selectFrom("org_anonymous_accounts")
18
+ .select("account_id")
19
+ .where("org_id", "=", orgId)
20
+ .executeTakeFirst();
21
+ let accountId = existing?.account_id;
22
+ if (accountId === undefined) {
23
+ accountId = randomUUID();
24
+ await t
25
+ .insertInto("accounts")
26
+ .values({ id: accountId, display_name: ANONYMOUS_DISPLAY_NAME, email: null })
27
+ .execute();
28
+ await t
29
+ .insertInto("org_anonymous_accounts")
30
+ .values({ org_id: orgId, account_id: accountId })
31
+ .execute();
32
+ await audit(t, {
33
+ orgId,
34
+ action: "account.created",
35
+ target: accountId,
36
+ detail: { anonymousGuest: true },
37
+ });
38
+ }
39
+ await t
40
+ .insertInto("memberships")
41
+ .values({
42
+ org_id: orgId,
43
+ account_id: accountId,
44
+ role: "guest",
45
+ source: ANONYMOUS_MEMBERSHIP_SOURCE,
46
+ })
47
+ .onConflict((oc) => oc.columns(["org_id", "account_id"]).doNothing())
48
+ .execute();
49
+ return accountId;
50
+ });
51
+ }
52
+ /**
53
+ * 话题键:私聊 `dm:<externalId>`;群聊用平台话题 id,消息不在话题里(开启新话题)时用该消息 id——
54
+ * 机器人回复在以它为根的话题里,后续消息的 threadId 就是它,于是落到同一个对话。
55
+ */
56
+ export function threadKeyOf(target, senderExternalId, messageId) {
57
+ if (target.chatType === "dm")
58
+ return `dm:${senderExternalId}`;
59
+ return target.threadId ?? messageId;
60
+ }
61
+ /** 未归档的话题行对应的会话;没有返回 undefined。 */
62
+ export async function findThread(db, k) {
63
+ const row = await db
64
+ .selectFrom("channel_threads")
65
+ .select("conversation_id")
66
+ .where("connection_id", "=", k.connectionId)
67
+ .where("chat_id", "=", k.chatId)
68
+ .where("thread_key", "=", k.threadKey)
69
+ .where(sql `coalesce(account_id::text, '')`, "=", k.accountId ?? "")
70
+ .where("archived_at", "is", null)
71
+ .executeTakeFirst();
72
+ return row?.conversation_id;
73
+ }
74
+ /**
75
+ * 记下话题 → 会话;同一话题已有未归档的行(并发的另一条消息抢先建了)时不写,返回已有的会话 id。
76
+ * 返回实际生效的会话 id。
77
+ */
78
+ export async function insertThread(db, k, conversationId) {
79
+ const r = await sql `
80
+ INSERT INTO capybara.channel_threads (id, connection_id, chat_id, thread_key, account_id, conversation_id)
81
+ VALUES (${randomUUID()}, ${k.connectionId}, ${k.chatId}, ${k.threadKey}, ${k.accountId}, ${conversationId})
82
+ ON CONFLICT (connection_id, chat_id, thread_key, coalesce(account_id::text, ''))
83
+ WHERE archived_at IS NULL DO NOTHING
84
+ RETURNING conversation_id`.execute(db);
85
+ if (r.rows[0])
86
+ return r.rows[0].conversation_id;
87
+ const winner = await findThread(db, k);
88
+ if (winner === undefined)
89
+ throw new Error("channel thread vanished after a conflicting insert");
90
+ return winner;
91
+ }
92
+ /** 私聊 `/new`:归档当前话题行(下一条消息新建对话)。返回是否归档了一行。 */
93
+ export async function archiveThread(db, k) {
94
+ const r = await db
95
+ .updateTable("channel_threads")
96
+ .set({ archived_at: sql `now()` })
97
+ .where("connection_id", "=", k.connectionId)
98
+ .where("chat_id", "=", k.chatId)
99
+ .where("thread_key", "=", k.threadKey)
100
+ .where(sql `coalesce(account_id::text, '')`, "=", k.accountId ?? "")
101
+ .where("archived_at", "is", null)
102
+ .executeTakeFirst();
103
+ return r.numUpdatedRows > 0n;
104
+ }
@@ -0,0 +1,16 @@
1
+ import type { KernelConfig } from "../config/schema.js";
2
+ /** Path prefix of the channel webhook route on the gateway role (F9). */
3
+ export declare const CHANNEL_WEBHOOK_PREFIX = "/channels/webhook/";
4
+ type WebhookConfig = Pick<KernelConfig, "channels"> & {
5
+ tools: Pick<KernelConfig["tools"], "oauthAllowInsecureLoopback">;
6
+ };
7
+ /**
8
+ * Why `channels.webhookBaseUrl` is unusable, or null when it is unset or fine. It must be https;
9
+ * plain http is accepted only for loopback hosts with `tools.oauthAllowInsecureLoopback` (tests).
10
+ */
11
+ export declare function webhookBaseUrlProblem(config: WebhookConfig): string | null;
12
+ /** The usable webhook base without a trailing slash, or undefined when unset or unusable. */
13
+ export declare function webhookBase(config: WebhookConfig): string | undefined;
14
+ /** The callback URL the admin registers with the platform: `<base>/channels/webhook/<id>`. */
15
+ export declare const webhookUrlOf: (base: string, connectionId: string) => string;
16
+ export {};
@@ -0,0 +1,34 @@
1
+ import { isIP } from "node:net";
2
+ /** Path prefix of the channel webhook route on the gateway role (F9). */
3
+ export const CHANNEL_WEBHOOK_PREFIX = "/channels/webhook/";
4
+ const isLoopbackHost = (host) => {
5
+ const h = host.replace(/^\[|\]$/g, "");
6
+ return h === "localhost" || h === "::1" || (isIP(h) === 4 && h.startsWith("127."));
7
+ };
8
+ /**
9
+ * Why `channels.webhookBaseUrl` is unusable, or null when it is unset or fine. It must be https;
10
+ * plain http is accepted only for loopback hosts with `tools.oauthAllowInsecureLoopback` (tests).
11
+ */
12
+ export function webhookBaseUrlProblem(config) {
13
+ const raw = config.channels.webhookBaseUrl;
14
+ if (raw === undefined)
15
+ return null;
16
+ const u = new URL(raw);
17
+ if (u.protocol === "https:")
18
+ return null;
19
+ if (u.protocol === "http:" &&
20
+ isLoopbackHost(u.hostname) &&
21
+ config.tools.oauthAllowInsecureLoopback) {
22
+ return null;
23
+ }
24
+ return "channels.webhookBaseUrl must be an https URL (plain http only for loopback hosts with tools.oauthAllowInsecureLoopback)";
25
+ }
26
+ /** The usable webhook base without a trailing slash, or undefined when unset or unusable. */
27
+ export function webhookBase(config) {
28
+ const raw = config.channels.webhookBaseUrl;
29
+ if (raw === undefined || webhookBaseUrlProblem(config) !== null)
30
+ return undefined;
31
+ return raw.replace(/\/+$/, "");
32
+ }
33
+ /** The callback URL the admin registers with the platform: `<base>/channels/webhook/<id>`. */
34
+ export const webhookUrlOf = (base, connectionId) => `${base}${CHANNEL_WEBHOOK_PREFIX}${connectionId}`;
@@ -0,0 +1,19 @@
1
+ import type { Logger } from "@capybara-hq/plugin-sdk";
2
+ import type { FastifyInstance } from "fastify";
3
+ import { type ChannelWebhooks } from "./webhook.js";
4
+ /** Fastify route template of the channel webhook (F9). */
5
+ export declare const CHANNEL_WEBHOOK_ROUTE = "/channels/webhook/:connectionId";
6
+ export interface ChannelWebhookRouteOptions {
7
+ webhooks: Pick<ChannelWebhooks, "handle">;
8
+ /** `channels.webhookMaxBodyBytes`: a larger body is answered 413 before the handler runs. */
9
+ maxBodyBytes: number;
10
+ log: Pick<Logger, "error">;
11
+ }
12
+ /**
13
+ * Registers `POST /channels/webhook/:connectionId` as a raw Fastify route in its own encapsulated
14
+ * scope (P-4), like `/plugins/*`: outside Nest, so neither the global `AuthGuard` nor the CSRF
15
+ * check applies (platforms send neither; the plugin verifies signatures). Inside this scope only,
16
+ * every content type is read as a raw Buffer (the global JSON parser is untouched), limited to
17
+ * `maxBodyBytes`. Must be called before Nest `app.init()`.
18
+ */
19
+ export declare function registerChannelWebhookRoute(fastify: FastifyInstance, opts: ChannelWebhookRouteOptions): Promise<void>;
@@ -0,0 +1,72 @@
1
+ import { errorBody } from "../errors.js";
2
+ import { codeForStatus, redactPath } from "../http/error.filter.js";
3
+ import { WEBHOOK_SECURITY_HEADERS } from "./webhook.js";
4
+ import { CHANNEL_WEBHOOK_PREFIX } from "./webhook-url.js";
5
+ /** Fastify route template of the channel webhook (F9). */
6
+ export const CHANNEL_WEBHOOK_ROUTE = `${CHANNEL_WEBHOOK_PREFIX}:connectionId`;
7
+ /** Request headers as the plugin sees them: lowercase names, repeats joined, no cookies. */
8
+ function headersOf(req) {
9
+ const out = {};
10
+ for (const [name, value] of Object.entries(req.headers)) {
11
+ if (value === undefined || name === "cookie")
12
+ continue;
13
+ out[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
14
+ }
15
+ return out;
16
+ }
17
+ /**
18
+ * Registers `POST /channels/webhook/:connectionId` as a raw Fastify route in its own encapsulated
19
+ * scope (P-4), like `/plugins/*`: outside Nest, so neither the global `AuthGuard` nor the CSRF
20
+ * check applies (platforms send neither; the plugin verifies signatures). Inside this scope only,
21
+ * every content type is read as a raw Buffer (the global JSON parser is untouched), limited to
22
+ * `maxBodyBytes`. Must be called before Nest `app.init()`.
23
+ */
24
+ export async function registerChannelWebhookRoute(fastify, opts) {
25
+ const handler = async (req, reply) => {
26
+ const { connectionId } = req.params;
27
+ // Aborts only when the platform hangs up before the response is written
28
+ const ac = new AbortController();
29
+ reply.raw.once("close", () => {
30
+ if (!reply.raw.writableFinished)
31
+ ac.abort();
32
+ });
33
+ const body = Buffer.isBuffer(req.body) ? req.body : Buffer.alloc(0);
34
+ let res;
35
+ try {
36
+ res = await opts.webhooks.handle(connectionId, {
37
+ method: "POST",
38
+ headers: headersOf(req),
39
+ body: new Uint8Array(body.buffer, body.byteOffset, body.byteLength),
40
+ receivedAt: Date.now(),
41
+ }, ac.signal);
42
+ }
43
+ catch (err) {
44
+ opts.log.error("channel webhook failed", { path: redactPath(req.url), err });
45
+ return reply.code(500).send(errorBody("internal", "Internal error"));
46
+ }
47
+ reply.code(res.status);
48
+ for (const [name, value] of Object.entries(res.headers ?? {}))
49
+ reply.header(name, value);
50
+ return reply.send(res.body ?? "");
51
+ };
52
+ await fastify.register(async (scope) => {
53
+ // Every response of the route, including Fastify's own 413 / 415 / 500
54
+ scope.addHook("onSend", async (_req, reply, payload) => {
55
+ for (const [name, value] of Object.entries(WEBHOOK_SECURITY_HEADERS)) {
56
+ reply.header(name, value);
57
+ }
58
+ return payload;
59
+ });
60
+ scope.removeAllContentTypeParsers();
61
+ scope.addContentTypeParser("*", { parseAs: "buffer" }, (_req, body, done) => done(null, body));
62
+ scope.setErrorHandler((err, req, reply) => {
63
+ const status = typeof err.statusCode === "number" ? err.statusCode : 500;
64
+ if (status >= 400 && status < 500) {
65
+ return reply.code(status).send(errorBody(codeForStatus(status), err.message));
66
+ }
67
+ opts.log.error("channel webhook request failed", { path: redactPath(req.url), err });
68
+ return reply.code(500).send(errorBody("internal", "Internal error"));
69
+ });
70
+ scope.post(CHANNEL_WEBHOOK_ROUTE, { bodyLimit: opts.maxBodyBytes }, handler);
71
+ });
72
+ }
@@ -0,0 +1,73 @@
1
+ import type { ChannelWebhookRequest, ChannelWebhookResponse, Logger } from "@capybara-hq/plugin-sdk";
2
+ import type { ChannelConnections } from "./connections.service.js";
3
+ import type { ChannelInbound } from "./inbound.js";
4
+ /**
5
+ * Deadline of one webhook request: connection lookups, the plugin's `webhook.handle` and handing
6
+ * its events to `onEvent` (platform ack deadlines are a few seconds). Past it the kernel answers 503.
7
+ */
8
+ export declare const WEBHOOK_HANDLE_TIMEOUT_MS = 10000;
9
+ /** How long a connection's decrypted runtime (plugin + config) is reused across requests. */
10
+ export declare const WEBHOOK_RUNTIME_CACHE_MS = 5000;
11
+ /** Most connections whose runtime is cached in one process. */
12
+ export declare const WEBHOOK_RUNTIME_CACHE_MAX = 1000;
13
+ /**
14
+ * Headers every webhook response carries; a plugin cannot override them (the body is never meant to
15
+ * be rendered or sniffed by a browser).
16
+ */
17
+ export declare const WEBHOOK_SECURITY_HEADERS: Readonly<Record<string, string>>;
18
+ export interface ChannelWebhooksDeps {
19
+ connections: Pick<ChannelConnections, "row" | "runtime">;
20
+ inbound: Pick<ChannelInbound, "onEvent">;
21
+ log: Pick<Logger, "warn">;
22
+ /** Defaults to {@link WEBHOOK_HANDLE_TIMEOUT_MS}. */
23
+ handleTimeoutMs?: number;
24
+ /** Defaults to {@link WEBHOOK_RUNTIME_CACHE_MS}; 0 disables the cache. */
25
+ runtimeCacheMs?: number;
26
+ }
27
+ /**
28
+ * Channel webhook inbound (F8 / F9), framework free. The gateway route
29
+ * `POST /channels/webhook/:connectionId` hands every request here; the kernel applies no auth, so
30
+ * everything a request can do goes through the plugin's `webhook.handle`, which verifies the
31
+ * signature, decrypts and checks timestamps:
32
+ * - unknown connection, not in webhook mode, not active or plugin off for the org → uniform 404
33
+ * `channel.webhook_not_found` (the connection row is read on every request);
34
+ * - plugin not loaded on this replica, being disabled / upgraded, or stored config no longer valid →
35
+ * 503 `extension.unavailable`.
36
+ * Deliberate tradeoff: during a rolling upgrade the platform retries and reaches a replica that
37
+ * has the plugin. It is only reachable with the UUID of an existing webhook-mode connection
38
+ * (the URL the platform already has), so it reveals nothing to a guesser;
39
+ * - `respond` → written back (minus framing / cookie headers);
40
+ * - `events` → each goes through the same `onEvent` as the long connection (dedupe by `messageId` /
41
+ * `eventId`, durable enqueue); the plugin's `ack` is written only after every one resolved, and
42
+ * any rejection answers 503 `channel.webhook_retry` so the platform redelivers;
43
+ * - `reject` → that status (400 / 401 / 403), nothing enqueued;
44
+ * - plugin throws or returns something else → 500 `internal`;
45
+ * - the whole request (connection lookups, handle, onEvent) has one deadline ({@link WEBHOOK_HANDLE_TIMEOUT_MS}): a
46
+ * plugin that ignores its `signal` or an enqueue stuck on Redis answers 503 `channel.webhook_retry`
47
+ * when it passes (late work is not cancelled; dedupe makes the redelivery safe).
48
+ * - `webhook.handle` counts toward the plugin instance's in-flight calls: a disable or upgrade waits
49
+ * for it (`extensionHost.drainSeconds`) before `dispose`; past that the call is aborted → 503
50
+ * `channel.webhook_retry`.
51
+ * Every response carries {@link WEBHOOK_SECURITY_HEADERS}.
52
+ *
53
+ * The decrypted runtime (plugin implementation + config) is cached per connection for a few seconds
54
+ * (bounded, process local), so unauthenticated requests stay cheap before the signature check. It is
55
+ * a read-through cache only: the kernel calls {@link invalidate} on `channel.changed` (config rotation,
56
+ * mode switch, deletion…) and {@link invalidateAll} when a plugin instance changes; a generation
57
+ * counter keeps a fetch that started before `invalidateAll` from storing the old plugin instance.
58
+ */
59
+ export declare class ChannelWebhooks {
60
+ private readonly deps;
61
+ private readonly runtimes;
62
+ /** Bumped by {@link invalidateAll}: a fetch started before the bump is not stored. */
63
+ private generation;
64
+ constructor(deps: ChannelWebhooksDeps);
65
+ /** Drops the cached runtime of one connection (on `channel.changed`). */
66
+ invalidate(connectionId: string): void;
67
+ /** Drops every cached runtime (a plugin was replaced, revoked or reloaded). */
68
+ invalidateAll(): void;
69
+ handle(connectionId: string, request: ChannelWebhookRequest, signal: AbortSignal): Promise<ChannelWebhookResponse>;
70
+ private runtime;
71
+ private respond;
72
+ private respondBefore;
73
+ }
@@ -0,0 +1,274 @@
1
+ import { ApiError, errorBody } from "../errors.js";
2
+ import { ExtensionUnloadedError } from "../extensions/inflight.js";
3
+ /**
4
+ * Deadline of one webhook request: connection lookups, the plugin's `webhook.handle` and handing
5
+ * its events to `onEvent` (platform ack deadlines are a few seconds). Past it the kernel answers 503.
6
+ */
7
+ export const WEBHOOK_HANDLE_TIMEOUT_MS = 10_000;
8
+ /** How long a connection's decrypted runtime (plugin + config) is reused across requests. */
9
+ export const WEBHOOK_RUNTIME_CACHE_MS = 5_000;
10
+ /** Most connections whose runtime is cached in one process. */
11
+ export const WEBHOOK_RUNTIME_CACHE_MAX = 1_000;
12
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13
+ /**
14
+ * Headers every webhook response carries; a plugin cannot override them (the body is never meant to
15
+ * be rendered or sniffed by a browser).
16
+ */
17
+ export const WEBHOOK_SECURITY_HEADERS = {
18
+ "x-content-type-options": "nosniff",
19
+ "content-security-policy": "default-src 'none'",
20
+ };
21
+ /** Response headers a plugin may not set (the HTTP server owns framing, cookies and the above). */
22
+ const DROPPED_HEADERS = new Set([
23
+ "connection",
24
+ "content-length",
25
+ "keep-alive",
26
+ "set-cookie",
27
+ "transfer-encoding",
28
+ ...Object.keys(WEBHOOK_SECURITY_HEADERS),
29
+ ]);
30
+ const jsonError = (status, code, message) => ({
31
+ status,
32
+ headers: { "content-type": "application/json; charset=utf-8" },
33
+ body: JSON.stringify(errorBody(code, message)),
34
+ });
35
+ /**
36
+ * The one answer for an unknown connection, a connection not in webhook mode, a disabled one, or
37
+ * one whose plugin is off for its org: the response never reveals whether the connection exists.
38
+ */
39
+ const notFound = () => jsonError(404, "channel.webhook_not_found", "No webhook is registered at this address");
40
+ const retryLater = () => jsonError(503, "channel.webhook_retry", "The event could not be accepted; retry later");
41
+ /** Thrown by {@link raceAbort} when the request's deadline (or the platform hanging up) wins. */
42
+ class WebhookDeadline extends Error {
43
+ }
44
+ /** Settles with `p`, or rejects with {@link WebhookDeadline} once `signal` aborts (whatever `p` does). */
45
+ function raceAbort(p, signal) {
46
+ if (signal.aborted) {
47
+ p.catch(() => { });
48
+ return Promise.reject(new WebhookDeadline());
49
+ }
50
+ return new Promise((resolve, reject) => {
51
+ const onAbort = () => reject(new WebhookDeadline());
52
+ signal.addEventListener("abort", onAbort, { once: true });
53
+ p.then((v) => {
54
+ signal.removeEventListener("abort", onAbort);
55
+ resolve(v);
56
+ }, (e) => {
57
+ signal.removeEventListener("abort", onAbort);
58
+ reject(e);
59
+ });
60
+ });
61
+ }
62
+ /**
63
+ * Channel webhook inbound (F8 / F9), framework free. The gateway route
64
+ * `POST /channels/webhook/:connectionId` hands every request here; the kernel applies no auth, so
65
+ * everything a request can do goes through the plugin's `webhook.handle`, which verifies the
66
+ * signature, decrypts and checks timestamps:
67
+ * - unknown connection, not in webhook mode, not active or plugin off for the org → uniform 404
68
+ * `channel.webhook_not_found` (the connection row is read on every request);
69
+ * - plugin not loaded on this replica, being disabled / upgraded, or stored config no longer valid →
70
+ * 503 `extension.unavailable`.
71
+ * Deliberate tradeoff: during a rolling upgrade the platform retries and reaches a replica that
72
+ * has the plugin. It is only reachable with the UUID of an existing webhook-mode connection
73
+ * (the URL the platform already has), so it reveals nothing to a guesser;
74
+ * - `respond` → written back (minus framing / cookie headers);
75
+ * - `events` → each goes through the same `onEvent` as the long connection (dedupe by `messageId` /
76
+ * `eventId`, durable enqueue); the plugin's `ack` is written only after every one resolved, and
77
+ * any rejection answers 503 `channel.webhook_retry` so the platform redelivers;
78
+ * - `reject` → that status (400 / 401 / 403), nothing enqueued;
79
+ * - plugin throws or returns something else → 500 `internal`;
80
+ * - the whole request (connection lookups, handle, onEvent) has one deadline ({@link WEBHOOK_HANDLE_TIMEOUT_MS}): a
81
+ * plugin that ignores its `signal` or an enqueue stuck on Redis answers 503 `channel.webhook_retry`
82
+ * when it passes (late work is not cancelled; dedupe makes the redelivery safe).
83
+ * - `webhook.handle` counts toward the plugin instance's in-flight calls: a disable or upgrade waits
84
+ * for it (`extensionHost.drainSeconds`) before `dispose`; past that the call is aborted → 503
85
+ * `channel.webhook_retry`.
86
+ * Every response carries {@link WEBHOOK_SECURITY_HEADERS}.
87
+ *
88
+ * The decrypted runtime (plugin implementation + config) is cached per connection for a few seconds
89
+ * (bounded, process local), so unauthenticated requests stay cheap before the signature check. It is
90
+ * a read-through cache only: the kernel calls {@link invalidate} on `channel.changed` (config rotation,
91
+ * mode switch, deletion…) and {@link invalidateAll} when a plugin instance changes; a generation
92
+ * counter keeps a fetch that started before `invalidateAll` from storing the old plugin instance.
93
+ */
94
+ export class ChannelWebhooks {
95
+ deps;
96
+ runtimes = new Map();
97
+ /** Bumped by {@link invalidateAll}: a fetch started before the bump is not stored. */
98
+ generation = 0;
99
+ constructor(deps) {
100
+ this.deps = deps;
101
+ }
102
+ /** Drops the cached runtime of one connection (on `channel.changed`). */
103
+ invalidate(connectionId) {
104
+ this.runtimes.delete(connectionId);
105
+ }
106
+ /** Drops every cached runtime (a plugin was replaced, revoked or reloaded). */
107
+ invalidateAll() {
108
+ this.generation++;
109
+ this.runtimes.clear();
110
+ }
111
+ async handle(connectionId, request, signal) {
112
+ return secure(await this.respond(connectionId, request, signal));
113
+ }
114
+ async runtime(connectionId, deadline) {
115
+ const ttl = this.deps.runtimeCacheMs ?? WEBHOOK_RUNTIME_CACHE_MS;
116
+ const now = Date.now();
117
+ const hit = this.runtimes.get(connectionId);
118
+ if (hit && hit.expiresAt > now)
119
+ return hit.value;
120
+ const generation = this.generation;
121
+ const value = await raceAbort(this.deps.connections.runtime(connectionId), deadline);
122
+ // A plugin instance changed while fetching: use the value once, keep no stale instance
123
+ if (ttl > 0 && generation === this.generation) {
124
+ this.runtimes.delete(connectionId);
125
+ while (this.runtimes.size >= WEBHOOK_RUNTIME_CACHE_MAX) {
126
+ const oldest = this.runtimes.keys().next().value;
127
+ if (oldest === undefined)
128
+ break;
129
+ this.runtimes.delete(oldest);
130
+ }
131
+ this.runtimes.set(connectionId, { value, expiresAt: now + ttl });
132
+ }
133
+ return value;
134
+ }
135
+ async respond(connectionId, request, signal) {
136
+ if (!UUID_RE.test(connectionId))
137
+ return notFound();
138
+ // One deadline for the whole request (DB lookups, handle, onEvent); also aborts when the
139
+ // platform hangs up
140
+ const deadline = AbortSignal.any([
141
+ signal,
142
+ AbortSignal.timeout(this.deps.handleTimeoutMs ?? WEBHOOK_HANDLE_TIMEOUT_MS),
143
+ ]);
144
+ try {
145
+ return await this.respondBefore(connectionId, request, deadline);
146
+ }
147
+ catch (err) {
148
+ if (!(err instanceof WebhookDeadline))
149
+ throw err;
150
+ this.deps.log.warn("channel webhook timed out; the platform will retry", { connectionId });
151
+ return retryLater();
152
+ }
153
+ }
154
+ async respondBefore(connectionId, request, deadline) {
155
+ const row = await raceAbort(this.deps.connections.row(connectionId), deadline);
156
+ if (row === undefined ||
157
+ row.inboundMode !== "webhook" ||
158
+ row.status !== "active" ||
159
+ !row.pluginEnabled) {
160
+ this.invalidate(connectionId);
161
+ return notFound();
162
+ }
163
+ let runtime;
164
+ try {
165
+ runtime = await this.runtime(connectionId, deadline);
166
+ }
167
+ catch (err) {
168
+ if (err instanceof WebhookDeadline)
169
+ throw err;
170
+ if (err instanceof ApiError &&
171
+ (err.code === "channel.not_found" || err.code === "extension.not_enabled")) {
172
+ return notFound();
173
+ }
174
+ this.deps.log.warn("channel webhook cannot load its connection", {
175
+ connectionId,
176
+ code: err instanceof ApiError ? err.code : undefined,
177
+ });
178
+ return jsonError(503, "extension.unavailable", "The channel is not available right now");
179
+ }
180
+ const webhook = runtime.channel.webhook;
181
+ if (webhook === undefined)
182
+ return notFound();
183
+ // The call counts toward the plugin instance's in-flight work, so disabling or upgrading the
184
+ // plugin drains it before `dispose` (and aborts it past extensionHost.drainSeconds).
185
+ let inflight;
186
+ try {
187
+ inflight = runtime.inflight?.enter(deadline);
188
+ }
189
+ catch (err) {
190
+ if (!(err instanceof ExtensionUnloadedError))
191
+ throw err;
192
+ // The cached runtime belongs to a revoked instance: the next request loads the new one
193
+ this.invalidate(connectionId);
194
+ return jsonError(503, "extension.unavailable", "The channel is not available right now");
195
+ }
196
+ const callSignal = inflight?.signal ?? deadline;
197
+ let result;
198
+ try {
199
+ result = await raceAbort(Promise.resolve().then(() => webhook.handle({ connectionId, config: runtime.config, request, signal: callSignal })), callSignal);
200
+ }
201
+ catch (err) {
202
+ if (err instanceof WebhookDeadline) {
203
+ this.deps.log.warn("channel webhook handler timed out; the platform will retry", {
204
+ connectionId,
205
+ });
206
+ return retryLater();
207
+ }
208
+ // The kernel log redacts the connection's secrets (runtime() registered them)
209
+ this.deps.log.warn("channel webhook handler failed", { connectionId, err });
210
+ return jsonError(500, "internal", "Internal error");
211
+ }
212
+ finally {
213
+ inflight?.leave();
214
+ }
215
+ switch (result?.kind) {
216
+ case "respond":
217
+ return sanitize(result.response);
218
+ case "reject":
219
+ return rejected(result.status);
220
+ case "events": {
221
+ const events = result.events;
222
+ if (!Array.isArray(events))
223
+ break;
224
+ for (const e of events) {
225
+ try {
226
+ await raceAbort(this.deps.inbound.onEvent(connectionId, e), deadline);
227
+ }
228
+ catch (err) {
229
+ this.deps.log.warn("channel webhook event not accepted; the platform will retry", {
230
+ connectionId,
231
+ ...(err instanceof WebhookDeadline ? { timedOut: true } : { err }),
232
+ });
233
+ return retryLater();
234
+ }
235
+ }
236
+ return sanitize(result.ack);
237
+ }
238
+ }
239
+ this.deps.log.warn("channel webhook handler returned an invalid result", { connectionId });
240
+ return jsonError(500, "internal", "Internal error");
241
+ }
242
+ }
243
+ /** Generic codes for the statuses a plugin may reject with (same as the HTTP error filter's). */
244
+ const REJECT_CODES = { 400: "validation_failed", 401: "auth.required", 403: "forbidden" };
245
+ function rejected(status) {
246
+ const s = status === 401 || status === 403 ? status : 400;
247
+ return jsonError(s, REJECT_CODES[s], "Webhook request rejected");
248
+ }
249
+ /** The plugin's response with a valid status and only string headers it may set. */
250
+ function sanitize(r) {
251
+ const status = r !== undefined && Number.isInteger(r.status) && r.status >= 200 && r.status <= 599
252
+ ? r.status
253
+ : 500;
254
+ const headers = {};
255
+ for (const [name, value] of Object.entries(r?.headers ?? {})) {
256
+ if (typeof value === "string" && !DROPPED_HEADERS.has(name.toLowerCase())) {
257
+ headers[name] = value;
258
+ }
259
+ }
260
+ return {
261
+ status,
262
+ headers,
263
+ ...(typeof r?.body === "string" && { body: r.body }),
264
+ };
265
+ }
266
+ /** Adds {@link WEBHOOK_SECURITY_HEADERS}, replacing any same-named header whatever its case. */
267
+ function secure(r) {
268
+ const headers = {};
269
+ for (const [name, value] of Object.entries(r.headers ?? {})) {
270
+ if (!(name.toLowerCase() in WEBHOOK_SECURITY_HEADERS))
271
+ headers[name] = value;
272
+ }
273
+ return { ...r, headers: { ...headers, ...WEBHOOK_SECURITY_HEADERS } };
274
+ }
@@ -0,0 +1,9 @@
1
+ import type { core } from "zod";
2
+ /** `db.poolMax` -> `CAPYBARA_DB__POOL_MAX` (the inverse of the envOverrides mapping)。 */
3
+ export declare function envName(path: string): string;
4
+ /**
5
+ * Renders the config schema as a deterministic Markdown table: dotted path, env var, type, default,
6
+ * hot-reloadable, secret, description. The default of a secret field is always printed as "—" and
7
+ * never reaches the document.
8
+ */
9
+ export declare function renderConfigDocs(schema: core.$ZodType): string;