@bevel-software/platform-core-backend 0.1.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 (720) hide show
  1. package/LICENSE +202 -0
  2. package/dist/assets.d.ts +5 -0
  3. package/dist/assets.d.ts.map +1 -0
  4. package/dist/assets.js +23 -0
  5. package/dist/assets.js.map +1 -0
  6. package/dist/core/core-ports.d.ts +83 -0
  7. package/dist/core/core-ports.d.ts.map +1 -0
  8. package/dist/core/core-ports.js +12 -0
  9. package/dist/core/core-ports.js.map +1 -0
  10. package/dist/core/create-core-server.d.ts +62 -0
  11. package/dist/core/create-core-server.d.ts.map +1 -0
  12. package/dist/core/create-core-server.js +204 -0
  13. package/dist/core/create-core-server.js.map +1 -0
  14. package/dist/core/create-core-services.d.ts +95 -0
  15. package/dist/core/create-core-services.d.ts.map +1 -0
  16. package/dist/core/create-core-services.js +352 -0
  17. package/dist/core/create-core-services.js.map +1 -0
  18. package/dist/core-config.d.ts +119 -0
  19. package/dist/core-config.d.ts.map +1 -0
  20. package/dist/core-config.js +240 -0
  21. package/dist/core-config.js.map +1 -0
  22. package/dist/index.d.ts +36 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +36 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/modules/access/access-control.interface.d.ts +348 -0
  27. package/dist/modules/access/access-control.interface.d.ts.map +1 -0
  28. package/dist/modules/access/access-control.interface.js +2 -0
  29. package/dist/modules/access/access-control.interface.js.map +1 -0
  30. package/dist/modules/access/access-control.service.d.ts +323 -0
  31. package/dist/modules/access/access-control.service.d.ts.map +1 -0
  32. package/dist/modules/access/access-control.service.js +1431 -0
  33. package/dist/modules/access/access-control.service.js.map +1 -0
  34. package/dist/modules/access/access-errors.d.ts +34 -0
  35. package/dist/modules/access/access-errors.d.ts.map +1 -0
  36. package/dist/modules/access/access-errors.js +40 -0
  37. package/dist/modules/access/access-errors.js.map +1 -0
  38. package/dist/modules/access/access-mutation.service.d.ts +176 -0
  39. package/dist/modules/access/access-mutation.service.d.ts.map +1 -0
  40. package/dist/modules/access/access-mutation.service.js +307 -0
  41. package/dist/modules/access/access-mutation.service.js.map +1 -0
  42. package/dist/modules/access/access-splice.d.ts +98 -0
  43. package/dist/modules/access/access-splice.d.ts.map +1 -0
  44. package/dist/modules/access/access-splice.js +346 -0
  45. package/dist/modules/access/access-splice.js.map +1 -0
  46. package/dist/modules/access/access.routes.d.ts +10 -0
  47. package/dist/modules/access/access.routes.d.ts.map +1 -0
  48. package/dist/modules/access/access.routes.js +757 -0
  49. package/dist/modules/access/access.routes.js.map +1 -0
  50. package/dist/modules/access/creator-access.d.ts +113 -0
  51. package/dist/modules/access/creator-access.d.ts.map +1 -0
  52. package/dist/modules/access/creator-access.js +212 -0
  53. package/dist/modules/access/creator-access.js.map +1 -0
  54. package/dist/modules/access/kb-read-filter.d.ts +41 -0
  55. package/dist/modules/access/kb-read-filter.d.ts.map +1 -0
  56. package/dist/modules/access/kb-read-filter.js +60 -0
  57. package/dist/modules/access/kb-read-filter.js.map +1 -0
  58. package/dist/modules/access/roles-admin.service.d.ts +240 -0
  59. package/dist/modules/access/roles-admin.service.d.ts.map +1 -0
  60. package/dist/modules/access/roles-admin.service.js +630 -0
  61. package/dist/modules/access/roles-admin.service.js.map +1 -0
  62. package/dist/modules/access/roles-edit.d.ts +91 -0
  63. package/dist/modules/access/roles-edit.d.ts.map +1 -0
  64. package/dist/modules/access/roles-edit.js +232 -0
  65. package/dist/modules/access/roles-edit.js.map +1 -0
  66. package/dist/modules/access/roles-yaml-guard.d.ts +56 -0
  67. package/dist/modules/access/roles-yaml-guard.d.ts.map +1 -0
  68. package/dist/modules/access/roles-yaml-guard.js +79 -0
  69. package/dist/modules/access/roles-yaml-guard.js.map +1 -0
  70. package/dist/modules/admin/admin-access.routes.d.ts +18 -0
  71. package/dist/modules/admin/admin-access.routes.d.ts.map +1 -0
  72. package/dist/modules/admin/admin-access.routes.js +26 -0
  73. package/dist/modules/admin/admin-access.routes.js.map +1 -0
  74. package/dist/modules/admin/admin-access.service.d.ts +24 -0
  75. package/dist/modules/admin/admin-access.service.d.ts.map +1 -0
  76. package/dist/modules/admin/admin-access.service.js +41 -0
  77. package/dist/modules/admin/admin-access.service.js.map +1 -0
  78. package/dist/modules/admin/admin.interface.d.ts +11 -0
  79. package/dist/modules/admin/admin.interface.d.ts.map +1 -0
  80. package/dist/modules/admin/admin.interface.js +2 -0
  81. package/dist/modules/admin/admin.interface.js.map +1 -0
  82. package/dist/modules/auth/account-erasure.service.d.ts +80 -0
  83. package/dist/modules/auth/account-erasure.service.d.ts.map +1 -0
  84. package/dist/modules/auth/account-erasure.service.js +91 -0
  85. package/dist/modules/auth/account-erasure.service.js.map +1 -0
  86. package/dist/modules/auth/auth.middleware.d.ts +23 -0
  87. package/dist/modules/auth/auth.middleware.d.ts.map +1 -0
  88. package/dist/modules/auth/auth.middleware.js +68 -0
  89. package/dist/modules/auth/auth.middleware.js.map +1 -0
  90. package/dist/modules/auth/auth.routes.d.ts +25 -0
  91. package/dist/modules/auth/auth.routes.d.ts.map +1 -0
  92. package/dist/modules/auth/auth.routes.js +72 -0
  93. package/dist/modules/auth/auth.routes.js.map +1 -0
  94. package/dist/modules/auth/auth.service.d.ts +76 -0
  95. package/dist/modules/auth/auth.service.d.ts.map +1 -0
  96. package/dist/modules/auth/auth.service.js +168 -0
  97. package/dist/modules/auth/auth.service.js.map +1 -0
  98. package/dist/modules/code-mode/code-mode-names.d.ts +16 -0
  99. package/dist/modules/code-mode/code-mode-names.d.ts.map +1 -0
  100. package/dist/modules/code-mode/code-mode-names.js +30 -0
  101. package/dist/modules/code-mode/code-mode-names.js.map +1 -0
  102. package/dist/modules/code-mode/code-mode.tool.d.ts +13 -0
  103. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -0
  104. package/dist/modules/code-mode/code-mode.tool.js +112 -0
  105. package/dist/modules/code-mode/code-mode.tool.js.map +1 -0
  106. package/dist/modules/code-mode/index.d.ts +3 -0
  107. package/dist/modules/code-mode/index.d.ts.map +1 -0
  108. package/dist/modules/code-mode/index.js +3 -0
  109. package/dist/modules/code-mode/index.js.map +1 -0
  110. package/dist/modules/database/connection.d.ts +6 -0
  111. package/dist/modules/database/connection.d.ts.map +1 -0
  112. package/dist/modules/database/connection.js +12 -0
  113. package/dist/modules/database/connection.js.map +1 -0
  114. package/dist/modules/database/core-schema.d.ts +2273 -0
  115. package/dist/modules/database/core-schema.d.ts.map +1 -0
  116. package/dist/modules/database/core-schema.js +413 -0
  117. package/dist/modules/database/core-schema.js.map +1 -0
  118. package/dist/modules/database/migrate.d.ts +10 -0
  119. package/dist/modules/database/migrate.d.ts.map +1 -0
  120. package/dist/modules/database/migrate.js +40 -0
  121. package/dist/modules/database/migrate.js.map +1 -0
  122. package/dist/modules/database/schema.d.ts +12 -0
  123. package/dist/modules/database/schema.d.ts.map +1 -0
  124. package/dist/modules/database/schema.js +12 -0
  125. package/dist/modules/database/schema.js.map +1 -0
  126. package/dist/modules/diff/diff-paths.d.ts +2 -0
  127. package/dist/modules/diff/diff-paths.d.ts.map +1 -0
  128. package/dist/modules/diff/diff-paths.js +9 -0
  129. package/dist/modules/diff/diff-paths.js.map +1 -0
  130. package/dist/modules/diff/diff.config.d.ts +8 -0
  131. package/dist/modules/diff/diff.config.d.ts.map +1 -0
  132. package/dist/modules/diff/diff.config.js +13 -0
  133. package/dist/modules/diff/diff.config.js.map +1 -0
  134. package/dist/modules/diff/diff.interface.d.ts +73 -0
  135. package/dist/modules/diff/diff.interface.d.ts.map +1 -0
  136. package/dist/modules/diff/diff.interface.js +2 -0
  137. package/dist/modules/diff/diff.interface.js.map +1 -0
  138. package/dist/modules/diff/diff.routes.d.ts +35 -0
  139. package/dist/modules/diff/diff.routes.d.ts.map +1 -0
  140. package/dist/modules/diff/diff.routes.js +228 -0
  141. package/dist/modules/diff/diff.routes.js.map +1 -0
  142. package/dist/modules/diff/diff.service.d.ts +51 -0
  143. package/dist/modules/diff/diff.service.d.ts.map +1 -0
  144. package/dist/modules/diff/diff.service.js +489 -0
  145. package/dist/modules/diff/diff.service.js.map +1 -0
  146. package/dist/modules/diff/line-diff.d.ts +16 -0
  147. package/dist/modules/diff/line-diff.d.ts.map +1 -0
  148. package/dist/modules/diff/line-diff.js +67 -0
  149. package/dist/modules/diff/line-diff.js.map +1 -0
  150. package/dist/modules/mcp/mcp-auth.middleware.d.ts +27 -0
  151. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -0
  152. package/dist/modules/mcp/mcp-auth.middleware.js +116 -0
  153. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -0
  154. package/dist/modules/mcp/mcp-session-store.d.ts +74 -0
  155. package/dist/modules/mcp/mcp-session-store.d.ts.map +1 -0
  156. package/dist/modules/mcp/mcp-session-store.js +131 -0
  157. package/dist/modules/mcp/mcp-session-store.js.map +1 -0
  158. package/dist/modules/mcp/mcp.routes.d.ts +24 -0
  159. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -0
  160. package/dist/modules/mcp/mcp.routes.js +229 -0
  161. package/dist/modules/mcp/mcp.routes.js.map +1 -0
  162. package/dist/modules/mcp/mcp.service.d.ts +198 -0
  163. package/dist/modules/mcp/mcp.service.d.ts.map +1 -0
  164. package/dist/modules/mcp/mcp.service.js +840 -0
  165. package/dist/modules/mcp/mcp.service.js.map +1 -0
  166. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +76 -0
  167. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -0
  168. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +291 -0
  169. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -0
  170. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +18 -0
  171. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -0
  172. package/dist/modules/mcp/oauth/oauth-consent.routes.js +52 -0
  173. package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -0
  174. package/dist/modules/mcp/oauth/oauth-state.d.ts +32 -0
  175. package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -0
  176. package/dist/modules/mcp/oauth/oauth-state.js +34 -0
  177. package/dist/modules/mcp/oauth/oauth-state.js.map +1 -0
  178. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +92 -0
  179. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -0
  180. package/dist/modules/secrets-vault/db-secrets-vault.service.js +728 -0
  181. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -0
  182. package/dist/modules/secrets-vault/index.d.ts +7 -0
  183. package/dist/modules/secrets-vault/index.d.ts.map +1 -0
  184. package/dist/modules/secrets-vault/index.js +6 -0
  185. package/dist/modules/secrets-vault/index.js.map +1 -0
  186. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts +63 -0
  187. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts.map +1 -0
  188. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js +269 -0
  189. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js.map +1 -0
  190. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +46 -0
  191. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -0
  192. package/dist/modules/secrets-vault/secrets-variable-loader.js +87 -0
  193. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -0
  194. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +210 -0
  195. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -0
  196. package/dist/modules/secrets-vault/secrets-vault.contract.js +90 -0
  197. package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -0
  198. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +30 -0
  199. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -0
  200. package/dist/modules/secrets-vault/secrets-vault.routes.js +490 -0
  201. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -0
  202. package/dist/modules/skills/index.d.ts +5 -0
  203. package/dist/modules/skills/index.d.ts.map +1 -0
  204. package/dist/modules/skills/index.js +4 -0
  205. package/dist/modules/skills/index.js.map +1 -0
  206. package/dist/modules/skills/skills.contract.d.ts +58 -0
  207. package/dist/modules/skills/skills.contract.d.ts.map +1 -0
  208. package/dist/modules/skills/skills.contract.js +10 -0
  209. package/dist/modules/skills/skills.contract.js.map +1 -0
  210. package/dist/modules/skills/skills.routes.d.ts +15 -0
  211. package/dist/modules/skills/skills.routes.d.ts.map +1 -0
  212. package/dist/modules/skills/skills.routes.js +34 -0
  213. package/dist/modules/skills/skills.routes.js.map +1 -0
  214. package/dist/modules/skills/skills.service.d.ts +21 -0
  215. package/dist/modules/skills/skills.service.d.ts.map +1 -0
  216. package/dist/modules/skills/skills.service.js +202 -0
  217. package/dist/modules/skills/skills.service.js.map +1 -0
  218. package/dist/modules/skills/skills.tools.d.ts +15 -0
  219. package/dist/modules/skills/skills.tools.d.ts.map +1 -0
  220. package/dist/modules/skills/skills.tools.js +96 -0
  221. package/dist/modules/skills/skills.tools.js.map +1 -0
  222. package/dist/modules/tool-auth/external-api-key.errors.d.ts +14 -0
  223. package/dist/modules/tool-auth/external-api-key.errors.d.ts.map +1 -0
  224. package/dist/modules/tool-auth/external-api-key.errors.js +23 -0
  225. package/dist/modules/tool-auth/external-api-key.errors.js.map +1 -0
  226. package/dist/modules/tool-auth/external-api-key.interface.d.ts +90 -0
  227. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -0
  228. package/dist/modules/tool-auth/external-api-key.interface.js +2 -0
  229. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -0
  230. package/dist/modules/tool-auth/external-api-key.service.d.ts +25 -0
  231. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -0
  232. package/dist/modules/tool-auth/external-api-key.service.js +164 -0
  233. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -0
  234. package/dist/modules/tool-auth/internal-token.service.d.ts +62 -0
  235. package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -0
  236. package/dist/modules/tool-auth/internal-token.service.js +85 -0
  237. package/dist/modules/tool-auth/internal-token.service.js.map +1 -0
  238. package/dist/modules/tool-auth/llm-usage-meter.d.ts +16 -0
  239. package/dist/modules/tool-auth/llm-usage-meter.d.ts.map +1 -0
  240. package/dist/modules/tool-auth/llm-usage-meter.js +6 -0
  241. package/dist/modules/tool-auth/llm-usage-meter.js.map +1 -0
  242. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +101 -0
  243. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -0
  244. package/dist/modules/tool-auth/tool-auth.middleware.js +166 -0
  245. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -0
  246. package/dist/modules/tool-helpers/index.d.ts +19 -0
  247. package/dist/modules/tool-helpers/index.d.ts.map +1 -0
  248. package/dist/modules/tool-helpers/index.js +18 -0
  249. package/dist/modules/tool-helpers/index.js.map +1 -0
  250. package/dist/modules/tool-helpers/tool-context.d.ts +35 -0
  251. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -0
  252. package/dist/modules/tool-helpers/tool-context.js +66 -0
  253. package/dist/modules/tool-helpers/tool-context.js.map +1 -0
  254. package/dist/modules/tool-helpers/tool-def.d.ts +33 -0
  255. package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -0
  256. package/dist/modules/tool-helpers/tool-def.js +57 -0
  257. package/dist/modules/tool-helpers/tool-def.js.map +1 -0
  258. package/dist/modules/tool-helpers/tool-handler.d.ts +19 -0
  259. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -0
  260. package/dist/modules/tool-helpers/tool-handler.js +84 -0
  261. package/dist/modules/tool-helpers/tool-handler.js.map +1 -0
  262. package/dist/modules/tool-helpers/tool.contract.d.ts +64 -0
  263. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -0
  264. package/dist/modules/tool-helpers/tool.contract.js +24 -0
  265. package/dist/modules/tool-helpers/tool.contract.js.map +1 -0
  266. package/dist/modules/tool-helpers/validate-token.d.ts +31 -0
  267. package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -0
  268. package/dist/modules/tool-helpers/validate-token.js +20 -0
  269. package/dist/modules/tool-helpers/validate-token.js.map +1 -0
  270. package/dist/modules/tool-manuals/index.d.ts +5 -0
  271. package/dist/modules/tool-manuals/index.d.ts.map +1 -0
  272. package/dist/modules/tool-manuals/index.js +5 -0
  273. package/dist/modules/tool-manuals/index.js.map +1 -0
  274. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +182 -0
  275. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -0
  276. package/dist/modules/tool-manuals/tool-manuals.contract.js +19 -0
  277. package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -0
  278. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +24 -0
  279. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -0
  280. package/dist/modules/tool-manuals/tool-manuals.routes.js +102 -0
  281. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -0
  282. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +108 -0
  283. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -0
  284. package/dist/modules/tool-manuals/tool-manuals.service.js +710 -0
  285. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -0
  286. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +35 -0
  287. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -0
  288. package/dist/modules/tool-manuals/tool-manuals.tools.js +157 -0
  289. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -0
  290. package/dist/modules/tool-registry/manual.routes.d.ts +6 -0
  291. package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -0
  292. package/dist/modules/tool-registry/manual.routes.js +76 -0
  293. package/dist/modules/tool-registry/manual.routes.js.map +1 -0
  294. package/dist/modules/tool-registry/tool-registry.d.ts +23 -0
  295. package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -0
  296. package/dist/modules/tool-registry/tool-registry.js +46 -0
  297. package/dist/modules/tool-registry/tool-registry.js.map +1 -0
  298. package/dist/modules/tool-registry/tool.contract.d.ts +48 -0
  299. package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -0
  300. package/dist/modules/tool-registry/tool.contract.js +2 -0
  301. package/dist/modules/tool-registry/tool.contract.js.map +1 -0
  302. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +14 -0
  303. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -0
  304. package/dist/modules/workflow/agent-tools/workflow.tools.js +437 -0
  305. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -0
  306. package/dist/modules/workflow/event-bus.d.ts +107 -0
  307. package/dist/modules/workflow/event-bus.d.ts.map +1 -0
  308. package/dist/modules/workflow/event-bus.js +224 -0
  309. package/dist/modules/workflow/event-bus.js.map +1 -0
  310. package/dist/modules/workflow/events.routes.d.ts +80 -0
  311. package/dist/modules/workflow/events.routes.d.ts.map +1 -0
  312. package/dist/modules/workflow/events.routes.js +216 -0
  313. package/dist/modules/workflow/events.routes.js.map +1 -0
  314. package/dist/modules/workflow/file-change-notifier.d.ts +38 -0
  315. package/dist/modules/workflow/file-change-notifier.d.ts.map +1 -0
  316. package/dist/modules/workflow/file-change-notifier.js +22 -0
  317. package/dist/modules/workflow/file-change-notifier.js.map +1 -0
  318. package/dist/modules/workflow/file-lock.service.d.ts +57 -0
  319. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -0
  320. package/dist/modules/workflow/file-lock.service.js +202 -0
  321. package/dist/modules/workflow/file-lock.service.js.map +1 -0
  322. package/dist/modules/workflow/git/branch-name.d.ts +10 -0
  323. package/dist/modules/workflow/git/branch-name.d.ts.map +1 -0
  324. package/dist/modules/workflow/git/branch-name.js +76 -0
  325. package/dist/modules/workflow/git/branch-name.js.map +1 -0
  326. package/dist/modules/workflow/git/clone-config.d.ts +61 -0
  327. package/dist/modules/workflow/git/clone-config.d.ts.map +1 -0
  328. package/dist/modules/workflow/git/clone-config.js +69 -0
  329. package/dist/modules/workflow/git/clone-config.js.map +1 -0
  330. package/dist/modules/workflow/git/git-version.d.ts +34 -0
  331. package/dist/modules/workflow/git/git-version.d.ts.map +1 -0
  332. package/dist/modules/workflow/git/git-version.js +63 -0
  333. package/dist/modules/workflow/git/git-version.js.map +1 -0
  334. package/dist/modules/workflow/git/git.service.d.ts +427 -0
  335. package/dist/modules/workflow/git/git.service.d.ts.map +1 -0
  336. package/dist/modules/workflow/git/git.service.js +1987 -0
  337. package/dist/modules/workflow/git/git.service.js.map +1 -0
  338. package/dist/modules/workflow/git/mutex.d.ts +11 -0
  339. package/dist/modules/workflow/git/mutex.d.ts.map +1 -0
  340. package/dist/modules/workflow/git/mutex.js +23 -0
  341. package/dist/modules/workflow/git/mutex.js.map +1 -0
  342. package/dist/modules/workflow/git/pull-request.service.d.ts +124 -0
  343. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -0
  344. package/dist/modules/workflow/git/pull-request.service.js +328 -0
  345. package/dist/modules/workflow/git/pull-request.service.js.map +1 -0
  346. package/dist/modules/workflow/locking-filesystem.d.ts +133 -0
  347. package/dist/modules/workflow/locking-filesystem.d.ts.map +1 -0
  348. package/dist/modules/workflow/locking-filesystem.js +400 -0
  349. package/dist/modules/workflow/locking-filesystem.js.map +1 -0
  350. package/dist/modules/workflow/pending-commits.service.d.ts +221 -0
  351. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -0
  352. package/dist/modules/workflow/pending-commits.service.js +364 -0
  353. package/dist/modules/workflow/pending-commits.service.js.map +1 -0
  354. package/dist/modules/workflow/pending-commits.worker.d.ts +148 -0
  355. package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -0
  356. package/dist/modules/workflow/pending-commits.worker.js +245 -0
  357. package/dist/modules/workflow/pending-commits.worker.js.map +1 -0
  358. package/dist/modules/workflow/read-only-filesystem.d.ts +24 -0
  359. package/dist/modules/workflow/read-only-filesystem.d.ts.map +1 -0
  360. package/dist/modules/workflow/read-only-filesystem.js +39 -0
  361. package/dist/modules/workflow/read-only-filesystem.js.map +1 -0
  362. package/dist/modules/workflow/recovery-bot.d.ts +31 -0
  363. package/dist/modules/workflow/recovery-bot.d.ts.map +1 -0
  364. package/dist/modules/workflow/recovery-bot.js +64 -0
  365. package/dist/modules/workflow/recovery-bot.js.map +1 -0
  366. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts +137 -0
  367. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +1 -0
  368. package/dist/modules/workflow/review-workflow/review-workflow.interface.js +2 -0
  369. package/dist/modules/workflow/review-workflow/review-workflow.interface.js.map +1 -0
  370. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +26 -0
  371. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -0
  372. package/dist/modules/workflow/review-workflow/review-workflow.service.js +636 -0
  373. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -0
  374. package/dist/modules/workflow/sanitize-error.d.ts +29 -0
  375. package/dist/modules/workflow/sanitize-error.d.ts.map +1 -0
  376. package/dist/modules/workflow/sanitize-error.js +60 -0
  377. package/dist/modules/workflow/sanitize-error.js.map +1 -0
  378. package/dist/modules/workflow/session-ontology.policy.d.ts +52 -0
  379. package/dist/modules/workflow/session-ontology.policy.d.ts.map +1 -0
  380. package/dist/modules/workflow/session-ontology.policy.js +62 -0
  381. package/dist/modules/workflow/session-ontology.policy.js.map +1 -0
  382. package/dist/modules/workflow/session-ontology.service.d.ts +100 -0
  383. package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -0
  384. package/dist/modules/workflow/session-ontology.service.js +143 -0
  385. package/dist/modules/workflow/session-ontology.service.js.map +1 -0
  386. package/dist/modules/workflow/workflow-hooks.d.ts +87 -0
  387. package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -0
  388. package/dist/modules/workflow/workflow-hooks.js +35 -0
  389. package/dist/modules/workflow/workflow-hooks.js.map +1 -0
  390. package/dist/modules/workflow/workflow.errors.d.ts +171 -0
  391. package/dist/modules/workflow/workflow.errors.d.ts.map +1 -0
  392. package/dist/modules/workflow/workflow.errors.js +260 -0
  393. package/dist/modules/workflow/workflow.errors.js.map +1 -0
  394. package/dist/modules/workflow/workflow.routes.d.ts +26 -0
  395. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -0
  396. package/dist/modules/workflow/workflow.routes.js +804 -0
  397. package/dist/modules/workflow/workflow.routes.js.map +1 -0
  398. package/dist/modules/workflow/workflow.service.d.ts +385 -0
  399. package/dist/modules/workflow/workflow.service.d.ts.map +1 -0
  400. package/dist/modules/workflow/workflow.service.js +1155 -0
  401. package/dist/modules/workflow/workflow.service.js.map +1 -0
  402. package/dist/modules/workspace/bevel-ignore.d.ts +25 -0
  403. package/dist/modules/workspace/bevel-ignore.d.ts.map +1 -0
  404. package/dist/modules/workspace/bevel-ignore.js +57 -0
  405. package/dist/modules/workspace/bevel-ignore.js.map +1 -0
  406. package/dist/modules/workspace/kb-seed.interface.d.ts +36 -0
  407. package/dist/modules/workspace/kb-seed.interface.d.ts.map +1 -0
  408. package/dist/modules/workspace/kb-seed.interface.js +2 -0
  409. package/dist/modules/workspace/kb-seed.interface.js.map +1 -0
  410. package/dist/modules/workspace/kb-seed.service.d.ts +70 -0
  411. package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -0
  412. package/dist/modules/workspace/kb-seed.service.js +325 -0
  413. package/dist/modules/workspace/kb-seed.service.js.map +1 -0
  414. package/dist/modules/workspace/routine-write-policy.d.ts +49 -0
  415. package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -0
  416. package/dist/modules/workspace/routine-write-policy.js +46 -0
  417. package/dist/modules/workspace/routine-write-policy.js.map +1 -0
  418. package/dist/modules/workspace/session-ontology.gate.d.ts +112 -0
  419. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -0
  420. package/dist/modules/workspace/session-ontology.gate.js +161 -0
  421. package/dist/modules/workspace/session-ontology.gate.js.map +1 -0
  422. package/dist/modules/workspace/session-sink.d.ts +25 -0
  423. package/dist/modules/workspace/session-sink.d.ts.map +1 -0
  424. package/dist/modules/workspace/session-sink.js +8 -0
  425. package/dist/modules/workspace/session-sink.js.map +1 -0
  426. package/dist/modules/workspace/spill-store.d.ts +24 -0
  427. package/dist/modules/workspace/spill-store.d.ts.map +1 -0
  428. package/dist/modules/workspace/spill-store.js +87 -0
  429. package/dist/modules/workspace/spill-store.js.map +1 -0
  430. package/dist/modules/workspace/workspace.routes.d.ts +25 -0
  431. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -0
  432. package/dist/modules/workspace/workspace.routes.js +1046 -0
  433. package/dist/modules/workspace/workspace.routes.js.map +1 -0
  434. package/dist/modules/workspace/workspace.service.d.ts +339 -0
  435. package/dist/modules/workspace/workspace.service.d.ts.map +1 -0
  436. package/dist/modules/workspace/workspace.service.js +1221 -0
  437. package/dist/modules/workspace/workspace.service.js.map +1 -0
  438. package/dist/modules/workspace/workspace.tools.d.ts +19 -0
  439. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -0
  440. package/dist/modules/workspace/workspace.tools.js +767 -0
  441. package/dist/modules/workspace/workspace.tools.js.map +1 -0
  442. package/dist/shared/frontmatter-id.d.ts +35 -0
  443. package/dist/shared/frontmatter-id.d.ts.map +1 -0
  444. package/dist/shared/frontmatter-id.js +68 -0
  445. package/dist/shared/frontmatter-id.js.map +1 -0
  446. package/dist/shared/fs-walk.d.ts +9 -0
  447. package/dist/shared/fs-walk.d.ts.map +1 -0
  448. package/dist/shared/fs-walk.js +34 -0
  449. package/dist/shared/fs-walk.js.map +1 -0
  450. package/dist/shared/hash-email.d.ts +11 -0
  451. package/dist/shared/hash-email.d.ts.map +1 -0
  452. package/dist/shared/hash-email.js +14 -0
  453. package/dist/shared/hash-email.js.map +1 -0
  454. package/dist/shared/kb-layout.d.ts +38 -0
  455. package/dist/shared/kb-layout.d.ts.map +1 -0
  456. package/dist/shared/kb-layout.js +102 -0
  457. package/dist/shared/kb-layout.js.map +1 -0
  458. package/dist/shared/kb-layout.test.d.ts +2 -0
  459. package/dist/shared/kb-layout.test.d.ts.map +1 -0
  460. package/dist/shared/kb-layout.test.js +67 -0
  461. package/dist/shared/kb-layout.test.js.map +1 -0
  462. package/dist/shared/ssrf.d.ts +20 -0
  463. package/dist/shared/ssrf.d.ts.map +1 -0
  464. package/dist/shared/ssrf.js +89 -0
  465. package/dist/shared/ssrf.js.map +1 -0
  466. package/dist/shared/token-crypto.d.ts +16 -0
  467. package/dist/shared/token-crypto.d.ts.map +1 -0
  468. package/dist/shared/token-crypto.js +49 -0
  469. package/dist/shared/token-crypto.js.map +1 -0
  470. package/dist/shared/ttl-cache.d.ts +16 -0
  471. package/dist/shared/ttl-cache.d.ts.map +1 -0
  472. package/dist/shared/ttl-cache.js +27 -0
  473. package/dist/shared/ttl-cache.js.map +1 -0
  474. package/dist/shared/utcp-namespace.d.ts +46 -0
  475. package/dist/shared/utcp-namespace.d.ts.map +1 -0
  476. package/dist/shared/utcp-namespace.js +82 -0
  477. package/dist/shared/utcp-namespace.js.map +1 -0
  478. package/dist/version.d.ts +17 -0
  479. package/dist/version.d.ts.map +1 -0
  480. package/dist/version.js +19 -0
  481. package/dist/version.js.map +1 -0
  482. package/kb-template/.bevelignore +21 -0
  483. package/kb-template/Agents/.gitkeep +0 -0
  484. package/kb-template/Agents/README.md +38 -0
  485. package/kb-template/CLAUDE.md +419 -0
  486. package/kb-template/Data/.gitkeep +0 -0
  487. package/kb-template/Data/README.md +39 -0
  488. package/kb-template/KnowledgeBase/.gitkeep +0 -0
  489. package/kb-template/KnowledgeBase/README.md +37 -0
  490. package/kb-template/Pipelines/.gitkeep +0 -0
  491. package/kb-template/Pipelines/README.md +38 -0
  492. package/kb-template/Skills/.gitkeep +0 -0
  493. package/kb-template/Skills/README.md +32 -0
  494. package/kb-template/Tools/.gitkeep +0 -0
  495. package/kb-template/Tools/README.md +42 -0
  496. package/kb-template/access.md +36 -0
  497. package/migrations/0000_core_init.sql +243 -0
  498. package/migrations/meta/0000_snapshot.json +1480 -0
  499. package/migrations/meta/_journal.json +13 -0
  500. package/package.json +80 -0
  501. package/src/assets.ts +25 -0
  502. package/src/core/core-ports.ts +91 -0
  503. package/src/core/create-core-server.ts +338 -0
  504. package/src/core/create-core-services.ts +501 -0
  505. package/src/core-config.ts +257 -0
  506. package/src/index.ts +69 -0
  507. package/src/modules/access/__tests__/access-control.atref-batch.test.ts +98 -0
  508. package/src/modules/access/__tests__/access-control.read-batch.test.ts +132 -0
  509. package/src/modules/access/__tests__/access-control.service.test.ts +1011 -0
  510. package/src/modules/access/__tests__/access-mutation.service.test.ts +439 -0
  511. package/src/modules/access/__tests__/access-splice.test.ts +247 -0
  512. package/src/modules/access/__tests__/access.routes.revoke.test.ts +407 -0
  513. package/src/modules/access/__tests__/creator-access.test.ts +217 -0
  514. package/src/modules/access/__tests__/grant-sources.test.ts +204 -0
  515. package/src/modules/access/__tests__/kb-read-filter.test.ts +70 -0
  516. package/src/modules/access/__tests__/roles-admin.service.test.ts +469 -0
  517. package/src/modules/access/__tests__/roles-edit.test.ts +138 -0
  518. package/src/modules/access/__tests__/roles-yaml-guard.test.ts +70 -0
  519. package/src/modules/access/__tests__/roles.routes.test.ts +234 -0
  520. package/src/modules/access/access-control.interface.ts +383 -0
  521. package/src/modules/access/access-control.service.ts +1794 -0
  522. package/src/modules/access/access-errors.ts +60 -0
  523. package/src/modules/access/access-mutation.service.ts +369 -0
  524. package/src/modules/access/access-splice.ts +413 -0
  525. package/src/modules/access/access.routes.ts +894 -0
  526. package/src/modules/access/creator-access.ts +270 -0
  527. package/src/modules/access/kb-read-filter.ts +76 -0
  528. package/src/modules/access/roles-admin.service.ts +741 -0
  529. package/src/modules/access/roles-edit.ts +248 -0
  530. package/src/modules/access/roles-yaml-guard.ts +89 -0
  531. package/src/modules/admin/admin-access.routes.ts +29 -0
  532. package/src/modules/admin/admin-access.service.ts +38 -0
  533. package/src/modules/admin/admin.interface.ts +10 -0
  534. package/src/modules/auth/account-erasure.service.ts +183 -0
  535. package/src/modules/auth/auth.middleware.ts +78 -0
  536. package/src/modules/auth/auth.routes.ts +97 -0
  537. package/src/modules/auth/auth.service.ts +199 -0
  538. package/src/modules/code-mode/code-mode-names.ts +38 -0
  539. package/src/modules/code-mode/code-mode.tool.ts +117 -0
  540. package/src/modules/code-mode/index.ts +6 -0
  541. package/src/modules/database/connection.ts +15 -0
  542. package/src/modules/database/core-schema.ts +431 -0
  543. package/src/modules/database/migrate.ts +43 -0
  544. package/src/modules/database/schema.ts +11 -0
  545. package/src/modules/diff/__tests__/diff.routes.read-gate.test.ts +87 -0
  546. package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +150 -0
  547. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +184 -0
  548. package/src/modules/diff/__tests__/diff.service.test.ts +202 -0
  549. package/src/modules/diff/diff-paths.ts +9 -0
  550. package/src/modules/diff/diff.config.ts +12 -0
  551. package/src/modules/diff/diff.interface.ts +78 -0
  552. package/src/modules/diff/diff.routes.ts +277 -0
  553. package/src/modules/diff/diff.service.ts +508 -0
  554. package/src/modules/diff/line-diff.ts +79 -0
  555. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +287 -0
  556. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +249 -0
  557. package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +253 -0
  558. package/src/modules/mcp/__tests__/mcp-session-store.test.ts +151 -0
  559. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +150 -0
  560. package/src/modules/mcp/__tests__/mcp.routes.delete.test.ts +92 -0
  561. package/src/modules/mcp/__tests__/mcp.service.test.ts +414 -0
  562. package/src/modules/mcp/mcp-auth.middleware.ts +126 -0
  563. package/src/modules/mcp/mcp-session-store.ts +162 -0
  564. package/src/modules/mcp/mcp.routes.ts +263 -0
  565. package/src/modules/mcp/mcp.service.ts +973 -0
  566. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +401 -0
  567. package/src/modules/mcp/oauth/oauth-consent.routes.ts +60 -0
  568. package/src/modules/mcp/oauth/oauth-state.ts +61 -0
  569. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +277 -0
  570. package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +206 -0
  571. package/src/modules/secrets-vault/__tests__/mcp-oauth-discovery.service.test.ts +178 -0
  572. package/src/modules/secrets-vault/__tests__/scopes-covered.test.ts +101 -0
  573. package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +54 -0
  574. package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +143 -0
  575. package/src/modules/secrets-vault/db-secrets-vault.service.ts +792 -0
  576. package/src/modules/secrets-vault/index.ts +25 -0
  577. package/src/modules/secrets-vault/mcp-oauth-discovery.service.ts +289 -0
  578. package/src/modules/secrets-vault/secrets-variable-loader.ts +104 -0
  579. package/src/modules/secrets-vault/secrets-vault.contract.ts +270 -0
  580. package/src/modules/secrets-vault/secrets-vault.routes.ts +526 -0
  581. package/src/modules/skills/__tests__/skills.service.test.ts +176 -0
  582. package/src/modules/skills/index.ts +10 -0
  583. package/src/modules/skills/skills.contract.ts +54 -0
  584. package/src/modules/skills/skills.routes.ts +38 -0
  585. package/src/modules/skills/skills.service.ts +245 -0
  586. package/src/modules/skills/skills.tools.ts +121 -0
  587. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +358 -0
  588. package/src/modules/tool-auth/__tests__/internal-token.service.test.ts +79 -0
  589. package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +88 -0
  590. package/src/modules/tool-auth/external-api-key.errors.ts +25 -0
  591. package/src/modules/tool-auth/external-api-key.interface.ts +99 -0
  592. package/src/modules/tool-auth/external-api-key.service.ts +209 -0
  593. package/src/modules/tool-auth/internal-token.service.ts +124 -0
  594. package/src/modules/tool-auth/llm-usage-meter.ts +19 -0
  595. package/src/modules/tool-auth/tool-auth.middleware.ts +220 -0
  596. package/src/modules/tool-helpers/__tests__/phase0-loopback-spike.test.ts +129 -0
  597. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +95 -0
  598. package/src/modules/tool-helpers/__tests__/tools-surface.test.ts +146 -0
  599. package/src/modules/tool-helpers/__tests__/validate-token.test.ts +75 -0
  600. package/src/modules/tool-helpers/index.ts +18 -0
  601. package/src/modules/tool-helpers/tool-context.ts +98 -0
  602. package/src/modules/tool-helpers/tool-def.ts +73 -0
  603. package/src/modules/tool-helpers/tool-handler.ts +91 -0
  604. package/src/modules/tool-helpers/tool.contract.ts +85 -0
  605. package/src/modules/tool-helpers/validate-token.ts +50 -0
  606. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +200 -0
  607. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +499 -0
  608. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +156 -0
  609. package/src/modules/tool-manuals/index.ts +12 -0
  610. package/src/modules/tool-manuals/tool-manuals.contract.ts +183 -0
  611. package/src/modules/tool-manuals/tool-manuals.routes.ts +110 -0
  612. package/src/modules/tool-manuals/tool-manuals.service.ts +781 -0
  613. package/src/modules/tool-manuals/tool-manuals.tools.ts +202 -0
  614. package/src/modules/tool-registry/__tests__/tool-registry.test.ts +64 -0
  615. package/src/modules/tool-registry/manual.routes.ts +87 -0
  616. package/src/modules/tool-registry/tool-registry.ts +55 -0
  617. package/src/modules/tool-registry/tool.contract.ts +52 -0
  618. package/src/modules/workflow/__tests__/event-bus.test.ts +322 -0
  619. package/src/modules/workflow/__tests__/file-change-notifier.test.ts +51 -0
  620. package/src/modules/workflow/__tests__/format-affected-owners.test.ts +67 -0
  621. package/src/modules/workflow/__tests__/locking-filesystem.test.ts +445 -0
  622. package/src/modules/workflow/__tests__/pending-commits.canonical.test.ts +36 -0
  623. package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +243 -0
  624. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +308 -0
  625. package/src/modules/workflow/__tests__/sanitize-error.test.ts +67 -0
  626. package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +62 -0
  627. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +200 -0
  628. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +232 -0
  629. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +380 -0
  630. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +340 -0
  631. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +192 -0
  632. package/src/modules/workflow/agent-tools/workflow.tools.ts +502 -0
  633. package/src/modules/workflow/event-bus.ts +262 -0
  634. package/src/modules/workflow/events.routes.ts +266 -0
  635. package/src/modules/workflow/file-change-notifier.ts +54 -0
  636. package/src/modules/workflow/file-lock.service.ts +269 -0
  637. package/src/modules/workflow/git/__tests__/branch-name.test.ts +86 -0
  638. package/src/modules/workflow/git/__tests__/branchAuthor.test.ts +80 -0
  639. package/src/modules/workflow/git/__tests__/clone-config.test.ts +15 -0
  640. package/src/modules/workflow/git/__tests__/git-test-helpers.ts +47 -0
  641. package/src/modules/workflow/git/__tests__/git-version.failure.test.ts +24 -0
  642. package/src/modules/workflow/git/__tests__/git-version.test.ts +49 -0
  643. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +389 -0
  644. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
  645. package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +105 -0
  646. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +211 -0
  647. package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +154 -0
  648. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +320 -0
  649. package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +202 -0
  650. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +453 -0
  651. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +198 -0
  652. package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +125 -0
  653. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +219 -0
  654. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +145 -0
  655. package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +240 -0
  656. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +272 -0
  657. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +232 -0
  658. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +101 -0
  659. package/src/modules/workflow/git/__tests__/git.service.status.test.ts +127 -0
  660. package/src/modules/workflow/git/__tests__/mutex.test.ts +78 -0
  661. package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +225 -0
  662. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +101 -0
  663. package/src/modules/workflow/git/branch-name.ts +70 -0
  664. package/src/modules/workflow/git/clone-config.ts +71 -0
  665. package/src/modules/workflow/git/git-version.ts +70 -0
  666. package/src/modules/workflow/git/git.service.ts +2248 -0
  667. package/src/modules/workflow/git/mutex.ts +22 -0
  668. package/src/modules/workflow/git/pull-request.service.ts +447 -0
  669. package/src/modules/workflow/locking-filesystem.ts +489 -0
  670. package/src/modules/workflow/pending-commits.service.ts +444 -0
  671. package/src/modules/workflow/pending-commits.worker.ts +361 -0
  672. package/src/modules/workflow/read-only-filesystem.ts +54 -0
  673. package/src/modules/workflow/recovery-bot.ts +73 -0
  674. package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +560 -0
  675. package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +176 -0
  676. package/src/modules/workflow/review-workflow/__tests__/merge-gate.test.ts +258 -0
  677. package/src/modules/workflow/review-workflow/review-workflow.interface.ts +199 -0
  678. package/src/modules/workflow/review-workflow/review-workflow.service.ts +806 -0
  679. package/src/modules/workflow/sanitize-error.ts +62 -0
  680. package/src/modules/workflow/session-ontology.policy.ts +70 -0
  681. package/src/modules/workflow/session-ontology.service.ts +178 -0
  682. package/src/modules/workflow/workflow-hooks.ts +101 -0
  683. package/src/modules/workflow/workflow.errors.ts +285 -0
  684. package/src/modules/workflow/workflow.routes.ts +858 -0
  685. package/src/modules/workflow/workflow.service.ts +1555 -0
  686. package/src/modules/workspace/__tests__/kb-seed.service.test.ts +213 -0
  687. package/src/modules/workspace/__tests__/routine-write-policy.test.ts +68 -0
  688. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +237 -0
  689. package/src/modules/workspace/__tests__/spill-store.test.ts +43 -0
  690. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +233 -0
  691. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +176 -0
  692. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +303 -0
  693. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +276 -0
  694. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +120 -0
  695. package/src/modules/workspace/__tests__/workspace.service.test.ts +565 -0
  696. package/src/modules/workspace/__tests__/workspace.tools.test.ts +504 -0
  697. package/src/modules/workspace/bevel-ignore.ts +62 -0
  698. package/src/modules/workspace/kb-seed.interface.ts +36 -0
  699. package/src/modules/workspace/kb-seed.service.ts +361 -0
  700. package/src/modules/workspace/routine-write-policy.ts +79 -0
  701. package/src/modules/workspace/session-ontology.gate.ts +189 -0
  702. package/src/modules/workspace/session-sink.ts +25 -0
  703. package/src/modules/workspace/spill-store.ts +87 -0
  704. package/src/modules/workspace/workspace.routes.ts +1114 -0
  705. package/src/modules/workspace/workspace.service.ts +1343 -0
  706. package/src/modules/workspace/workspace.tools.ts +885 -0
  707. package/src/shared/__tests__/frontmatter-id.test.ts +88 -0
  708. package/src/shared/__tests__/fs-walk.test.ts +42 -0
  709. package/src/shared/__tests__/ssrf.test.ts +53 -0
  710. package/src/shared/__tests__/utcp-namespace.test.ts +19 -0
  711. package/src/shared/frontmatter-id.ts +72 -0
  712. package/src/shared/fs-walk.ts +30 -0
  713. package/src/shared/hash-email.ts +14 -0
  714. package/src/shared/kb-layout.test.ts +88 -0
  715. package/src/shared/kb-layout.ts +101 -0
  716. package/src/shared/ssrf.ts +78 -0
  717. package/src/shared/token-crypto.ts +54 -0
  718. package/src/shared/ttl-cache.ts +27 -0
  719. package/src/shared/utcp-namespace.ts +88 -0
  720. package/src/version.ts +19 -0
