@vurb/core 3.2.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 (642) hide show
  1. package/README.md +677 -0
  2. package/dist/cli/args.d.ts +26 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +117 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/commands/create.d.ts +11 -0
  7. package/dist/cli/commands/create.d.ts.map +1 -0
  8. package/dist/cli/commands/create.js +121 -0
  9. package/dist/cli/commands/create.js.map +1 -0
  10. package/dist/cli/commands/deploy.d.ts +3 -0
  11. package/dist/cli/commands/deploy.d.ts.map +1 -0
  12. package/dist/cli/commands/deploy.js +268 -0
  13. package/dist/cli/commands/deploy.js.map +1 -0
  14. package/dist/cli/commands/dev.d.ts +9 -0
  15. package/dist/cli/commands/dev.d.ts.map +1 -0
  16. package/dist/cli/commands/dev.js +58 -0
  17. package/dist/cli/commands/dev.js.map +1 -0
  18. package/dist/cli/commands/lock.d.ts +5 -0
  19. package/dist/cli/commands/lock.d.ts.map +1 -0
  20. package/dist/cli/commands/lock.js +94 -0
  21. package/dist/cli/commands/lock.js.map +1 -0
  22. package/dist/cli/commands/remote.d.ts +3 -0
  23. package/dist/cli/commands/remote.d.ts.map +1 -0
  24. package/dist/cli/commands/remote.js +37 -0
  25. package/dist/cli/commands/remote.js.map +1 -0
  26. package/dist/cli/constants.d.ts +18 -0
  27. package/dist/cli/constants.d.ts.map +1 -0
  28. package/dist/cli/constants.js +95 -0
  29. package/dist/cli/constants.js.map +1 -0
  30. package/dist/cli/progress.d.ts +34 -0
  31. package/dist/cli/progress.d.ts.map +1 -0
  32. package/dist/cli/progress.js +102 -0
  33. package/dist/cli/progress.js.map +1 -0
  34. package/dist/cli/rc.d.ts +11 -0
  35. package/dist/cli/rc.d.ts.map +1 -0
  36. package/dist/cli/rc.js +75 -0
  37. package/dist/cli/rc.js.map +1 -0
  38. package/dist/cli/registry.d.ts +25 -0
  39. package/dist/cli/registry.d.ts.map +1 -0
  40. package/dist/cli/registry.js +86 -0
  41. package/dist/cli/registry.js.map +1 -0
  42. package/dist/cli/scaffold.d.ts +10 -0
  43. package/dist/cli/scaffold.d.ts.map +1 -0
  44. package/dist/cli/scaffold.js +105 -0
  45. package/dist/cli/scaffold.js.map +1 -0
  46. package/dist/cli/templates/config.d.ts +14 -0
  47. package/dist/cli/templates/config.d.ts.map +1 -0
  48. package/dist/cli/templates/config.js +133 -0
  49. package/dist/cli/templates/config.js.map +1 -0
  50. package/dist/cli/templates/constants.d.ts +9 -0
  51. package/dist/cli/templates/constants.d.ts.map +1 -0
  52. package/dist/cli/templates/constants.js +9 -0
  53. package/dist/cli/templates/constants.js.map +1 -0
  54. package/dist/cli/templates/core.d.ts +14 -0
  55. package/dist/cli/templates/core.d.ts.map +1 -0
  56. package/dist/cli/templates/core.js +186 -0
  57. package/dist/cli/templates/core.js.map +1 -0
  58. package/dist/cli/templates/cursor.d.ts +8 -0
  59. package/dist/cli/templates/cursor.d.ts.map +1 -0
  60. package/dist/cli/templates/cursor.js +13 -0
  61. package/dist/cli/templates/cursor.js.map +1 -0
  62. package/dist/cli/templates/index.d.ts +17 -0
  63. package/dist/cli/templates/index.d.ts.map +1 -0
  64. package/dist/cli/templates/index.js +27 -0
  65. package/dist/cli/templates/index.js.map +1 -0
  66. package/dist/cli/templates/middleware.d.ts +7 -0
  67. package/dist/cli/templates/middleware.d.ts.map +1 -0
  68. package/dist/cli/templates/middleware.js +34 -0
  69. package/dist/cli/templates/middleware.js.map +1 -0
  70. package/dist/cli/templates/presenter.d.ts +7 -0
  71. package/dist/cli/templates/presenter.d.ts.map +1 -0
  72. package/dist/cli/templates/presenter.js +46 -0
  73. package/dist/cli/templates/presenter.js.map +1 -0
  74. package/dist/cli/templates/prompt.d.ts +7 -0
  75. package/dist/cli/templates/prompt.d.ts.map +1 -0
  76. package/dist/cli/templates/prompt.js +42 -0
  77. package/dist/cli/templates/prompt.js.map +1 -0
  78. package/dist/cli/templates/readme.d.ts +8 -0
  79. package/dist/cli/templates/readme.d.ts.map +1 -0
  80. package/dist/cli/templates/readme.js +173 -0
  81. package/dist/cli/templates/readme.js.map +1 -0
  82. package/dist/cli/templates/testing.d.ts +11 -0
  83. package/dist/cli/templates/testing.d.ts.map +1 -0
  84. package/dist/cli/templates/testing.js +101 -0
  85. package/dist/cli/templates/testing.js.map +1 -0
  86. package/dist/cli/templates/tools.d.ts +13 -0
  87. package/dist/cli/templates/tools.d.ts.map +1 -0
  88. package/dist/cli/templates/tools.js +63 -0
  89. package/dist/cli/templates/tools.js.map +1 -0
  90. package/dist/cli/templates/vectors/database.d.ts +9 -0
  91. package/dist/cli/templates/vectors/database.d.ts.map +1 -0
  92. package/dist/cli/templates/vectors/database.js +82 -0
  93. package/dist/cli/templates/vectors/database.js.map +1 -0
  94. package/dist/cli/templates/vectors/index.d.ts +9 -0
  95. package/dist/cli/templates/vectors/index.d.ts.map +1 -0
  96. package/dist/cli/templates/vectors/index.js +9 -0
  97. package/dist/cli/templates/vectors/index.js.map +1 -0
  98. package/dist/cli/templates/vectors/oauth.d.ts +10 -0
  99. package/dist/cli/templates/vectors/oauth.d.ts.map +1 -0
  100. package/dist/cli/templates/vectors/oauth.js +76 -0
  101. package/dist/cli/templates/vectors/oauth.js.map +1 -0
  102. package/dist/cli/templates/vectors/openapi.d.ts +10 -0
  103. package/dist/cli/templates/vectors/openapi.d.ts.map +1 -0
  104. package/dist/cli/templates/vectors/openapi.js +106 -0
  105. package/dist/cli/templates/vectors/openapi.js.map +1 -0
  106. package/dist/cli/templates/vectors/workflow.d.ts +7 -0
  107. package/dist/cli/templates/vectors/workflow.d.ts.map +1 -0
  108. package/dist/cli/templates/vectors/workflow.js +49 -0
  109. package/dist/cli/templates/vectors/workflow.js.map +1 -0
  110. package/dist/cli/types.d.ts +36 -0
  111. package/dist/cli/types.d.ts.map +1 -0
  112. package/dist/cli/types.js +10 -0
  113. package/dist/cli/types.js.map +1 -0
  114. package/dist/cli/utils.d.ts +27 -0
  115. package/dist/cli/utils.d.ts.map +1 -0
  116. package/dist/cli/utils.js +73 -0
  117. package/dist/cli/utils.js.map +1 -0
  118. package/dist/cli/vurb.d.ts +15 -0
  119. package/dist/cli/vurb.d.ts.map +1 -0
  120. package/dist/cli/vurb.js +87 -0
  121. package/dist/cli/vurb.js.map +1 -0
  122. package/dist/client/InferRouter.d.ts +92 -0
  123. package/dist/client/InferRouter.d.ts.map +1 -0
  124. package/dist/client/InferRouter.js +31 -0
  125. package/dist/client/InferRouter.js.map +1 -0
  126. package/dist/client/VurbClient.d.ts +282 -0
  127. package/dist/client/VurbClient.d.ts.map +1 -0
  128. package/dist/client/VurbClient.js +287 -0
  129. package/dist/client/VurbClient.js.map +1 -0
  130. package/dist/client/createTypedRegistry.d.ts +25 -0
  131. package/dist/client/createTypedRegistry.d.ts.map +1 -0
  132. package/dist/client/createTypedRegistry.js +74 -0
  133. package/dist/client/createTypedRegistry.js.map +1 -0
  134. package/dist/client/index.d.ts +6 -0
  135. package/dist/client/index.d.ts.map +1 -0
  136. package/dist/client/index.js +4 -0
  137. package/dist/client/index.js.map +1 -0
  138. package/dist/converters/ConverterBase.d.ts +68 -0
  139. package/dist/converters/ConverterBase.d.ts.map +1 -0
  140. package/dist/converters/ConverterBase.js +62 -0
  141. package/dist/converters/ConverterBase.js.map +1 -0
  142. package/dist/converters/GroupConverter.d.ts +33 -0
  143. package/dist/converters/GroupConverter.d.ts.map +1 -0
  144. package/dist/converters/GroupConverter.js +26 -0
  145. package/dist/converters/GroupConverter.js.map +1 -0
  146. package/dist/converters/PromptConverter.d.ts +33 -0
  147. package/dist/converters/PromptConverter.d.ts.map +1 -0
  148. package/dist/converters/PromptConverter.js +26 -0
  149. package/dist/converters/PromptConverter.js.map +1 -0
  150. package/dist/converters/ResourceConverter.d.ts +35 -0
  151. package/dist/converters/ResourceConverter.d.ts.map +1 -0
  152. package/dist/converters/ResourceConverter.js +28 -0
  153. package/dist/converters/ResourceConverter.js.map +1 -0
  154. package/dist/converters/ToolAnnotationsConverter.d.ts +33 -0
  155. package/dist/converters/ToolAnnotationsConverter.d.ts.map +1 -0
  156. package/dist/converters/ToolAnnotationsConverter.js +26 -0
  157. package/dist/converters/ToolAnnotationsConverter.js.map +1 -0
  158. package/dist/converters/ToolConverter.d.ts +35 -0
  159. package/dist/converters/ToolConverter.d.ts.map +1 -0
  160. package/dist/converters/ToolConverter.js +28 -0
  161. package/dist/converters/ToolConverter.js.map +1 -0
  162. package/dist/converters/index.d.ts +7 -0
  163. package/dist/converters/index.d.ts.map +1 -0
  164. package/dist/converters/index.js +7 -0
  165. package/dist/converters/index.js.map +1 -0
  166. package/dist/core/StandardSchema.d.ts +178 -0
  167. package/dist/core/StandardSchema.d.ts.map +1 -0
  168. package/dist/core/StandardSchema.js +174 -0
  169. package/dist/core/StandardSchema.js.map +1 -0
  170. package/dist/core/builder/ActionGroupBuilder.d.ts +208 -0
  171. package/dist/core/builder/ActionGroupBuilder.d.ts.map +1 -0
  172. package/dist/core/builder/ActionGroupBuilder.js +193 -0
  173. package/dist/core/builder/ActionGroupBuilder.js.map +1 -0
  174. package/dist/core/builder/ErrorBuilder.d.ts +59 -0
  175. package/dist/core/builder/ErrorBuilder.d.ts.map +1 -0
  176. package/dist/core/builder/ErrorBuilder.js +99 -0
  177. package/dist/core/builder/ErrorBuilder.js.map +1 -0
  178. package/dist/core/builder/FluentRouter.d.ts +96 -0
  179. package/dist/core/builder/FluentRouter.d.ts.map +1 -0
  180. package/dist/core/builder/FluentRouter.js +116 -0
  181. package/dist/core/builder/FluentRouter.js.map +1 -0
  182. package/dist/core/builder/FluentSchemaHelpers.d.ts +237 -0
  183. package/dist/core/builder/FluentSchemaHelpers.d.ts.map +1 -0
  184. package/dist/core/builder/FluentSchemaHelpers.js +227 -0
  185. package/dist/core/builder/FluentSchemaHelpers.js.map +1 -0
  186. package/dist/core/builder/FluentToolBuilder.d.ts +419 -0
  187. package/dist/core/builder/FluentToolBuilder.d.ts.map +1 -0
  188. package/dist/core/builder/FluentToolBuilder.js +643 -0
  189. package/dist/core/builder/FluentToolBuilder.js.map +1 -0
  190. package/dist/core/builder/GroupedToolBuilder.d.ts +832 -0
  191. package/dist/core/builder/GroupedToolBuilder.d.ts.map +1 -0
  192. package/dist/core/builder/GroupedToolBuilder.js +1306 -0
  193. package/dist/core/builder/GroupedToolBuilder.js.map +1 -0
  194. package/dist/core/builder/ParamDescriptors.d.ts +142 -0
  195. package/dist/core/builder/ParamDescriptors.d.ts.map +1 -0
  196. package/dist/core/builder/ParamDescriptors.js +164 -0
  197. package/dist/core/builder/ParamDescriptors.js.map +1 -0
  198. package/dist/core/builder/ToolDefinitionCompiler.d.ts +37 -0
  199. package/dist/core/builder/ToolDefinitionCompiler.d.ts.map +1 -0
  200. package/dist/core/builder/ToolDefinitionCompiler.js +72 -0
  201. package/dist/core/builder/ToolDefinitionCompiler.js.map +1 -0
  202. package/dist/core/builder/defineTool.d.ts +180 -0
  203. package/dist/core/builder/defineTool.d.ts.map +1 -0
  204. package/dist/core/builder/defineTool.js +164 -0
  205. package/dist/core/builder/defineTool.js.map +1 -0
  206. package/dist/core/builder/index.d.ts +13 -0
  207. package/dist/core/builder/index.d.ts.map +1 -0
  208. package/dist/core/builder/index.js +13 -0
  209. package/dist/core/builder/index.js.map +1 -0
  210. package/dist/core/createGroup.d.ts +140 -0
  211. package/dist/core/createGroup.d.ts.map +1 -0
  212. package/dist/core/createGroup.js +144 -0
  213. package/dist/core/createGroup.js.map +1 -0
  214. package/dist/core/execution/ConcurrencyGuard.d.ts +103 -0
  215. package/dist/core/execution/ConcurrencyGuard.d.ts.map +1 -0
  216. package/dist/core/execution/ConcurrencyGuard.js +147 -0
  217. package/dist/core/execution/ConcurrencyGuard.js.map +1 -0
  218. package/dist/core/execution/EgressGuard.d.ts +72 -0
  219. package/dist/core/execution/EgressGuard.d.ts.map +1 -0
  220. package/dist/core/execution/EgressGuard.js +163 -0
  221. package/dist/core/execution/EgressGuard.js.map +1 -0
  222. package/dist/core/execution/ExecutionPipeline.d.ts +67 -0
  223. package/dist/core/execution/ExecutionPipeline.d.ts.map +1 -0
  224. package/dist/core/execution/ExecutionPipeline.js +176 -0
  225. package/dist/core/execution/ExecutionPipeline.js.map +1 -0
  226. package/dist/core/execution/MiddlewareCompiler.d.ts +35 -0
  227. package/dist/core/execution/MiddlewareCompiler.d.ts.map +1 -0
  228. package/dist/core/execution/MiddlewareCompiler.js +111 -0
  229. package/dist/core/execution/MiddlewareCompiler.js.map +1 -0
  230. package/dist/core/execution/MutationSerializer.d.ts +78 -0
  231. package/dist/core/execution/MutationSerializer.d.ts.map +1 -0
  232. package/dist/core/execution/MutationSerializer.js +106 -0
  233. package/dist/core/execution/MutationSerializer.js.map +1 -0
  234. package/dist/core/execution/PipelineHooks.d.ts +46 -0
  235. package/dist/core/execution/PipelineHooks.d.ts.map +1 -0
  236. package/dist/core/execution/PipelineHooks.js +66 -0
  237. package/dist/core/execution/PipelineHooks.js.map +1 -0
  238. package/dist/core/execution/ProgressHelper.d.ts +67 -0
  239. package/dist/core/execution/ProgressHelper.d.ts.map +1 -0
  240. package/dist/core/execution/ProgressHelper.js +59 -0
  241. package/dist/core/execution/ProgressHelper.js.map +1 -0
  242. package/dist/core/execution/ValidationErrorFormatter.d.ts +34 -0
  243. package/dist/core/execution/ValidationErrorFormatter.d.ts.map +1 -0
  244. package/dist/core/execution/ValidationErrorFormatter.js +193 -0
  245. package/dist/core/execution/ValidationErrorFormatter.js.map +1 -0
  246. package/dist/core/execution/index.d.ts +9 -0
  247. package/dist/core/execution/index.d.ts.map +1 -0
  248. package/dist/core/execution/index.js +9 -0
  249. package/dist/core/execution/index.js.map +1 -0
  250. package/dist/core/index.d.ts +34 -0
  251. package/dist/core/index.d.ts.map +1 -0
  252. package/dist/core/index.js +29 -0
  253. package/dist/core/index.js.map +1 -0
  254. package/dist/core/initVurb.d.ts +295 -0
  255. package/dist/core/initVurb.d.ts.map +1 -0
  256. package/dist/core/initVurb.js +171 -0
  257. package/dist/core/initVurb.js.map +1 -0
  258. package/dist/core/middleware/ContextDerivation.d.ts +124 -0
  259. package/dist/core/middleware/ContextDerivation.d.ts.map +1 -0
  260. package/dist/core/middleware/ContextDerivation.js +117 -0
  261. package/dist/core/middleware/ContextDerivation.js.map +1 -0
  262. package/dist/core/middleware/index.d.ts +4 -0
  263. package/dist/core/middleware/index.d.ts.map +1 -0
  264. package/dist/core/middleware/index.js +3 -0
  265. package/dist/core/middleware/index.js.map +1 -0
  266. package/dist/core/registry/ToolFilterEngine.d.ts +27 -0
  267. package/dist/core/registry/ToolFilterEngine.d.ts.map +1 -0
  268. package/dist/core/registry/ToolFilterEngine.js +45 -0
  269. package/dist/core/registry/ToolFilterEngine.js.map +1 -0
  270. package/dist/core/registry/ToolRegistry.d.ts +259 -0
  271. package/dist/core/registry/ToolRegistry.d.ts.map +1 -0
  272. package/dist/core/registry/ToolRegistry.js +343 -0
  273. package/dist/core/registry/ToolRegistry.js.map +1 -0
  274. package/dist/core/registry/index.d.ts +4 -0
  275. package/dist/core/registry/index.d.ts.map +1 -0
  276. package/dist/core/registry/index.js +3 -0
  277. package/dist/core/registry/index.js.map +1 -0
  278. package/dist/core/response.d.ts +289 -0
  279. package/dist/core/response.d.ts.map +1 -0
  280. package/dist/core/response.js +286 -0
  281. package/dist/core/response.js.map +1 -0
  282. package/dist/core/result.d.ts +93 -0
  283. package/dist/core/result.d.ts.map +1 -0
  284. package/dist/core/result.js +66 -0
  285. package/dist/core/result.js.map +1 -0
  286. package/dist/core/schema/AnnotationAggregator.d.ts +11 -0
  287. package/dist/core/schema/AnnotationAggregator.d.ts.map +1 -0
  288. package/dist/core/schema/AnnotationAggregator.js +40 -0
  289. package/dist/core/schema/AnnotationAggregator.js.map +1 -0
  290. package/dist/core/schema/DescriptionGenerator.d.ts +12 -0
  291. package/dist/core/schema/DescriptionGenerator.d.ts.map +1 -0
  292. package/dist/core/schema/DescriptionGenerator.js +81 -0
  293. package/dist/core/schema/DescriptionGenerator.js.map +1 -0
  294. package/dist/core/schema/SchemaGenerator.d.ts +15 -0
  295. package/dist/core/schema/SchemaGenerator.d.ts.map +1 -0
  296. package/dist/core/schema/SchemaGenerator.js +192 -0
  297. package/dist/core/schema/SchemaGenerator.js.map +1 -0
  298. package/dist/core/schema/SchemaUtils.d.ts +26 -0
  299. package/dist/core/schema/SchemaUtils.d.ts.map +1 -0
  300. package/dist/core/schema/SchemaUtils.js +85 -0
  301. package/dist/core/schema/SchemaUtils.js.map +1 -0
  302. package/dist/core/schema/ToonDescriptionGenerator.d.ts +3 -0
  303. package/dist/core/schema/ToonDescriptionGenerator.d.ts.map +1 -0
  304. package/dist/core/schema/ToonDescriptionGenerator.js +65 -0
  305. package/dist/core/schema/ToonDescriptionGenerator.js.map +1 -0
  306. package/dist/core/schema/index.d.ts +7 -0
  307. package/dist/core/schema/index.d.ts.map +1 -0
  308. package/dist/core/schema/index.js +7 -0
  309. package/dist/core/schema/index.js.map +1 -0
  310. package/dist/core/serialization/JsonSerializer.d.ts +71 -0
  311. package/dist/core/serialization/JsonSerializer.d.ts.map +1 -0
  312. package/dist/core/serialization/JsonSerializer.js +192 -0
  313. package/dist/core/serialization/JsonSerializer.js.map +1 -0
  314. package/dist/core/serialization/index.d.ts +7 -0
  315. package/dist/core/serialization/index.d.ts.map +1 -0
  316. package/dist/core/serialization/index.js +7 -0
  317. package/dist/core/serialization/index.js.map +1 -0
  318. package/dist/core/types.d.ts +303 -0
  319. package/dist/core/types.d.ts.map +1 -0
  320. package/dist/core/types.js +17 -0
  321. package/dist/core/types.js.map +1 -0
  322. package/dist/domain/Annotations.d.ts +42 -0
  323. package/dist/domain/Annotations.d.ts.map +1 -0
  324. package/dist/domain/Annotations.js +16 -0
  325. package/dist/domain/Annotations.js.map +1 -0
  326. package/dist/domain/BaseModel.d.ts +50 -0
  327. package/dist/domain/BaseModel.d.ts.map +1 -0
  328. package/dist/domain/BaseModel.js +41 -0
  329. package/dist/domain/BaseModel.js.map +1 -0
  330. package/dist/domain/Group.d.ts +99 -0
  331. package/dist/domain/Group.d.ts.map +1 -0
  332. package/dist/domain/Group.js +172 -0
  333. package/dist/domain/Group.js.map +1 -0
  334. package/dist/domain/GroupItem.d.ts +46 -0
  335. package/dist/domain/GroupItem.d.ts.map +1 -0
  336. package/dist/domain/GroupItem.js +58 -0
  337. package/dist/domain/GroupItem.js.map +1 -0
  338. package/dist/domain/Icon.d.ts +41 -0
  339. package/dist/domain/Icon.d.ts.map +1 -0
  340. package/dist/domain/Icon.js +15 -0
  341. package/dist/domain/Icon.js.map +1 -0
  342. package/dist/domain/Prompt.d.ts +49 -0
  343. package/dist/domain/Prompt.d.ts.map +1 -0
  344. package/dist/domain/Prompt.js +59 -0
  345. package/dist/domain/Prompt.js.map +1 -0
  346. package/dist/domain/PromptArgument.d.ts +23 -0
  347. package/dist/domain/PromptArgument.d.ts.map +1 -0
  348. package/dist/domain/PromptArgument.js +27 -0
  349. package/dist/domain/PromptArgument.js.map +1 -0
  350. package/dist/domain/Resource.d.ts +37 -0
  351. package/dist/domain/Resource.d.ts.map +1 -0
  352. package/dist/domain/Resource.js +39 -0
  353. package/dist/domain/Resource.js.map +1 -0
  354. package/dist/domain/Role.d.ts +23 -0
  355. package/dist/domain/Role.d.ts.map +1 -0
  356. package/dist/domain/Role.js +24 -0
  357. package/dist/domain/Role.js.map +1 -0
  358. package/dist/domain/Tool.d.ts +39 -0
  359. package/dist/domain/Tool.d.ts.map +1 -0
  360. package/dist/domain/Tool.js +41 -0
  361. package/dist/domain/Tool.js.map +1 -0
  362. package/dist/domain/ToolAnnotations.d.ts +48 -0
  363. package/dist/domain/ToolAnnotations.d.ts.map +1 -0
  364. package/dist/domain/ToolAnnotations.js +15 -0
  365. package/dist/domain/ToolAnnotations.js.map +1 -0
  366. package/dist/domain/index.d.ts +16 -0
  367. package/dist/domain/index.d.ts.map +1 -0
  368. package/dist/domain/index.js +13 -0
  369. package/dist/domain/index.js.map +1 -0
  370. package/dist/domain/utils.d.ts +6 -0
  371. package/dist/domain/utils.d.ts.map +1 -0
  372. package/dist/domain/utils.js +12 -0
  373. package/dist/domain/utils.js.map +1 -0
  374. package/dist/edge-stub.d.ts +73 -0
  375. package/dist/edge-stub.d.ts.map +1 -0
  376. package/dist/edge-stub.js +83 -0
  377. package/dist/edge-stub.js.map +1 -0
  378. package/dist/exposition/ExpositionCompiler.d.ts +66 -0
  379. package/dist/exposition/ExpositionCompiler.d.ts.map +1 -0
  380. package/dist/exposition/ExpositionCompiler.js +279 -0
  381. package/dist/exposition/ExpositionCompiler.js.map +1 -0
  382. package/dist/exposition/index.d.ts +4 -0
  383. package/dist/exposition/index.d.ts.map +1 -0
  384. package/dist/exposition/index.js +2 -0
  385. package/dist/exposition/index.js.map +1 -0
  386. package/dist/exposition/types.d.ts +58 -0
  387. package/dist/exposition/types.d.ts.map +1 -0
  388. package/dist/exposition/types.js +11 -0
  389. package/dist/exposition/types.js.map +1 -0
  390. package/dist/fsm/StateMachineGate.d.ts +294 -0
  391. package/dist/fsm/StateMachineGate.d.ts.map +1 -0
  392. package/dist/fsm/StateMachineGate.js +400 -0
  393. package/dist/fsm/StateMachineGate.js.map +1 -0
  394. package/dist/index.d.ts +148 -0
  395. package/dist/index.d.ts.map +1 -0
  396. package/dist/index.js +112 -0
  397. package/dist/index.js.map +1 -0
  398. package/dist/introspection/BehaviorDigest.d.ts +112 -0
  399. package/dist/introspection/BehaviorDigest.d.ts.map +1 -0
  400. package/dist/introspection/BehaviorDigest.js +149 -0
  401. package/dist/introspection/BehaviorDigest.js.map +1 -0
  402. package/dist/introspection/CapabilityLockfile.d.ts +261 -0
  403. package/dist/introspection/CapabilityLockfile.d.ts.map +1 -0
  404. package/dist/introspection/CapabilityLockfile.js +395 -0
  405. package/dist/introspection/CapabilityLockfile.js.map +1 -0
  406. package/dist/introspection/ContractAwareSelfHealing.d.ts +90 -0
  407. package/dist/introspection/ContractAwareSelfHealing.d.ts.map +1 -0
  408. package/dist/introspection/ContractAwareSelfHealing.js +132 -0
  409. package/dist/introspection/ContractAwareSelfHealing.js.map +1 -0
  410. package/dist/introspection/ContractDiff.d.ts +91 -0
  411. package/dist/introspection/ContractDiff.d.ts.map +1 -0
  412. package/dist/introspection/ContractDiff.js +466 -0
  413. package/dist/introspection/ContractDiff.js.map +1 -0
  414. package/dist/introspection/CryptoAttestation.d.ts +143 -0
  415. package/dist/introspection/CryptoAttestation.d.ts.map +1 -0
  416. package/dist/introspection/CryptoAttestation.js +192 -0
  417. package/dist/introspection/CryptoAttestation.js.map +1 -0
  418. package/dist/introspection/EntitlementScanner.d.ts +177 -0
  419. package/dist/introspection/EntitlementScanner.d.ts.map +1 -0
  420. package/dist/introspection/EntitlementScanner.js +459 -0
  421. package/dist/introspection/EntitlementScanner.js.map +1 -0
  422. package/dist/introspection/GovernanceObserver.d.ts +88 -0
  423. package/dist/introspection/GovernanceObserver.d.ts.map +1 -0
  424. package/dist/introspection/GovernanceObserver.js +136 -0
  425. package/dist/introspection/GovernanceObserver.js.map +1 -0
  426. package/dist/introspection/IntrospectionResource.d.ts +20 -0
  427. package/dist/introspection/IntrospectionResource.d.ts.map +1 -0
  428. package/dist/introspection/IntrospectionResource.js +112 -0
  429. package/dist/introspection/IntrospectionResource.js.map +1 -0
  430. package/dist/introspection/ManifestCompiler.d.ts +33 -0
  431. package/dist/introspection/ManifestCompiler.d.ts.map +1 -0
  432. package/dist/introspection/ManifestCompiler.js +88 -0
  433. package/dist/introspection/ManifestCompiler.js.map +1 -0
  434. package/dist/introspection/SemanticProbe.d.ts +207 -0
  435. package/dist/introspection/SemanticProbe.d.ts.map +1 -0
  436. package/dist/introspection/SemanticProbe.js +274 -0
  437. package/dist/introspection/SemanticProbe.js.map +1 -0
  438. package/dist/introspection/TokenEconomics.d.ts +210 -0
  439. package/dist/introspection/TokenEconomics.d.ts.map +1 -0
  440. package/dist/introspection/TokenEconomics.js +292 -0
  441. package/dist/introspection/TokenEconomics.js.map +1 -0
  442. package/dist/introspection/ToolContract.d.ts +161 -0
  443. package/dist/introspection/ToolContract.d.ts.map +1 -0
  444. package/dist/introspection/ToolContract.js +218 -0
  445. package/dist/introspection/ToolContract.js.map +1 -0
  446. package/dist/introspection/canonicalize.d.ts +35 -0
  447. package/dist/introspection/canonicalize.d.ts.map +1 -0
  448. package/dist/introspection/canonicalize.js +72 -0
  449. package/dist/introspection/canonicalize.js.map +1 -0
  450. package/dist/introspection/index.d.ts +26 -0
  451. package/dist/introspection/index.d.ts.map +1 -0
  452. package/dist/introspection/index.js +24 -0
  453. package/dist/introspection/index.js.map +1 -0
  454. package/dist/introspection/types.d.ts +120 -0
  455. package/dist/introspection/types.d.ts.map +1 -0
  456. package/dist/introspection/types.js +13 -0
  457. package/dist/introspection/types.js.map +1 -0
  458. package/dist/observability/DebugObserver.d.ts +185 -0
  459. package/dist/observability/DebugObserver.d.ts.map +1 -0
  460. package/dist/observability/DebugObserver.js +102 -0
  461. package/dist/observability/DebugObserver.js.map +1 -0
  462. package/dist/observability/TelemetryBus.d.ts +88 -0
  463. package/dist/observability/TelemetryBus.d.ts.map +1 -0
  464. package/dist/observability/TelemetryBus.js +463 -0
  465. package/dist/observability/TelemetryBus.js.map +1 -0
  466. package/dist/observability/TelemetryEvent.d.ts +177 -0
  467. package/dist/observability/TelemetryEvent.d.ts.map +1 -0
  468. package/dist/observability/TelemetryEvent.js +2 -0
  469. package/dist/observability/TelemetryEvent.js.map +1 -0
  470. package/dist/observability/Tracing.d.ts +155 -0
  471. package/dist/observability/Tracing.d.ts.map +1 -0
  472. package/dist/observability/Tracing.js +67 -0
  473. package/dist/observability/Tracing.js.map +1 -0
  474. package/dist/observability/index.d.ts +13 -0
  475. package/dist/observability/index.d.ts.map +1 -0
  476. package/dist/observability/index.js +12 -0
  477. package/dist/observability/index.js.map +1 -0
  478. package/dist/presenter/PostProcessor.d.ts +52 -0
  479. package/dist/presenter/PostProcessor.d.ts.map +1 -0
  480. package/dist/presenter/PostProcessor.js +148 -0
  481. package/dist/presenter/PostProcessor.js.map +1 -0
  482. package/dist/presenter/Presenter.d.ts +575 -0
  483. package/dist/presenter/Presenter.d.ts.map +1 -0
  484. package/dist/presenter/Presenter.js +768 -0
  485. package/dist/presenter/Presenter.js.map +1 -0
  486. package/dist/presenter/PresenterValidationError.d.ts +42 -0
  487. package/dist/presenter/PresenterValidationError.d.ts.map +1 -0
  488. package/dist/presenter/PresenterValidationError.js +55 -0
  489. package/dist/presenter/PresenterValidationError.js.map +1 -0
  490. package/dist/presenter/RedactEngine.d.ts +110 -0
  491. package/dist/presenter/RedactEngine.d.ts.map +1 -0
  492. package/dist/presenter/RedactEngine.js +128 -0
  493. package/dist/presenter/RedactEngine.js.map +1 -0
  494. package/dist/presenter/ResponseBuilder.d.ts +262 -0
  495. package/dist/presenter/ResponseBuilder.d.ts.map +1 -0
  496. package/dist/presenter/ResponseBuilder.js +374 -0
  497. package/dist/presenter/ResponseBuilder.js.map +1 -0
  498. package/dist/presenter/SelectUtils.d.ts +78 -0
  499. package/dist/presenter/SelectUtils.d.ts.map +1 -0
  500. package/dist/presenter/SelectUtils.js +141 -0
  501. package/dist/presenter/SelectUtils.js.map +1 -0
  502. package/dist/presenter/ZodDescriptionExtractor.d.ts +54 -0
  503. package/dist/presenter/ZodDescriptionExtractor.d.ts.map +1 -0
  504. package/dist/presenter/ZodDescriptionExtractor.js +131 -0
  505. package/dist/presenter/ZodDescriptionExtractor.js.map +1 -0
  506. package/dist/presenter/definePresenter.d.ts +193 -0
  507. package/dist/presenter/definePresenter.d.ts.map +1 -0
  508. package/dist/presenter/definePresenter.js +99 -0
  509. package/dist/presenter/definePresenter.js.map +1 -0
  510. package/dist/presenter/index.d.ts +21 -0
  511. package/dist/presenter/index.d.ts.map +1 -0
  512. package/dist/presenter/index.js +28 -0
  513. package/dist/presenter/index.js.map +1 -0
  514. package/dist/presenter/suggest.d.ts +39 -0
  515. package/dist/presenter/suggest.d.ts.map +1 -0
  516. package/dist/presenter/suggest.js +41 -0
  517. package/dist/presenter/suggest.js.map +1 -0
  518. package/dist/presenter/typeHelpers.d.ts +147 -0
  519. package/dist/presenter/typeHelpers.d.ts.map +1 -0
  520. package/dist/presenter/typeHelpers.js +152 -0
  521. package/dist/presenter/typeHelpers.js.map +1 -0
  522. package/dist/presenter/ui.d.ts +205 -0
  523. package/dist/presenter/ui.d.ts.map +1 -0
  524. package/dist/presenter/ui.js +222 -0
  525. package/dist/presenter/ui.js.map +1 -0
  526. package/dist/prompt/CursorCodec.d.ts +43 -0
  527. package/dist/prompt/CursorCodec.d.ts.map +1 -0
  528. package/dist/prompt/CursorCodec.js +171 -0
  529. package/dist/prompt/CursorCodec.js.map +1 -0
  530. package/dist/prompt/FluentPromptBuilder.d.ts +155 -0
  531. package/dist/prompt/FluentPromptBuilder.d.ts.map +1 -0
  532. package/dist/prompt/FluentPromptBuilder.js +195 -0
  533. package/dist/prompt/FluentPromptBuilder.js.map +1 -0
  534. package/dist/prompt/HydrationSandbox.d.ts +55 -0
  535. package/dist/prompt/HydrationSandbox.d.ts.map +1 -0
  536. package/dist/prompt/HydrationSandbox.js +122 -0
  537. package/dist/prompt/HydrationSandbox.js.map +1 -0
  538. package/dist/prompt/PromptExecutionPipeline.d.ts +61 -0
  539. package/dist/prompt/PromptExecutionPipeline.d.ts.map +1 -0
  540. package/dist/prompt/PromptExecutionPipeline.js +177 -0
  541. package/dist/prompt/PromptExecutionPipeline.js.map +1 -0
  542. package/dist/prompt/PromptMessage.d.ts +133 -0
  543. package/dist/prompt/PromptMessage.d.ts.map +1 -0
  544. package/dist/prompt/PromptMessage.js +182 -0
  545. package/dist/prompt/PromptMessage.js.map +1 -0
  546. package/dist/prompt/PromptRegistry.d.ts +236 -0
  547. package/dist/prompt/PromptRegistry.d.ts.map +1 -0
  548. package/dist/prompt/PromptRegistry.js +399 -0
  549. package/dist/prompt/PromptRegistry.js.map +1 -0
  550. package/dist/prompt/definePrompt.d.ts +111 -0
  551. package/dist/prompt/definePrompt.d.ts.map +1 -0
  552. package/dist/prompt/definePrompt.js +130 -0
  553. package/dist/prompt/definePrompt.js.map +1 -0
  554. package/dist/prompt/index.d.ts +12 -0
  555. package/dist/prompt/index.d.ts.map +1 -0
  556. package/dist/prompt/index.js +13 -0
  557. package/dist/prompt/index.js.map +1 -0
  558. package/dist/prompt/types.d.ts +425 -0
  559. package/dist/prompt/types.d.ts.map +1 -0
  560. package/dist/prompt/types.js +19 -0
  561. package/dist/prompt/types.js.map +1 -0
  562. package/dist/sandbox/SandboxEngine.d.ts +225 -0
  563. package/dist/sandbox/SandboxEngine.d.ts.map +1 -0
  564. package/dist/sandbox/SandboxEngine.js +437 -0
  565. package/dist/sandbox/SandboxEngine.js.map +1 -0
  566. package/dist/sandbox/SandboxGuard.d.ts +47 -0
  567. package/dist/sandbox/SandboxGuard.d.ts.map +1 -0
  568. package/dist/sandbox/SandboxGuard.js +127 -0
  569. package/dist/sandbox/SandboxGuard.js.map +1 -0
  570. package/dist/sandbox/index.d.ts +23 -0
  571. package/dist/sandbox/index.d.ts.map +1 -0
  572. package/dist/sandbox/index.js +26 -0
  573. package/dist/sandbox/index.js.map +1 -0
  574. package/dist/server/DevServer.d.ts +120 -0
  575. package/dist/server/DevServer.d.ts.map +1 -0
  576. package/dist/server/DevServer.js +252 -0
  577. package/dist/server/DevServer.js.map +1 -0
  578. package/dist/server/ServerAttachment.d.ts +354 -0
  579. package/dist/server/ServerAttachment.d.ts.map +1 -0
  580. package/dist/server/ServerAttachment.js +709 -0
  581. package/dist/server/ServerAttachment.js.map +1 -0
  582. package/dist/server/ServerResolver.d.ts +24 -0
  583. package/dist/server/ServerResolver.d.ts.map +1 -0
  584. package/dist/server/ServerResolver.js +50 -0
  585. package/dist/server/ServerResolver.js.map +1 -0
  586. package/dist/server/autoDiscover.d.ts +75 -0
  587. package/dist/server/autoDiscover.d.ts.map +1 -0
  588. package/dist/server/autoDiscover.js +164 -0
  589. package/dist/server/autoDiscover.js.map +1 -0
  590. package/dist/server/index.d.ts +12 -0
  591. package/dist/server/index.d.ts.map +1 -0
  592. package/dist/server/index.js +11 -0
  593. package/dist/server/index.js.map +1 -0
  594. package/dist/server/startServer.d.ts +81 -0
  595. package/dist/server/startServer.d.ts.map +1 -0
  596. package/dist/server/startServer.js +143 -0
  597. package/dist/server/startServer.js.map +1 -0
  598. package/dist/state-sync/CausalEngine.d.ts +28 -0
  599. package/dist/state-sync/CausalEngine.d.ts.map +1 -0
  600. package/dist/state-sync/CausalEngine.js +17 -0
  601. package/dist/state-sync/CausalEngine.js.map +1 -0
  602. package/dist/state-sync/DescriptionDecorator.d.ts +31 -0
  603. package/dist/state-sync/DescriptionDecorator.d.ts.map +1 -0
  604. package/dist/state-sync/DescriptionDecorator.js +38 -0
  605. package/dist/state-sync/DescriptionDecorator.js.map +1 -0
  606. package/dist/state-sync/GlobMatcher.d.ts +29 -0
  607. package/dist/state-sync/GlobMatcher.d.ts.map +1 -0
  608. package/dist/state-sync/GlobMatcher.js +79 -0
  609. package/dist/state-sync/GlobMatcher.js.map +1 -0
  610. package/dist/state-sync/PolicyEngine.d.ts +75 -0
  611. package/dist/state-sync/PolicyEngine.d.ts.map +1 -0
  612. package/dist/state-sync/PolicyEngine.js +107 -0
  613. package/dist/state-sync/PolicyEngine.js.map +1 -0
  614. package/dist/state-sync/PolicyValidator.d.ts +67 -0
  615. package/dist/state-sync/PolicyValidator.d.ts.map +1 -0
  616. package/dist/state-sync/PolicyValidator.js +122 -0
  617. package/dist/state-sync/PolicyValidator.js.map +1 -0
  618. package/dist/state-sync/ResponseDecorator.d.ts +33 -0
  619. package/dist/state-sync/ResponseDecorator.d.ts.map +1 -0
  620. package/dist/state-sync/ResponseDecorator.js +20 -0
  621. package/dist/state-sync/ResponseDecorator.js.map +1 -0
  622. package/dist/state-sync/StateSyncBuilder.d.ts +77 -0
  623. package/dist/state-sync/StateSyncBuilder.d.ts.map +1 -0
  624. package/dist/state-sync/StateSyncBuilder.js +129 -0
  625. package/dist/state-sync/StateSyncBuilder.js.map +1 -0
  626. package/dist/state-sync/StateSyncLayer.d.ts +107 -0
  627. package/dist/state-sync/StateSyncLayer.d.ts.map +1 -0
  628. package/dist/state-sync/StateSyncLayer.js +158 -0
  629. package/dist/state-sync/StateSyncLayer.js.map +1 -0
  630. package/dist/state-sync/index.d.ts +27 -0
  631. package/dist/state-sync/index.d.ts.map +1 -0
  632. package/dist/state-sync/index.js +27 -0
  633. package/dist/state-sync/index.js.map +1 -0
  634. package/dist/state-sync/types.d.ts +174 -0
  635. package/dist/state-sync/types.d.ts.map +1 -0
  636. package/dist/state-sync/types.js +17 -0
  637. package/dist/state-sync/types.js.map +1 -0
  638. package/dist/testing/MvaMetaSymbol.d.ts +45 -0
  639. package/dist/testing/MvaMetaSymbol.d.ts.map +1 -0
  640. package/dist/testing/MvaMetaSymbol.js +34 -0
  641. package/dist/testing/MvaMetaSymbol.js.map +1 -0
  642. package/package.json +153 -0
