@bevel-software/platform-core-backend 0.25.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/agent-guide/access-control.md +251 -0
  2. package/agent-guide/conventions.md +35 -0
  3. package/agent-guide/directory-structure.md +145 -0
  4. package/agent-guide/finding-things.md +7 -0
  5. package/agent-guide/html-views.md +83 -0
  6. package/agent-guide/introduction.md +27 -0
  7. package/agent-guide/new-knowledge-base.md +24 -0
  8. package/agent-guide/skills.md +47 -0
  9. package/agent-guide/tool-manuals.md +227 -0
  10. package/agent-guide/where-a-new-file-goes.md +36 -0
  11. package/dist/assets.d.ts +26 -0
  12. package/dist/assets.d.ts.map +1 -1
  13. package/dist/assets.js +35 -2
  14. package/dist/assets.js.map +1 -1
  15. package/dist/core/catalog-revision.d.ts +19 -1
  16. package/dist/core/catalog-revision.d.ts.map +1 -1
  17. package/dist/core/catalog-revision.js +14 -3
  18. package/dist/core/catalog-revision.js.map +1 -1
  19. package/dist/core/core-ports.d.ts +11 -0
  20. package/dist/core/core-ports.d.ts.map +1 -1
  21. package/dist/core/core-ports.js.map +1 -1
  22. package/dist/core/create-core-server.d.ts +5 -0
  23. package/dist/core/create-core-server.d.ts.map +1 -1
  24. package/dist/core/create-core-server.js +65 -3
  25. package/dist/core/create-core-server.js.map +1 -1
  26. package/dist/core/create-core-services.d.ts +35 -0
  27. package/dist/core/create-core-services.d.ts.map +1 -1
  28. package/dist/core/create-core-services.js +114 -12
  29. package/dist/core/create-core-services.js.map +1 -1
  30. package/dist/core/lifecycle.d.ts +16 -1
  31. package/dist/core/lifecycle.d.ts.map +1 -1
  32. package/dist/core/lifecycle.js +18 -1
  33. package/dist/core/lifecycle.js.map +1 -1
  34. package/dist/core-config.d.ts +21 -0
  35. package/dist/core-config.d.ts.map +1 -1
  36. package/dist/core-config.js +22 -1
  37. package/dist/core-config.js.map +1 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +2 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/modules/access/access-control.interface.d.ts +17 -0
  43. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  44. package/dist/modules/access/access-control.service.d.ts +2 -0
  45. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  46. package/dist/modules/access/access-control.service.js +27 -0
  47. package/dist/modules/access/access-control.service.js.map +1 -1
  48. package/dist/modules/access/directory-sync-bot.js +1 -1
  49. package/dist/modules/access/directory-sync-bot.js.map +1 -1
  50. package/dist/modules/agent-guide/agent-guide.d.ts +145 -0
  51. package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
  52. package/dist/modules/agent-guide/agent-guide.js +199 -0
  53. package/dist/modules/agent-guide/agent-guide.js.map +1 -0
  54. package/dist/modules/agent-guide/agent-guide.tools.d.ts +24 -0
  55. package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -0
  56. package/dist/modules/agent-guide/agent-guide.tools.js +100 -0
  57. package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -0
  58. package/dist/modules/agent-guide/index.d.ts +4 -0
  59. package/dist/modules/agent-guide/index.d.ts.map +1 -0
  60. package/dist/modules/agent-guide/index.js +4 -0
  61. package/dist/modules/agent-guide/index.js.map +1 -0
  62. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +3 -2
  63. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
  64. package/dist/modules/agent-instructions/agent-instructions.routes.js +3 -2
  65. package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
  66. package/dist/modules/agent-instructions/compose.d.ts +14 -6
  67. package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
  68. package/dist/modules/agent-instructions/compose.js +28 -8
  69. package/dist/modules/agent-instructions/compose.js.map +1 -1
  70. package/dist/modules/agent-instructions/index.d.ts +1 -1
  71. package/dist/modules/agent-instructions/index.d.ts.map +1 -1
  72. package/dist/modules/agent-instructions/index.js +1 -1
  73. package/dist/modules/agent-instructions/index.js.map +1 -1
  74. package/dist/modules/agent-instructions/shared-file-rules.d.ts +10 -50
  75. package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
  76. package/dist/modules/agent-instructions/shared-file-rules.js +51 -104
  77. package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
  78. package/dist/modules/audit/agent-audit.service.d.ts +21 -2
  79. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  80. package/dist/modules/audit/agent-audit.service.js +43 -2
  81. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  82. package/dist/modules/audit/agent-connection.routes.d.ts +34 -0
  83. package/dist/modules/audit/agent-connection.routes.d.ts.map +1 -0
  84. package/dist/modules/audit/agent-connection.routes.js +38 -0
  85. package/dist/modules/audit/agent-connection.routes.js.map +1 -0
  86. package/dist/modules/audit/audit.contract.d.ts +24 -0
  87. package/dist/modules/audit/audit.contract.d.ts.map +1 -1
  88. package/dist/modules/audit/audit.contract.js.map +1 -1
  89. package/dist/modules/audit/index.d.ts +1 -0
  90. package/dist/modules/audit/index.d.ts.map +1 -1
  91. package/dist/modules/audit/index.js +1 -0
  92. package/dist/modules/audit/index.js.map +1 -1
  93. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  94. package/dist/modules/auth/account.routes.js +10 -3
  95. package/dist/modules/auth/account.routes.js.map +1 -1
  96. package/dist/modules/auth/auth.middleware.d.ts +7 -0
  97. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  98. package/dist/modules/auth/auth.middleware.js +1 -1
  99. package/dist/modules/auth/auth.middleware.js.map +1 -1
  100. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
  101. package/dist/modules/code-mode/code-mode.tool.js +11 -3
  102. package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
  103. package/dist/modules/database/core-schema.d.ts +96 -0
  104. package/dist/modules/database/core-schema.d.ts.map +1 -1
  105. package/dist/modules/database/core-schema.js +32 -3
  106. package/dist/modules/database/core-schema.js.map +1 -1
  107. package/dist/modules/embed/account-link.service.d.ts +42 -0
  108. package/dist/modules/embed/account-link.service.d.ts.map +1 -0
  109. package/dist/modules/embed/account-link.service.js +50 -0
  110. package/dist/modules/embed/account-link.service.js.map +1 -0
  111. package/dist/modules/embed/embed-link.d.ts +58 -0
  112. package/dist/modules/embed/embed-link.d.ts.map +1 -0
  113. package/dist/modules/embed/embed-link.js +160 -0
  114. package/dist/modules/embed/embed-link.js.map +1 -0
  115. package/dist/modules/embed/embed.errors.d.ts +30 -0
  116. package/dist/modules/embed/embed.errors.d.ts.map +1 -0
  117. package/dist/modules/embed/embed.errors.js +42 -0
  118. package/dist/modules/embed/embed.errors.js.map +1 -0
  119. package/dist/modules/embed/embed.interface.d.ts +204 -0
  120. package/dist/modules/embed/embed.interface.d.ts.map +1 -0
  121. package/dist/modules/embed/embed.interface.js +2 -0
  122. package/dist/modules/embed/embed.interface.js.map +1 -0
  123. package/dist/modules/embed/embed.routes.d.ts +59 -0
  124. package/dist/modules/embed/embed.routes.d.ts.map +1 -0
  125. package/dist/modules/embed/embed.routes.js +343 -0
  126. package/dist/modules/embed/embed.routes.js.map +1 -0
  127. package/dist/modules/embed/embed.service.d.ts +169 -0
  128. package/dist/modules/embed/embed.service.d.ts.map +1 -0
  129. package/dist/modules/embed/embed.service.js +627 -0
  130. package/dist/modules/embed/embed.service.js.map +1 -0
  131. package/dist/modules/embed/embed.tools.d.ts +51 -0
  132. package/dist/modules/embed/embed.tools.d.ts.map +1 -0
  133. package/dist/modules/embed/embed.tools.js +170 -0
  134. package/dist/modules/embed/embed.tools.js.map +1 -0
  135. package/dist/modules/embed/mcp-app.d.ts +64 -0
  136. package/dist/modules/embed/mcp-app.d.ts.map +1 -0
  137. package/dist/modules/embed/mcp-app.js +147 -0
  138. package/dist/modules/embed/mcp-app.js.map +1 -0
  139. package/dist/modules/embed/mcp-app.routes.d.ts +21 -0
  140. package/dist/modules/embed/mcp-app.routes.d.ts.map +1 -0
  141. package/dist/modules/embed/mcp-app.routes.js +36 -0
  142. package/dist/modules/embed/mcp-app.routes.js.map +1 -0
  143. package/dist/modules/github-app/github-app.connection.d.ts +15 -0
  144. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -1
  145. package/dist/modules/github-app/github-app.connection.js +34 -3
  146. package/dist/modules/github-app/github-app.connection.js.map +1 -1
  147. package/dist/modules/kb-fs/locking-filesystem.d.ts +65 -0
  148. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  149. package/dist/modules/kb-fs/locking-filesystem.js +300 -0
  150. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  151. package/dist/modules/kb-sync/kb-sync.interface.d.ts +5 -0
  152. package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -1
  153. package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -1
  154. package/dist/modules/kb-sync/kb-sync.service.js +6 -0
  155. package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
  156. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  157. package/dist/modules/mcp/mcp-auth.middleware.js +2 -1
  158. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  159. package/dist/modules/mcp/mcp.service.d.ts +57 -3
  160. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  161. package/dist/modules/mcp/mcp.service.js +177 -24
  162. package/dist/modules/mcp/mcp.service.js.map +1 -1
  163. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -0
  164. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  165. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +32 -4
  166. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  167. package/dist/modules/mcp/tool-schema-guard.d.ts +105 -0
  168. package/dist/modules/mcp/tool-schema-guard.d.ts.map +1 -0
  169. package/dist/modules/mcp/tool-schema-guard.js +171 -0
  170. package/dist/modules/mcp/tool-schema-guard.js.map +1 -0
  171. package/dist/modules/onboarding/onboarding.contract.d.ts +80 -0
  172. package/dist/modules/onboarding/onboarding.contract.d.ts.map +1 -0
  173. package/dist/modules/onboarding/onboarding.contract.js +7 -0
  174. package/dist/modules/onboarding/onboarding.contract.js.map +1 -0
  175. package/dist/modules/onboarding/onboarding.routes.d.ts +18 -0
  176. package/dist/modules/onboarding/onboarding.routes.d.ts.map +1 -0
  177. package/dist/modules/onboarding/onboarding.routes.js +81 -0
  178. package/dist/modules/onboarding/onboarding.routes.js.map +1 -0
  179. package/dist/modules/onboarding/starter-pack.service.d.ts +213 -0
  180. package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -0
  181. package/dist/modules/onboarding/starter-pack.service.js +492 -0
  182. package/dist/modules/onboarding/starter-pack.service.js.map +1 -0
  183. package/dist/modules/onboarding/starter-packs.d.ts +78 -0
  184. package/dist/modules/onboarding/starter-packs.d.ts.map +1 -0
  185. package/dist/modules/onboarding/starter-packs.js +156 -0
  186. package/dist/modules/onboarding/starter-packs.js.map +1 -0
  187. package/dist/modules/plugins/index.d.ts +1 -1
  188. package/dist/modules/plugins/index.d.ts.map +1 -1
  189. package/dist/modules/plugins/index.js +1 -1
  190. package/dist/modules/plugins/index.js.map +1 -1
  191. package/dist/modules/plugins/plugin-provision.service.d.ts +19 -0
  192. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  193. package/dist/modules/plugins/plugin-provision.service.js +18 -1
  194. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  195. package/dist/modules/plugins/plugins.routes.d.ts +0 -36
  196. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  197. package/dist/modules/plugins/plugins.routes.js +31 -0
  198. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  199. package/dist/modules/plugins/plugins.tools.d.ts +36 -2
  200. package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
  201. package/dist/modules/plugins/plugins.tools.js +71 -14
  202. package/dist/modules/plugins/plugins.tools.js.map +1 -1
  203. package/dist/modules/settings/deployment-settings.service.d.ts +34 -7
  204. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  205. package/dist/modules/settings/deployment-settings.service.js +148 -54
  206. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  207. package/dist/modules/settings/repository-source.d.ts +1 -0
  208. package/dist/modules/settings/repository-source.d.ts.map +1 -1
  209. package/dist/modules/settings/repository-source.js +3 -3
  210. package/dist/modules/settings/repository-source.js.map +1 -1
  211. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  212. package/dist/modules/settings/setup.routes.js +3 -6
  213. package/dist/modules/settings/setup.routes.js.map +1 -1
  214. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  215. package/dist/modules/skills/skills.tools.js +103 -43
  216. package/dist/modules/skills/skills.tools.js.map +1 -1
  217. package/dist/modules/tool-auth/connection-key-rejection.d.ts +10 -1
  218. package/dist/modules/tool-auth/connection-key-rejection.d.ts.map +1 -1
  219. package/dist/modules/tool-auth/connection-key-rejection.js +11 -3
  220. package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -1
  221. package/dist/modules/tool-auth/external-api-key.interface.d.ts +8 -0
  222. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  223. package/dist/modules/tool-auth/external-api-key.service.d.ts +24 -2
  224. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  225. package/dist/modules/tool-auth/external-api-key.service.js +59 -2
  226. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  227. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  228. package/dist/modules/tool-auth/tool-auth.middleware.js +9 -4
  229. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  230. package/dist/modules/tool-helpers/index.d.ts +28 -1
  231. package/dist/modules/tool-helpers/index.d.ts.map +1 -1
  232. package/dist/modules/tool-helpers/index.js +28 -1
  233. package/dist/modules/tool-helpers/index.js.map +1 -1
  234. package/dist/modules/tool-helpers/route-argument-check.d.ts +10 -0
  235. package/dist/modules/tool-helpers/route-argument-check.d.ts.map +1 -0
  236. package/dist/modules/tool-helpers/route-argument-check.js +132 -0
  237. package/dist/modules/tool-helpers/route-argument-check.js.map +1 -0
  238. package/dist/modules/tool-helpers/route-tool-schemas.d.ts +89 -0
  239. package/dist/modules/tool-helpers/route-tool-schemas.d.ts.map +1 -0
  240. package/dist/modules/tool-helpers/route-tool-schemas.js +113 -0
  241. package/dist/modules/tool-helpers/route-tool-schemas.js.map +1 -0
  242. package/dist/modules/tool-helpers/tool-def.d.ts +71 -0
  243. package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -1
  244. package/dist/modules/tool-helpers/tool-def.js +70 -6
  245. package/dist/modules/tool-helpers/tool-def.js.map +1 -1
  246. package/dist/modules/tool-helpers/tool-handler.d.ts +46 -6
  247. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  248. package/dist/modules/tool-helpers/tool-handler.js +157 -8
  249. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  250. package/dist/modules/tool-helpers/tool.contract.d.ts +9 -0
  251. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  252. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  253. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +23 -4
  254. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  255. package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
  256. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -0
  257. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  258. package/dist/modules/tool-manuals/tool-manuals.service.js +14 -0
  259. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  260. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +7 -0
  261. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  262. package/dist/modules/tool-manuals/tool-manuals.tools.js +77 -38
  263. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  264. package/dist/modules/tool-registry/description-length.d.ts +20 -16
  265. package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
  266. package/dist/modules/tool-registry/description-length.js +50 -30
  267. package/dist/modules/tool-registry/description-length.js.map +1 -1
  268. package/dist/modules/tool-registry/guide-first.d.ts +27 -0
  269. package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
  270. package/dist/modules/tool-registry/guide-first.js +40 -0
  271. package/dist/modules/tool-registry/guide-first.js.map +1 -0
  272. package/dist/modules/tool-registry/tool-registry.d.ts +6 -0
  273. package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -1
  274. package/dist/modules/tool-registry/tool-registry.js +9 -2
  275. package/dist/modules/tool-registry/tool-registry.js.map +1 -1
  276. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +449 -0
  277. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -0
  278. package/dist/modules/workflow/agent-tools/change-request-read-shape.js +481 -0
  279. package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -0
  280. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +126 -0
  281. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -0
  282. package/dist/modules/workflow/agent-tools/change-request-read.tools.js +611 -0
  283. package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -0
  284. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +12 -1
  285. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
  286. package/dist/modules/workflow/agent-tools/change-request-summary.js +5 -1
  287. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
  288. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +8 -1
  289. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  290. package/dist/modules/workflow/agent-tools/workflow.tools.js +133 -37
  291. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  292. package/dist/modules/workflow/file-lock.service.d.ts +29 -5
  293. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  294. package/dist/modules/workflow/file-lock.service.js +62 -5
  295. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  296. package/dist/modules/workflow/git/git.service.d.ts +282 -14
  297. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  298. package/dist/modules/workflow/git/git.service.js +627 -126
  299. package/dist/modules/workflow/git/git.service.js.map +1 -1
  300. package/dist/modules/workflow/git/merge-commit.d.ts +73 -0
  301. package/dist/modules/workflow/git/merge-commit.d.ts.map +1 -0
  302. package/dist/modules/workflow/git/merge-commit.js +89 -0
  303. package/dist/modules/workflow/git/merge-commit.js.map +1 -0
  304. package/dist/modules/workflow/git/node-git-runner.d.ts +15 -0
  305. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  306. package/dist/modules/workflow/git/node-git-runner.js +78 -6
  307. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  308. package/dist/modules/workflow/git/pull-request.service.d.ts +94 -1
  309. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  310. package/dist/modules/workflow/git/pull-request.service.js +332 -37
  311. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  312. package/dist/modules/workflow/pending-commits.service.d.ts +15 -0
  313. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  314. package/dist/modules/workflow/pending-commits.service.js +25 -1
  315. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  316. package/dist/modules/workflow/pending-commits.worker.d.ts +6 -1
  317. package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -1
  318. package/dist/modules/workflow/pending-commits.worker.js +23 -6
  319. package/dist/modules/workflow/pending-commits.worker.js.map +1 -1
  320. package/dist/modules/workflow/recovery-bot.js +1 -1
  321. package/dist/modules/workflow/recovery-bot.js.map +1 -1
  322. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +35 -0
  323. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  324. package/dist/modules/workflow/review-workflow/review-workflow.service.js +180 -13
  325. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  326. package/dist/modules/workflow/sanitize-error.d.ts +16 -0
  327. package/dist/modules/workflow/sanitize-error.d.ts.map +1 -1
  328. package/dist/modules/workflow/sanitize-error.js +45 -0
  329. package/dist/modules/workflow/sanitize-error.js.map +1 -1
  330. package/dist/modules/workflow/workflow.routes.d.ts +6 -2
  331. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  332. package/dist/modules/workflow/workflow.routes.js +7 -2
  333. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  334. package/dist/modules/workflow/workflow.service.d.ts +187 -15
  335. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  336. package/dist/modules/workflow/workflow.service.js +808 -106
  337. package/dist/modules/workflow/workflow.service.js.map +1 -1
  338. package/dist/modules/workspace/agent-download.builder.d.ts +105 -0
  339. package/dist/modules/workspace/agent-download.builder.d.ts.map +1 -0
  340. package/dist/modules/workspace/agent-download.builder.js +238 -0
  341. package/dist/modules/workspace/agent-download.builder.js.map +1 -0
  342. package/dist/modules/workspace/agent-download.routes.d.ts +77 -0
  343. package/dist/modules/workspace/agent-download.routes.d.ts.map +1 -0
  344. package/dist/modules/workspace/agent-download.routes.js +156 -0
  345. package/dist/modules/workspace/agent-download.routes.js.map +1 -0
  346. package/dist/modules/workspace/agent-download.store.d.ts +225 -0
  347. package/dist/modules/workspace/agent-download.store.d.ts.map +1 -0
  348. package/dist/modules/workspace/agent-download.store.js +423 -0
  349. package/dist/modules/workspace/agent-download.store.js.map +1 -0
  350. package/dist/modules/workspace/agent-upload.store.d.ts +10 -1
  351. package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -1
  352. package/dist/modules/workspace/agent-upload.store.js +16 -6
  353. package/dist/modules/workspace/agent-upload.store.js.map +1 -1
  354. package/dist/modules/workspace/file-readers/raw-mime.d.ts +6 -0
  355. package/dist/modules/workspace/file-readers/raw-mime.d.ts.map +1 -0
  356. package/dist/modules/workspace/file-readers/raw-mime.js +38 -0
  357. package/dist/modules/workspace/file-readers/raw-mime.js.map +1 -0
  358. package/dist/modules/workspace/file-readers/text-reader.d.ts +5 -5
  359. package/dist/modules/workspace/file-readers/text-reader.d.ts.map +1 -1
  360. package/dist/modules/workspace/file-readers/text-reader.js +5 -8
  361. package/dist/modules/workspace/file-readers/text-reader.js.map +1 -1
  362. package/dist/modules/workspace/first-run.d.ts +111 -0
  363. package/dist/modules/workspace/first-run.d.ts.map +1 -0
  364. package/dist/modules/workspace/first-run.js +181 -0
  365. package/dist/modules/workspace/first-run.js.map +1 -0
  366. package/dist/modules/workspace/move-links.d.ts +92 -0
  367. package/dist/modules/workspace/move-links.d.ts.map +1 -0
  368. package/dist/modules/workspace/move-links.js +173 -0
  369. package/dist/modules/workspace/move-links.js.map +1 -0
  370. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  371. package/dist/modules/workspace/startup/steps/seed-tree.js +24 -39
  372. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  373. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +58 -52
  374. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  375. package/dist/modules/workspace/startup/steps/template-files.step.js +209 -223
  376. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  377. package/dist/modules/workspace/startup/steps/template-source.d.ts +5 -3
  378. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  379. package/dist/modules/workspace/startup/steps/template-source.js +5 -3
  380. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  381. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  382. package/dist/modules/workspace/workspace.routes.js +63 -22
  383. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  384. package/dist/modules/workspace/workspace.service.d.ts +75 -2
  385. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  386. package/dist/modules/workspace/workspace.service.js +197 -24
  387. package/dist/modules/workspace/workspace.service.js.map +1 -1
  388. package/dist/modules/workspace/workspace.tools.d.ts +68 -1
  389. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  390. package/dist/modules/workspace/workspace.tools.js +642 -71
  391. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  392. package/dist/modules/write-access/write-access.d.ts.map +1 -1
  393. package/dist/modules/write-access/write-access.js +9 -0
  394. package/dist/modules/write-access/write-access.js.map +1 -1
  395. package/dist/shared/domain-errors.d.ts +84 -1
  396. package/dist/shared/domain-errors.d.ts.map +1 -1
  397. package/dist/shared/domain-errors.js +100 -12
  398. package/dist/shared/domain-errors.js.map +1 -1
  399. package/dist/shared/git.contract.d.ts +10 -1
  400. package/dist/shared/git.contract.d.ts.map +1 -1
  401. package/dist/shared/git.contract.js.map +1 -1
  402. package/dist/shared/hidden-tools.d.ts +44 -0
  403. package/dist/shared/hidden-tools.d.ts.map +1 -0
  404. package/dist/shared/hidden-tools.js +13 -0
  405. package/dist/shared/hidden-tools.js.map +1 -0
  406. package/dist/shared/utf8-text.d.ts +15 -0
  407. package/dist/shared/utf8-text.d.ts.map +1 -0
  408. package/dist/shared/utf8-text.js +20 -0
  409. package/dist/shared/utf8-text.js.map +1 -0
  410. package/dist/tenancy/static-tenant-source.d.ts +2 -1
  411. package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
  412. package/dist/tenancy/static-tenant-source.js +9 -2
  413. package/dist/tenancy/static-tenant-source.js.map +1 -1
  414. package/kb-template/.bevelignore +0 -5
  415. package/mcp-app/page.html +349 -0
  416. package/migrations/0017_atlassian_account_links.sql +37 -0
  417. package/migrations/meta/0017_snapshot.json +2396 -0
  418. package/migrations/meta/_journal.json +8 -1
  419. package/package.json +6 -3
  420. package/src/__tests__/kb-layout-config.test.ts +10 -100
  421. package/src/__tests__/packaged-assets-ship.test.ts +66 -0
  422. package/src/assets.ts +38 -2
  423. package/src/core/__tests__/catalog-revision.test.ts +40 -0
  424. package/src/core/__tests__/gated-boot.test.ts +1 -0
  425. package/src/core/__tests__/lifecycle.test.ts +14 -0
  426. package/src/core/catalog-revision.ts +15 -2
  427. package/src/core/core-ports.ts +11 -0
  428. package/src/core/create-core-server.ts +78 -3
  429. package/src/core/create-core-services.ts +168 -10
  430. package/src/core/lifecycle.ts +28 -2
  431. package/src/core-config.ts +24 -1
  432. package/src/index.ts +2 -2
  433. package/src/modules/access/__tests__/access-control.atref-batch.test.ts +58 -0
  434. package/src/modules/access/__tests__/access-control.platform-restore.test.ts +8 -7
  435. package/src/modules/access/__tests__/access-control.service.test.ts +19 -0
  436. package/src/modules/access/__tests__/access-personal-plugin.test.ts +1 -18
  437. package/src/modules/access/access-control.interface.ts +28 -0
  438. package/src/modules/access/access-control.service.ts +37 -0
  439. package/src/modules/access/directory-sync-bot.ts +1 -1
  440. package/src/modules/agent-guide/__tests__/agent-guide.test.ts +386 -0
  441. package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +207 -0
  442. package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
  443. package/src/modules/agent-guide/agent-guide.ts +300 -0
  444. package/src/modules/agent-guide/index.ts +22 -0
  445. package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +39 -118
  446. package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
  447. package/src/modules/agent-instructions/compose.ts +26 -8
  448. package/src/modules/agent-instructions/index.ts +0 -3
  449. package/src/modules/agent-instructions/shared-file-rules.ts +50 -112
  450. package/src/modules/audit/__tests__/agent-audit.service.test.ts +64 -4
  451. package/src/modules/audit/__tests__/agent-connection.routes.test.ts +102 -0
  452. package/src/modules/audit/agent-audit.service.ts +58 -3
  453. package/src/modules/audit/agent-connection.routes.ts +56 -0
  454. package/src/modules/audit/audit.contract.ts +26 -0
  455. package/src/modules/audit/index.ts +1 -0
  456. package/src/modules/auth/__tests__/account.routes.test.ts +5 -3
  457. package/src/modules/auth/account.routes.ts +10 -3
  458. package/src/modules/auth/auth.middleware.ts +1 -1
  459. package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +18 -2
  460. package/src/modules/code-mode/code-mode.tool.ts +13 -2
  461. package/src/modules/database/core-schema.ts +33 -3
  462. package/src/modules/embed/__tests__/account-links.migration.test.ts +98 -0
  463. package/src/modules/embed/__tests__/embed-link.test.ts +122 -0
  464. package/src/modules/embed/__tests__/embed.routes.test.ts +362 -0
  465. package/src/modules/embed/__tests__/embed.service.lock.test.ts +193 -0
  466. package/src/modules/embed/__tests__/embed.service.test.ts +805 -0
  467. package/src/modules/embed/__tests__/embed.tools.test.ts +304 -0
  468. package/src/modules/embed/__tests__/mcp-app.test.ts +207 -0
  469. package/src/modules/embed/account-link.service.ts +76 -0
  470. package/src/modules/embed/embed-link.ts +180 -0
  471. package/src/modules/embed/embed.errors.ts +43 -0
  472. package/src/modules/embed/embed.interface.ts +203 -0
  473. package/src/modules/embed/embed.routes.ts +363 -0
  474. package/src/modules/embed/embed.service.ts +705 -0
  475. package/src/modules/embed/embed.tools.ts +206 -0
  476. package/src/modules/embed/mcp-app.routes.ts +41 -0
  477. package/src/modules/embed/mcp-app.ts +173 -0
  478. package/src/modules/github-app/__tests__/github-app.test.ts +76 -0
  479. package/src/modules/github-app/github-app.connection.ts +38 -4
  480. package/src/modules/kb-fs/__tests__/move-with-edits.test.ts +304 -0
  481. package/src/modules/kb-fs/locking-filesystem.ts +287 -0
  482. package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +35 -0
  483. package/src/modules/kb-sync/kb-sync.interface.ts +2 -0
  484. package/src/modules/kb-sync/kb-sync.service.ts +6 -0
  485. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +68 -11
  486. package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
  487. package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +37 -2
  488. package/src/modules/mcp/__tests__/mcp.app.e2e.test.ts +200 -0
  489. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +252 -0
  490. package/src/modules/mcp/__tests__/mcp.service.test.ts +42 -24
  491. package/src/modules/mcp/__tests__/tool-call-interface.e2e.test.ts +499 -0
  492. package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
  493. package/src/modules/mcp/mcp-auth.middleware.ts +2 -1
  494. package/src/modules/mcp/mcp.service.ts +218 -31
  495. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +42 -4
  496. package/src/modules/mcp/tool-schema-guard.ts +196 -0
  497. package/src/modules/onboarding/__tests__/onboarding.routes.test.ts +163 -0
  498. package/src/modules/onboarding/__tests__/starter-pack.service.test.ts +635 -0
  499. package/src/modules/onboarding/__tests__/starter-packs.test.ts +169 -0
  500. package/src/modules/onboarding/onboarding.contract.ts +85 -0
  501. package/src/modules/onboarding/onboarding.routes.ts +85 -0
  502. package/src/modules/onboarding/starter-pack.service.ts +580 -0
  503. package/src/modules/onboarding/starter-packs.ts +182 -0
  504. package/src/modules/plugins/__tests__/plugins.tools.test.ts +177 -4
  505. package/src/modules/plugins/index.ts +1 -0
  506. package/src/modules/plugins/plugin-provision.service.ts +22 -1
  507. package/src/modules/plugins/plugins.routes.ts +29 -0
  508. package/src/modules/plugins/plugins.tools.ts +75 -15
  509. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +176 -56
  510. package/src/modules/settings/__tests__/repository-source.test.ts +9 -0
  511. package/src/modules/settings/deployment-settings.service.ts +144 -55
  512. package/src/modules/settings/repository-source.ts +4 -4
  513. package/src/modules/settings/setup.routes.ts +3 -6
  514. package/src/modules/skills/__tests__/skills.tools.description.test.ts +95 -0
  515. package/src/modules/skills/skills.tools.ts +112 -46
  516. package/src/modules/tool-auth/__tests__/connection-key-rejection.test.ts +32 -0
  517. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +65 -0
  518. package/src/modules/tool-auth/connection-key-rejection.ts +13 -3
  519. package/src/modules/tool-auth/external-api-key.interface.ts +9 -0
  520. package/src/modules/tool-auth/external-api-key.service.ts +61 -4
  521. package/src/modules/tool-auth/tool-auth.middleware.ts +13 -4
  522. package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +502 -0
  523. package/src/modules/tool-helpers/__tests__/route-argument-check.test.ts +337 -0
  524. package/src/modules/tool-helpers/index.ts +34 -1
  525. package/src/modules/tool-helpers/route-argument-check.ts +149 -0
  526. package/src/modules/tool-helpers/route-tool-schemas.ts +171 -0
  527. package/src/modules/tool-helpers/tool-def.ts +132 -7
  528. package/src/modules/tool-helpers/tool-handler.ts +196 -8
  529. package/src/modules/tool-helpers/tool.contract.ts +9 -0
  530. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +57 -0
  531. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +73 -4
  532. package/src/modules/tool-manuals/tool-manuals.contract.ts +24 -4
  533. package/src/modules/tool-manuals/tool-manuals.service.ts +17 -0
  534. package/src/modules/tool-manuals/tool-manuals.tools.ts +86 -38
  535. package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +173 -0
  536. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +81 -66
  537. package/src/modules/tool-registry/description-length.ts +57 -32
  538. package/src/modules/tool-registry/guide-first.ts +41 -0
  539. package/src/modules/tool-registry/tool-registry.ts +9 -2
  540. package/src/modules/workflow/__tests__/apply-failure.test.ts +6 -1
  541. package/src/modules/workflow/__tests__/file-lock.service.deletion-gate.test.ts +104 -0
  542. package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +66 -0
  543. package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +31 -2
  544. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +110 -6
  545. package/src/modules/workflow/__tests__/sanitize-error.test.ts +89 -1
  546. package/src/modules/workflow/__tests__/workflow.routes.push-refused.test.ts +202 -0
  547. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +6 -6
  548. package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +1026 -0
  549. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +468 -10
  550. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +4 -0
  551. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +5 -4
  552. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +54 -2
  553. package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
  554. package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1554 -0
  555. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +150 -4
  556. package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
  557. package/src/modules/workflow/agent-tools/change-request-read.tools.ts +759 -0
  558. package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
  559. package/src/modules/workflow/agent-tools/workflow.tools.ts +137 -35
  560. package/src/modules/workflow/file-lock.service.ts +67 -5
  561. package/src/modules/workflow/git/__tests__/git.service.appliedChange.test.ts +285 -0
  562. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
  563. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +164 -0
  564. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +334 -0
  565. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +48 -1
  566. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +231 -2
  567. package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +72 -2
  568. package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +24 -2
  569. package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +620 -1
  570. package/src/modules/workflow/git/git.service.ts +714 -133
  571. package/src/modules/workflow/git/merge-commit.ts +88 -0
  572. package/src/modules/workflow/git/node-git-runner.ts +82 -7
  573. package/src/modules/workflow/git/pull-request.service.ts +380 -54
  574. package/src/modules/workflow/pending-commits.service.ts +29 -1
  575. package/src/modules/workflow/pending-commits.worker.ts +24 -6
  576. package/src/modules/workflow/recovery-bot.ts +1 -1
  577. package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +7 -1
  578. package/src/modules/workflow/review-workflow/__tests__/merge-records-own-commit.test.ts +407 -0
  579. package/src/modules/workflow/review-workflow/review-workflow.service.ts +191 -12
  580. package/src/modules/workflow/sanitize-error.ts +50 -0
  581. package/src/modules/workflow/workflow.routes.ts +7 -2
  582. package/src/modules/workflow/workflow.service.ts +886 -112
  583. package/src/modules/workspace/__tests__/agent-downloads.test.ts +823 -0
  584. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
  585. package/src/modules/workspace/__tests__/first-run.test.ts +234 -0
  586. package/src/modules/workspace/__tests__/git-internals.security.test.ts +5 -2
  587. package/src/modules/workspace/__tests__/md-links.test.ts +353 -0
  588. package/src/modules/workspace/__tests__/move-links.test.ts +261 -0
  589. package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +219 -0
  590. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -0
  591. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +102 -0
  592. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +52 -5
  593. package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +190 -0
  594. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
  595. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +8 -4
  596. package/src/modules/workspace/__tests__/workspace.service.test.ts +50 -8
  597. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
  598. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +44 -1
  599. package/src/modules/workspace/__tests__/workspace.tools.test.ts +664 -34
  600. package/src/modules/workspace/agent-download.builder.ts +308 -0
  601. package/src/modules/workspace/agent-download.routes.ts +183 -0
  602. package/src/modules/workspace/agent-download.store.ts +533 -0
  603. package/src/modules/workspace/agent-upload.store.ts +23 -7
  604. package/src/modules/workspace/file-readers/raw-mime.ts +40 -0
  605. package/src/modules/workspace/file-readers/text-reader.ts +5 -8
  606. package/src/modules/workspace/first-run.ts +222 -0
  607. package/src/modules/workspace/move-links.ts +237 -0
  608. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
  609. package/src/modules/workspace/startup/steps/seed-tree.ts +23 -38
  610. package/src/modules/workspace/startup/steps/template-files.step.ts +217 -249
  611. package/src/modules/workspace/startup/steps/template-source.ts +5 -3
  612. package/src/modules/workspace/workspace.routes.ts +64 -22
  613. package/src/modules/workspace/workspace.service.ts +202 -25
  614. package/src/modules/workspace/workspace.tools.ts +707 -68
  615. package/src/modules/write-access/__tests__/write-access.test.ts +13 -0
  616. package/src/modules/write-access/write-access.ts +9 -0
  617. package/src/shared/domain-errors.ts +123 -11
  618. package/src/shared/git.contract.ts +8 -1
  619. package/src/shared/hidden-tools.ts +45 -0
  620. package/src/shared/utf8-text.ts +21 -0
  621. package/src/tenancy/__tests__/static-tenant-source.test.ts +1 -0
  622. package/src/tenancy/static-tenant-source.ts +10 -2
  623. package/starter-packs/README.md +103 -0
  624. package/starter-packs/engineering/KnowledgeBase/About us.md +9 -0
  625. package/starter-packs/engineering/KnowledgeBase/Architecture.md +9 -0
  626. package/starter-packs/engineering/KnowledgeBase/Glossary.md +9 -0
  627. package/starter-packs/engineering/KnowledgeBase/How we ship.md +9 -0
  628. package/starter-packs/engineering/Plugins/engineering-starter/LICENSE +21 -0
  629. package/starter-packs/engineering/Plugins/engineering-starter/SOURCE.md +20 -0
  630. package/starter-packs/engineering/Plugins/engineering-starter/access.md +19 -0
  631. package/starter-packs/engineering/Plugins/engineering-starter/plugin.json +10 -0
  632. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/SKILL.md +171 -0
  633. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2a-startup-diagnostic.md +157 -0
  634. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2b-builder-brainstorm.md +39 -0
  635. package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-ceo-review/SKILL.md +144 -0
  636. package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-eng-review/SKILL.md +144 -0
  637. package/starter-packs/engineering/Plugins/engineering-starter/skills/review/SKILL.md +80 -0
  638. package/starter-packs/engineering/Plugins/engineering-starter/skills/review/checklist.md +184 -0
  639. package/starter-packs/engineering/pack.yaml +11 -0
  640. package/starter-packs/general/KnowledgeBase/About us.md +9 -0
  641. package/starter-packs/general/KnowledgeBase/Glossary.md +9 -0
  642. package/starter-packs/general/KnowledgeBase/How we work.md +9 -0
  643. package/starter-packs/general/Plugins/general-starter/LICENSE +202 -0
  644. package/starter-packs/general/Plugins/general-starter/SOURCE.md +10 -0
  645. package/starter-packs/general/Plugins/general-starter/access.md +19 -0
  646. package/starter-packs/general/Plugins/general-starter/plugin.json +10 -0
  647. package/starter-packs/general/Plugins/general-starter/skills/memory-management/SKILL.md +332 -0
  648. package/starter-packs/general/Plugins/general-starter/skills/productivity-start/SKILL.md +163 -0
  649. package/starter-packs/general/Plugins/general-starter/skills/productivity-update/SKILL.md +167 -0
  650. package/starter-packs/general/Plugins/general-starter/skills/task-management/SKILL.md +83 -0
  651. package/starter-packs/general/pack.yaml +10 -0
  652. package/starter-packs/operations/KnowledgeBase/Glossary.md +9 -0
  653. package/starter-packs/operations/KnowledgeBase/How we work.md +9 -0
  654. package/starter-packs/operations/KnowledgeBase/Processes.md +9 -0
  655. package/starter-packs/operations/KnowledgeBase/Tools we use.md +9 -0
  656. package/starter-packs/operations/KnowledgeBase/Vendors.md +9 -0
  657. package/starter-packs/operations/Plugins/operations-starter/LICENSE +202 -0
  658. package/starter-packs/operations/Plugins/operations-starter/SOURCE.md +10 -0
  659. package/starter-packs/operations/Plugins/operations-starter/access.md +19 -0
  660. package/starter-packs/operations/Plugins/operations-starter/plugin.json +10 -0
  661. package/starter-packs/operations/Plugins/operations-starter/skills/capacity-plan/SKILL.md +111 -0
  662. package/starter-packs/operations/Plugins/operations-starter/skills/change-request/SKILL.md +119 -0
  663. package/starter-packs/operations/Plugins/operations-starter/skills/compliance-tracking/SKILL.md +44 -0
  664. package/starter-packs/operations/Plugins/operations-starter/skills/process-doc/SKILL.md +80 -0
  665. package/starter-packs/operations/Plugins/operations-starter/skills/process-optimization/SKILL.md +39 -0
  666. package/starter-packs/operations/Plugins/operations-starter/skills/risk-assessment/SKILL.md +40 -0
  667. package/starter-packs/operations/Plugins/operations-starter/skills/runbook/SKILL.md +85 -0
  668. package/starter-packs/operations/Plugins/operations-starter/skills/status-report/SKILL.md +75 -0
  669. package/starter-packs/operations/Plugins/operations-starter/skills/vendor-review/SKILL.md +102 -0
  670. package/starter-packs/operations/pack.yaml +12 -0
  671. package/starter-packs/sales/KnowledgeBase/About us.md +9 -0
  672. package/starter-packs/sales/KnowledgeBase/Customers.md +9 -0
  673. package/starter-packs/sales/KnowledgeBase/Glossary.md +9 -0
  674. package/starter-packs/sales/KnowledgeBase/How we sell.md +9 -0
  675. package/starter-packs/sales/KnowledgeBase/Objections.md +9 -0
  676. package/starter-packs/sales/KnowledgeBase/Pricing.md +9 -0
  677. package/starter-packs/sales/Plugins/sales-starter/LICENSE +202 -0
  678. package/starter-packs/sales/Plugins/sales-starter/SOURCE.md +10 -0
  679. package/starter-packs/sales/Plugins/sales-starter/access.md +19 -0
  680. package/starter-packs/sales/Plugins/sales-starter/plugin.json +10 -0
  681. package/starter-packs/sales/Plugins/sales-starter/skills/account-context/SKILL.md +94 -0
  682. package/starter-packs/sales/Plugins/sales-starter/skills/account-plan/SKILL.md +95 -0
  683. package/starter-packs/sales/Plugins/sales-starter/skills/account-research/SKILL.md +99 -0
  684. package/starter-packs/sales/Plugins/sales-starter/skills/account-tiering/SKILL.md +101 -0
  685. package/starter-packs/sales/Plugins/sales-starter/skills/call-prep/SKILL.md +111 -0
  686. package/starter-packs/sales/Plugins/sales-starter/skills/call-summary/SKILL.md +111 -0
  687. package/starter-packs/sales/Plugins/sales-starter/skills/close-plan/SKILL.md +106 -0
  688. package/starter-packs/sales/Plugins/sales-starter/skills/competitive-intelligence/SKILL.md +102 -0
  689. package/starter-packs/sales/Plugins/sales-starter/skills/create-an-asset/SKILL.md +105 -0
  690. package/starter-packs/sales/Plugins/sales-starter/skills/crm-hygiene-check/SKILL.md +103 -0
  691. package/starter-packs/sales/Plugins/sales-starter/skills/customer-health/SKILL.md +108 -0
  692. package/starter-packs/sales/Plugins/sales-starter/skills/customer-voice/SKILL.md +94 -0
  693. package/starter-packs/sales/Plugins/sales-starter/skills/daily-briefing/SKILL.md +61 -0
  694. package/starter-packs/sales/Plugins/sales-starter/skills/deal-advance-gap/SKILL.md +102 -0
  695. package/starter-packs/sales/Plugins/sales-starter/skills/deal-review/SKILL.md +105 -0
  696. package/starter-packs/sales/Plugins/sales-starter/skills/deal-signals/SKILL.md +96 -0
  697. package/starter-packs/sales/Plugins/sales-starter/skills/deal-slip-scenario/SKILL.md +104 -0
  698. package/starter-packs/sales/Plugins/sales-starter/skills/draft-outreach/SKILL.md +116 -0
  699. package/starter-packs/sales/Plugins/sales-starter/skills/end-of-day/SKILL.md +114 -0
  700. package/starter-packs/sales/Plugins/sales-starter/skills/expansion-whitespace/SKILL.md +97 -0
  701. package/starter-packs/sales/Plugins/sales-starter/skills/forecast/SKILL.md +100 -0
  702. package/starter-packs/sales/Plugins/sales-starter/skills/handle-objection/SKILL.md +93 -0
  703. package/starter-packs/sales/Plugins/sales-starter/skills/inbox-sweep/SKILL.md +114 -0
  704. package/starter-packs/sales/Plugins/sales-starter/skills/lead-triage/SKILL.md +106 -0
  705. package/starter-packs/sales/Plugins/sales-starter/skills/log-activity/SKILL.md +111 -0
  706. package/starter-packs/sales/Plugins/sales-starter/skills/pipeline-review/SKILL.md +97 -0
  707. package/starter-packs/sales/Plugins/sales-starter/skills/renewal-radar/SKILL.md +95 -0
  708. package/starter-packs/sales/Plugins/sales-starter/skills/rep-context/SKILL.md +90 -0
  709. package/starter-packs/sales/Plugins/sales-starter/skills/route-lead/SKILL.md +111 -0
  710. package/starter-packs/sales/Plugins/sales-starter/skills/sales-setup/SKILL.md +200 -0
  711. package/starter-packs/sales/Plugins/sales-starter/skills/schedule-meeting/SKILL.md +99 -0
  712. package/starter-packs/sales/Plugins/sales-starter/skills/stakeholder-map/SKILL.md +107 -0
  713. package/starter-packs/sales/Plugins/sales-starter/skills/team-pipeline/SKILL.md +105 -0
  714. package/starter-packs/sales/Plugins/sales-starter/skills/update-opportunity/SKILL.md +112 -0
  715. package/starter-packs/sales/Plugins/sales-starter/skills/weekly-wrap/SKILL.md +90 -0
  716. package/starter-packs/sales/Plugins/sales-starter/skills/win-loss-review/SKILL.md +88 -0
  717. package/starter-packs/sales/pack.yaml +13 -0
  718. package/starter-packs/support/KnowledgeBase/Escalations.md +9 -0
  719. package/starter-packs/support/KnowledgeBase/Glossary.md +9 -0
  720. package/starter-packs/support/KnowledgeBase/Known issues.md +9 -0
  721. package/starter-packs/support/KnowledgeBase/Products.md +9 -0
  722. package/starter-packs/support/KnowledgeBase/Tone of voice.md +9 -0
  723. package/starter-packs/support/Plugins/support-starter/LICENSE +202 -0
  724. package/starter-packs/support/Plugins/support-starter/SOURCE.md +10 -0
  725. package/starter-packs/support/Plugins/support-starter/access.md +19 -0
  726. package/starter-packs/support/Plugins/support-starter/plugin.json +10 -0
  727. package/starter-packs/support/Plugins/support-starter/skills/customer-escalation/SKILL.md +246 -0
  728. package/starter-packs/support/Plugins/support-starter/skills/customer-research/SKILL.md +250 -0
  729. package/starter-packs/support/Plugins/support-starter/skills/draft-response/SKILL.md +416 -0
  730. package/starter-packs/support/Plugins/support-starter/skills/kb-article/SKILL.md +350 -0
  731. package/starter-packs/support/Plugins/support-starter/skills/ticket-triage/SKILL.md +273 -0
  732. package/starter-packs/support/pack.yaml +12 -0
  733. package/kb-template/AGENTS.md +0 -730