@@ -0,0 +1,840 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
5
+ import '@utcp/http'; // side effect: registers the 'http' UTCP communication protocol
6
+ import '@utcp/mcp'; // side effect: registers the 'mcp' protocol (native MCP-server `.tool` sources)
7
+ import { UtcpClientConfigSerializer, CallTemplateSerializer, } from '@utcp/sdk';
8
+ import { CodeModeUtcpClient } from '@utcp/code-mode';
9
+ import { utcpNameToTsInterfaceName, findToolByName } from '../code-mode/code-mode-names.js';
10
+ import { bevelSecretsLoaderConfig } from '../secrets-vault/index.js';
11
+ import { scopesCovered } from '../secrets-vault/secrets-vault.contract.js';
12
+ import { EXTERNAL_KB_MANUAL_NAME } from '../tool-manuals/tool-manuals.contract.js';
13
+ import { seedBevelHostedManualVars } from '../../shared/utcp-namespace.js';
14
+ /** Default cap on a `call_tool_chain` result's stringified size before it spills. */
15
+ const CALL_TOOL_CHAIN_MAX_OUTPUT = 200_000;
16
+ /**
17
+ * Upper bound on one `loopbackJson` round-trip (manual list, skill fetch) so a
18
+ * hung loopback can't stall `createSession`. Generous: these endpoints answer
19
+ * in milliseconds; only a wedged process ever comes near it.
20
+ */
21
+ const LOOPBACK_TIMEOUT_MS = 15_000;
22
+ /**
23
+ * Lifetime of the internal token minted as an OAuth/JWT session's loopback
24
+ * bearer. Longer than the session store's 4h idle eviction (see
25
+ * `DEFAULT_IDLE_TTL_MS` in mcp-session-store.ts) so the credential is not the
26
+ * first thing to die under a session's normal lifecycle. A continuously-active
27
+ * session CAN outlive it — its tool calls then fail at the loopback and the
28
+ * client recovers by re-initializing, which mints a fresh token.
29
+ */
30
+ const MCP_LOOPBACK_TOKEN_TTL_MS = 5 * 60 * 60 * 1000;
31
+ const callTemplateSerializer = new CallTemplateSerializer();
32
+ /**
33
+ * Code-mode meta-tools exposed ALONGSIDE the direct tools. They let an external
34
+ * agent batch many Bevel calls into one isolated-vm run (`call_tool_chain`)
35
+ * instead of one MCP round-trip per call — the same efficiency our own agent
36
+ * gets. `call_tool_chain`'s description carries the code-mode protocol (there is
37
+ * no system prompt over MCP), so the client learns the convention from the tool
38
+ * itself; `list_tools`/`tools_info` are how it discovers what to call.
39
+ *
40
+ * Security is identical to the direct surface: the chain runs in our isolated-vm
41
+ * but calls tools over loopback with the CALLER's key against the external
42
+ * catalog — internal-only tools aren't in that catalog, so a chain can't reach
43
+ * them either.
44
+ */
45
+ const CALL_TOOL_CHAIN_DESCRIPTION = [
46
+ 'Execute a short JavaScript program with direct access to every registered UTCP tool as a synchronous function. Call tools as `KNOWLEDGE_BASE.<tool>({ body: { ...args } })` with NO `await` (results are already resolved), and `return` the final value. The runtime is plain JavaScript (no type annotations / no TypeScript-only syntax).',
47
+ 'Discover first: `list_tools` lists every tool in callable form (e.g. `KNOWLEDGE_BASE.read_file`); `tools_info` returns their exact argument + return shapes — do not guess. Batch multiple tool calls into one chain to avoid a round-trip per call. The chain runs with your own connection key, so it can only reach the tools you can already call directly.',
48
+ 'Large results: if the combined result+logs exceed `max_output_size` (default 200000 chars) the full JSON is spilled to a shared store and you get back a `__tool_chain_spill__/…` ref instead. Read it with `read_file` (pass that ref as `path` — `branch` is ignored — plus `offset`/`limit` to slice it), or better, re-run a narrower chain that returns only what you need.',
49
+ ].join('\n\n');
50
+ const CODE_MODE_META_TOOLS = [
51
+ {
52
+ name: 'list_tools',
53
+ description: 'List every UTCP tool currently registered, in TypeScript-accessible form (e.g. `KNOWLEDGE_BASE.read_file`) for use inside `call_tool_chain`.',
54
+ inputSchema: { type: 'object', properties: {}, additionalProperties: false },
55
+ },
56
+ {
57
+ name: 'tools_info',
58
+ description: 'Get full TypeScript interface definitions for named tools (names from `list_tools`). The schemas are the source of truth — do not guess shapes.',
59
+ inputSchema: {
60
+ type: 'object',
61
+ properties: {
62
+ tool_names: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Tool names to describe.' },
63
+ },
64
+ required: ['tool_names'],
65
+ additionalProperties: false,
66
+ },
67
+ },
68
+ {
69
+ name: 'call_tool_chain',
70
+ description: CALL_TOOL_CHAIN_DESCRIPTION,
71
+ inputSchema: {
72
+ type: 'object',
73
+ properties: {
74
+ code: { type: 'string', minLength: 1, description: 'JavaScript to execute against the registered tools.' },
75
+ timeout: { type: 'integer', minimum: 1000, maximum: 120000, description: 'Timeout in ms (default 30000).' },
76
+ max_output_size: { type: 'integer', minimum: 1000, maximum: 1000000, description: 'Max result+logs size in chars before spilling (default 200000, max 1000000).' },
77
+ },
78
+ required: ['code'],
79
+ additionalProperties: false,
80
+ },
81
+ },
82
+ ];
83
+ const META_TOOL_NAMES = new Set(CODE_MODE_META_TOOLS.map((t) => t.name));
84
+ /** The prompt message text for a loaded skill: its instructions body + a pointer to bundled files. */
85
+ function skillPromptText(skill) {
86
+ const rel = skill.files.map((f) => f.startsWith(`${skill.path}/`) ? f.slice(skill.path.length + 1) : f);
87
+ const footer = rel.length
88
+ ? `\n\n---\nSkill folder: ${skill.path}\nBundled files (fetch each with the get_skill tool: { name: "${skill.name}", file }): ${rel.join(', ')}`
89
+ : '';
90
+ return `${skill.body}${footer}`;
91
+ }
92
+ /**
93
+ * The MCP server is a GENERIC proxy over the UTCP tool surface. It owns no tool
94
+ * logic: per MCP session it stands up a `UtcpClient` pointed at the backend's
95
+ * own `GET /api/agent/utcp` manual (over loopback, authenticated with the
96
+ * caller's connection key), discovers every tool, and re-exposes each one to
97
+ * the MCP client. A tool call is dispatched straight back through the same REST
98
+ * endpoint the tool's UTCP `tool_call_template` names — so the agent logic,
99
+ * thread continuity, and per-key token metering all live ONCE behind that REST
100
+ * endpoint (`AgentAskService` for `ask`), never duplicated here.
101
+ *
102
+ * Dispatch always uses `callToolStreaming`, which is uniform across tool kinds:
103
+ * a plain `http` tool yields exactly one chunk (its final result, emitted as
104
+ * the tool result with no progress), while a `streamable_http` tool yields many
105
+ * (the all-but-last become `notifications/progress`, the last is the result).
106
+ * Because of that, adding — or later upgrading a tool to streaming — never
107
+ * touches this file.
108
+ *
109
+ * Auth note: `/api/agent/*` accepts connection keys and internal tokens only.
110
+ * Connection-key sessions pass the caller's own key through to the loopback;
111
+ * OAuth/JWT sessions can't (their bearer would 401 there), so `createSession`
112
+ * mints a least-privilege internal token for the resolved user and uses THAT
113
+ * as the session's loopback bearer instead.
114
+ */
115
+ export class McpService {
116
+ sessionStore;
117
+ opts;
118
+ secretsVault;
119
+ toolManuals;
120
+ internalTokens;
121
+ revokeOAuthAccess;
122
+ constructor(sessionStore, opts,
123
+ // The vault + manual catalog, used to check a caller's per-user credentials
124
+ // before dispatching a tool. Optional so existing constructions/tests that
125
+ // don't exercise the check keep working (the check is skipped when absent).
126
+ secretsVault, toolManuals,
127
+ // Mints the loopback bearer for OAuth/JWT sessions (see class doc).
128
+ // Optional for the same test-compat reason; without it those sessions
129
+ // fall back to the old pass-through (and 401 at the loopback hop).
130
+ internalTokens,
131
+ // Revokes an MCP OAuth access token (BevelOAuthProvider.revokeByAccessToken)
132
+ // — the reset that sends an interactive session back through the browser
133
+ // authorization when one of its TOOL sign-ins breaks. Optional: without
134
+ // it, broken sign-ins surface only as the /connect link in the result.
135
+ revokeOAuthAccess) {
136
+ this.sessionStore = sessionStore;
137
+ this.opts = opts;
138
+ this.secretsVault = secretsVault;
139
+ this.toolManuals = toolManuals;
140
+ this.internalTokens = internalTokens;
141
+ this.revokeOAuthAccess = revokeOAuthAccess;
142
+ }
143
+ /**
144
+ * Subscribe to store-driven evictions (idle-TTL sweep, size-cap eviction) so
145
+ * the route layer can drop its transport mirror. Returns an unsubscribe fn.
146
+ */
147
+ onSessionEvicted(listener) {
148
+ return this.sessionStore.onEvict(listener);
149
+ }
150
+ /**
151
+ * Build a fresh per-session (transport, server) pair. Async because tool
152
+ * discovery (a loopback round-trip authenticated with `bearer`) happens here,
153
+ * before the server is returned, so `tools/list` is ready the moment the
154
+ * client asks. The route awaits this, then `server.connect(transport)`.
155
+ */
156
+ async createSession(userId, tokenId, bearer, onSessionInitialized) {
157
+ // The loopback surface (`/api/agent/*`) accepts connection keys and
158
+ // internal tokens only. A connection-key session passes the caller's own
159
+ // key through (per-key metering rides on it); an OAuth/JWT session's
160
+ // bearer would 401 there, so mint a least-privilege internal token for
161
+ // the resolved user instead — flagged `externalProxy` so the tool-auth
162
+ // verifier resolves it to `source: 'external'`: the caller IS an external
163
+ // agent and must be treated like one (admitted to `start_session`/`ask`,
164
+ // refused from internal-only tools). TTL covers the session store's 4h
165
+ // idle eviction — an evicted session re-initializes and re-mints.
166
+ const loopbackBearer = tokenId == null && this.internalTokens
167
+ ? this.internalTokens.mint({ userId, externalProxy: true }, MCP_LOOPBACK_TOKEN_TTL_MS)
168
+ : bearer;
169
+ // The list of manuals this caller gets: the KB manual + each `.tool` they
170
+ // can read. Fetched over loopback with the caller's key, so ACL filtering
171
+ // lives ONCE behind the REST surface.
172
+ const manuals = await this.fetchManualTemplates(loopbackBearer);
173
+ const client = await this.buildClient(loopbackBearer, userId, manuals);
174
+ const tools = await this.discoverTools(client, manuals);
175
+ // Confirms the MCP session was built for a connecting client (vs. an
176
+ // in-process agent code-mode client, which never runs createSession) and
177
+ // how many tools discovery yielded before listing/filtering.
178
+ console.log(`[mcp] createSession: user=${userId} tokenId=${tokenId ?? 'none'} — ` +
179
+ `discovered ${tools.length} tool(s) across ${manuals.length} manual(s)`);
180
+ const transport = new StreamableHTTPServerTransport({
181
+ sessionIdGenerator: () => randomUUID(),
182
+ onsessioninitialized: (sessionId) => {
183
+ this.sessionStore.create(sessionId, userId, tokenId);
184
+ onSessionInitialized(sessionId);
185
+ },
186
+ onsessionclosed: (sessionId) => {
187
+ this.sessionStore.delete(sessionId);
188
+ },
189
+ });
190
+ const server = new Server({ name: 'bevel-mcp', version: '0.1.0' }, { capabilities: { tools: {}, prompts: {} } });
191
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
192
+ // A discovered tool whose name collides with a meta-tool would be
193
+ // listed but never callable (the dispatcher routes the name to the
194
+ // meta-tool first), so drop it from the listing entirely.
195
+ let listed = tools.filter((t) => !META_TOOL_NAMES.has(t.mcpName));
196
+ // Connection-key sessions are autonomous pipelines — nobody is present
197
+ // to complete a sign-in mid-run, so register ONLY the tools whose
198
+ // per-user credentials are already satisfied. Interactive (OAuth/JWT)
199
+ // sessions keep the full listing: their caller can configure a tool on
200
+ // /connect when the call-time check points them there.
201
+ if (tokenId != null) {
202
+ const ready = await Promise.all(
203
+ // A per-tool check that throws must NOT reject the whole list (which
204
+ // would blank every tool) — fail that one tool closed and move on.
205
+ listed.map((t) => this.missingUserSecrets(userId, t).then((missing) => missing.length === 0, () => false)));
206
+ listed = listed.filter((_, i) => ready[i]);
207
+ }
208
+ // Validate + dedupe each discovered tool so ONE non-conforming or
209
+ // duplicate-named entry can't make an MCP client reject the whole
210
+ // `tools/list` (blanking every tool). Every drop is logged with a reason
211
+ // so a missing tool is diagnosable instead of silent.
212
+ const seen = new Set(META_TOOL_NAMES);
213
+ const dropped = [];
214
+ const direct = [];
215
+ for (const t of listed) {
216
+ const entry = toListedTool(t); // logs its own reason on a name/schema drop
217
+ if (!entry) {
218
+ dropped.push(t.mcpName);
219
+ continue;
220
+ }
221
+ if (seen.has(entry.name)) {
222
+ dropped.push(`${entry.name} (duplicate)`);
223
+ continue;
224
+ }
225
+ seen.add(entry.name);
226
+ direct.push(entry);
227
+ }
228
+ // Log only when a tool was dropped (name/schema/duplicate) — that's the
229
+ // anomaly worth surfacing, since a downstream client would otherwise hide
230
+ // it by rejecting the whole response. The steady-state served count is
231
+ // already visible once per session in the createSession log above.
232
+ if (dropped.length) {
233
+ console.warn(`[mcp] tools/list: serving ${CODE_MODE_META_TOOLS.length + direct.length} tool(s); ` +
234
+ `dropped ${dropped.length} non-listable: ${dropped.join(', ')}`);
235
+ }
236
+ return {
237
+ // Code-mode meta-tools first, then every validated direct tool.
238
+ tools: [...CODE_MODE_META_TOOLS, ...direct],
239
+ };
240
+ });
241
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
242
+ if (META_TOOL_NAMES.has(request.params.name)) {
243
+ return this.dispatchMetaTool(client, request.params.name, request.params.arguments ?? {});
244
+ }
245
+ const proxied = tools.find((t) => t.mcpName === request.params.name);
246
+ if (!proxied) {
247
+ return toolError(`Unknown tool "${request.params.name}".`);
248
+ }
249
+ // Stop before running a tool whose personal (user-scoped) credentials the
250
+ // caller hasn't provided — return a setup link instead of a blank-credential
251
+ // request that would fail opaquely at the provider.
252
+ const needsAuth = await this.checkUserSecrets(userId, proxied);
253
+ if (needsAuth) {
254
+ // A sign-in that EXISTS but is broken (expired grant, abandoned
255
+ // consent, missing scopes) on an interactive OAuth session: revoke the
256
+ // agent's own grant too. Its next request then 401s, its refresh
257
+ // fails, and it re-runs the browser authorization — landing the user
258
+ // on /connect where the broken sign-in shows as not-connected, to
259
+ // re-authorize or deselect. Never-configured tools keep the plain
260
+ // link (revoking for those would loop on every poke at a tool the
261
+ // user simply hasn't set up). Connection-key sessions have no grant
262
+ // to reset; the revoke no-ops on non-OAuth bearers anyway.
263
+ if (needsAuth.brokenSignIn && tokenId == null && this.revokeOAuthAccess) {
264
+ try {
265
+ await this.revokeOAuthAccess(bearer);
266
+ }
267
+ catch (err) {
268
+ console.warn('[mcp] failed to reset the session grant for re-auth:', err);
269
+ }
270
+ }
271
+ return needsAuth.result;
272
+ }
273
+ return this.dispatch(client, proxied, request, extra);
274
+ });
275
+ // Prompts = skills. Each skill becomes a user-callable prompt (slash command
276
+ // in MCP clients). Backed by the same skill endpoints the tools use, over
277
+ // loopback with the caller's key — so the default-branch catalog, access
278
+ // filtering, and progressive disclosure all live ONCE behind that REST
279
+ // surface, never duplicated here.
280
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
281
+ const skills = await this.fetchSkillList(loopbackBearer);
282
+ const prompts = skills.map((s) => ({
283
+ name: s.name,
284
+ description: s.description,
285
+ arguments: [],
286
+ }));
287
+ return { prompts };
288
+ });
289
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
290
+ const skill = await this.fetchSkill(loopbackBearer, request.params.name);
291
+ if (!skill) {
292
+ throw new McpError(ErrorCode.InvalidParams, `Unknown skill "${request.params.name}".`);
293
+ }
294
+ return {
295
+ description: skill.description,
296
+ messages: [{ role: 'user', content: { type: 'text', text: skillPromptText(skill) } }],
297
+ };
298
+ });
299
+ return { transport, server };
300
+ }
301
+ /** Loopback GET of the default-branch skill catalog (via the `list_skills` tool). */
302
+ async fetchSkillList(bearer) {
303
+ const res = await this.loopbackTool(bearer, 'list_skills', {});
304
+ const skills = res?.skills;
305
+ return Array.isArray(skills) ? skills : [];
306
+ }
307
+ /** Loopback GET of one skill's body (via the `get_skill` tool); null if unavailable. */
308
+ async fetchSkill(bearer, name) {
309
+ const res = (await this.loopbackTool(bearer, 'get_skill', { name }));
310
+ if (res?.ok && res.kind === 'skill' && res.skill)
311
+ return res.skill;
312
+ return null;
313
+ }
314
+ /**
315
+ * The ONE loopback round-trip: fetch `path` on our own REST surface with the
316
+ * caller's bearer, parse JSON. Failures are logged under `label` (never the
317
+ * bearer) and degrade to null — a loopback hiccup must not throw into the
318
+ * MCP session. GET when `json` is absent, POST with a JSON body when present.
319
+ * Bounded: a hung loopback (e.g. mid-restart) must not block `createSession`
320
+ * or a prompts handler indefinitely; a timeout aborts and degrades to null
321
+ * like any other failure.
322
+ */
323
+ async loopbackJson(bearer, path, label, json) {
324
+ try {
325
+ const res = await fetch(`${this.opts.loopbackBaseUrl}${path}`, {
326
+ headers: {
327
+ Authorization: `Bearer ${bearer}`,
328
+ ...(json !== undefined ? { 'Content-Type': 'application/json' } : {}),
329
+ },
330
+ ...(json !== undefined ? { method: 'POST', body: JSON.stringify(json) } : {}),
331
+ signal: AbortSignal.timeout(LOOPBACK_TIMEOUT_MS),
332
+ });
333
+ if (!res.ok) {
334
+ console.error(`[mcp] ${label} loopback failed: HTTP ${res.status} ${await res.text().catch(() => '')}`);
335
+ return null;
336
+ }
337
+ return await res.json();
338
+ }
339
+ catch (err) {
340
+ console.error(`[mcp] ${label} loopback threw:`, err instanceof Error ? err.message : err);
341
+ return null;
342
+ }
343
+ }
344
+ /** POST a skill tool endpoint over loopback with the caller's bearer; parsed JSON or null. */
345
+ async loopbackTool(bearer, tool, body) {
346
+ return this.loopbackJson(bearer, `/api/agent/tools/${tool}`, `skill ${tool}`, body);
347
+ }
348
+ /**
349
+ * Loopback GET of the caller's manual list (KB + accessible `.tool` manuals),
350
+ * validated into `CallTemplate`s at the boundary. The KB manual is guaranteed
351
+ * present (a fallback covers an unavailable endpoint); a user manual that
352
+ * fails validation is dropped + logged so one bad `.tool` can't break the
353
+ * session. HTTP transport loses the `CallTemplate` type, so we re-validate the
354
+ * received JSON even though the producing endpoint already validated it.
355
+ */
356
+ async fetchManualTemplates(bearer) {
357
+ // This is the REMOTE proxy, so ask for remote-capable manuals only — local-only
358
+ // `.tool`s are surfaced instead via the `list_local_tools` tool in the KB manual.
359
+ const body = (await this.loopbackJson(bearer, '/api/agent/all-tools?remote=true', 'all-tools'));
360
+ const rawManuals = Array.isArray(body?.manuals) ? body.manuals : [];
361
+ const out = [];
362
+ let hasKb = false;
363
+ for (const raw of rawManuals) {
364
+ const isKb = raw?.name === EXTERNAL_KB_MANUAL_NAME;
365
+ try {
366
+ out.push(callTemplateSerializer.validateDict(raw));
367
+ if (isKb)
368
+ hasKb = true;
369
+ }
370
+ catch (err) {
371
+ const name = String(raw?.name ?? '');
372
+ if (isKb)
373
+ throw err; // the KB manual must be valid — the core toolset depends on it
374
+ console.warn(`[mcp] skipping manual "${name}": ${err instanceof Error ? err.message : String(err)}`);
375
+ }
376
+ }
377
+ // Always include the KB manual, even if `all-tools` was unavailable/regressed.
378
+ if (!hasKb)
379
+ out.unshift(this.kbManualTemplate());
380
+ return out;
381
+ }
382
+ /** The KB manual's discovery template — the fallback if `all-tools` is unavailable. */
383
+ kbManualTemplate() {
384
+ return callTemplateSerializer.validateDict({
385
+ name: EXTERNAL_KB_MANUAL_NAME,
386
+ call_template_type: 'http',
387
+ http_method: 'GET',
388
+ url: '${API_URL}/api/agent/utcp',
389
+ content_type: 'application/json',
390
+ headers: { Authorization: 'Bearer ${CONNECTION_KEY}' },
391
+ });
392
+ }
393
+ /**
394
+ * One `CodeModeUtcpClient` per session. Reserved `API_URL`/`CONNECTION_KEY` are
395
+ * seeded (namespaced) ONLY for Bevel-hosted manuals — the KB manual and inline
396
+ * `.tool` sub-manuals, whose discovery template targets the loopback (`${API_URL}`).
397
+ * Third-party http/mcp `.tool`s point at arbitrary user URLs, so we must NOT seed
398
+ * them the caller's bearer: a malicious `.tool` referencing `${CONNECTION_KEY}`
399
+ * would otherwise exfiltrate the caller's token to its own endpoint. Tool
400
+ * `${SECRET}` refs resolve lazily via the per-user `bevel-secrets` loader.
401
+ */
402
+ async buildClient(bearer, userId, manuals) {
403
+ // Bevel-hosted manuals (KB + inline `.tool` sub-manuals, discovery url
404
+ // `${API_URL}/…`) get the loopback creds; third-party `.tool` URLs are never
405
+ // seeded so the bearer can't leak. Same rule the in-process agent factory uses.
406
+ const variables = seedBevelHostedManualVars(manuals, this.opts.loopbackBaseUrl, bearer);
407
+ const config = new UtcpClientConfigSerializer().validateDict({
408
+ variables,
409
+ load_variables_from: [bevelSecretsLoaderConfig(userId)],
410
+ });
411
+ return CodeModeUtcpClient.create(process.cwd(), config);
412
+ }
413
+ /**
414
+ * Register EVERY manual on the client, then flatten each discovered tool into
415
+ * the proxy's advertised shape. A failure registering a user `.tool` is
416
+ * isolated (logged + skipped) so one broken manual never breaks the session;
417
+ * the KB manual failing is fatal (the core toolset is unusable).
418
+ */
419
+ async discoverTools(client, manuals) {
420
+ for (const m of manuals) {
421
+ const isKb = m.name === EXTERNAL_KB_MANUAL_NAME;
422
+ try {
423
+ const result = await client.registerManual(m);
424
+ if (result && result.success === false) {
425
+ const errs = Array.isArray(result.errors) ? result.errors.join('; ') : 'unknown error';
426
+ if (isKb)
427
+ throw new Error(`Bevel tool discovery failed: ${errs}`);
428
+ console.warn(`[mcp] skipping manual "${String(m.name)}": ${errs}`);
429
+ }
430
+ }
431
+ catch (err) {
432
+ // Registration (network/discovery) failure — the templates are already
433
+ // validated, so this is a runtime, not a schema, problem.
434
+ if (isKb)
435
+ throw err;
436
+ console.warn(`[mcp] skipping manual "${String(m.name)}": ${err instanceof Error ? err.message : String(err)}`);
437
+ }
438
+ }
439
+ const utcpTools = await client.getTools();
440
+ return utcpTools.map((tool) => flattenManualTool(tool));
441
+ }
442
+ /**
443
+ * Run one tool call through `callToolStreaming` with a one-chunk lookahead:
444
+ * every chunk except the last becomes a progress notification, the last is
445
+ * the result. Continuity is the caller's: a tool that supports it (e.g.
446
+ * `ask`) returns its `sessionId` in the result verbatim, and the caller
447
+ * echoes it back per the tool's own schema — the proxy never rewrites args.
448
+ */
449
+ /**
450
+ * If the tool declares per-user credentials the caller hasn't set, return a
451
+ * needs-authorization result (naming the tool + a setup link); otherwise null
452
+ * to proceed. Reads the manual's `user`-scoped variables and asks the vault,
453
+ * with the SAME keys `resolve` uses, which the caller has configured — so the
454
+ * check can't drift from the actual resolution. A no-op when the vault/manual
455
+ * services aren't wired, or the tool's manual declares no per-user credential
456
+ * (e.g. the built-in KB tools).
457
+ */
458
+ async checkUserSecrets(userId, tool) {
459
+ const missing = await this.missingUserSecrets(userId, tool);
460
+ if (missing.length === 0)
461
+ return null;
462
+ return {
463
+ result: needsAuthorizationResult(tool.mcpName, missing.map((v) => v.label ?? v.name), `${this.opts.publicFrontendUrl}/connect`),
464
+ // At least one missing item is a sign-in the caller already HAS a row
465
+ // for (dead grant, abandoned consent, or missing scopes) — the state
466
+ // that warrants resetting an interactive session for re-auth, as
467
+ // opposed to a tool the caller never set up at all.
468
+ brokenSignIn: missing.some((v) => v.brokenSignIn),
469
+ };
470
+ }
471
+ /**
472
+ * The per-user variables of `tool`'s manual the caller has NOT satisfied.
473
+ * Shared by the call-time needs-authorization check above and the
474
+ * listing-time filter for connection-key sessions (which registers only
475
+ * ready tools). Empty when the vault/manual services aren't wired or the
476
+ * manual declares no per-user credential.
477
+ */
478
+ async missingUserSecrets(userId, tool) {
479
+ if (!this.secretsVault || !this.toolManuals || !tool.manualName)
480
+ return [];
481
+ const userVars = await this.toolManuals.userScopedKeysForManual(tool.manualName);
482
+ if (userVars.length === 0)
483
+ return [];
484
+ const status = await this.secretsVault.statusFor(userId, userVars.map((v) => v.key));
485
+ const statusMap = new Map(status.map((s) => [s.key, s]));
486
+ const missing = [];
487
+ for (const v of userVars) {
488
+ const st = statusMap.get(v.key);
489
+ // A sign-in the caller already HAS a row for but that isn't (or is no
490
+ // longer) usable: dead/wiped grant, abandoned consent, missing scopes.
491
+ const brokenSignIn = Boolean(v.oauth && st?.userConfigured);
492
+ if (!st?.userConfigured) {
493
+ missing.push({ name: v.name, label: v.label, brokenSignIn }); // no row at all → needs a value / sign-in
494
+ continue;
495
+ }
496
+ // An OAuth-backed var whose row exists but has no token yet is NOT ready —
497
+ // the user has registered but not completed sign-in. Fail closed: anything
498
+ // other than a confirmed `true` (including a non-oauth row → undefined)
499
+ // counts as not-yet-authorized.
500
+ if (v.oauth && st.userAuthorized !== true) {
501
+ missing.push({ name: v.name, label: v.label, brokenSignIn });
502
+ continue;
503
+ }
504
+ // An OAuth-backed var the user signed in for, but whose token was granted
505
+ // fewer scopes than the tool now declares, is ALSO not ready — the call would
506
+ // otherwise fail opaquely at the provider. Compare the live required scopes
507
+ // against the token's recorded granted scopes; an under-scoped (or unknown)
508
+ // token needs re-authorization.
509
+ if (v.oauth && !scopesCovered(v.oauthScopes, st.grantedScopes)) {
510
+ missing.push({ name: v.name, label: v.label, brokenSignIn });
511
+ }
512
+ }
513
+ return missing;
514
+ }
515
+ async dispatch(client, tool, request,
516
+ // `sendNotification` typed loosely (`any`) so a `notifications/progress`
517
+ // payload without a `progressToken` is accepted — same approach the prior
518
+ // handler used; the strict ServerNotification type requires the token.
519
+ extra) {
520
+ const args = request.params.arguments ?? {};
521
+ const progressToken = request.params._meta?.progressToken;
522
+ let prev;
523
+ let hasPrev = false;
524
+ let progress = 0;
525
+ try {
526
+ // Args pass through to UTCP verbatim — each communication protocol does
527
+ // its own serialization (http reads the template's `body_field` out of the
528
+ // args, mcp forwards them untouched as MCP `arguments`). The advertised
529
+ // schema is the tool's UTCP `inputs` verbatim too, so what the caller
530
+ // sends is already in the shape the protocol expects; any reshaping here
531
+ // would be wrong for at least one protocol.
532
+ for await (const chunk of client.callToolStreaming(tool.utcpName, args)) {
533
+ if (hasPrev) {
534
+ progress += 1;
535
+ await extra
536
+ .sendNotification({
537
+ method: 'notifications/progress',
538
+ params: {
539
+ ...(progressToken !== undefined ? { progressToken } : {}),
540
+ progress,
541
+ message: renderProgress(prev),
542
+ },
543
+ })
544
+ .catch((err) => console.warn('[mcp] progress notification failed:', err));
545
+ }
546
+ prev = chunk;
547
+ hasPrev = true;
548
+ }
549
+ }
550
+ catch (err) {
551
+ return toolError(`The "${tool.mcpName}" tool failed: ${describeToolFailure(err)}`);
552
+ }
553
+ return toCallToolResult(prev);
554
+ }
555
+ /**
556
+ * Handle a code-mode meta-tool. `list_tools`/`tools_info` reflect on the
557
+ * session client's discovered catalog; `call_tool_chain` runs the caller's
558
+ * JavaScript in the client's isolated-vm, where every tool is reachable as
559
+ * `<manual>.tool(...)` and resolves over loopback with the caller's key.
560
+ */
561
+ async dispatchMetaTool(client, name, args) {
562
+ try {
563
+ if (name === 'list_tools') {
564
+ const tools = await client.config.tool_repository.getTools();
565
+ return toCallToolResult({ tools: tools.map((t) => utcpNameToTsInterfaceName(t.name)) });
566
+ }
567
+ if (name === 'tools_info') {
568
+ const names = Array.isArray(args.tool_names) ? args.tool_names : [];
569
+ const interfaces = [];
570
+ const notFound = [];
571
+ for (const n of names) {
572
+ const found = await findToolByName(client, n);
573
+ if (found)
574
+ interfaces.push(client.toolToTypeScriptInterface(found.tool));
575
+ else
576
+ notFound.push(n);
577
+ }
578
+ return toCallToolResult({ interfaces: interfaces.join('\n\n'), not_found: notFound });
579
+ }
580
+ // call_tool_chain
581
+ const code = typeof args.code === 'string' ? args.code : '';
582
+ const timeout = typeof args.timeout === 'number' ? args.timeout : 30_000;
583
+ // Clamp to [1000, 1_000_000] so a caller can't force oversized inline
584
+ // output past the spill (schema bounds are advisory over a raw JSON-RPC call).
585
+ const maxOutputSize = typeof args.max_output_size === 'number'
586
+ ? Math.min(1_000_000, Math.max(1_000, Math.trunc(args.max_output_size)))
587
+ : CALL_TOOL_CHAIN_MAX_OUTPUT;
588
+ const { result, logs } = await client.callToolChain(code, timeout);
589
+ // Bound the payload: an external session has no ambient workspace, so an
590
+ // oversized result spills to the shared store and we return only a ref —
591
+ // parity with the in-process agent's `call_tool_chain`.
592
+ if (JSON.stringify({ success: true, result, logs }).length <= maxOutputSize) {
593
+ return toCallToolResult({ success: true, result, logs });
594
+ }
595
+ const fullJson = JSON.stringify({ result, logs }, null, 2);
596
+ const { ref, bytes } = await this.opts.spillStore.write(fullJson);
597
+ return toCallToolResult({
598
+ success: true,
599
+ truncated: true,
600
+ result_ref: ref,
601
+ result_bytes: bytes,
602
+ message: `Result+logs payload was ${fullJson.length} characters (exceeded max_output_size of ${maxOutputSize}). Full JSON saved to the shared spill store as \`${ref}\`. Read it back with \`read_file\` (pass that ref as \`path\`, \`branch\` ignored, plus \`offset\`/\`limit\` to slice), or re-run a narrower chain that returns only what you need.`,
603
+ });
604
+ }
605
+ catch (err) {
606
+ return toolError(`The "${name}" tool failed: ${describeToolFailure(err)}`);
607
+ }
608
+ }
609
+ }
610
+ /**
611
+ * Flatten a discovered UTCP tool (`<manual>.<tool>`) into the proxy's advertised
612
+ * shape when MULTIPLE manuals are registered. KB tools keep their bare name (so
613
+ * existing external agents still call `read_file`); a user `.tool`'s tool is
614
+ * namespaced as `<manual>_<tool>` to guarantee a unique, dot-free MCP name.
615
+ */
616
+ /**
617
+ * MCP tool-name grammar (also the Anthropic API's), and a length bound. A
618
+ * remote MCP server can expose a tool whose flattened name breaks this — too
619
+ * long, or an illegal char the `<manual>_<name>` flattening didn't remove — and
620
+ * an MCP client (or the model API behind it) rejects the ENTIRE `tools/list`
621
+ * response when a single entry is non-conforming. That makes EVERY tool vanish
622
+ * the moment one bad tool from a newly-added server enters the catalog, with no
623
+ * server-side error (the rejection is the client's). `toListedTool` isolates it
624
+ * per tool: drop the offender (logged), normalize an odd schema, keep the rest.
625
+ */
626
+ const MCP_TOOL_NAME_RE = /^[a-zA-Z0-9_-]+$/;
627
+ // The Anthropic API caps a tool name at 128 chars — but the MCP CLIENT (Claude
628
+ // Code, claude.ai) prepends `mcp__<server>__` (≈20+ chars) before sending it,
629
+ // and that FULL name is what the 128 applies to. So budget for the prefix here,
630
+ // or a long `googlecalendar_…` name we pass gets the whole request 400'd. This
631
+ // is deliberately conservative; a dropped tool is logged so it's diagnosable.
632
+ const MCP_TOOL_NAME_MAX = 100;
633
+ /** A discovered tool as an MCP listing entry, or null if its name can't be listed. */
634
+ export function toListedTool(tool) {
635
+ if (!MCP_TOOL_NAME_RE.test(tool.mcpName) || tool.mcpName.length > MCP_TOOL_NAME_MAX) {
636
+ console.warn(`[mcp] dropping tool "${tool.mcpName}" from the listing — not a valid MCP tool name ` +
637
+ `(must match ${MCP_TOOL_NAME_RE} and be ≤${MCP_TOOL_NAME_MAX} chars). ` +
638
+ 'One non-conforming tool would otherwise make the whole toolset disappear on the client.');
639
+ return null;
640
+ }
641
+ // MCP requires an object inputSchema. A remote server's schema that isn't a
642
+ // plain object (or omits `type: 'object'`) can invalidate the whole response,
643
+ // so normalize it — keeping any declared properties — rather than pass it
644
+ // through verbatim.
645
+ const raw = tool.inputSchema;
646
+ let inputSchema = raw && typeof raw === 'object' && !Array.isArray(raw)
647
+ ? { type: 'object', ...raw }
648
+ : { type: 'object', properties: {} };
649
+ // Sanitize the schema into what the Anthropic tool validator accepts. A
650
+ // remote server that emits a construct the validator rejects — Google's
651
+ // gmail/calendar use `$ref`/`$defs` AND OpenAPI `format` values like
652
+ // `int32`/`byte` — makes the CLIENT reject the ENTIRE tools/list response,
653
+ // so all tools vanish and nothing registers. Sanitizing per-tool means one
654
+ // odd server can't blank the whole toolset.
655
+ inputSchema = sanitizeInputSchema(inputSchema);
656
+ // The MCP/Anthropic validator requires the top-level `type` to be exactly
657
+ // "object" and (for the Anthropic API) `properties` to be present. Force both
658
+ // so a remote schema that declared something else — or a union like
659
+ // `["object","null"]` — can't reject the whole tools/list.
660
+ inputSchema.type = 'object';
661
+ if (typeof inputSchema.properties !== 'object' || inputSchema.properties === null) {
662
+ inputSchema.properties = {};
663
+ }
664
+ return {
665
+ name: tool.mcpName,
666
+ description: tool.description,
667
+ inputSchema: inputSchema,
668
+ };
669
+ }
670
+ /** JSON-Schema string `format` values the Anthropic tool validator accepts. */
671
+ const SUPPORTED_SCHEMA_FORMATS = new Set([
672
+ 'date-time',
673
+ 'time',
674
+ 'date',
675
+ 'duration',
676
+ 'email',
677
+ 'hostname',
678
+ 'uri',
679
+ 'ipv4',
680
+ 'ipv6',
681
+ 'uuid',
682
+ ]);
683
+ /**
684
+ * Make a remote server's JSON Schema safe for the Anthropic tool validator:
685
+ * - inline local `$ref` pointers (`#/$defs/...`, `#/definitions/...`) and drop
686
+ * the now-unreferenced `$defs`/`definitions` blocks (the API restricts `$ref`
687
+ * and MCP clients converting our schemas reject it outright);
688
+ * - drop non-standard `format` values (OpenAPI's `int32`/`byte`/… — only the
689
+ * JSON-Schema-standard formats above are accepted; `format` is advisory, so
690
+ * dropping it doesn't change tool behavior).
691
+ * Depth-bounded so a recursive schema degrades to a permissive `{}` node instead
692
+ * of hanging or emitting the unsupported recursion; non-local/external refs
693
+ * degrade the same way. Exported for direct testing.
694
+ */
695
+ export function sanitizeInputSchema(schema) {
696
+ const root = schema;
697
+ const resolvePointer = (pointer) => {
698
+ if (!pointer.startsWith('#/'))
699
+ return undefined;
700
+ let node = root;
701
+ for (const partRaw of pointer.slice(2).split('/')) {
702
+ const part = partRaw.replace(/~1/g, '/').replace(/~0/g, '~');
703
+ if (!node || typeof node !== 'object')
704
+ return undefined;
705
+ node = node[part];
706
+ }
707
+ return node;
708
+ };
709
+ const walk = (node, depth) => {
710
+ if (depth > 20)
711
+ return {}; // recursion/cycle guard — permissive fallback
712
+ if (Array.isArray(node))
713
+ return node.map((item) => walk(item, depth + 1));
714
+ if (!node || typeof node !== 'object')
715
+ return node;
716
+ const obj = node;
717
+ if (typeof obj.$ref === 'string') {
718
+ const target = resolvePointer(obj.$ref);
719
+ // JSON Schema allows siblings next to $ref; keep them, target wins ties.
720
+ const { $ref: _ref, ...siblings } = obj;
721
+ const resolved = walk(target ?? {}, depth + 1);
722
+ return resolved && typeof resolved === 'object' && !Array.isArray(resolved)
723
+ ? { ...siblings, ...resolved }
724
+ : Object.keys(siblings).length
725
+ ? siblings
726
+ : resolved ?? {};
727
+ }
728
+ const out = {};
729
+ for (const [key, value] of Object.entries(obj)) {
730
+ if (key === '$defs' || key === 'definitions')
731
+ continue; // inlined above
732
+ // Drop a non-standard `format` (OpenAPI `int32`/`byte`/…) — the validator
733
+ // only allows the JSON-Schema-standard set; the annotation is non-load-bearing.
734
+ if (key === 'format' && (typeof value !== 'string' || !SUPPORTED_SCHEMA_FORMATS.has(value))) {
735
+ continue;
736
+ }
737
+ out[key] = walk(value, depth + 1);
738
+ }
739
+ return out;
740
+ };
741
+ return walk(schema, 0);
742
+ }
743
+ export function flattenManualTool(tool) {
744
+ const dot = tool.name.indexOf('.');
745
+ const manual = dot >= 0 ? tool.name.slice(0, dot) : '';
746
+ const bare = dot >= 0 ? tool.name.slice(dot + 1) : tool.name;
747
+ const mcpName = manual === EXTERNAL_KB_MANUAL_NAME ? bare : tool.name.replace(/\./g, '_');
748
+ return {
749
+ utcpName: tool.name,
750
+ mcpName,
751
+ description: tool.description,
752
+ inputSchema: tool.inputs,
753
+ manualName: manual,
754
+ };
755
+ }
756
+ /**
757
+ * Flatten one discovered UTCP tool into the proxy's advertised shape: strip the
758
+ * `<manual>.` namespace prefix for the MCP name and keep the UTCP input schema
759
+ * verbatim (Bevel-hosted HTTP tools show their `{body}` envelope, exactly as in
760
+ * `call_tool_chain`).
761
+ */
762
+ export function flattenDiscoveredTool(prefix, tool) {
763
+ return {
764
+ utcpName: tool.name,
765
+ mcpName: tool.name.startsWith(prefix) ? tool.name.slice(prefix.length) : tool.name,
766
+ description: tool.description,
767
+ inputSchema: tool.inputs,
768
+ // `prefix` is `<manual>.`; the manual is that without the trailing dot.
769
+ manualName: prefix.endsWith('.') ? prefix.slice(0, -1) : prefix,
770
+ };
771
+ }
772
+ /**
773
+ * Extract a human-meaningful failure message from a tool-call error. UTCP's
774
+ * HTTP protocol surfaces a non-2xx as an axios-style error whose `.response.data`
775
+ * is the REST endpoint's JSON body (`{ error: "..." }`). Pull that out so the
776
+ * MCP caller sees the tool's real message instead of a bare "status code 500".
777
+ */
778
+ export function describeToolFailure(err) {
779
+ const data = err?.response?.data;
780
+ if (data && typeof data === 'object') {
781
+ const inner = data.error;
782
+ if (typeof inner === 'string' && inner.length > 0)
783
+ return inner;
784
+ }
785
+ if (typeof data === 'string' && data.length > 0)
786
+ return data;
787
+ return err instanceof Error ? err.message : String(err);
788
+ }
789
+ /**
790
+ * Turn a tool's final value into an MCP result:
791
+ * - a tool that already returns the MCP agentic shape (`{ content: [...] }`,
792
+ * each entry a real content block) is passed through unchanged;
793
+ * - a bare string becomes the text content;
794
+ * - anything else is JSON-stringified into one text block.
795
+ *
796
+ * Note we do NOT collapse a structured object down to its `text` field: doing
797
+ * so silently dropped the other fields (e.g. `ask`'s `status` / `sessionId`,
798
+ * the id a caller must echo back to poll or continue a conversation).
799
+ * Stringifying the whole object keeps every field, so the caller always sees
800
+ * the id it is responsible for echoing.
801
+ *
802
+ * The passthrough guard checks the entries, not just that `content` is an array:
803
+ * a domain value that merely happens to carry a `content` array of non-blocks
804
+ * (e.g. `{ content: ['a', 'b'] }`) is data, not an MCP result, so it falls
805
+ * through to JSON-stringify and survives intact instead of being emitted as a
806
+ * malformed result the client can't parse.
807
+ */
808
+ function isMcpContentBlock(entry) {
809
+ return typeof entry === 'object' && entry !== null && typeof entry.type === 'string';
810
+ }
811
+ export function toCallToolResult(value) {
812
+ // Already in MCP agentic format — pass through untouched, but only when every
813
+ // `content` entry is a real content block (has a string `type`).
814
+ const content = value?.content;
815
+ if (value && typeof value === 'object' && Array.isArray(content) && content.every(isMcpContentBlock)) {
816
+ return value;
817
+ }
818
+ const text = typeof value === 'string' ? value : JSON.stringify(value ?? null);
819
+ return { content: [{ type: 'text', text: text || '(tool produced no output)' }] };
820
+ }
821
+ function renderProgress(chunk) {
822
+ const s = typeof chunk === 'string' ? chunk : JSON.stringify(chunk);
823
+ return s.length > 500 ? s.slice(0, 497) + '...' : s;
824
+ }
825
+ function toolError(message) {
826
+ return { isError: true, content: [{ type: 'text', text: message }] };
827
+ }
828
+ /**
829
+ * The result returned when the caller is missing personal credentials a tool
830
+ * needs. Marked `isError` so the external agent surfaces it to the person rather
831
+ * than treating it as tool output. Names the tool, lists the missing items, and
832
+ * gives the absolute setup-page URL so the person can provide them and retry.
833
+ */
834
+ export function needsAuthorizationResult(toolName, missing, connectUrl) {
835
+ const items = missing.join(', ');
836
+ const text = `The "${toolName}" tool needs credentials you haven't set up yet: ${items}. ` +
837
+ `Open ${connectUrl} to connect your accounts and enter your keys, then run the tool again.`;
838
+ return { isError: true, content: [{ type: 'text', text }] };
839
+ }
840
+ //# sourceMappingURL=mcp.service.js.map