@@ -0,0 +1,1306 @@
1
+ /**
2
+ * GroupedToolBuilder — Fluent API for MCP Tool Construction
3
+ *
4
+ * The primary entry point for building grouped MCP tools. Consolidates
5
+ * multiple related actions behind a single discriminator field, reducing
6
+ * tool count and improving LLM routing accuracy.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createTool, success, error } from 'vurb';
11
+ * import { z } from 'zod';
12
+ *
13
+ * const projects = createTool<AppContext>('projects')
14
+ * .description('Manage workspace projects')
15
+ * .commonSchema(z.object({
16
+ * workspace_id: z.string().describe('Workspace identifier'),
17
+ * }))
18
+ * .action({
19
+ * name: 'list',
20
+ * readOnly: true,
21
+ * schema: z.object({ status: z.enum(['active', 'archived']).optional() }),
22
+ * handler: async (ctx, args) => {
23
+ * const projects = await ctx.db.projects.findMany({
24
+ * where: { workspaceId: args.workspace_id, status: args.status },
25
+ * });
26
+ * return success(projects);
27
+ * },
28
+ * })
29
+ * .action({
30
+ * name: 'delete',
31
+ * destructive: true,
32
+ * schema: z.object({ project_id: z.string() }),
33
+ * handler: async (ctx, args) => {
34
+ * await ctx.db.projects.delete({ where: { id: args.project_id } });
35
+ * return success('Deleted');
36
+ * },
37
+ * });
38
+ * ```
39
+ *
40
+ * @see {@link createTool} for the recommended factory function
41
+ * @see {@link ToolRegistry} for registration and server attachment
42
+ * @see {@link ActionGroupBuilder} for hierarchical group configuration
43
+ *
44
+ * @module
45
+ */
46
+ import {} from 'zod';
47
+ import {} from '@modelcontextprotocol/sdk/types.js';
48
+ import { error, toolError } from '../response.js';
49
+ import {} from '../types.js';
50
+ import {} from '../../observability/DebugObserver.js';
51
+ import {} from '../../observability/TelemetryEvent.js';
52
+ import { resolveMiddleware } from '../middleware/ContextDerivation.js';
53
+ import { SpanStatusCode } from '../../observability/Tracing.js';
54
+ import { getActionRequiredFields } from '../schema/SchemaUtils.js';
55
+ import { parseDiscriminator, resolveAction, validateArgs, runChain, } from '../execution/ExecutionPipeline.js';
56
+ import {} from '../../presenter/PostProcessor.js';
57
+ import {} from '../execution/ProgressHelper.js';
58
+ import { ConcurrencyGuard } from '../execution/ConcurrencyGuard.js';
59
+ import { applyEgressGuard } from '../execution/EgressGuard.js';
60
+ import {} from '../../sandbox/SandboxEngine.js';
61
+ import { MutationSerializer } from '../execution/MutationSerializer.js';
62
+ import { computeResponseSize, mergeHooks } from '../execution/PipelineHooks.js';
63
+ import { compileToolDefinition } from './ToolDefinitionCompiler.js';
64
+ import { ActionGroupBuilder, mapConfigToActionFields, } from './ActionGroupBuilder.js';
65
+ // ── Re-exports for Public API Compatibility ──────────────
66
+ export { ActionGroupBuilder } from './ActionGroupBuilder.js';
67
+ // ── Factory Function ─────────────────────────────────────
68
+ /**
69
+ * Create a new grouped tool builder.
70
+ *
71
+ * This is the **recommended entry point** for building MCP tools.
72
+ * Equivalent to `new GroupedToolBuilder<TContext>(name)` but more
73
+ * concise and idiomatic.
74
+ *
75
+ * @typeParam TContext - Application context type passed to every handler.
76
+ * Use `void` (default) if your handlers don't need context.
77
+ *
78
+ * @param name - Tool name as it appears in the MCP `tools/list` response.
79
+ * Must be unique across all registered tools.
80
+ *
81
+ * @returns A new {@link GroupedToolBuilder} configured with the given name.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * // Simple tool (no context)
86
+ * const echo = createTool('echo')
87
+ * .action({
88
+ * name: 'say',
89
+ * schema: z.object({ message: z.string() }),
90
+ * handler: async (_ctx, args) => success(args.message),
91
+ * });
92
+ *
93
+ * // With application context
94
+ * const users = createTool<AppContext>('users')
95
+ * .description('User management')
96
+ * .use(requireAuth)
97
+ * .action({
98
+ * name: 'list',
99
+ * readOnly: true,
100
+ * handler: async (ctx, _args) => success(await ctx.db.users.findMany()),
101
+ * });
102
+ *
103
+ * // With hierarchical groups
104
+ * const platform = createTool<AppContext>('platform')
105
+ * .tags('core')
106
+ * .group('users', 'User management', g => {
107
+ * g.action({ name: 'list', readOnly: true, handler: listUsers });
108
+ * })
109
+ * .group('billing', 'Billing operations', g => {
110
+ * g.action({ name: 'refund', destructive: true, schema: refundSchema, handler: issueRefund });
111
+ * });
112
+ * ```
113
+ *
114
+ * @see {@link GroupedToolBuilder} for the full builder API
115
+ * @see {@link ToolRegistry.register} for tool registration
116
+ */
117
+ export function createTool(name) {
118
+ return new GroupedToolBuilder(name);
119
+ }
120
+ // ============================================================================
121
+ // GroupedToolBuilder
122
+ // ============================================================================
123
+ /**
124
+ * Fluent builder for creating consolidated MCP tools.
125
+ *
126
+ * Groups multiple related operations behind a single discriminator field
127
+ * (default: `"action"`), producing one MCP tool definition with a
128
+ * union schema and auto-generated descriptions.
129
+ *
130
+ * @typeParam TContext - Application context passed to every handler
131
+ * @typeParam TCommon - Shape of the common schema (inferred automatically)
132
+ * @typeParam TName - Tool name literal (inferred by createTool)
133
+ * @typeParam TRouterMap - Accumulated action entries for InferRouter (phantom type)
134
+ *
135
+ * @see {@link createTool} for the recommended factory function
136
+ */
137
+ export class GroupedToolBuilder {
138
+ _name;
139
+ _description;
140
+ _discriminator = 'action';
141
+ _annotations;
142
+ _tags = [];
143
+ _commonSchema;
144
+ _middlewares = [];
145
+ _actions = [];
146
+ _hasFlat = false;
147
+ _hasGroup = false;
148
+ _toonMode = false;
149
+ _selectEnabled = false;
150
+ _frozen = false;
151
+ _debug;
152
+ _tracer;
153
+ _telemetry;
154
+ _concurrencyGuard;
155
+ _egressMaxBytes;
156
+ _sandboxConfig;
157
+ _mutationSerializer;
158
+ _stateSyncHints = new Map();
159
+ _fsmStates;
160
+ _fsmTransition;
161
+ // Cached build result
162
+ _cachedTool;
163
+ _executionContext;
164
+ constructor(name) {
165
+ this._name = name;
166
+ }
167
+ // ── Configuration (fluent) ──────────────────────────
168
+ /**
169
+ * Set the discriminator field name.
170
+ *
171
+ * The discriminator is the field the LLM uses to select which action
172
+ * to execute. Defaults to `"action"`.
173
+ *
174
+ * @param field - Field name for the discriminator enum
175
+ * @returns `this` for chaining
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * // Custom discriminator
180
+ * const builder = createTool('projects')
181
+ * .discriminator('operation')
182
+ * .action({ name: 'list', handler: listProjects });
183
+ * // LLM sends: { operation: 'list' }
184
+ * ```
185
+ *
186
+ * @defaultValue `"action"`
187
+ */
188
+ discriminator(field) {
189
+ this._assertNotFrozen();
190
+ this._discriminator = field;
191
+ return this;
192
+ }
193
+ /**
194
+ * Set the tool description.
195
+ *
196
+ * Appears as the first line in the auto-generated tool description
197
+ * that the LLM sees.
198
+ *
199
+ * @param desc - Human-readable description of what this tool does
200
+ * @returns `this` for chaining
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * createTool('projects')
205
+ * .description('Manage workspace projects')
206
+ * ```
207
+ */
208
+ description(desc) {
209
+ this._assertNotFrozen();
210
+ this._description = desc;
211
+ return this;
212
+ }
213
+ /**
214
+ * Set MCP tool annotations.
215
+ *
216
+ * Manual override for tool-level annotations. If not set,
217
+ * annotations are automatically aggregated from per-action properties.
218
+ *
219
+ * @param a - Annotation key-value pairs
220
+ * @returns `this` for chaining
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * createTool('admin')
225
+ * .annotations({ openWorldHint: true, returnDirect: false })
226
+ * ```
227
+ *
228
+ * @see {@link https://modelcontextprotocol.io/specification/2025-03-26/server/tools#annotations | MCP Tool Annotations}
229
+ */
230
+ annotations(a) {
231
+ this._assertNotFrozen();
232
+ this._annotations = a;
233
+ return this;
234
+ }
235
+ /**
236
+ * Set capability tags for selective tool exposure.
237
+ *
238
+ * Tags control which tools the LLM sees via
239
+ * {@link ToolRegistry.attachToServer}'s `filter` option.
240
+ * Use tags to implement per-session context gating.
241
+ *
242
+ * @param tags - One or more string tags
243
+ * @returns `this` for chaining
244
+ *
245
+ * @example
246
+ * ```typescript
247
+ * const users = createTool<AppContext>('users').tags('core');
248
+ * const admin = createTool<AppContext>('admin').tags('admin', 'internal');
249
+ *
250
+ * // Expose only 'core' tools to the LLM:
251
+ * registry.attachToServer(server, { filter: { tags: ['core'] } });
252
+ * ```
253
+ *
254
+ * @see {@link ToolRegistry.getTools} for filtered tool retrieval
255
+ */
256
+ tags(...tags) {
257
+ this._assertNotFrozen();
258
+ this._tags.push(...tags);
259
+ return this;
260
+ }
261
+ /**
262
+ * Set a common schema shared by all actions.
263
+ *
264
+ * Fields from this schema are injected into every action's input
265
+ * and marked as `(always required)` in the auto-generated description.
266
+ * The return type narrows to propagate types to all handlers.
267
+ *
268
+ * @typeParam TSchema - Zod object schema type (inferred)
269
+ * @param schema - A `z.object()` defining shared fields
270
+ * @returns A narrowed builder with `TCommon` set to `TSchema["_output"]`
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * createTool<AppContext>('projects')
275
+ * .commonSchema(z.object({
276
+ * workspace_id: z.string().describe('Workspace identifier'),
277
+ * }))
278
+ * .action({
279
+ * name: 'list',
280
+ * handler: async (ctx, args) => {
281
+ * // ✅ args.workspace_id is typed as string
282
+ * const projects = await ctx.db.projects.findMany({
283
+ * where: { workspaceId: args.workspace_id },
284
+ * });
285
+ * return success(projects);
286
+ * },
287
+ * });
288
+ * ```
289
+ */
290
+ commonSchema(schema) {
291
+ this._assertNotFrozen();
292
+ this._commonSchema = schema;
293
+ return this;
294
+ }
295
+ /**
296
+ * Enable TOON-formatted descriptions for token optimization.
297
+ *
298
+ * Uses TOON (Token-Oriented Object Notation) to encode action metadata
299
+ * in a compact tabular format, reducing description token count by ~30-50%.
300
+ *
301
+ * @returns `this` for chaining
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * createTool('projects')
306
+ * .toonDescription() // Compact descriptions
307
+ * .action({ name: 'list', handler: listProjects })
308
+ * ```
309
+ *
310
+ * @see {@link toonSuccess} for TOON-encoded responses
311
+ */
312
+ toonDescription() {
313
+ this._assertNotFrozen();
314
+ this._toonMode = true;
315
+ return this;
316
+ }
317
+ // ── State Sync (Fluent) ──────────────────────────────
318
+ /**
319
+ * Declare glob patterns invalidated when this tool succeeds.
320
+ *
321
+ * Eliminates manual `stateSync.policies` configuration —
322
+ * the framework auto-collects hints from all builders.
323
+ *
324
+ * @param patterns - Glob patterns (e.g. `'sprints.*'`, `'tasks.*'`)
325
+ * @returns `this` for chaining
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * createTool('tasks')
330
+ * .invalidates('tasks.*', 'sprints.*')
331
+ * .action({ name: 'update', handler: updateTask });
332
+ * ```
333
+ *
334
+ * @see {@link StateSyncConfig} for centralized configuration
335
+ */
336
+ invalidates(...patterns) {
337
+ this._assertNotFrozen();
338
+ // Store under tool-level key '*' — applies to all actions
339
+ const existing = this._stateSyncHints.get('*');
340
+ this._stateSyncHints.set('*', {
341
+ ...existing,
342
+ invalidates: [...(existing?.invalidates ?? []), ...patterns],
343
+ });
344
+ return this;
345
+ }
346
+ /**
347
+ * Mark this tool's data as immutable (safe to cache forever).
348
+ *
349
+ * Use for reference data: countries, currencies, ICD-10 codes.
350
+ * Equivalent to `cacheControl: 'immutable'` in manual policies.
351
+ *
352
+ * @returns `this` for chaining
353
+ *
354
+ * @example
355
+ * ```typescript
356
+ * createTool('countries')
357
+ * .cached()
358
+ * .action({ name: 'list', readOnly: true, handler: listCountries });
359
+ * ```
360
+ */
361
+ cached() {
362
+ return this._setCacheDirective('immutable');
363
+ }
364
+ /**
365
+ * Mark this tool's data as volatile (never cache).
366
+ *
367
+ * Equivalent to `cacheControl: 'no-store'` in manual policies.
368
+ * Use for dynamic data that changes frequently.
369
+ *
370
+ * @returns `this` for chaining
371
+ */
372
+ stale() {
373
+ return this._setCacheDirective('no-store');
374
+ }
375
+ /** @internal */
376
+ _setCacheDirective(directive) {
377
+ this._assertNotFrozen();
378
+ const existing = this._stateSyncHints.get('*');
379
+ this._stateSyncHints.set('*', { ...existing, cacheControl: directive });
380
+ return this;
381
+ }
382
+ /**
383
+ * Enable `_select` reflection for context window optimization.
384
+ *
385
+ * When enabled, actions that use a Presenter with a Zod schema
386
+ * expose an optional `_select` parameter in the input schema.
387
+ * The AI can send `_select: ['status', 'amount']` to receive
388
+ * only the specified top-level fields in the data payload,
389
+ * reducing context window usage without developer effort.
390
+ *
391
+ * **Disabled by default** — opt-in to avoid changing existing
392
+ * tool schemas.
393
+ *
394
+ * **Late Guillotine**: UI blocks, system rules, and action
395
+ * suggestions are always computed with the **full** validated
396
+ * data. Only the wire-facing data block is filtered.
397
+ *
398
+ * **Shallow (top-level only)**: Nested objects are returned
399
+ * whole. If the AI selects `'user'`, it gets the entire `user`
400
+ * object. No recursive GraphQL-style traversal.
401
+ *
402
+ * @returns `this` for chaining
403
+ *
404
+ * @example
405
+ * ```typescript
406
+ * createTool<AppContext>('invoices')
407
+ * .enableSelect() // Expose _select in input schema
408
+ * .action({
409
+ * name: 'get',
410
+ * returns: InvoicePresenter,
411
+ * handler: async (ctx, args) => ctx.db.invoices.findUnique(args.id),
412
+ * });
413
+ * // AI sends: { action: 'get', id: '123', _select: ['status'] }
414
+ * // Returns: { status: 'paid' } instead of full invoice
415
+ * ```
416
+ *
417
+ * @see {@link Presenter.getSchemaKeys} for introspection
418
+ */
419
+ enableSelect() {
420
+ this._assertNotFrozen();
421
+ this._selectEnabled = true;
422
+ return this;
423
+ }
424
+ /**
425
+ * Set concurrency limits for this tool (Semaphore + Queue pattern).
426
+ *
427
+ * Prevents thundering-herd scenarios where the LLM fires N
428
+ * concurrent calls in the same millisecond. Implements a
429
+ * semaphore with backpressure queue and load shedding.
430
+ *
431
+ * When all active slots are occupied, new calls enter the queue.
432
+ * When the queue is full, calls are immediately rejected with
433
+ * a self-healing `SERVER_BUSY` error.
434
+ *
435
+ * **MCP Spec Compliance**: The MCP specification requires servers
436
+ * to rate-limit tool invocations. This method fulfills that requirement.
437
+ *
438
+ * **Zero overhead** when not configured — no semaphore exists.
439
+ *
440
+ * @param config - Concurrency configuration
441
+ * @returns `this` for chaining
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * createTool<AppContext>('billing')
446
+ * .concurrency({ maxActive: 5, maxQueue: 20 })
447
+ * .action({ name: 'process_invoice', handler: processInvoice });
448
+ * // 5 concurrent executions, 20 queued, rest rejected
449
+ * ```
450
+ *
451
+ * @see {@link ConcurrencyConfig} for configuration options
452
+ */
453
+ concurrency(config) {
454
+ this._assertNotFrozen();
455
+ this._concurrencyGuard = new ConcurrencyGuard(config);
456
+ return this;
457
+ }
458
+ /**
459
+ * Set maximum payload size for tool responses (Egress Guard).
460
+ *
461
+ * Prevents oversized responses from crashing the Node process
462
+ * with OOM or overflowing the LLM context window.
463
+ *
464
+ * When a response exceeds the limit, the text content is truncated
465
+ * and a system intervention message is injected, forcing the LLM
466
+ * to use pagination or filters.
467
+ *
468
+ * This is a **brute-force safety net**. For domain-aware truncation
469
+ * with guidance, use Presenter `.agentLimit()` instead.
470
+ *
471
+ * **Zero overhead** when not configured.
472
+ *
473
+ * @param bytes - Maximum payload size in bytes
474
+ * @returns `this` for chaining
475
+ *
476
+ * @example
477
+ * ```typescript
478
+ * createTool<AppContext>('logs')
479
+ * .maxPayloadBytes(2 * 1024 * 1024) // 2MB
480
+ * .action({ name: 'search', handler: searchLogs });
481
+ * ```
482
+ *
483
+ * @see {@link Presenter.agentLimit} for domain-level truncation
484
+ */
485
+ maxPayloadBytes(bytes) {
486
+ this._assertNotFrozen();
487
+ this._egressMaxBytes = Math.max(1024, Math.floor(bytes));
488
+ return this;
489
+ }
490
+ /**
491
+ * Enable zero-trust sandboxed execution for this tool.
492
+ *
493
+ * Stores the sandbox configuration so that tools built with
494
+ * `.sandboxed()` on the FluentToolBuilder can propagate it.
495
+ *
496
+ * @param config - Sandbox configuration (timeout, memory, output size)
497
+ * @returns `this` for chaining
498
+ *
499
+ * @example
500
+ * ```typescript
501
+ * createTool<AppContext>('analytics')
502
+ * .sandbox({ timeout: 5000, memoryLimit: 128 })
503
+ * .action({ name: 'compute', handler: computeHandler });
504
+ * ```
505
+ *
506
+ * @see {@link SandboxConfig} for configuration options
507
+ * @see {@link SandboxEngine} for the execution engine
508
+ */
509
+ sandbox(config) {
510
+ this._assertNotFrozen();
511
+ this._sandboxConfig = config;
512
+ return this;
513
+ }
514
+ /**
515
+ * Get the sandbox configuration (if any).
516
+ *
517
+ * **Important**: This is metadata only — it does NOT auto-create a
518
+ * `SandboxEngine` nor inject it into the execution pipeline.
519
+ * The developer must create the engine manually (e.g. via `f.sandbox()`).
520
+ * This accessor exists for introspection, testing, and contract tooling.
521
+ *
522
+ * @returns The stored `SandboxConfig`, or `undefined` if `.sandbox()` was not called
523
+ */
524
+ getSandboxConfig() {
525
+ return this._sandboxConfig;
526
+ }
527
+ // ── FSM State Gate (Temporal Anti-Hallucination) ─────
528
+ /**
529
+ * Bind this tool to specific FSM states.
530
+ *
531
+ * When a `StateMachineGate` is configured, this tool is only
532
+ * visible in `tools/list` when the FSM is in one of the specified states.
533
+ *
534
+ * @param states - FSM state(s) where this tool is visible
535
+ * @param transition - Event to send on successful execution
536
+ * @returns `this` for chaining
537
+ */
538
+ bindState(states, transition) {
539
+ this._assertNotFrozen();
540
+ this._fsmStates = states;
541
+ if (transition !== undefined)
542
+ this._fsmTransition = transition;
543
+ return this;
544
+ }
545
+ /**
546
+ * Get the FSM binding metadata (if any).
547
+ * Used by `ToolRegistry` and `ServerAttachment` for FSM gating.
548
+ */
549
+ getFsmBinding() {
550
+ if (!this._fsmStates)
551
+ return undefined;
552
+ const binding = {
553
+ states: this._fsmStates,
554
+ };
555
+ if (this._fsmTransition)
556
+ binding.transition = this._fsmTransition;
557
+ return binding;
558
+ }
559
+ /**
560
+ * Get the tool name.
561
+ * Used by framework internals for tool routing and FSM binding.
562
+ */
563
+ getToolName() {
564
+ return this._name;
565
+ }
566
+ /**
567
+ * Add middleware to the execution chain.
568
+ *
569
+ * Middleware runs in **registration order** (first registered = outermost).
570
+ * Chains are pre-compiled at build time — zero runtime assembly cost.
571
+ *
572
+ * Accepts both `MiddlewareDefinition` from `f.middleware()` and
573
+ * raw `MiddlewareFn` functions.
574
+ *
575
+ * @param mw - Middleware function or MiddlewareDefinition
576
+ * @returns `this` for chaining
577
+ *
578
+ * @example
579
+ * ```typescript
580
+ * const requireAuth: MiddlewareFn<AppContext> = async (ctx, args, next) => {
581
+ * if (!ctx.user) return error('Unauthorized');
582
+ * return next();
583
+ * };
584
+ *
585
+ * createTool<AppContext>('projects')
586
+ * .use(requireAuth) // Runs on every action
587
+ * .action({ name: 'list', handler: listProjects });
588
+ * ```
589
+ *
590
+ * @see {@link MiddlewareFn} for the middleware signature
591
+ * @see {@link ActionGroupBuilder.use} for group-scoped middleware
592
+ */
593
+ use(mw) {
594
+ this._assertNotFrozen();
595
+ this._middlewares.push(resolveMiddleware(mw));
596
+ return this;
597
+ }
598
+ action(config) {
599
+ this._assertNotFrozen();
600
+ if (this._hasGroup) {
601
+ throw new Error(`Cannot use .action() and .group() on the same builder "${this._name}". ` +
602
+ `Use .action() for flat tools OR .group() for hierarchical tools.`);
603
+ }
604
+ this._hasFlat = true;
605
+ // Bug #115 fix: reject empty or whitespace-only action names.
606
+ if (!config.name || !config.name.trim()) {
607
+ throw new Error(`Action name must be a non-empty string on builder "${this._name}". ` +
608
+ `Received: ${JSON.stringify(config.name)}.`);
609
+ }
610
+ if (config.name.includes('.')) {
611
+ throw new Error(`Action name "${config.name}" must not contain dots. ` +
612
+ `The framework uses dots internally for group.action compound keys.`);
613
+ }
614
+ // Bug #112 fix: reject duplicate action names instead of silently
615
+ // registering two actions with the same discriminator key.
616
+ if (this._actions.some(a => a.key === config.name)) {
617
+ throw new Error(`Duplicate action name "${config.name}" on builder "${this._name}". ` +
618
+ `Each action must have a unique name within its tool.`);
619
+ }
620
+ this._actions.push({
621
+ key: config.name,
622
+ groupName: undefined,
623
+ groupDescription: undefined,
624
+ ...mapConfigToActionFields(config, (config.omitCommon?.length ?? 0) > 0 ? config.omitCommon : undefined),
625
+ middlewares: undefined,
626
+ });
627
+ return this;
628
+ }
629
+ group(name, descriptionOrConfigure, maybeConfigure) {
630
+ this._assertNotFrozen();
631
+ const description = typeof descriptionOrConfigure === 'string'
632
+ ? descriptionOrConfigure
633
+ : undefined;
634
+ const configure = typeof descriptionOrConfigure === 'function'
635
+ ? descriptionOrConfigure
636
+ : maybeConfigure;
637
+ if (!configure) {
638
+ throw new Error(`Group "${name}" requires a configure callback.`);
639
+ }
640
+ if (this._hasFlat) {
641
+ throw new Error(`Cannot use .group() and .action() on the same builder "${this._name}". ` +
642
+ `Use .action() for flat tools OR .group() for hierarchical tools.`);
643
+ }
644
+ if (name.includes('.')) {
645
+ throw new Error(`Group name "${name}" must not contain dots.`);
646
+ }
647
+ this._hasGroup = true;
648
+ const groupBuilder = new ActionGroupBuilder(name, description);
649
+ configure(groupBuilder);
650
+ this._actions.push(...groupBuilder._actions);
651
+ return this;
652
+ }
653
+ // ── Build (delegates to ToolDefinitionCompiler) ─────
654
+ /**
655
+ * Generate the MCP Tool definition.
656
+ *
657
+ * Compiles all actions into a single MCP tool with auto-generated
658
+ * description, union schema, and aggregated annotations. Caches
659
+ * the result and permanently freezes the builder.
660
+ *
661
+ * Called automatically by {@link execute} if not called explicitly.
662
+ *
663
+ * @returns The compiled MCP Tool object
664
+ * @throws If no actions are registered
665
+ *
666
+ * @example
667
+ * ```typescript
668
+ * const tool = builder.buildToolDefinition();
669
+ * console.log(tool.name); // "projects"
670
+ * console.log(tool.description); // Auto-generated
671
+ * console.log(tool.inputSchema); // Union of all action schemas
672
+ * ```
673
+ */
674
+ buildToolDefinition() {
675
+ if (this._cachedTool)
676
+ return this._cachedTool;
677
+ const result = compileToolDefinition({
678
+ name: this._name,
679
+ description: this._description,
680
+ discriminator: this._discriminator,
681
+ toonMode: this._toonMode,
682
+ selectEnabled: this._selectEnabled,
683
+ hasGroup: this._hasGroup,
684
+ actions: this._actions,
685
+ middlewares: this._middlewares,
686
+ commonSchema: this._commonSchema,
687
+ annotations: this._annotations,
688
+ });
689
+ this._cachedTool = result.tool;
690
+ this._executionContext = result.executionContext;
691
+ this._frozen = true;
692
+ Object.freeze(this._actions);
693
+ // Auto-create MutationSerializer if any action is destructive.
694
+ // Converts `destructive: true` from a manifest hint into a
695
+ // transactional isolation guarantee — concurrent mutations to
696
+ // the same action key are serialized in FIFO order.
697
+ if (this._actions.some(a => a.destructive === true)) {
698
+ this._mutationSerializer = new MutationSerializer();
699
+ }
700
+ return result.tool;
701
+ }
702
+ // ── Debug (opt-in observability) ──────────────────────
703
+ /**
704
+ * Enable debug observability for this tool.
705
+ *
706
+ * When enabled, structured {@link DebugEvent} events are emitted at
707
+ * each step of the execution pipeline.
708
+ *
709
+ * When disabled (the default), there is **zero runtime overhead** —
710
+ * no conditionals, no timing, no object allocations in the hot path.
711
+ *
712
+ * @param observer - A {@link DebugObserverFn} created by `createDebugObserver()`
713
+ * @returns `this` for chaining
714
+ *
715
+ * @example
716
+ * ```typescript
717
+ * import { createTool, createDebugObserver, success } from 'vurb';
718
+ *
719
+ * const debug = createDebugObserver();
720
+ *
721
+ * const tool = createTool<void>('users')
722
+ * .debug(debug) // ← enable observability
723
+ * .action({ name: 'list', handler: async () => success([]) });
724
+ * ```
725
+ */
726
+ debug(observer) {
727
+ // No frozen check — debug is safe to attach after build
728
+ this._debug = observer;
729
+ return this;
730
+ }
731
+ /**
732
+ * Enable out-of-band telemetry emission for Inspector TUI.
733
+ *
734
+ * When set, `validate`, `middleware`, `presenter.slice`, and
735
+ * `presenter.rules` events are emitted to the TelemetrySink
736
+ * (Shadow Socket IPC), enabling real-time monitoring in the
737
+ * Inspector dashboard.
738
+ *
739
+ * **Zero overhead** when not configured — no conditionals in
740
+ * the hot path.
741
+ *
742
+ * @param sink - A {@link TelemetrySink} from `startServer()` or `TelemetryBus`
743
+ * @returns `this` for chaining
744
+ */
745
+ telemetry(sink) {
746
+ this._telemetry = sink;
747
+ return this;
748
+ }
749
+ /**
750
+ * Enable OpenTelemetry-compatible tracing for this tool.
751
+ *
752
+ * When enabled, each `execute()` call creates a single span with
753
+ * structured events for each pipeline step (`mcp.route`, `mcp.validate`,
754
+ * `mcp.middleware`, `mcp.execute`).
755
+ *
756
+ * **Zero overhead** when disabled — the fast path has no conditionals.
757
+ *
758
+ * **OTel direct pass-through**: The `VurbTracer` interface is a
759
+ * structural subtype of OTel's `Tracer`, so you can pass an OTel
760
+ * tracer directly without any adapter:
761
+ *
762
+ * ```typescript
763
+ * import { trace } from '@opentelemetry/api';
764
+ *
765
+ * const tool = createTool<AppContext>('projects')
766
+ * .tracing(trace.getTracer('vurb'))
767
+ * .action({ name: 'list', handler: listProjects });
768
+ * ```
769
+ *
770
+ * **Error classification**:
771
+ * - Validation failures → `SpanStatusCode.UNSET` + `mcp.error_type` attribute
772
+ * - Handler exceptions → `SpanStatusCode.ERROR` + `recordException()`
773
+ *
774
+ * **Context propagation limitation**: Since Vurb does not depend
775
+ * on `@opentelemetry/api`, it cannot call `context.with(trace.setSpan(...))`.
776
+ * Auto-instrumented downstream calls (Prisma, HTTP, Redis) inside handlers
777
+ * will appear as siblings, not children, of the MCP span.
778
+ *
779
+ * @param tracer - A {@link VurbTracer} (or OTel `Tracer`) instance
780
+ * @returns `this` for chaining
781
+ *
782
+ * @see {@link VurbTracer} for the interface contract
783
+ * @see {@link SpanStatusCode} for status code semantics
784
+ */
785
+ tracing(tracer) {
786
+ // No frozen check — tracing is safe to attach after build (like debug)
787
+ this._tracer = tracer;
788
+ return this;
789
+ }
790
+ // ── Execute (delegates to ExecutionPipeline) ────────
791
+ /**
792
+ * Route a tool call to the correct action handler.
793
+ *
794
+ * Pipeline: `parseDiscriminator → resolveAction → validateArgs → runChain`
795
+ *
796
+ * Auto-calls {@link buildToolDefinition} if not called yet.
797
+ * If a debug observer is active, structured events are emitted
798
+ * at each pipeline step with timing information.
799
+ *
800
+ * @param ctx - Application context
801
+ * @param args - Raw arguments from the LLM (includes discriminator)
802
+ * @param progressSink - Optional callback for streaming progress notifications.
803
+ * When attached via `attachToServer()`, this is automatically wired to
804
+ * MCP `notifications/progress`. When omitted, progress events are silently consumed.
805
+ * @param signal - Optional AbortSignal from the MCP SDK protocol layer.
806
+ * Fired when the client sends `notifications/cancelled` or the connection drops.
807
+ * The framework checks this signal before handler execution and during
808
+ * generator iteration, aborting zombie operations immediately.
809
+ * @returns The handler's {@link ToolResponse}
810
+ *
811
+ * @example
812
+ * ```typescript
813
+ * // Direct execution (useful in tests)
814
+ * const result = await builder.execute(ctx, {
815
+ * action: 'list',
816
+ * workspace_id: 'ws_123',
817
+ * });
818
+ * ```
819
+ */
820
+ async execute(ctx, args, progressSink, signal) {
821
+ if (!this._executionContext) {
822
+ this.buildToolDefinition();
823
+ }
824
+ const execCtx = this._executionContext;
825
+ if (!execCtx) {
826
+ return error(`Builder "${this._name}" failed to initialize.`);
827
+ }
828
+ // ── Concurrency Gate (Semaphore + Queue) ──────────────────
829
+ // Acquire a slot BEFORE entering the pipeline.
830
+ // If acquire() returns null, load shedding kicks in.
831
+ let release;
832
+ if (this._concurrencyGuard) {
833
+ const result = this._concurrencyGuard.acquire(signal);
834
+ if (result === null) {
835
+ // Load shedding: all slots occupied + queue full
836
+ return toolError('SERVER_BUSY', {
837
+ message: `Tool "${this._name}" is at capacity (${this._concurrencyGuard.active} active, ${this._concurrencyGuard.queued} queued). Retry after a short delay.`,
838
+ suggestion: 'Reduce the number of concurrent calls to this tool. Send requests sequentially or in smaller batches.',
839
+ });
840
+ }
841
+ try {
842
+ release = await result;
843
+ }
844
+ catch {
845
+ // Waiter was cancelled while queued (AbortSignal)
846
+ return error(`[${this._name}] Request cancelled while waiting for execution slot.`);
847
+ }
848
+ }
849
+ try {
850
+ const response = await this._executeWithObservability(execCtx, ctx, args, progressSink, signal);
851
+ // ── Egress Guard (Payload Size Limiter) ──────
852
+ if (this._egressMaxBytes) {
853
+ return applyEgressGuard(response, this._egressMaxBytes);
854
+ }
855
+ return response;
856
+ }
857
+ finally {
858
+ release?.();
859
+ }
860
+ }
861
+ /**
862
+ * Internal: execute with the appropriate observability path.
863
+ * Extracted to keep the concurrency/egress guards clean.
864
+ */
865
+ async _executeWithObservability(execCtx, ctx, args, progressSink, signal) {
866
+ // Build telemetry hooks if sink is configured
867
+ const telemetryHooks = this._telemetry ? this._buildTelemetryHooks() : undefined;
868
+ // Traced path: wrap in try/catch for system error → graceful response
869
+ if (this._tracer) {
870
+ const hooks = mergeHooks(this._buildTracedHooks(), telemetryHooks);
871
+ try {
872
+ return await this._executePipeline(execCtx, ctx, args, progressSink, hooks, signal);
873
+ }
874
+ catch (err) {
875
+ // System failure caught here — hooks already recorded it on the span
876
+ const message = err instanceof Error ? err.message : String(err);
877
+ const response = error(`[${this._name}] ${message}`);
878
+ hooks.wrapResponse(response); // finalize span
879
+ return response;
880
+ }
881
+ }
882
+ // Debug path: hooks with event emission
883
+ if (this._debug) {
884
+ return this._executePipeline(execCtx, ctx, args, progressSink, mergeHooks(this._buildDebugHooks(), telemetryHooks), signal);
885
+ }
886
+ // Telemetry-only path: emit events without debug logs
887
+ if (telemetryHooks) {
888
+ return this._executePipeline(execCtx, ctx, args, progressSink, telemetryHooks, signal);
889
+ }
890
+ // Fast path: zero overhead (no hooks)
891
+ return this._executePipeline(execCtx, ctx, args, progressSink, undefined, signal);
892
+ }
893
+ // ── Execution Paths (private) ────────────────────────
894
+ /**
895
+ * Pipeline hooks for observability instrumentation.
896
+ *
897
+ * Each hook is called at the corresponding pipeline step.
898
+ * The fast path passes `undefined` (zero overhead).
899
+ * Debug and traced paths supply their hooks via factory methods.
900
+ */
901
+ async _executePipeline(execCtx, ctx, args, progressSink, hooks, signal) {
902
+ // Step 1: Route
903
+ const disc = parseDiscriminator(execCtx, args);
904
+ if (!disc.ok) {
905
+ hooks?.onRouteError?.();
906
+ return hooks?.wrapResponse?.(disc.response) ?? disc.response;
907
+ }
908
+ const actionName = disc.value;
909
+ hooks?.onRouteOk?.(actionName);
910
+ // Step 2: Resolve
911
+ const resolved = resolveAction(execCtx, actionName);
912
+ if (!resolved.ok) {
913
+ hooks?.onResolveError?.(actionName);
914
+ return hooks?.wrapResponse?.(resolved.response) ?? resolved.response;
915
+ }
916
+ // Step 3: Validate
917
+ const validateStart = performance.now();
918
+ const validationResult = validateArgs(execCtx, resolved.value, args);
919
+ const validateMs = performance.now() - validateStart;
920
+ if (!validationResult.ok) {
921
+ hooks?.onValidateError?.(actionName, validateMs);
922
+ return hooks?.wrapResponse?.(validationResult.response) ?? validationResult.response;
923
+ }
924
+ hooks?.onValidateOk?.(actionName, validateMs);
925
+ const { validated, selectFields } = validationResult.value;
926
+ // Step 4: Middleware info
927
+ const actionMwCount = resolved.value.action.middlewares?.length ?? 0;
928
+ const globalMwCount = this._middlewares.length;
929
+ const chainLength = globalMwCount + actionMwCount;
930
+ if (chainLength > 0) {
931
+ hooks?.onMiddleware?.(actionName, chainLength);
932
+ }
933
+ // Step 5: Execute
934
+ // If the action is destructive and a MutationSerializer exists,
935
+ // wrap the execution in a per-key mutex to prevent concurrent
936
+ // mutations (LLM hallucination anti-race-condition guard).
937
+ //
938
+ // _select is forwarded only when enableSelect() was called.
939
+ const effectiveSelect = this._selectEnabled ? selectFields : undefined;
940
+ const ppTelemetry = this._telemetry
941
+ ? { sink: this._telemetry, tool: execCtx.toolName, action: actionName }
942
+ : undefined;
943
+ const executeChain = () => runChain(execCtx, resolved.value, ctx, validated, progressSink, hooks?.rethrow, signal, effectiveSelect, ppTelemetry);
944
+ try {
945
+ const isDestructive = resolved.value.action.destructive === true;
946
+ const response = (isDestructive && this._mutationSerializer)
947
+ ? await this._mutationSerializer.serialize(actionName, executeChain, signal)
948
+ : await executeChain();
949
+ hooks?.onExecuteOk?.(actionName, response);
950
+ return hooks?.wrapResponse?.(response) ?? response;
951
+ }
952
+ catch (err) {
953
+ hooks?.onExecuteError?.(actionName, err);
954
+ if (hooks?.rethrow)
955
+ throw err;
956
+ // Convert MutationSerializer abort (or unexpected throws) to error response
957
+ const message = err instanceof Error ? err.message : String(err);
958
+ const response = error(`[${execCtx.toolName}/${actionName}] ${message}`);
959
+ return hooks?.wrapResponse?.(response) ?? response;
960
+ }
961
+ }
962
+ /**
963
+ * Build debug hooks: lightweight event emission.
964
+ */
965
+ _buildDebugHooks() {
966
+ const debug = this._debug;
967
+ const toolName = this._name;
968
+ const startTime = performance.now();
969
+ return {
970
+ onRouteError: () => {
971
+ debug({ type: 'error', tool: toolName, action: '?', error: 'Missing discriminator', step: 'route', timestamp: Date.now() });
972
+ },
973
+ onRouteOk: (action) => {
974
+ debug({ type: 'route', tool: toolName, action, timestamp: Date.now() });
975
+ },
976
+ onResolveError: (action) => {
977
+ debug({ type: 'error', tool: toolName, action, error: `Unknown action "${action}"`, step: 'route', timestamp: Date.now() });
978
+ },
979
+ onValidateError: (action, durationMs) => {
980
+ debug({ type: 'validate', tool: toolName, action, valid: false, error: 'Validation failed', durationMs, timestamp: Date.now() });
981
+ },
982
+ onValidateOk: (action, durationMs) => {
983
+ debug({ type: 'validate', tool: toolName, action, valid: true, durationMs, timestamp: Date.now() });
984
+ },
985
+ onMiddleware: (action, chainLength) => {
986
+ debug({ type: 'middleware', tool: toolName, action, chainLength, timestamp: Date.now() });
987
+ },
988
+ onExecuteOk: (action, response) => {
989
+ const isErr = response.isError === true;
990
+ debug({ type: 'execute', tool: toolName, action, durationMs: performance.now() - startTime, isError: isErr, timestamp: Date.now() });
991
+ },
992
+ onExecuteError: (action, err) => {
993
+ const message = err instanceof Error ? err.message : String(err);
994
+ debug({ type: 'error', tool: toolName, action, error: message, step: 'execute', timestamp: Date.now() });
995
+ },
996
+ };
997
+ }
998
+ /**
999
+ * Build traced hooks: OpenTelemetry-compatible span creation.
1000
+ *
1001
+ * Creates ONE span per tool call with events for pipeline steps.
1002
+ * Uses wrapResponse for leak-proof span closure.
1003
+ * AI errors → UNSET, system errors → ERROR.
1004
+ */
1005
+ _buildTracedHooks() {
1006
+ const tracer = this._tracer;
1007
+ const startAttrs = {
1008
+ 'mcp.system': 'vurb',
1009
+ 'mcp.tool': this._name,
1010
+ };
1011
+ if (this._tags.length > 0)
1012
+ startAttrs['mcp.tags'] = this._tags;
1013
+ if (this._description)
1014
+ startAttrs['mcp.description'] = this._description;
1015
+ const span = tracer.startSpan(`mcp.tool.${this._name}`, { attributes: startAttrs });
1016
+ const startTime = performance.now();
1017
+ let statusCode = SpanStatusCode.UNSET;
1018
+ let statusMessage;
1019
+ const finalizeSpan = (response) => {
1020
+ span.setAttribute('mcp.durationMs', performance.now() - startTime);
1021
+ if (response) {
1022
+ span.setAttribute('mcp.response_size', computeResponseSize(response));
1023
+ }
1024
+ span.setStatus(statusMessage !== undefined
1025
+ ? { code: statusCode, message: statusMessage }
1026
+ : { code: statusCode });
1027
+ span.end();
1028
+ };
1029
+ return {
1030
+ rethrow: true,
1031
+ onRouteError: () => {
1032
+ span.setAttribute('mcp.error_type', 'missing_discriminator');
1033
+ span.setAttribute('mcp.isError', true);
1034
+ },
1035
+ onRouteOk: (action) => {
1036
+ span.setAttribute('mcp.action', action);
1037
+ span.addEvent?.('mcp.route');
1038
+ },
1039
+ onResolveError: () => {
1040
+ span.setAttribute('mcp.error_type', 'unknown_action');
1041
+ span.setAttribute('mcp.isError', true);
1042
+ },
1043
+ onValidateError: (_action, durationMs) => {
1044
+ span.setAttribute('mcp.error_type', 'validation_failed');
1045
+ span.setAttribute('mcp.isError', true);
1046
+ span.addEvent?.('mcp.validate', { 'mcp.valid': false, 'mcp.durationMs': durationMs });
1047
+ },
1048
+ onValidateOk: (_action, durationMs) => {
1049
+ span.addEvent?.('mcp.validate', { 'mcp.valid': true, 'mcp.durationMs': durationMs });
1050
+ },
1051
+ onMiddleware: (_action, chainLength) => {
1052
+ span.addEvent?.('mcp.middleware', { 'mcp.chainLength': chainLength });
1053
+ },
1054
+ onExecuteOk: (_action, response) => {
1055
+ const isErr = response.isError === true;
1056
+ statusCode = isErr ? SpanStatusCode.UNSET : SpanStatusCode.OK;
1057
+ if (isErr)
1058
+ span.setAttribute('mcp.error_type', 'handler_returned_error');
1059
+ span.setAttribute('mcp.isError', isErr);
1060
+ },
1061
+ onExecuteError: (_action, err) => {
1062
+ const message = err instanceof Error ? err.message : String(err);
1063
+ span.recordException(err instanceof Error ? err : message);
1064
+ span.setAttribute('mcp.error_type', 'system_error');
1065
+ span.setAttribute('mcp.isError', true);
1066
+ statusCode = SpanStatusCode.ERROR;
1067
+ statusMessage = message;
1068
+ },
1069
+ wrapResponse: (response) => {
1070
+ finalizeSpan(response);
1071
+ return response;
1072
+ },
1073
+ };
1074
+ }
1075
+ /**
1076
+ * Build telemetry hooks: Shadow Socket event emission for Inspector TUI.
1077
+ *
1078
+ * Emits `validate`, `middleware`, and `execute` TelemetryEvents
1079
+ * to the IPC sink so that `vurb inspect` shows real pipeline data.
1080
+ */
1081
+ _buildTelemetryHooks() {
1082
+ const emit = this._telemetry;
1083
+ const toolName = this._name;
1084
+ const startTime = performance.now();
1085
+ return {
1086
+ onValidateError: (action, durationMs) => {
1087
+ emit({ type: 'validate', tool: toolName, action, valid: false, error: 'Validation failed', durationMs, timestamp: Date.now() });
1088
+ },
1089
+ onValidateOk: (action, durationMs) => {
1090
+ emit({ type: 'validate', tool: toolName, action, valid: true, durationMs, timestamp: Date.now() });
1091
+ },
1092
+ onMiddleware: (action, chainLength) => {
1093
+ emit({ type: 'middleware', tool: toolName, action, chainLength, timestamp: Date.now() });
1094
+ },
1095
+ onExecuteOk: (action, response) => {
1096
+ const isErr = response.isError === true;
1097
+ // Extract recovery data from error responses
1098
+ let recovery;
1099
+ let recoveryActions;
1100
+ if (isErr && response.content.length > 0) {
1101
+ const text = response.content[0].text;
1102
+ recovery = extractXmlTag(text, 'recovery');
1103
+ recoveryActions = extractXmlActions(text);
1104
+ }
1105
+ emit({
1106
+ type: 'execute', tool: toolName, action,
1107
+ durationMs: performance.now() - startTime,
1108
+ isError: isErr,
1109
+ ...(recovery ? { recovery } : {}),
1110
+ ...(recoveryActions && recoveryActions.length > 0 ? { recoveryActions } : {}),
1111
+ timestamp: Date.now(),
1112
+ });
1113
+ },
1114
+ onExecuteError: (action, err) => {
1115
+ const message = err instanceof Error ? err.message : String(err);
1116
+ emit({ type: 'error', tool: toolName, action, error: message, step: 'execute', timestamp: Date.now() });
1117
+ },
1118
+ };
1119
+ }
1120
+ // ── Introspection ───────────────────────────────────
1121
+ /** Get the tool name. */
1122
+ getName() { return this._name; }
1123
+ /** Get a copy of the capability tags. */
1124
+ getTags() { return [...this._tags]; }
1125
+ /** Get all registered action keys (e.g. `["list", "create"]` or `["users.list", "users.ban"]`). */
1126
+ getActionNames() { return this._actions.map(a => a.key); }
1127
+ // ── AST Reflection (Exposition Compiler) ─────────────
1128
+ /** Get the discriminator field name (e.g. `"action"`). Used by the Exposition Compiler. */
1129
+ getDiscriminator() { return this._discriminator; }
1130
+ /**
1131
+ * Get all registered internal actions.
1132
+ * Used by the Exposition Compiler for atomic tool expansion.
1133
+ * @returns Read-only array of internal action definitions
1134
+ */
1135
+ getActions() { return this._actions; }
1136
+ /**
1137
+ * Get the common schema shared across all actions.
1138
+ * Used by the Exposition Compiler for schema purification.
1139
+ * @returns The common Zod schema, or undefined if not set
1140
+ */
1141
+ getCommonSchema() { return this._commonSchema; }
1142
+ /** Check if `_select` reflection is enabled. Used by the Exposition Compiler. */
1143
+ getSelectEnabled() { return this._selectEnabled; }
1144
+ /** Get per-action state sync hints for auto-policy generation. */
1145
+ getStateSyncHints() { return this._stateSyncHints; }
1146
+ /**
1147
+ * Preview the exact MCP protocol payload that the LLM will receive.
1148
+ *
1149
+ * Builds the tool definition if not already built, then renders
1150
+ * a human-readable preview of the complete tool including:
1151
+ * - Tool name and description
1152
+ * - Input schema (JSON)
1153
+ * - Annotations (if any)
1154
+ * - Approximate token count (~4 chars per token, GPT-5.2 heuristic)
1155
+ *
1156
+ * Call this from your dev environment to optimize token usage
1157
+ * and verify the LLM-facing prompt without starting an MCP server.
1158
+ *
1159
+ * @returns Formatted string showing the exact MCP payload + token estimate
1160
+ *
1161
+ * @example
1162
+ * ```typescript
1163
+ * const projects = defineTool<AppContext>('projects', { ... });
1164
+ * console.log(projects.previewPrompt());
1165
+ *
1166
+ * // Output:
1167
+ * // ┌─────────────────────────────────────────┐
1168
+ * // │ MCP Tool Preview: projects │
1169
+ * // ├─────────────────────────────────────────┤
1170
+ * // │ Name: projects │
1171
+ * // │ Actions: 3 (list, create, delete) │
1172
+ * // │ Tags: api, admin │
1173
+ * // ├─── Description ─────────────────────────┤
1174
+ * // │ Manage workspace projects. ... │
1175
+ * // ├─── Input Schema ────────────────────────┤
1176
+ * // │ { "type": "object", ... } │
1177
+ * // ├─── Annotations ─────────────────────────┤
1178
+ * // │ readOnlyHint: false │
1179
+ * // │ destructiveHint: true │
1180
+ * // ├─── Token Estimate ──────────────────────┤
1181
+ * // │ ~342 tokens (1,368 chars) │
1182
+ * // └─────────────────────────────────────────┘
1183
+ * ```
1184
+ *
1185
+ * @see {@link buildToolDefinition} for the raw MCP Tool object
1186
+ */
1187
+ previewPrompt() {
1188
+ const tool = this.buildToolDefinition();
1189
+ const schemaJson = JSON.stringify(tool.inputSchema, null, 2);
1190
+ const annotations = tool.annotations;
1191
+ const annotationsJson = annotations
1192
+ ? JSON.stringify(annotations, null, 2)
1193
+ : undefined;
1194
+ // Calculate total char payload (what the MCP protocol transmits)
1195
+ const payloadParts = [
1196
+ tool.name,
1197
+ tool.description ?? '',
1198
+ schemaJson,
1199
+ annotationsJson ?? '',
1200
+ ];
1201
+ const totalChars = payloadParts.reduce((sum, part) => sum + part.length, 0);
1202
+ // GPT-5.2 heuristic: ~4 characters per token for English/code
1203
+ const estimatedTokens = Math.ceil(totalChars / 4);
1204
+ const W = 56;
1205
+ const divider = '─'.repeat(W);
1206
+ const line = (label, value) => `│ ${label}: ${value}`;
1207
+ const actionKeys = this._actions.map(a => a.key);
1208
+ const lines = [
1209
+ `┌${'─'.repeat(W)}┐`,
1210
+ `│ MCP Tool Preview: ${this._name}`,
1211
+ `├─── Summary ${'─'.repeat(W - 12)}┤`,
1212
+ line('Name', tool.name),
1213
+ line('Actions', `${actionKeys.length} (${actionKeys.join(', ')})`),
1214
+ ];
1215
+ if (this._tags.length > 0) {
1216
+ lines.push(line('Tags', this._tags.join(', ')));
1217
+ }
1218
+ lines.push(`├─── Description ${divider.slice(17)}┤`, `│ ${tool.description ?? '(none)'}`.split('\n').join('\n│ '), `├─── Input Schema ${divider.slice(18)}┤`, schemaJson.split('\n').map(l => `│ ${l}`).join('\n'));
1219
+ if (annotationsJson) {
1220
+ lines.push(`├─── Annotations ${divider.slice(17)}┤`, annotationsJson.split('\n').map(l => `│ ${l}`).join('\n'));
1221
+ }
1222
+ lines.push(`├─── Token Estimate ${divider.slice(20)}┤`, `│ ~${estimatedTokens} tokens (${totalChars.toLocaleString()} chars)`, `└${divider}┘`);
1223
+ return lines.join('\n');
1224
+ }
1225
+ /**
1226
+ * Get metadata for all registered actions.
1227
+ *
1228
+ * Useful for programmatic documentation, compliance audits,
1229
+ * dashboard generation, or runtime observability.
1230
+ *
1231
+ * @returns Array of {@link ActionMetadata} objects
1232
+ *
1233
+ * @example
1234
+ * ```typescript
1235
+ * const meta = builder.getActionMetadata();
1236
+ * for (const action of meta) {
1237
+ * console.log(`${action.key}: destructive=${action.destructive}, fields=${action.requiredFields}`);
1238
+ * }
1239
+ * ```
1240
+ *
1241
+ * @see {@link ActionMetadata} for the metadata shape
1242
+ */
1243
+ getActionMetadata() {
1244
+ return this._actions.map(a => {
1245
+ const presenter = a.returns;
1246
+ return {
1247
+ key: a.key,
1248
+ actionName: a.actionName,
1249
+ groupName: a.groupName,
1250
+ description: a.description,
1251
+ destructive: a.destructive ?? false,
1252
+ idempotent: a.idempotent ?? false,
1253
+ readOnly: a.readOnly ?? false,
1254
+ requiredFields: getActionRequiredFields(a),
1255
+ hasMiddleware: (a.middlewares?.length ?? 0) > 0,
1256
+ // Presenter metadata (introspection)
1257
+ presenterName: presenter?.name,
1258
+ presenterSchemaKeys: presenter?.getSchemaKeys(),
1259
+ presenterUiBlockTypes: presenter?.getUiBlockTypes(),
1260
+ presenterHasContextualRules: presenter?.hasContextualRules(),
1261
+ presenterStaticRules: presenter?.getStaticRuleStrings(),
1262
+ };
1263
+ });
1264
+ }
1265
+ // ── Private ─────────────────────────────────────────
1266
+ _assertNotFrozen() {
1267
+ if (this._frozen) {
1268
+ throw new Error(`Builder "${this._name}" is frozen after buildToolDefinition(). ` +
1269
+ `Cannot modify a built tool.`);
1270
+ }
1271
+ }
1272
+ }
1273
+ // ── XML Extraction Helpers (Telemetry) ───────────────────
1274
+ /**
1275
+ * Extract content from a simple XML tag.
1276
+ * @example extractXmlTag('<recovery>Fix X</recovery>', 'recovery') → 'Fix X'
1277
+ * @internal
1278
+ */
1279
+ function extractXmlTag(text, tag) {
1280
+ const re = new RegExp(`<${tag}>(.*?)</${tag}>`, 's');
1281
+ const m = re.exec(text);
1282
+ return m?.[1]?.trim() || undefined;
1283
+ }
1284
+ /**
1285
+ * Extract `<action>` elements from `<available_actions>` block.
1286
+ * @internal
1287
+ */
1288
+ function extractXmlActions(text) {
1289
+ const block = extractXmlTag(text, 'available_actions');
1290
+ if (!block)
1291
+ return undefined;
1292
+ const actions = [];
1293
+ const re = /<action>(.*?)<\/action>/gs;
1294
+ let m;
1295
+ while ((m = re.exec(block)) !== null) {
1296
+ const v = m[1]?.trim();
1297
+ if (v)
1298
+ actions.push(v);
1299
+ }
1300
+ // If no individual <action> tags, the content might be a comma/space list
1301
+ if (actions.length === 0 && block.trim().length > 0) {
1302
+ actions.push(...block.split(/[,\s]+/).filter(Boolean));
1303
+ }
1304
+ return actions.length > 0 ? actions : undefined;
1305
+ }
1306
+ //# sourceMappingURL=GroupedToolBuilder.js.map