@@ -0,0 +1,533 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
+ import { promises as fs } from 'node:fs';
4
+ import path from 'node:path';
5
+ import { logger } from '../../shared/logging.js';
6
+
7
+ const log = logger('agent-downloads');
8
+
9
+ /** How long an issued link, and the bytes behind it, stay usable. */
10
+ export const DOWNLOAD_TOKEN_TTL_MS = 15 * 60 * 1000; // 15 minutes
11
+
12
+ /** How often the store looks for links that have expired. */
13
+ const SWEEP_INTERVAL_MS = 60 * 1000;
14
+
15
+ /**
16
+ * How long past its expiry a fetch that is still SENDING keeps its bytes.
17
+ *
18
+ * A link fetched a moment before it expires may take longer than the moment
19
+ * to send a large file. Its bytes are being read right now, so the sweep
20
+ * leaves them alone — but only for this long: a response that has neither
21
+ * finished nor failed within it belongs to a process that died, and the
22
+ * record is in memory, so there is no third possibility.
23
+ */
24
+ const SEND_GRACE_MS = 10 * 60 * 1000; // 10 minutes
25
+
26
+ /**
27
+ * THE one refusal for every way a download link can fail to be usable: it was
28
+ * never issued, it has already been fetched, it has expired, or it belongs to
29
+ * somebody else. One sentence for all four, for the reason the upload token
30
+ * gives (`UPLOAD_TOKEN_REFUSAL`): the token is the whole credential the route
31
+ * has, and an answer that told the cases apart would let a guesser learn which
32
+ * guesses exist.
33
+ */
34
+ export const DOWNLOAD_TOKEN_REFUSAL =
35
+ 'That download link cannot be used: it is unknown, already fetched, expired, or was issued to someone else. ' +
36
+ 'Call `request_file_download` for a new one.';
37
+
38
+ /**
39
+ * How many download REQUESTS one user may hold open at once — however many
40
+ * links each carries. A request with forty files and two folders is one.
41
+ *
42
+ * A request is permission to keep up to the whole download limit on the
43
+ * deployment's disk for a TTL; without a bound, one caller asks for a hundred.
44
+ */
45
+ export const MAX_OPEN_DOWNLOADS_PER_USER = 10;
46
+
47
+ /** A refusal with the HTTP status the download route and the tool both answer. */
48
+ export class DownloadTokenError extends Error {
49
+ constructor(
50
+ message: string,
51
+ readonly status: number,
52
+ ) {
53
+ super(message);
54
+ this.name = 'DownloadTokenError';
55
+ }
56
+ }
57
+
58
+ /** One thing a link serves: a file's bytes, or a folder's zip. */
59
+ export interface DownloadArtifact {
60
+ /** The bytes, captured when the request was made. */
61
+ data: Buffer;
62
+ /** The `Content-Type` the link answers with. */
63
+ contentType: string;
64
+ /** The name the attachment is saved under. */
65
+ filename: string;
66
+ }
67
+
68
+ /** What the `issue` {@link AgentDownloadStore.withRequestSlot} hands its work answers: one link per artifact, in order, and the terms. */
69
+ export interface IssuedDownload {
70
+ /** One absolute URL per artifact, in the order the artifacts were given. */
71
+ downloadUrls: string[];
72
+ /** ISO-8601 instant after which every link of the request, and its bytes, are gone. */
73
+ expiresAt: string;
74
+ /** Seconds from now until `expiresAt`, so a caller need not parse the date. */
75
+ expiresInSeconds: number;
76
+ }
77
+
78
+ /** A link being fetched: what to send, and how. */
79
+ export interface ClaimedDownload {
80
+ /** Absolute path of the stored bytes — OUTSIDE every workspace. */
81
+ absolutePath: string;
82
+ contentType: string;
83
+ filename: string;
84
+ bytes: number;
85
+ }
86
+
87
+ interface ArtifactRecord {
88
+ requestId: string;
89
+ /** The file name under the request's directory. Never derived from a path or a name. */
90
+ file: string;
91
+ contentType: string;
92
+ filename: string;
93
+ bytes: number;
94
+ /** Set by the fetch that took it: a link answers once. */
95
+ claimedAt?: number;
96
+ }
97
+
98
+ interface RequestRecord {
99
+ id: string;
100
+ userId: string;
101
+ expiresAt: number;
102
+ /** Token hashes of the artifacts not yet fetched to the end. */
103
+ pending: Set<string>;
104
+ }
105
+
106
+ export interface AgentDownloadStoreOptions {
107
+ /** Directory the bytes are written to. A sibling of `workspacesRoot`, never inside one. */
108
+ root: string;
109
+ /** Absolute base URL of this deployment's API, e.g. `https://core.example.com`. */
110
+ publicBaseUrl: string;
111
+ /** Token prefix, so a leaked credential can be recognised by shape. */
112
+ tokenPrefix?: string;
113
+ ttlMs?: number;
114
+ /** How many requests one user may hold open at once. Defaults to {@link MAX_OPEN_DOWNLOADS_PER_USER}. */
115
+ maxOpenPerUser?: number;
116
+ }
117
+
118
+ /**
119
+ * The download links an agent takes files OUT of the knowledge base by — the
120
+ * twin of the upload store (`agent-upload.store.ts`), and built on the same
121
+ * three properties, because the download route is likewise authenticated by
122
+ * a token alone:
123
+ *
124
+ * - **Unguessable.** 32 random bytes, base64url, per link.
125
+ * - **Never stored in the clear.** Records are keyed by the token's SHA-256.
126
+ * - **Bound and single-use.** A link answers ONE fetch; a second, an expired
127
+ * one and an unknown one all meet {@link DOWNLOAD_TOKEN_REFUSAL}.
128
+ *
129
+ * The bytes are captured at request time (by `request_file_download`, which
130
+ * judges every file before it gets here) and written under `root/<request>/` —
131
+ * a directory beside the workspaces root, which no file tool can name. A link
132
+ * fetched has its bytes deleted once the response ends, however it ends; a
133
+ * link nobody fetched is deleted when it expires.
134
+ */
135
+ /**
136
+ * The download store as its consumers see it — the port the tool, the
137
+ * download routes and the lifecycle depend on, so a deployment may substitute
138
+ * its own keeper of one-time links.
139
+ */
140
+ export interface IAgentDownloadStore {
141
+ /** The absolute address a token's link is fetched at. */
142
+ downloadUrlFor(token: string): string;
143
+ /** Refuse, with the cap's sentence, when `user` holds the most requests allowed. */
144
+ assertCanIssue(user: { id: string }): void;
145
+ /** Take one of `user`'s request slots and run `work` in their turn — see the class. */
146
+ withRequestSlot<T>(
147
+ user: { id: string },
148
+ work: (issue: (items: DownloadArtifact[]) => Promise<IssuedDownload>) => Promise<T>,
149
+ ): Promise<T>;
150
+ /** Take `token`'s link for ONE fetch and answer what to send. */
151
+ claim(token: string, fetcherIds?: readonly string[]): ClaimedDownload;
152
+ /** A fetch is over: the link's bytes are gone. Idempotent. */
153
+ finish(token: string): Promise<void>;
154
+ /** How many requests `userId` holds open. */
155
+ openRequestsOf(userId: string): number;
156
+ /** Delete every expired request and every orphaned directory, once. */
157
+ sweepNow(): Promise<void>;
158
+ /** Sweep now, and keep sweeping. */
159
+ startSweeping(intervalMs?: number): void;
160
+ /** Stop the sweeps. */
161
+ stopSweeping(): void;
162
+ /** Wait for a sweep in flight, so a root can be torn down after it. */
163
+ drainSweep(): Promise<void>;
164
+ }
165
+
166
+ export class AgentDownloadStore implements IAgentDownloadStore {
167
+ /** Token hash → the one artifact that link serves. */
168
+ private readonly artifacts = new Map<string, ArtifactRecord>();
169
+ /** Request id → the request its links belong to. */
170
+ private readonly requests = new Map<string, RequestRecord>();
171
+ /** Per user, the request in flight — see {@link withRequestSlot}. */
172
+ private readonly building = new Map<string, Promise<unknown>>();
173
+ /** Per user, slots held by calls still waiting, building or writing — counted as open. */
174
+ private readonly reserved = new Map<string, number>();
175
+ /**
176
+ * Request ids whose bytes are being written right now: named in no map yet,
177
+ * and not the sweep's to reclaim. Entered before the first write and left
178
+ * once the request is recorded or its directory removed.
179
+ */
180
+ private readonly writing = new Set<string>();
181
+ /** The users whose turn the current async context is running in — see {@link withRequestSlot}. */
182
+ private readonly inTurn = new AsyncLocalStorage<ReadonlySet<string>>();
183
+ private readonly root: string;
184
+ private readonly publicBaseUrl: string;
185
+ private readonly tokenPrefix: string;
186
+ private readonly ttlMs: number;
187
+ private readonly maxOpenPerUser: number;
188
+ private sweepTimer: ReturnType<typeof setInterval> | null = null;
189
+ private sweeping: Promise<void> | null = null;
190
+ private stopped = false;
191
+
192
+ constructor(options: AgentDownloadStoreOptions) {
193
+ this.root = options.root;
194
+ this.publicBaseUrl = options.publicBaseUrl.replace(/\/+$/, '');
195
+ this.tokenPrefix = options.tokenPrefix ?? '';
196
+ this.ttlMs = options.ttlMs ?? DOWNLOAD_TOKEN_TTL_MS;
197
+ this.maxOpenPerUser = options.maxOpenPerUser ?? MAX_OPEN_DOWNLOADS_PER_USER;
198
+ }
199
+
200
+ /** The URL a link's bytes are fetched from. The one spelling of this route's address. */
201
+ downloadUrlFor(token: string): string {
202
+ return `${this.publicBaseUrl}/api/agent/downloads/${encodeURIComponent(token)}`;
203
+ }
204
+
205
+ /**
206
+ * Refuse `user` a new request when they already hold the most one user may
207
+ * — issued requests and slots still being filled alike.
208
+ */
209
+ assertCanIssue(user: { id: string }): void {
210
+ const open = this.openRequestsOf(user.id);
211
+ if (open >= this.maxOpenPerUser) {
212
+ throw new DownloadTokenError(
213
+ `You already hold ${open} open download requests, the most one user may have at once. Fetch their links, ` +
214
+ 'or wait for them to expire, then ask again. One request carries any number of files and folders.',
215
+ 429,
216
+ );
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Take one of `user`'s request slots, then run `work` after any request of
222
+ * theirs already running; `work` is handed the `issue` that fills the slot.
223
+ *
224
+ * The slot is taken AT ONCE, before the turn is waited for, and counts as an
225
+ * open request until `work` ends: a caller at the cap is refused before the
226
+ * server spends a zip's worth of work on it, and ten calls in parallel cannot
227
+ * all pass the count and then all build. A call that ends without issuing
228
+ * (nothing included, a refusal, a failure) gives its slot back.
229
+ *
230
+ * The build AND the write of its bytes run in the turn: a build reads every
231
+ * included file into memory and may zip up to the download limit, so one
232
+ * request at a time per user bounds what one caller can make the process
233
+ * hold or the disk stage. Different users do not wait on each other.
234
+ *
235
+ * The ONE way a request is issued: there is no public `issue` to call on
236
+ * the side. `work`'s `issue` fills the slot once — a second call would be
237
+ * a second request on one slot, past the cap — and a `withRequestSlot` for
238
+ * the same user from inside `work` throws rather than wait for the turn it
239
+ * is itself holding, which would never come.
240
+ */
241
+ async withRequestSlot<T>(
242
+ user: { id: string },
243
+ work: (issue: (items: DownloadArtifact[]) => Promise<IssuedDownload>) => Promise<T>,
244
+ ): Promise<T> {
245
+ const held = this.inTurn.getStore();
246
+ if (held?.has(user.id)) {
247
+ throw new Error('A download request slot was asked for inside one already held for the same user.');
248
+ }
249
+ this.assertCanIssue(user);
250
+ this.reserved.set(user.id, (this.reserved.get(user.id) ?? 0) + 1);
251
+ // Once the request is recorded, the record is what counts as open and the
252
+ // reservation is given back by `write` — not here as well, which would
253
+ // count the request twice while `work` finishes.
254
+ let issued = false;
255
+ try {
256
+ const issue = (items: DownloadArtifact[]): Promise<IssuedDownload> => {
257
+ if (issued) return Promise.reject(new Error('A download request slot issues once.'));
258
+ issued = true;
259
+ return this.write(user, items);
260
+ };
261
+ const turn = new Set(held ?? []).add(user.id);
262
+ const before = this.building.get(user.id) ?? Promise.resolve();
263
+ const mine = before.catch(() => undefined).then(() => this.inTurn.run(turn, () => work(issue)));
264
+ this.building.set(user.id, mine);
265
+ try {
266
+ return await mine;
267
+ } finally {
268
+ if (this.building.get(user.id) === mine) this.building.delete(user.id);
269
+ }
270
+ } finally {
271
+ if (!issued) this.releaseReservation(user.id);
272
+ }
273
+ }
274
+
275
+ /** Give back one of `userId`'s reserved slots. */
276
+ private releaseReservation(userId: string): void {
277
+ const left = (this.reserved.get(userId) ?? 1) - 1;
278
+ if (left > 0) this.reserved.set(userId, left);
279
+ else this.reserved.delete(userId);
280
+ }
281
+
282
+ /**
283
+ * Store every artifact of one request and answer a link per artifact, all
284
+ * sharing the request's expiry, within a slot already held: the slot is the
285
+ * capacity check. Nothing is issued unless every artifact is on disk: a
286
+ * request whose bytes could not all be written leaves nothing.
287
+ */
288
+ private async write(user: { id: string }, items: DownloadArtifact[]): Promise<IssuedDownload> {
289
+ if (items.length === 0) throw new Error('A download request must carry at least one artifact.');
290
+ const requestId = `download-${Date.now()}-${randomBytes(8).toString('hex')}`;
291
+ const dir = path.join(this.root, requestId);
292
+ const minted: { key: string; token: string; record: ArtifactRecord }[] = [];
293
+ // Reserved BEFORE the first filesystem await: a sweep running while a slow
294
+ // disk takes these writes would otherwise find a directory no request
295
+ // names and, past the age bound, reclaim it under the write.
296
+ this.writing.add(requestId);
297
+ try {
298
+ await fs.mkdir(dir, { recursive: true });
299
+ for (let i = 0; i < items.length; i++) {
300
+ const item = items[i]!;
301
+ const file = String(i);
302
+ await fs.writeFile(path.join(dir, file), item.data);
303
+ const token = this.tokenPrefix + randomBytes(32).toString('base64url');
304
+ minted.push({
305
+ key: hash(token),
306
+ token,
307
+ record: {
308
+ requestId,
309
+ file,
310
+ contentType: item.contentType,
311
+ filename: item.filename,
312
+ bytes: item.data.byteLength,
313
+ },
314
+ });
315
+ }
316
+ } catch (err) {
317
+ try {
318
+ await this.removeDir(requestId);
319
+ } finally {
320
+ this.writing.delete(requestId);
321
+ // Nothing issued: the slot goes back here, since `withRequestSlot`
322
+ // treats an `issue` that was called as one that filled its slot.
323
+ this.releaseReservation(user.id);
324
+ }
325
+ throw err;
326
+ }
327
+ // The TTL runs from the moment the links exist, not from when the build
328
+ // started: a 500 MB build must not hand out links with minutes already gone.
329
+ const expiresAt = Date.now() + this.ttlMs;
330
+ const request: RequestRecord = { id: requestId, userId: user.id, expiresAt, pending: new Set() };
331
+ for (const { key, record } of minted) {
332
+ this.artifacts.set(key, record);
333
+ request.pending.add(key);
334
+ }
335
+ this.requests.set(requestId, request);
336
+ this.writing.delete(requestId);
337
+ // The record counts as open from here; the reservation that held the
338
+ // place until now is given back, so the request is counted once.
339
+ this.releaseReservation(user.id);
340
+ // AFTER the records exist: the first sweep runs at once and would
341
+ // otherwise take this request's directory for an orphan. And never once
342
+ // the store is stopped: a request finishing after shutdown's
343
+ // `stopSweeping` must not re-arm the sweeper that was stopped for good.
344
+ if (!this.stopped) this.startSweeping();
345
+ return {
346
+ downloadUrls: minted.map((m) => this.downloadUrlFor(m.token)),
347
+ expiresAt: new Date(expiresAt).toISOString(),
348
+ expiresInSeconds: Math.round(this.ttlMs / 1000),
349
+ };
350
+ }
351
+
352
+ /**
353
+ * Take `token`'s link for ONE fetch and answer what to send. Spent the
354
+ * moment it is claimed, before a byte goes out: a second fetch arriving
355
+ * while the first is still sending is refused, not served twice.
356
+ *
357
+ * `fetcherIds` are the users the fetch identified itself as, by every
358
+ * credential it carried — usually none. The link works for anyone holding
359
+ * it — an agent's `curl` carries no session — but a fetch that says it is
360
+ * SOMEONE ELSE, by any of its credentials, is refused: that user holds a
361
+ * link issued to another.
362
+ */
363
+ claim(token: string, fetcherIds: readonly string[] = []): ClaimedDownload {
364
+ const key = hash(token);
365
+ const record = this.artifacts.get(key);
366
+ if (!record || record.claimedAt !== undefined) throw refusal();
367
+ const request = this.requests.get(record.requestId);
368
+ if (!request) throw refusal();
369
+ if (request.expiresAt <= Date.now()) {
370
+ void this.forget(key);
371
+ throw refusal();
372
+ }
373
+ if (fetcherIds.some((id) => id !== request.userId)) throw refusal();
374
+ record.claimedAt = Date.now();
375
+ return {
376
+ absolutePath: path.join(this.root, record.requestId, record.file),
377
+ contentType: record.contentType,
378
+ filename: record.filename,
379
+ bytes: record.bytes,
380
+ };
381
+ }
382
+
383
+ /**
384
+ * The fetch of `token` has ended — sent in full, failed, or the client went
385
+ * away. The bytes go either way: a link answers once, so nothing will ever
386
+ * read them again. Idempotent.
387
+ */
388
+ async finish(token: string): Promise<void> {
389
+ const key = hash(token);
390
+ const record = this.artifacts.get(key);
391
+ if (!record) return;
392
+ await this.forget(key);
393
+ }
394
+
395
+ /**
396
+ * How many requests `userId` holds open: unexpired with a link unfetched, or
397
+ * with a fetch still sending — and the slots of calls still under way.
398
+ */
399
+ openRequestsOf(userId: string): number {
400
+ const now = Date.now();
401
+ let open = this.reserved.get(userId) ?? 0;
402
+ for (const request of this.requests.values()) {
403
+ if (request.userId !== userId) continue;
404
+ if (request.expiresAt > now || this.sending(request, now)) open += 1;
405
+ }
406
+ return open;
407
+ }
408
+
409
+ /**
410
+ * Delete every request whose links have expired, with its bytes — then any
411
+ * directory in the root that no live request names and that has outlived
412
+ * every link that could name it (a process killed between issue and fetch
413
+ * leaves one no map will ever mention again; by AGE, because during a
414
+ * restart two processes share the root, as the upload store explains).
415
+ */
416
+ async sweepNow(): Promise<void> {
417
+ if (this.stopped) return;
418
+ const now = Date.now();
419
+ for (const request of [...this.requests.values()]) {
420
+ if (request.expiresAt > now) continue;
421
+ if (this.sending(request, now)) continue;
422
+ await this.dropRequest(request);
423
+ }
424
+ let names: string[];
425
+ try {
426
+ names = await fs.readdir(this.root);
427
+ } catch {
428
+ return; // root not created yet — nothing to reclaim
429
+ }
430
+ // Read AFTER the listing, so a request issued while it was read is named.
431
+ const live = new Set(this.requests.keys());
432
+ for (const name of names) {
433
+ if (this.stopped) return;
434
+ if (live.has(name) || this.writing.has(name)) continue;
435
+ if (await this.outlivedEveryLink(name, now)) await this.removeDir(name);
436
+ }
437
+ }
438
+
439
+ /** Sweep now, and keep sweeping. Started by the first request issued; idempotent; `unref`'d. */
440
+ startSweeping(intervalMs: number = SWEEP_INTERVAL_MS): void {
441
+ if (this.sweepTimer) return;
442
+ this.stopped = false;
443
+ this.sweep();
444
+ this.sweepTimer = setInterval(() => this.sweep(), intervalMs);
445
+ this.sweepTimer.unref?.();
446
+ }
447
+
448
+ /** Stop sweeping for good — see `AgentUploadStore.stopSweeping` for why a stopped graph must. */
449
+ stopSweeping(): void {
450
+ this.stopped = true;
451
+ if (this.sweepTimer) clearInterval(this.sweepTimer);
452
+ this.sweepTimer = null;
453
+ }
454
+
455
+ /** Wait for the sweep in flight, if any. Pairs with {@link stopSweeping} on shutdown. */
456
+ async drainSweep(): Promise<void> {
457
+ await this.sweeping;
458
+ }
459
+
460
+ private sweep(): void {
461
+ // One sweep at a time: a second starting while the first still deletes
462
+ // would make `drainSweep` wait for the newer and miss the older.
463
+ if (this.sweeping) return;
464
+ const running = this.sweepNow()
465
+ .catch((err: unknown) => {
466
+ log.warn('could not sweep expired downloads:', { err });
467
+ })
468
+ .finally(() => {
469
+ if (this.sweeping === running) this.sweeping = null;
470
+ });
471
+ this.sweeping = running;
472
+ }
473
+
474
+ /** Whether a fetch of one of `request`'s links is still sending, within its grace. */
475
+ private sending(request: RequestRecord, now: number): boolean {
476
+ for (const key of request.pending) {
477
+ const claimedAt = this.artifacts.get(key)?.claimedAt;
478
+ if (claimedAt !== undefined && now - claimedAt < SEND_GRACE_MS) return true;
479
+ }
480
+ return false;
481
+ }
482
+
483
+ /** Drop one artifact's link and bytes; the request goes with its last one. */
484
+ private async forget(key: string): Promise<void> {
485
+ const record = this.artifacts.get(key);
486
+ if (!record) return;
487
+ this.artifacts.delete(key);
488
+ const request = this.requests.get(record.requestId);
489
+ request?.pending.delete(key);
490
+ if (request && request.pending.size === 0) {
491
+ this.requests.delete(request.id);
492
+ await this.removeDir(request.id);
493
+ return;
494
+ }
495
+ try {
496
+ await fs.rm(path.join(this.root, record.requestId, record.file), { force: true });
497
+ } catch (err) {
498
+ log.warn(`could not delete a fetched download of "${record.requestId}":`, { err });
499
+ }
500
+ }
501
+
502
+ private async dropRequest(request: RequestRecord): Promise<void> {
503
+ for (const key of request.pending) this.artifacts.delete(key);
504
+ this.requests.delete(request.id);
505
+ await this.removeDir(request.id);
506
+ }
507
+
508
+ private async outlivedEveryLink(name: string, now: number): Promise<boolean> {
509
+ try {
510
+ const { mtimeMs } = await fs.stat(path.join(this.root, name));
511
+ return now - mtimeMs > this.ttlMs + SEND_GRACE_MS;
512
+ } catch {
513
+ return false;
514
+ }
515
+ }
516
+
517
+ /** Best-effort delete of one request's directory. Never throws. */
518
+ private async removeDir(id: string): Promise<void> {
519
+ try {
520
+ await fs.rm(path.join(this.root, id), { recursive: true, force: true });
521
+ } catch (err) {
522
+ log.warn(`could not delete the stored download "${id}":`, { err });
523
+ }
524
+ }
525
+ }
526
+
527
+ function refusal(): DownloadTokenError {
528
+ return new DownloadTokenError(DOWNLOAD_TOKEN_REFUSAL, 404);
529
+ }
530
+
531
+ function hash(token: string): string {
532
+ return createHash('sha256').update(token).digest('hex');
533
+ }
@@ -260,8 +260,10 @@ export class AgentUploadStore {
260
260
  });
261
261
  // AFTER the record exists, not before. The first sweep runs the moment the
262
262
  // timer starts, and started from an empty map it would be a sweep that
263
- // believes nothing is live — this token's own id included.
264
- this.startSweeping();
263
+ // believes nothing is live — this token's own id included. And never once
264
+ // the store is stopped: a token issued after shutdown's `stopSweeping`
265
+ // must not re-arm the sweeper that was stopped for good.
266
+ if (!this.stopped) this.startSweeping();
265
267
  return {
266
268
  uploadUrl: this.uploadUrlFor(token),
267
269
  token,
@@ -621,25 +623,39 @@ function hash(token: string): string {
621
623
  * Both directions and both spellings: equal paths, either containing the
622
624
  * other, and the real paths, so a root that is a LINK into the workspaces tree
623
625
  * is refused too.
626
+ *
627
+ * `what` names the root being checked, for a boot failure that sends the
628
+ * operator to the right setting: the upload root by default; the download
629
+ * root (derived from it) says so itself.
624
630
  */
625
631
  export async function assertUploadsRootOutsideWorkspaces(
626
632
  uploadsRoot: string,
627
633
  workspacesRoot: string,
634
+ what: StagingRootDescription = UPLOADS_ROOT_DESCRIPTION,
628
635
  ): Promise<void> {
629
636
  for (const [uploads, workspaces] of [
630
637
  [path.resolve(uploadsRoot), path.resolve(workspacesRoot)],
631
638
  [await realBase(uploadsRoot), await realBase(workspacesRoot)],
632
639
  ]) {
633
640
  if (uploads === workspaces || contains(workspaces, uploads) || contains(uploads, workspaces)) {
634
- throw new Error(
635
- `AGENT_UPLOADS_ROOT ("${uploadsRoot}") must be outside WORKSPACES_ROOT ("${workspacesRoot}"): uploaded ` +
636
- 'bytes are staged there before any access or platform-file rule has judged them, so a root inside a ' +
637
- 'workspace would let the file tools read them. Point it at a sibling directory.',
638
- );
641
+ throw new Error(`${what.name} ("${uploadsRoot}") must be outside WORKSPACES_ROOT ("${workspacesRoot}"): ${what.why}`);
639
642
  }
640
643
  }
641
644
  }
642
645
 
646
+ /** A staging root {@link assertUploadsRootOutsideWorkspaces} checks: what it is called, and why and how to fix it. */
647
+ export interface StagingRootDescription {
648
+ name: string;
649
+ why: string;
650
+ }
651
+
652
+ const UPLOADS_ROOT_DESCRIPTION: StagingRootDescription = {
653
+ name: 'AGENT_UPLOADS_ROOT',
654
+ why:
655
+ 'uploaded bytes are staged there before any access or platform-file rule has judged them, so a root inside a ' +
656
+ 'workspace would let the file tools read them. Point it at a sibling directory.',
657
+ };
658
+
643
659
  /** Whether `child` is inside `parent`. Paths already resolved. */
644
660
  function contains(parent: string, child: string): boolean {
645
661
  return child.startsWith(parent.endsWith(path.sep) ? parent : parent + path.sep);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The content type a raw route declares for bytes a renderer fetches to
3
+ * draw INLINE — the app's `/raw` file route and the embed's raw route read
4
+ * it from here, so a picture or a document the app shows is the same type
5
+ * inside a chat. Anything outside this table is `application/octet-stream`:
6
+ * bytes the browser is told nothing about, under `nosniff`, so a file the
7
+ * table does not name can never be promoted to active content.
8
+ *
9
+ * SVG is listed because the renderers draw it through `<img>`, where its
10
+ * scripts never run; a route that serves it as a DOCUMENT sandboxes it (see
11
+ * the routes), and a download of it is forced to octet-stream there.
12
+ */
13
+ const RAW_INLINE_MIME: Record<string, string> = {
14
+ '.png': 'image/png',
15
+ '.jpg': 'image/jpeg',
16
+ '.jpeg': 'image/jpeg',
17
+ '.gif': 'image/gif',
18
+ '.webp': 'image/webp',
19
+ '.svg': 'image/svg+xml',
20
+ '.bmp': 'image/bmp',
21
+ '.ico': 'image/x-icon',
22
+ '.avif': 'image/avif',
23
+ '.pdf': 'application/pdf',
24
+ '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
25
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
26
+ };
27
+
28
+ export const OCTET_STREAM = 'application/octet-stream';
29
+
30
+ /** The lower-cased extension of `path`, dot included; `''` when it has none. */
31
+ export function rawExtensionOf(path: string): string {
32
+ const dot = path.lastIndexOf('.');
33
+ const slash = path.lastIndexOf('/');
34
+ return dot > slash ? path.slice(dot).toLowerCase() : '';
35
+ }
36
+
37
+ /** The inline content type for `path`'s extension, `application/octet-stream` when the table has none. */
38
+ export function rawMimeFor(path: string): string {
39
+ return RAW_INLINE_MIME[rawExtensionOf(path)] ?? OCTET_STREAM;
40
+ }
@@ -1,4 +1,4 @@
1
- import { isUtf8 } from 'node:buffer';
1
+ import { isTextBytes } from '../../../shared/utf8-text.js';
2
2
  import { fileExtension } from './doc-extract.types.js';
3
3
  import { displayPath, type FileKind, type FileReader, type ReadResult } from './file-reader.js';
4
4
 
@@ -64,14 +64,11 @@ export function extensionMime(path: string): string | undefined {
64
64
 
65
65
  /**
66
66
  * Text is what the fallback reader may hand to the text tools: no NUL byte
67
- * AND valid UTF-8. A NUL-free file that does not decode as UTF-8 is still
68
- * binary here — the decode would be lossy, so text written back could never
69
- * round-trip the original bytes. Checked on the raw bytes, so a large binary
70
- * is refused without allocating its full decoded string first.
67
+ * AND valid UTF-8 — the one policy in `shared/utf8-text.ts`, which the
68
+ * seeder and the starter packs read as well. Re-exported here for the
69
+ * readers' callers.
71
70
  */
72
- export function isTextBytes(bytes: Buffer): boolean {
73
- return !bytes.includes(0) && isUtf8(bytes);
74
- }
71
+ export { isTextBytes };
75
72
 
76
73
  /**
77
74
  * The DEFAULT reader — the registry's fallback for every extension no other