@easynet/agent-tool 1.0.0 → 1.0.2

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 (309) hide show
  1. package/README.md +90 -73
  2. package/dist/api/adapters/LangChainToolsHub.d.ts +34 -0
  3. package/dist/api/adapters/LangChainToolsHub.d.ts.map +1 -0
  4. package/dist/api/createAgentTools.d.ts +24 -0
  5. package/dist/api/createAgentTools.d.ts.map +1 -0
  6. package/dist/api/expose/index.d.ts +16 -0
  7. package/dist/api/expose/index.d.ts.map +1 -0
  8. package/dist/api/expose/mcp-build/build.d.ts.map +1 -0
  9. package/dist/{codegen → api/expose/mcp-build}/generator.d.ts +3 -3
  10. package/dist/api/expose/mcp-build/generator.d.ts.map +1 -0
  11. package/dist/api/expose/mcp-build/index.d.ts +8 -0
  12. package/dist/api/expose/mcp-build/index.d.ts.map +1 -0
  13. package/dist/api/expose/mcp-build/init.d.ts.map +1 -0
  14. package/dist/api/expose/mcp-build/run.d.ts.map +1 -0
  15. package/dist/api/expose/mcp-build/types.d.ts +25 -0
  16. package/dist/api/expose/mcp-build/types.d.ts.map +1 -0
  17. package/dist/api/expose/mcpServer.d.ts +75 -0
  18. package/dist/api/expose/mcpServer.d.ts.map +1 -0
  19. package/dist/api/expose/openapi.d.ts +23 -0
  20. package/dist/api/expose/openapi.d.ts.map +1 -0
  21. package/dist/api/expose/openapiHttp.d.ts +67 -0
  22. package/dist/api/expose/openapiHttp.d.ts.map +1 -0
  23. package/dist/api/main.cjs +56 -0
  24. package/dist/api/main.cjs.map +1 -0
  25. package/dist/api/main.d.ts +23 -0
  26. package/dist/api/main.d.ts.map +1 -0
  27. package/dist/api/main.js +7 -0
  28. package/dist/api/main.js.map +1 -0
  29. package/dist/api/runtimeFromConfig.d.ts +34 -0
  30. package/dist/api/runtimeFromConfig.d.ts.map +1 -0
  31. package/dist/canonicalCoreSchemas-CTW6CCFY.cjs +20 -0
  32. package/dist/canonicalCoreSchemas-CTW6CCFY.cjs.map +1 -0
  33. package/dist/canonicalCoreSchemas-YLHVHYJZ.js +3 -0
  34. package/dist/canonicalCoreSchemas-YLHVHYJZ.js.map +1 -0
  35. package/dist/{chunk-AXUNV4MK.js → chunk-5SWSNVMI.js} +3 -3
  36. package/dist/chunk-5SWSNVMI.js.map +1 -0
  37. package/dist/chunk-6F5JHLZ7.cjs +243 -0
  38. package/dist/chunk-6F5JHLZ7.cjs.map +1 -0
  39. package/dist/chunk-AE6FSNGY.js +201 -0
  40. package/dist/chunk-AE6FSNGY.js.map +1 -0
  41. package/dist/chunk-BZOKPJMP.cjs +120 -0
  42. package/dist/chunk-BZOKPJMP.cjs.map +1 -0
  43. package/dist/chunk-FA2ZEICE.cjs +1620 -0
  44. package/dist/chunk-FA2ZEICE.cjs.map +1 -0
  45. package/dist/chunk-FR2CXERF.js +239 -0
  46. package/dist/chunk-FR2CXERF.js.map +1 -0
  47. package/dist/chunk-MGEQPAHV.cjs +475 -0
  48. package/dist/chunk-MGEQPAHV.cjs.map +1 -0
  49. package/dist/{chunk-BM4EVYI5.js → chunk-PJ4RUBZL.js} +836 -122
  50. package/dist/chunk-PJ4RUBZL.js.map +1 -0
  51. package/dist/chunk-Q7KPGWC6.js +1584 -0
  52. package/dist/chunk-Q7KPGWC6.js.map +1 -0
  53. package/dist/chunk-QVH6IQKQ.js +469 -0
  54. package/dist/chunk-QVH6IQKQ.js.map +1 -0
  55. package/dist/{chunk-3YLVPZRJ.cjs → chunk-SOFUWEZ6.cjs} +3 -3
  56. package/dist/chunk-SOFUWEZ6.cjs.map +1 -0
  57. package/dist/chunk-TBMWJWQ2.js +116 -0
  58. package/dist/chunk-TBMWJWQ2.js.map +1 -0
  59. package/dist/{chunk-Z7TGIG77.cjs → chunk-ZBNRHRGM.cjs} +843 -127
  60. package/dist/chunk-ZBNRHRGM.cjs.map +1 -0
  61. package/dist/chunk-ZNJBRLKN.cjs +210 -0
  62. package/dist/chunk-ZNJBRLKN.cjs.map +1 -0
  63. package/dist/core/index.cjs +20 -0
  64. package/dist/core/index.cjs.map +1 -0
  65. package/dist/{core.d.ts → core/index.d.ts} +2 -3
  66. package/dist/core/index.d.ts.map +1 -0
  67. package/dist/core/index.js +3 -0
  68. package/dist/core/index.js.map +1 -0
  69. package/dist/core/registry/ToolRegistry.d.ts.map +1 -0
  70. package/dist/core/runtime/Budget.d.ts.map +1 -0
  71. package/dist/core/runtime/Evidence.d.ts.map +1 -0
  72. package/dist/{runtime → core/runtime}/PTCRuntime.d.ts +4 -4
  73. package/dist/core/runtime/PTCRuntime.d.ts.map +1 -0
  74. package/dist/{runtime → core/runtime}/PTCRuntimeObservability.d.ts +4 -4
  75. package/dist/core/runtime/PTCRuntimeObservability.d.ts.map +1 -0
  76. package/dist/{runtime → core/runtime}/PTCRuntimePipeline.d.ts +4 -4
  77. package/dist/core/runtime/PTCRuntimePipeline.d.ts.map +1 -0
  78. package/dist/core/runtime/PolicyEngine.d.ts.map +1 -0
  79. package/dist/core/runtime/Retry.d.ts.map +1 -0
  80. package/dist/core/runtime/SchemaValidator.d.ts.map +1 -0
  81. package/dist/core/runtime.cjs +24 -0
  82. package/dist/core/runtime.cjs.map +1 -0
  83. package/dist/core/runtime.d.ts +12 -0
  84. package/dist/core/runtime.d.ts.map +1 -0
  85. package/dist/core/runtime.js +3 -0
  86. package/dist/core/runtime.js.map +1 -0
  87. package/dist/core/types/Events.d.ts.map +1 -0
  88. package/dist/core/types/ToolIntent.d.ts.map +1 -0
  89. package/dist/{types → core/types}/ToolResult.d.ts +6 -1
  90. package/dist/core/types/ToolResult.d.ts.map +1 -0
  91. package/dist/{types → core/types}/ToolSpec.d.ts +15 -5
  92. package/dist/core/types/ToolSpec.d.ts.map +1 -0
  93. package/dist/core/types/ToolTypeHandler.d.ts +88 -0
  94. package/dist/core/types/ToolTypeHandler.d.ts.map +1 -0
  95. package/dist/{types → core/types}/index.d.ts +2 -1
  96. package/dist/core/types/index.d.ts.map +1 -0
  97. package/dist/index.cjs +249 -2749
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.d.ts +61 -55
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +126 -2688
  102. package/dist/index.js.map +1 -1
  103. package/dist/observability/EventLog.d.ts +1 -1
  104. package/dist/observability/EventLog.d.ts.map +1 -1
  105. package/dist/tools/discoveryFactory.d.ts +117 -0
  106. package/dist/tools/discoveryFactory.d.ts.map +1 -0
  107. package/dist/tools/function/index.d.ts +10 -0
  108. package/dist/tools/function/index.d.ts.map +1 -0
  109. package/dist/{codegen/scan → tools/function}/scanner.d.ts +5 -2
  110. package/dist/{codegen/scan → tools/function}/scanner.d.ts.map +1 -1
  111. package/dist/{codegen/scan → tools/function}/schemaFromTs.d.ts +1 -1
  112. package/dist/tools/function/schemaFromTs.d.ts.map +1 -0
  113. package/dist/tools/function/types.d.ts +20 -0
  114. package/dist/tools/function/types.d.ts.map +1 -0
  115. package/dist/tools/index.d.ts +13 -0
  116. package/dist/tools/index.d.ts.map +1 -0
  117. package/dist/{discovery/load → tools/langchain}/LangChainLoader.d.ts +1 -1
  118. package/dist/tools/langchain/LangChainLoader.d.ts.map +1 -0
  119. package/dist/tools/langchain/directoryApply.d.ts +5 -0
  120. package/dist/tools/langchain/directoryApply.d.ts.map +1 -0
  121. package/dist/tools/langchain/directoryLoad.d.ts +13 -0
  122. package/dist/tools/langchain/directoryLoad.d.ts.map +1 -0
  123. package/dist/tools/langchain/index.d.ts +3 -0
  124. package/dist/tools/langchain/index.d.ts.map +1 -0
  125. package/dist/tools/langchain/scanner.d.ts +8 -0
  126. package/dist/tools/langchain/scanner.d.ts.map +1 -0
  127. package/dist/tools/langchain/types.d.ts +5 -0
  128. package/dist/tools/langchain/types.d.ts.map +1 -0
  129. package/dist/{mcp → tools/mcp}/MCPClientAdapter.d.ts +3 -3
  130. package/dist/tools/mcp/MCPClientAdapter.d.ts.map +1 -0
  131. package/dist/{discovery/load → tools/mcp}/MCPLoader.d.ts +1 -1
  132. package/dist/tools/mcp/MCPLoader.d.ts.map +1 -0
  133. package/dist/tools/mcp/MCPProcessManager.d.ts +29 -0
  134. package/dist/tools/mcp/MCPProcessManager.d.ts.map +1 -0
  135. package/dist/{mcp → tools/mcp}/connectMCP.d.ts +3 -3
  136. package/dist/tools/mcp/connectMCP.d.ts.map +1 -0
  137. package/dist/tools/mcp/directoryApply.d.ts +10 -0
  138. package/dist/tools/mcp/directoryApply.d.ts.map +1 -0
  139. package/dist/{mcp → tools/mcp}/index.d.ts +6 -1
  140. package/dist/tools/mcp/index.d.ts.map +1 -0
  141. package/dist/tools/mcp/mcpSpecToToolSpec.d.ts +8 -0
  142. package/dist/tools/mcp/mcpSpecToToolSpec.d.ts.map +1 -0
  143. package/dist/{mcp → tools/mcp}/registerMCPTools.d.ts +2 -2
  144. package/dist/tools/mcp/registerMCPTools.d.ts.map +1 -0
  145. package/dist/tools/mcp/scanner.d.ts +8 -0
  146. package/dist/tools/mcp/scanner.d.ts.map +1 -0
  147. package/dist/tools/mcp/types.d.ts +3 -0
  148. package/dist/tools/mcp/types.d.ts.map +1 -0
  149. package/dist/{discovery/load → tools/n8n}/N8nLoader.d.ts +3 -3
  150. package/dist/tools/n8n/N8nLoader.d.ts.map +1 -0
  151. package/dist/tools/n8n/directoryApply.d.ts +10 -0
  152. package/dist/tools/n8n/directoryApply.d.ts.map +1 -0
  153. package/dist/tools/n8n/index.d.ts +6 -0
  154. package/dist/tools/n8n/index.d.ts.map +1 -0
  155. package/dist/tools/n8n/scanN8n.d.ts +20 -0
  156. package/dist/tools/n8n/scanN8n.d.ts.map +1 -0
  157. package/dist/tools/n8n/types.d.ts +18 -0
  158. package/dist/tools/n8n/types.d.ts.map +1 -0
  159. package/dist/tools/scanPackage.d.ts +42 -0
  160. package/dist/tools/scanPackage.d.ts.map +1 -0
  161. package/dist/{discovery/load → tools/skill}/SkillLoader.d.ts +1 -1
  162. package/dist/tools/skill/SkillLoader.d.ts.map +1 -0
  163. package/dist/tools/skill/SkillManifest.d.ts.map +1 -0
  164. package/dist/tools/skill/SkillMdParser.d.ts.map +1 -0
  165. package/dist/tools/skill/directoryApply.d.ts +10 -0
  166. package/dist/tools/skill/directoryApply.d.ts.map +1 -0
  167. package/dist/tools/skill/index.d.ts +8 -0
  168. package/dist/tools/skill/index.d.ts.map +1 -0
  169. package/dist/tools/skill/scanSkill.d.ts +20 -0
  170. package/dist/tools/skill/scanSkill.d.ts.map +1 -0
  171. package/dist/tools/skill/types.d.ts +19 -0
  172. package/dist/tools/skill/types.d.ts.map +1 -0
  173. package/dist/tools/util/canonicalCoreSchemas.d.ts +19 -0
  174. package/dist/tools/util/canonicalCoreSchemas.d.ts.map +1 -0
  175. package/dist/tools/util/index.d.ts +13 -0
  176. package/dist/tools/util/index.d.ts.map +1 -0
  177. package/dist/tools/util/resolveEntry.d.ts +6 -0
  178. package/dist/tools/util/resolveEntry.d.ts.map +1 -0
  179. package/dist/tools/util/scanUtil.d.ts +9 -0
  180. package/dist/tools/util/scanUtil.d.ts.map +1 -0
  181. package/dist/tools/util/toolConfig.d.ts +32 -0
  182. package/dist/tools/util/toolConfig.d.ts.map +1 -0
  183. package/dist/tools/util/toolDescriptor.d.ts +92 -0
  184. package/dist/tools/util/toolDescriptor.d.ts.map +1 -0
  185. package/dist/utils/cli/index.cjs +419 -0
  186. package/dist/utils/cli/index.cjs.map +1 -0
  187. package/dist/utils/cli/index.d.ts +9 -0
  188. package/dist/utils/cli/index.d.ts.map +1 -0
  189. package/dist/utils/cli/index.js +412 -0
  190. package/dist/utils/cli/index.js.map +1 -0
  191. package/dist/utils/cli/toolRuntime.d.ts +19 -0
  192. package/dist/utils/cli/toolRuntime.d.ts.map +1 -0
  193. package/dist/utils/npmCache.d.ts +28 -0
  194. package/dist/utils/npmCache.d.ts.map +1 -0
  195. package/package.json +20 -11
  196. package/dist/chunk-3YLVPZRJ.cjs.map +0 -1
  197. package/dist/chunk-AXUNV4MK.js.map +0 -1
  198. package/dist/chunk-BM4EVYI5.js.map +0 -1
  199. package/dist/chunk-P3UEAZHK.cjs +0 -171
  200. package/dist/chunk-P3UEAZHK.cjs.map +0 -1
  201. package/dist/chunk-RPAMQCFH.js +0 -167
  202. package/dist/chunk-RPAMQCFH.js.map +0 -1
  203. package/dist/chunk-Z7TGIG77.cjs.map +0 -1
  204. package/dist/cli.cjs +0 -154
  205. package/dist/cli.cjs.map +0 -1
  206. package/dist/cli.d.ts +0 -10
  207. package/dist/cli.d.ts.map +0 -1
  208. package/dist/cli.js +0 -147
  209. package/dist/cli.js.map +0 -1
  210. package/dist/codegen/build.d.ts.map +0 -1
  211. package/dist/codegen/generator.d.ts.map +0 -1
  212. package/dist/codegen/index.d.ts +0 -21
  213. package/dist/codegen/index.d.ts.map +0 -1
  214. package/dist/codegen/init.d.ts.map +0 -1
  215. package/dist/codegen/run.d.ts.map +0 -1
  216. package/dist/codegen/scan/scanN8n.d.ts +0 -17
  217. package/dist/codegen/scan/scanN8n.d.ts.map +0 -1
  218. package/dist/codegen/scan/scanSkill.d.ts +0 -17
  219. package/dist/codegen/scan/scanSkill.d.ts.map +0 -1
  220. package/dist/codegen/scan/scanTools.d.ts +0 -31
  221. package/dist/codegen/scan/scanTools.d.ts.map +0 -1
  222. package/dist/codegen/scan/schemaFromTs.d.ts.map +0 -1
  223. package/dist/codegen/types.d.ts +0 -81
  224. package/dist/codegen/types.d.ts.map +0 -1
  225. package/dist/core.cjs +0 -20
  226. package/dist/core.cjs.map +0 -1
  227. package/dist/core.d.ts.map +0 -1
  228. package/dist/core.js +0 -3
  229. package/dist/core.js.map +0 -1
  230. package/dist/discovery/MCPProcessManager.d.ts +0 -57
  231. package/dist/discovery/MCPProcessManager.d.ts.map +0 -1
  232. package/dist/discovery/errors.d.ts +0 -13
  233. package/dist/discovery/errors.d.ts.map +0 -1
  234. package/dist/discovery/load/LangChainLoader.d.ts.map +0 -1
  235. package/dist/discovery/load/MCPLoader.d.ts.map +0 -1
  236. package/dist/discovery/load/N8nLoader.d.ts.map +0 -1
  237. package/dist/discovery/load/SkillLoader.d.ts.map +0 -1
  238. package/dist/discovery/load/SkillManifest.d.ts.map +0 -1
  239. package/dist/discovery/load/SkillMdParser.d.ts.map +0 -1
  240. package/dist/discovery/load/index.d.ts +0 -6
  241. package/dist/discovery/load/index.d.ts.map +0 -1
  242. package/dist/discovery/load/resolveEntry.d.ts +0 -7
  243. package/dist/discovery/load/resolveEntry.d.ts.map +0 -1
  244. package/dist/discovery/scan/DirectoryScanner.d.ts +0 -37
  245. package/dist/discovery/scan/DirectoryScanner.d.ts.map +0 -1
  246. package/dist/discovery/scan/scanUtil.d.ts +0 -16
  247. package/dist/discovery/scan/scanUtil.d.ts.map +0 -1
  248. package/dist/discovery/types.d.ts +0 -99
  249. package/dist/discovery/types.d.ts.map +0 -1
  250. package/dist/llm/AgentLLMAdapter.d.ts +0 -27
  251. package/dist/llm/AgentLLMAdapter.d.ts.map +0 -1
  252. package/dist/llm/LangChainToolsHub.d.ts +0 -31
  253. package/dist/llm/LangChainToolsHub.d.ts.map +0 -1
  254. package/dist/llm/OpenAICompatibleClient.d.ts +0 -64
  255. package/dist/llm/OpenAICompatibleClient.d.ts.map +0 -1
  256. package/dist/llm/ReActAgent.d.ts +0 -35
  257. package/dist/llm/ReActAgent.d.ts.map +0 -1
  258. package/dist/llm-export.cjs +0 -20
  259. package/dist/llm-export.cjs.map +0 -1
  260. package/dist/llm-export.d.ts +0 -9
  261. package/dist/llm-export.d.ts.map +0 -1
  262. package/dist/llm-export.js +0 -3
  263. package/dist/llm-export.js.map +0 -1
  264. package/dist/mcp/MCPClientAdapter.d.ts.map +0 -1
  265. package/dist/mcp/connectMCP.d.ts.map +0 -1
  266. package/dist/mcp/index.d.ts.map +0 -1
  267. package/dist/mcp/registerMCPTools.d.ts.map +0 -1
  268. package/dist/registry/ToolRegistry.d.ts.map +0 -1
  269. package/dist/report/AgentReportGenerator.d.ts +0 -53
  270. package/dist/report/AgentReportGenerator.d.ts.map +0 -1
  271. package/dist/report/agent-report-template.html +0 -362
  272. package/dist/report/index.d.ts +0 -3
  273. package/dist/report/index.d.ts.map +0 -1
  274. package/dist/report/types.d.ts +0 -101
  275. package/dist/report/types.d.ts.map +0 -1
  276. package/dist/runAgent.d.ts +0 -37
  277. package/dist/runAgent.d.ts.map +0 -1
  278. package/dist/runtime/Budget.d.ts.map +0 -1
  279. package/dist/runtime/Evidence.d.ts.map +0 -1
  280. package/dist/runtime/PTCRuntime.d.ts.map +0 -1
  281. package/dist/runtime/PTCRuntimeObservability.d.ts.map +0 -1
  282. package/dist/runtime/PTCRuntimePipeline.d.ts.map +0 -1
  283. package/dist/runtime/PolicyEngine.d.ts.map +0 -1
  284. package/dist/runtime/Retry.d.ts.map +0 -1
  285. package/dist/runtime/SchemaValidator.d.ts.map +0 -1
  286. package/dist/toolDescriptor.d.ts +0 -38
  287. package/dist/toolDescriptor.d.ts.map +0 -1
  288. package/dist/types/Events.d.ts.map +0 -1
  289. package/dist/types/ToolIntent.d.ts.map +0 -1
  290. package/dist/types/ToolResult.d.ts.map +0 -1
  291. package/dist/types/ToolSpec.d.ts.map +0 -1
  292. package/dist/types/index.d.ts.map +0 -1
  293. package/extensions/examples/README.md +0 -40
  294. package/extensions/examples/scripts/agent-tool-react-stock.mjs +0 -30
  295. package/extensions/examples/tools/instruction-only/skill/SKILL.md +0 -26
  296. package/extensions/examples/tools/web-search/mcp/mcp.json +0 -8
  297. /package/dist/{codegen → api/expose/mcp-build}/build.d.ts +0 -0
  298. /package/dist/{codegen → api/expose/mcp-build}/init.d.ts +0 -0
  299. /package/dist/{codegen → api/expose/mcp-build}/run.d.ts +0 -0
  300. /package/dist/{registry → core/registry}/ToolRegistry.d.ts +0 -0
  301. /package/dist/{runtime → core/runtime}/Budget.d.ts +0 -0
  302. /package/dist/{runtime → core/runtime}/Evidence.d.ts +0 -0
  303. /package/dist/{runtime → core/runtime}/PolicyEngine.d.ts +0 -0
  304. /package/dist/{runtime → core/runtime}/Retry.d.ts +0 -0
  305. /package/dist/{runtime → core/runtime}/SchemaValidator.d.ts +0 -0
  306. /package/dist/{types → core/types}/Events.d.ts +0 -0
  307. /package/dist/{types → core/types}/ToolIntent.d.ts +0 -0
  308. /package/dist/{discovery/load → tools/skill}/SkillManifest.d.ts +0 -0
  309. /package/dist/{discovery/load → tools/skill}/SkillMdParser.d.ts +0 -0
@@ -0,0 +1,1584 @@
1
+ import { ToolRegistry, createTaggedError, withRetry } from './chunk-AE6FSNGY.js';
2
+ import Ajv from 'ajv';
3
+ import addFormats from 'ajv-formats';
4
+ import { bulkhead, circuitBreaker, handleAll, ConsecutiveBreaker } from 'cockatiel';
5
+ import { EventEmitter } from 'eventemitter3';
6
+ import { v4 } from 'uuid';
7
+ import pTimeout from 'p-timeout';
8
+ import { readFileSync, existsSync } from 'fs';
9
+ import { resolve, dirname, join } from 'path';
10
+ import yaml from 'js-yaml';
11
+ import { registerCoreTools } from '@easynet/agent-tool-builtin-tools';
12
+ import { registerExampleTools } from '@easynet/agent-tool-example-tools';
13
+
14
+ var SchemaValidator = class {
15
+ ajv;
16
+ cache = /* @__PURE__ */ new Map();
17
+ constructor() {
18
+ this.ajv = new Ajv({
19
+ allErrors: true,
20
+ coerceTypes: true,
21
+ useDefaults: true,
22
+ removeAdditional: "failing",
23
+ strict: false
24
+ });
25
+ addFormats(this.ajv);
26
+ }
27
+ /**
28
+ * Validate data against a JSON Schema.
29
+ * Coerces types and applies defaults in-place.
30
+ */
31
+ validate(schema, data) {
32
+ const validate = this.getOrCompile(schema);
33
+ const cloned = structuredClone(data);
34
+ const valid = validate(cloned);
35
+ if (valid) {
36
+ return { valid: true, data: cloned };
37
+ }
38
+ return {
39
+ valid: false,
40
+ errors: validate.errors ?? void 0
41
+ };
42
+ }
43
+ /**
44
+ * Validate and return coerced data, or throw a descriptive error.
45
+ */
46
+ validateOrThrow(schema, data, context) {
47
+ const result = this.validate(schema, data);
48
+ if (!result.valid) {
49
+ const messages = (result.errors ?? []).map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ");
50
+ throw new SchemaValidationError(
51
+ `${context}: ${messages}`,
52
+ result.errors ?? []
53
+ );
54
+ }
55
+ return result.data;
56
+ }
57
+ /**
58
+ * Apply default values from schema to data without full validation.
59
+ */
60
+ enrichDefaults(schema, data) {
61
+ const validate = this.getOrCompile(schema);
62
+ const cloned = structuredClone(data);
63
+ validate(cloned);
64
+ return cloned;
65
+ }
66
+ getOrCompile(schema) {
67
+ const normalized = this.normalizeSchema(schema);
68
+ const key = JSON.stringify(normalized);
69
+ let cached = this.cache.get(key);
70
+ if (!cached) {
71
+ cached = this.ajv.compile(normalized);
72
+ this.cache.set(key, cached);
73
+ }
74
+ return cached;
75
+ }
76
+ /** Ensure schema is AJV-compatible (required = string[], nullable handled via type). */
77
+ normalizeSchema(schema) {
78
+ return this.normalizeSchemaRec(schema);
79
+ }
80
+ normalizeSchemaRec(s) {
81
+ const out = {};
82
+ for (const [key, value] of Object.entries(s)) {
83
+ if (key === "required") {
84
+ const raw = value;
85
+ out.required = Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : typeof raw === "string" ? [raw] : [];
86
+ continue;
87
+ }
88
+ if (key === "nullable") {
89
+ continue;
90
+ }
91
+ if (key === "properties" && value !== null && typeof value === "object") {
92
+ const props = {};
93
+ for (const [pk, pv] of Object.entries(value)) {
94
+ if (pv !== null && typeof pv === "object" && !Array.isArray(pv)) {
95
+ props[pk] = this.normalizeSchemaRec(pv);
96
+ } else {
97
+ props[pk] = pv;
98
+ }
99
+ }
100
+ out.properties = props;
101
+ continue;
102
+ }
103
+ if ((key === "items" || key === "additionalProperties") && value !== null && typeof value === "object" && !Array.isArray(value)) {
104
+ out[key] = this.normalizeSchemaRec(value);
105
+ continue;
106
+ }
107
+ if ((key === "oneOf" || key === "anyOf" || key === "allOf") && Array.isArray(value)) {
108
+ out[key] = value.map(
109
+ (item) => item !== null && typeof item === "object" && !Array.isArray(item) ? this.normalizeSchemaRec(item) : item
110
+ );
111
+ continue;
112
+ }
113
+ out[key] = value;
114
+ }
115
+ if (s.nullable === true) {
116
+ const existingType = out.type;
117
+ if (existingType === void 0) {
118
+ out.type = "object";
119
+ } else if (Array.isArray(existingType)) {
120
+ if (!existingType.includes("null")) out.type = [...existingType, "null"];
121
+ } else {
122
+ out.type = [existingType, "null"];
123
+ }
124
+ }
125
+ return out;
126
+ }
127
+ };
128
+ var SchemaValidationError = class extends Error {
129
+ constructor(message, errors) {
130
+ super(message);
131
+ this.errors = errors;
132
+ this.name = "SchemaValidationError";
133
+ }
134
+ };
135
+
136
+ // src/core/runtime/PolicyEngine.ts
137
+ var PolicyEngine = class {
138
+ config;
139
+ constructor(config = {}) {
140
+ this.config = {
141
+ requireExplicitDangerPermission: true,
142
+ deniedSqlPatterns: ["DROP\\s", "TRUNCATE\\s", "DELETE\\s+FROM\\s+\\w+\\s*$"],
143
+ ...config
144
+ };
145
+ }
146
+ /**
147
+ * Enforce all policy checks. Throws PolicyDeniedError if denied.
148
+ */
149
+ enforce(spec, args, ctx) {
150
+ const result = this.check(spec, args, ctx);
151
+ if (!result.allowed) {
152
+ throw new PolicyDeniedError(
153
+ result.reason ?? "Policy denied",
154
+ result.missingCapabilities
155
+ );
156
+ }
157
+ }
158
+ /**
159
+ * Check all policies without throwing.
160
+ */
161
+ check(spec, args, ctx) {
162
+ const capResult = this.checkCapabilities(spec, ctx);
163
+ if (!capResult.allowed) return capResult;
164
+ const paramResult = this.checkParameters(spec, args);
165
+ if (!paramResult.allowed) return paramResult;
166
+ return { allowed: true };
167
+ }
168
+ /**
169
+ * Check that context permissions cover tool capabilities.
170
+ */
171
+ checkCapabilities(spec, ctx) {
172
+ const missing = [];
173
+ for (const cap of spec.capabilities) {
174
+ if (cap === "danger:destructive") {
175
+ if (this.config.requireExplicitDangerPermission && !ctx.permissions.includes("danger:destructive")) {
176
+ missing.push(cap);
177
+ }
178
+ } else if (!ctx.permissions.includes(cap)) {
179
+ missing.push(cap);
180
+ }
181
+ }
182
+ if (missing.length > 0) {
183
+ return {
184
+ allowed: false,
185
+ reason: `Missing capabilities: ${missing.join(", ")}`,
186
+ missingCapabilities: missing
187
+ };
188
+ }
189
+ return { allowed: true };
190
+ }
191
+ /**
192
+ * Check parameter-level security constraints.
193
+ */
194
+ checkParameters(spec, args) {
195
+ if (!args || typeof args !== "object") return { allowed: true };
196
+ const argsObj = args;
197
+ if (spec.capabilities.includes("write:fs") && this.config.sandboxPaths) {
198
+ const pathResult = this.checkFilePaths(argsObj);
199
+ if (!pathResult.allowed) return pathResult;
200
+ }
201
+ if (spec.capabilities.includes("network") || spec.capabilities.includes("read:web")) {
202
+ const urlResult = this.checkUrls(argsObj);
203
+ if (!urlResult.allowed) return urlResult;
204
+ }
205
+ if (spec.capabilities.includes("write:db") || spec.capabilities.includes("read:db")) {
206
+ const sqlResult = this.checkSql(argsObj);
207
+ if (!sqlResult.allowed) return sqlResult;
208
+ }
209
+ if (spec.capabilities.includes("network") && this.config.allowedDomains) {
210
+ const domainResult = this.checkDomains(argsObj);
211
+ if (!domainResult.allowed) return domainResult;
212
+ }
213
+ return { allowed: true };
214
+ }
215
+ checkFilePaths(args) {
216
+ const paths = this.extractStringValues(args, ["path", "file", "filepath", "filename", "dir", "directory"]);
217
+ for (const p of paths) {
218
+ const normalized = p.replace(/\.\./g, "");
219
+ if (p.includes("..")) {
220
+ return {
221
+ allowed: false,
222
+ reason: `Path traversal detected: ${p}`
223
+ };
224
+ }
225
+ if (this.config.sandboxPaths && this.config.sandboxPaths.length > 0) {
226
+ const inSandbox = this.config.sandboxPaths.some(
227
+ (sp) => normalized.startsWith(sp)
228
+ );
229
+ if (!inSandbox) {
230
+ return {
231
+ allowed: false,
232
+ reason: `Path outside sandbox: ${p}. Allowed: ${this.config.sandboxPaths.join(", ")}`
233
+ };
234
+ }
235
+ }
236
+ }
237
+ return { allowed: true };
238
+ }
239
+ checkUrls(args) {
240
+ const urls = this.extractStringValues(args, ["url", "endpoint", "href", "uri"]);
241
+ for (const url of urls) {
242
+ if (this.config.urlDenylist) {
243
+ for (const pattern of this.config.urlDenylist) {
244
+ if (new RegExp(pattern, "i").test(url)) {
245
+ return {
246
+ allowed: false,
247
+ reason: `URL denied by policy: ${url}`
248
+ };
249
+ }
250
+ }
251
+ }
252
+ if (this.config.urlAllowlist && this.config.urlAllowlist.length > 0) {
253
+ const allowed = this.config.urlAllowlist.some(
254
+ (pattern) => new RegExp(pattern, "i").test(url)
255
+ );
256
+ if (!allowed) {
257
+ return {
258
+ allowed: false,
259
+ reason: `URL not in allowlist: ${url}`
260
+ };
261
+ }
262
+ }
263
+ }
264
+ return { allowed: true };
265
+ }
266
+ checkSql(args) {
267
+ const sqls = this.extractStringValues(args, ["sql", "query", "statement"]);
268
+ for (const sql of sqls) {
269
+ if (this.config.deniedSqlPatterns) {
270
+ for (const pattern of this.config.deniedSqlPatterns) {
271
+ if (new RegExp(pattern, "i").test(sql)) {
272
+ return {
273
+ allowed: false,
274
+ reason: `SQL pattern denied: ${sql.slice(0, 50)}...`
275
+ };
276
+ }
277
+ }
278
+ }
279
+ }
280
+ return { allowed: true };
281
+ }
282
+ checkDomains(args) {
283
+ const urls = this.extractStringValues(args, ["url", "endpoint", "href", "host", "domain"]);
284
+ for (const url of urls) {
285
+ try {
286
+ const hostname = url.includes("://") ? new URL(url).hostname : url;
287
+ if (this.config.allowedDomains && !this.config.allowedDomains.some(
288
+ (d) => hostname === d || hostname.endsWith(`.${d}`)
289
+ )) {
290
+ return {
291
+ allowed: false,
292
+ reason: `Domain not allowed: ${hostname}`
293
+ };
294
+ }
295
+ } catch {
296
+ }
297
+ }
298
+ return { allowed: true };
299
+ }
300
+ /**
301
+ * Extract string values from args matching given key patterns.
302
+ */
303
+ extractStringValues(args, keyPatterns) {
304
+ const results = [];
305
+ const walk = (obj) => {
306
+ for (const [key, val] of Object.entries(obj)) {
307
+ const lowerKey = key.toLowerCase();
308
+ if (typeof val === "string" && keyPatterns.some((p) => lowerKey.includes(p))) {
309
+ results.push(val);
310
+ } else if (val && typeof val === "object" && !Array.isArray(val)) {
311
+ walk(val);
312
+ }
313
+ }
314
+ };
315
+ walk(args);
316
+ return results;
317
+ }
318
+ };
319
+ var PolicyDeniedError = class extends Error {
320
+ constructor(message, missingCapabilities) {
321
+ super(message);
322
+ this.missingCapabilities = missingCapabilities;
323
+ this.name = "PolicyDeniedError";
324
+ }
325
+ kind = "POLICY_DENIED";
326
+ };
327
+ var RateLimiter = class {
328
+ constructor(maxCalls, windowMs) {
329
+ this.maxCalls = maxCalls;
330
+ this.windowMs = windowMs;
331
+ }
332
+ timestamps = [];
333
+ tryAcquire() {
334
+ const now = Date.now();
335
+ while (this.timestamps.length > 0 && this.timestamps[0] <= now - this.windowMs) {
336
+ this.timestamps.shift();
337
+ }
338
+ if (this.timestamps.length >= this.maxCalls) {
339
+ return false;
340
+ }
341
+ this.timestamps.push(now);
342
+ return true;
343
+ }
344
+ get remaining() {
345
+ const now = Date.now();
346
+ const active = this.timestamps.filter((t) => t > now - this.windowMs);
347
+ return Math.max(0, this.maxCalls - active.length);
348
+ }
349
+ };
350
+ var BudgetManager = class {
351
+ defaultTimeoutMs;
352
+ bulkheads = /* @__PURE__ */ new Map();
353
+ circuitBreakers = /* @__PURE__ */ new Map();
354
+ rateLimiters = /* @__PURE__ */ new Map();
355
+ options;
356
+ constructor(options = {}) {
357
+ this.options = options;
358
+ this.defaultTimeoutMs = options.defaultTimeoutMs ?? 3e4;
359
+ }
360
+ /**
361
+ * Get effective timeout for a tool invocation.
362
+ */
363
+ getTimeout(_toolName, contextTimeoutMs) {
364
+ return contextTimeoutMs ?? this.defaultTimeoutMs;
365
+ }
366
+ /**
367
+ * Check rate limit for a tool. Returns true if allowed.
368
+ */
369
+ checkRateLimit(toolName) {
370
+ if (!this.options.rateLimit) return true;
371
+ let limiter = this.rateLimiters.get(toolName);
372
+ if (!limiter) {
373
+ limiter = new RateLimiter(
374
+ this.options.rateLimit.maxCalls,
375
+ this.options.rateLimit.windowMs
376
+ );
377
+ this.rateLimiters.set(toolName, limiter);
378
+ }
379
+ return limiter.tryAcquire();
380
+ }
381
+ /**
382
+ * Get or create a bulkhead (concurrency limiter) for a tool.
383
+ */
384
+ getBulkhead(toolName) {
385
+ if (!this.options.maxConcurrency) return void 0;
386
+ let bh = this.bulkheads.get(toolName);
387
+ if (!bh) {
388
+ bh = bulkhead(this.options.maxConcurrency, 0);
389
+ this.bulkheads.set(toolName, bh);
390
+ }
391
+ return bh;
392
+ }
393
+ /**
394
+ * Get or create a circuit breaker for a tool.
395
+ */
396
+ getCircuitBreaker(toolName) {
397
+ if (!this.options.circuitBreaker) return void 0;
398
+ let breaker = this.circuitBreakers.get(toolName);
399
+ if (!breaker) {
400
+ breaker = circuitBreaker(handleAll, {
401
+ breaker: new ConsecutiveBreaker(this.options.circuitBreaker.threshold),
402
+ halfOpenAfter: this.options.circuitBreaker.halfOpenAfterMs
403
+ });
404
+ this.circuitBreakers.set(toolName, breaker);
405
+ }
406
+ return breaker;
407
+ }
408
+ /**
409
+ * Execute a function within budget constraints (bulkhead + circuit breaker).
410
+ */
411
+ async execute(toolName, fn) {
412
+ const bh = this.getBulkhead(toolName);
413
+ const breaker = this.getCircuitBreaker(toolName);
414
+ let wrapped = fn;
415
+ if (breaker) {
416
+ const prevWrapped = wrapped;
417
+ wrapped = () => breaker.execute(() => prevWrapped());
418
+ }
419
+ if (bh) {
420
+ const prevWrapped = wrapped;
421
+ wrapped = () => bh.execute(() => prevWrapped());
422
+ }
423
+ return wrapped();
424
+ }
425
+ /**
426
+ * Reset all policies for a tool (useful for testing).
427
+ */
428
+ reset(toolName) {
429
+ this.bulkheads.delete(toolName);
430
+ this.circuitBreakers.delete(toolName);
431
+ this.rateLimiters.delete(toolName);
432
+ }
433
+ /**
434
+ * Reset all policies globally.
435
+ */
436
+ resetAll() {
437
+ this.bulkheads.clear();
438
+ this.circuitBreakers.clear();
439
+ this.rateLimiters.clear();
440
+ }
441
+ };
442
+
443
+ // src/core/runtime/Evidence.ts
444
+ function buildEvidence(options) {
445
+ const { spec, args, result, ctx, durationMs } = options;
446
+ const now = (/* @__PURE__ */ new Date()).toISOString();
447
+ const evidence = [];
448
+ evidence.push({
449
+ type: "tool",
450
+ ref: `${spec.name}@${spec.version}`,
451
+ summary: summarizeToolCall(spec, args, result, durationMs),
452
+ createdAt: now
453
+ });
454
+ if (result && typeof result === "object") {
455
+ const urls = extractUrls(result);
456
+ for (const url of urls) {
457
+ evidence.push({
458
+ type: "url",
459
+ ref: url,
460
+ summary: `Output URL from ${spec.name}`,
461
+ createdAt: now
462
+ });
463
+ }
464
+ const files = extractFilePaths(result);
465
+ for (const file of files) {
466
+ evidence.push({
467
+ type: "file",
468
+ ref: file,
469
+ summary: `Output file from ${spec.name}`,
470
+ createdAt: now
471
+ });
472
+ }
473
+ }
474
+ if (durationMs !== void 0 && durationMs > 0) {
475
+ evidence.push({
476
+ type: "metric",
477
+ ref: `latency:${spec.name}`,
478
+ summary: `Completed in ${durationMs}ms (request: ${ctx.requestId})`,
479
+ createdAt: now
480
+ });
481
+ }
482
+ return evidence;
483
+ }
484
+ function summarizeToolCall(spec, args, result, durationMs) {
485
+ const argKeys = args && typeof args === "object" ? Object.keys(args).join(", ") : "none";
486
+ const duration = durationMs ? ` in ${durationMs}ms` : "";
487
+ const resultPreview = summarizeValue(result, 100);
488
+ return `${spec.kind}:${spec.name} called with [${argKeys}]${duration} \u2192 ${resultPreview}`;
489
+ }
490
+ function summarizeValue(value, maxLen) {
491
+ if (value === null || value === void 0) return "null";
492
+ if (typeof value === "string") {
493
+ return value.length > maxLen ? value.slice(0, maxLen) + "..." : value;
494
+ }
495
+ const str = JSON.stringify(value);
496
+ return str.length > maxLen ? str.slice(0, maxLen) + "..." : str;
497
+ }
498
+ function extractUrls(obj) {
499
+ const urls = [];
500
+ const walk = (val) => {
501
+ if (typeof val === "string" && /^https?:\/\//i.test(val)) {
502
+ urls.push(val);
503
+ } else if (val && typeof val === "object") {
504
+ for (const v of Object.values(val)) {
505
+ walk(v);
506
+ }
507
+ }
508
+ };
509
+ walk(obj);
510
+ return urls.slice(0, 10);
511
+ }
512
+ function extractFilePaths(obj) {
513
+ const paths = [];
514
+ const walk = (val) => {
515
+ if (typeof val === "string" && (val.startsWith("/") || val.startsWith("./")) && val.includes(".")) {
516
+ paths.push(val);
517
+ } else if (val && typeof val === "object") {
518
+ for (const v of Object.values(val)) {
519
+ walk(v);
520
+ }
521
+ }
522
+ };
523
+ walk(obj);
524
+ return paths.slice(0, 10);
525
+ }
526
+ var EventLog = class {
527
+ entries = [];
528
+ seq = 0;
529
+ maxEntries;
530
+ emitter = new EventEmitter();
531
+ constructor(options = {}) {
532
+ this.maxEntries = options.maxEntries ?? 1e4;
533
+ }
534
+ /**
535
+ * Append an event to the log.
536
+ */
537
+ append(event) {
538
+ const entry = { seq: ++this.seq, event };
539
+ this.entries.push(entry);
540
+ if (this.entries.length > this.maxEntries) {
541
+ this.entries.shift();
542
+ }
543
+ this.emitter.emit("event", entry);
544
+ this.emitter.emit(event.type, entry);
545
+ return entry;
546
+ }
547
+ /**
548
+ * Subscribe to all events.
549
+ */
550
+ on(listener) {
551
+ this.emitter.on("event", listener);
552
+ return () => this.emitter.off("event", listener);
553
+ }
554
+ /**
555
+ * Subscribe to events of a specific type.
556
+ */
557
+ onType(type, listener) {
558
+ this.emitter.on(type, listener);
559
+ return () => this.emitter.off(type, listener);
560
+ }
561
+ /**
562
+ * Query events by filter.
563
+ */
564
+ query(filter) {
565
+ let results = this.entries;
566
+ if (filter.since !== void 0) {
567
+ results = results.filter((e) => e.seq > filter.since);
568
+ }
569
+ if (filter.type) {
570
+ results = results.filter((e) => e.event.type === filter.type);
571
+ }
572
+ if (filter.toolName) {
573
+ results = results.filter((e) => e.event.toolName === filter.toolName);
574
+ }
575
+ if (filter.requestId) {
576
+ results = results.filter((e) => e.event.requestId === filter.requestId);
577
+ }
578
+ if (filter.limit) {
579
+ results = results.slice(-filter.limit);
580
+ }
581
+ return results;
582
+ }
583
+ /**
584
+ * Get all entries.
585
+ */
586
+ getAll() {
587
+ return this.entries;
588
+ }
589
+ /**
590
+ * Get entry count.
591
+ */
592
+ get size() {
593
+ return this.entries.length;
594
+ }
595
+ /**
596
+ * Clear all entries (for testing).
597
+ */
598
+ clear() {
599
+ this.entries.length = 0;
600
+ this.seq = 0;
601
+ }
602
+ };
603
+
604
+ // src/observability/Logger.ts
605
+ var LEVEL_ORDER = {
606
+ silent: 0,
607
+ error: 1,
608
+ warn: 2,
609
+ info: 3,
610
+ debug: 4,
611
+ trace: 5
612
+ };
613
+ function createLogger(options = {}) {
614
+ const resolved = resolveDebugOptions(options);
615
+ const log = (level, message, meta) => {
616
+ if (!resolved.enabled) return;
617
+ if (LEVEL_ORDER[level] > LEVEL_ORDER[resolved.level]) return;
618
+ const prefix = `[${resolved.prefix}]`;
619
+ const levelTag = `[${level.toUpperCase()}]`;
620
+ const metaText = meta ? ` ${safeStringify(meta, 1e3)}` : "";
621
+ switch (level) {
622
+ case "error":
623
+ console.error(`${prefix} ${levelTag} ${message}${metaText}`);
624
+ break;
625
+ case "warn":
626
+ console.warn(`${prefix} ${levelTag} ${message}${metaText}`);
627
+ break;
628
+ case "info":
629
+ console.info(`${prefix} ${levelTag} ${message}${metaText}`);
630
+ break;
631
+ default:
632
+ console.log(`${prefix} ${levelTag} ${message}${metaText}`);
633
+ break;
634
+ }
635
+ };
636
+ return {
637
+ options: resolved,
638
+ isEnabled: (level) => resolved.enabled && LEVEL_ORDER[level] <= LEVEL_ORDER[resolved.level],
639
+ error: (message, meta) => log("error", message, meta),
640
+ warn: (message, meta) => log("warn", message, meta),
641
+ info: (message, meta) => log("info", message, meta),
642
+ debug: (message, meta) => log("debug", message, meta),
643
+ trace: (message, meta) => log("trace", message, meta)
644
+ };
645
+ }
646
+ function resolveDebugOptions(options = {}) {
647
+ const envLevel = parseEnvLogLevel();
648
+ const enabledFromEnv = envLevel !== void 0 && envLevel !== "silent";
649
+ const enabled = options.enabled ?? enabledFromEnv ?? false;
650
+ const level = options.level ?? envLevel ?? (enabled ? "debug" : "silent");
651
+ return {
652
+ enabled,
653
+ level,
654
+ includeArgs: options.includeArgs ?? false,
655
+ includeResults: options.includeResults ?? false,
656
+ includeRaw: options.includeRaw ?? false,
657
+ logEvents: options.logEvents ?? false,
658
+ prefix: options.prefix ?? "agent-tool"
659
+ };
660
+ }
661
+ function sanitizeForLog(value, maxLen = 500) {
662
+ const str = safeStringify(value, maxLen);
663
+ return str.replace(
664
+ /"(password|token|secret|key|auth)":\s*"[^"]*"/gi,
665
+ '"$1":"[REDACTED]"'
666
+ );
667
+ }
668
+ function summarizeForLog(value, maxLen = 200) {
669
+ if (value === null) return "null";
670
+ if (value === void 0) return "undefined";
671
+ if (typeof value === "string") {
672
+ return value.length > maxLen ? `${value.slice(0, maxLen)}...` : value;
673
+ }
674
+ if (typeof value === "number" || typeof value === "boolean") {
675
+ return String(value);
676
+ }
677
+ if (Array.isArray(value)) {
678
+ return `Array(${value.length})`;
679
+ }
680
+ if (typeof value === "object") {
681
+ const keys = Object.keys(value);
682
+ const shown = keys.slice(0, 5).join(", ");
683
+ return `Object(keys: ${shown}${keys.length > 5 ? ", ..." : ""})`;
684
+ }
685
+ return String(value);
686
+ }
687
+ function safeStringify(value, maxLen) {
688
+ try {
689
+ const json = JSON.stringify(value);
690
+ if (!json) return String(value);
691
+ return json.length > maxLen ? `${json.slice(0, maxLen)}...` : json;
692
+ } catch {
693
+ const fallback = String(value);
694
+ return fallback.length > maxLen ? `${fallback.slice(0, maxLen)}...` : fallback;
695
+ }
696
+ }
697
+ function parseEnvLogLevel() {
698
+ const raw = process.env.TOOLHUB_LOG_LEVEL ?? process.env.TOOLHUB_DEBUG ?? process.env.DEBUG;
699
+ if (!raw) return void 0;
700
+ const value = raw.trim().toLowerCase();
701
+ if (!value || value === "0" || value === "false" || value === "off") {
702
+ return "silent";
703
+ }
704
+ if (value.includes("trace")) return "trace";
705
+ if (value.includes("debug") || value === "1" || value === "true" || value === "yes") {
706
+ return "debug";
707
+ }
708
+ if (value.includes("info")) return "info";
709
+ if (value.includes("warn")) return "warn";
710
+ if (value.includes("error")) return "error";
711
+ if (value.includes("silent")) return "silent";
712
+ return "debug";
713
+ }
714
+
715
+ // src/observability/Metrics.ts
716
+ var Metrics = class {
717
+ counters = /* @__PURE__ */ new Map();
718
+ histograms = /* @__PURE__ */ new Map();
719
+ defaultBuckets = [
720
+ 5,
721
+ 10,
722
+ 25,
723
+ 50,
724
+ 100,
725
+ 250,
726
+ 500,
727
+ 1e3,
728
+ 2500,
729
+ 5e3,
730
+ 1e4
731
+ ];
732
+ /**
733
+ * Increment a counter.
734
+ */
735
+ increment(name, labels = {}, value = 1) {
736
+ const key = this.makeKey(name, labels);
737
+ this.counters.set(key, (this.counters.get(key) ?? 0) + value);
738
+ }
739
+ /**
740
+ * Record a value in a histogram.
741
+ */
742
+ observe(name, labels, value) {
743
+ const key = this.makeKey(name, labels);
744
+ let hist = this.histograms.get(key);
745
+ if (!hist) {
746
+ hist = { count: 0, sum: 0, values: [] };
747
+ this.histograms.set(key, hist);
748
+ }
749
+ hist.count++;
750
+ hist.sum += value;
751
+ hist.values.push(value);
752
+ }
753
+ /**
754
+ * Get a counter value.
755
+ */
756
+ getCounter(name, labels = {}) {
757
+ return this.counters.get(this.makeKey(name, labels)) ?? 0;
758
+ }
759
+ /**
760
+ * Get histogram stats.
761
+ */
762
+ getHistogram(name, labels) {
763
+ const key = this.makeKey(name, labels);
764
+ const hist = this.histograms.get(key);
765
+ if (!hist) return void 0;
766
+ const buckets = /* @__PURE__ */ new Map();
767
+ for (const bound of this.defaultBuckets) {
768
+ buckets.set(bound, hist.values.filter((v) => v <= bound).length);
769
+ }
770
+ return { name, labels, count: hist.count, sum: hist.sum, buckets };
771
+ }
772
+ /**
773
+ * Get all counter values.
774
+ */
775
+ getAllCounters() {
776
+ const results = [];
777
+ for (const [key, value] of this.counters) {
778
+ const { name, labels } = this.parseKey(key);
779
+ results.push({ name, labels, value });
780
+ }
781
+ return results;
782
+ }
783
+ /**
784
+ * Get all histogram values.
785
+ */
786
+ getAllHistograms() {
787
+ const results = [];
788
+ for (const [key, hist] of this.histograms) {
789
+ const { name, labels } = this.parseKey(key);
790
+ const buckets = /* @__PURE__ */ new Map();
791
+ for (const bound of this.defaultBuckets) {
792
+ buckets.set(bound, hist.values.filter((v) => v <= bound).length);
793
+ }
794
+ results.push({ name, labels, count: hist.count, sum: hist.sum, buckets });
795
+ }
796
+ return results;
797
+ }
798
+ /**
799
+ * Record standard tool invocation metrics.
800
+ */
801
+ recordInvocation(toolName, ok, durationMs) {
802
+ this.increment("tool_invocations_total", {
803
+ toolName,
804
+ ok: String(ok)
805
+ });
806
+ this.observe("tool_latency_ms", { toolName }, durationMs);
807
+ }
808
+ /**
809
+ * Record a retry event.
810
+ */
811
+ recordRetry(toolName) {
812
+ this.increment("tool_retries_total", { toolName });
813
+ }
814
+ /**
815
+ * Record a policy denial.
816
+ */
817
+ recordPolicyDenied(toolName, reason) {
818
+ this.increment("policy_denied_total", { toolName, reason });
819
+ }
820
+ /**
821
+ * Reset all metrics (for testing).
822
+ */
823
+ reset() {
824
+ this.counters.clear();
825
+ this.histograms.clear();
826
+ }
827
+ makeKey(name, labels) {
828
+ const sortedLabels = Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
829
+ return `${name}{${sortedLabels}}`;
830
+ }
831
+ parseKey(key) {
832
+ const match = key.match(/^(.+?)\{(.*)\}$/);
833
+ if (!match) return { name: key, labels: {} };
834
+ const labels = {};
835
+ if (match[2]) {
836
+ for (const part of match[2].split(",")) {
837
+ const [k, v] = part.split("=");
838
+ if (k && v !== void 0) labels[k] = v;
839
+ }
840
+ }
841
+ return { name: match[1], labels };
842
+ }
843
+ };
844
+ var Tracing = class {
845
+ spans = /* @__PURE__ */ new Map();
846
+ traceSpans = /* @__PURE__ */ new Map();
847
+ // traceId → spanIds
848
+ /**
849
+ * Start a new span.
850
+ */
851
+ startSpan(options) {
852
+ const span = {
853
+ spanId: v4(),
854
+ traceId: options.traceId ?? v4(),
855
+ parentSpanId: options.parentSpanId,
856
+ name: options.name,
857
+ startTime: Date.now(),
858
+ status: "in_progress",
859
+ attributes: options.attributes ?? {},
860
+ events: []
861
+ };
862
+ this.spans.set(span.spanId, span);
863
+ const traceList = this.traceSpans.get(span.traceId) ?? [];
864
+ traceList.push(span.spanId);
865
+ this.traceSpans.set(span.traceId, traceList);
866
+ return span;
867
+ }
868
+ /**
869
+ * End a span and calculate duration.
870
+ */
871
+ endSpan(spanId, status = "ok") {
872
+ const span = this.spans.get(spanId);
873
+ if (!span) return void 0;
874
+ span.endTime = Date.now();
875
+ span.durationMs = span.endTime - span.startTime;
876
+ span.status = status;
877
+ return span;
878
+ }
879
+ /**
880
+ * Add an event to a span.
881
+ */
882
+ addEvent(spanId, name, attributes) {
883
+ const span = this.spans.get(spanId);
884
+ if (!span) return;
885
+ span.events.push({ name, timestamp: Date.now(), attributes });
886
+ }
887
+ /**
888
+ * Set attributes on a span.
889
+ */
890
+ setAttributes(spanId, attributes) {
891
+ const span = this.spans.get(spanId);
892
+ if (!span) return;
893
+ Object.assign(span.attributes, attributes);
894
+ }
895
+ /**
896
+ * Get a span by ID.
897
+ */
898
+ getSpan(spanId) {
899
+ return this.spans.get(spanId);
900
+ }
901
+ /**
902
+ * Get all spans for a trace.
903
+ */
904
+ getTrace(traceId) {
905
+ const spanIds = this.traceSpans.get(traceId) ?? [];
906
+ return spanIds.map((id) => this.spans.get(id)).filter((s) => s !== void 0);
907
+ }
908
+ /**
909
+ * Create a child span from a parent.
910
+ */
911
+ createChildSpan(parentSpanId, name, attributes) {
912
+ const parent = this.spans.get(parentSpanId);
913
+ if (!parent) return void 0;
914
+ return this.startSpan({
915
+ name,
916
+ traceId: parent.traceId,
917
+ parentSpanId: parent.spanId,
918
+ attributes
919
+ });
920
+ }
921
+ /**
922
+ * Clear all traces (for testing).
923
+ */
924
+ clear() {
925
+ this.spans.clear();
926
+ this.traceSpans.clear();
927
+ }
928
+ };
929
+ function resolveTool(toolName, registry) {
930
+ const spec = registry.get(toolName);
931
+ if (!spec) {
932
+ throw createTaggedError(
933
+ "TOOL_NOT_FOUND",
934
+ `Tool not found: ${toolName}`,
935
+ { availableTools: registry.snapshot().slice(0, 20).map((s) => s.name) }
936
+ );
937
+ }
938
+ return spec;
939
+ }
940
+ function validateInput(spec, args, validator) {
941
+ try {
942
+ return validator.validateOrThrow(
943
+ spec.inputSchema,
944
+ args,
945
+ `Input validation failed for ${spec.name}`
946
+ );
947
+ } catch (error) {
948
+ if (error instanceof SchemaValidationError) {
949
+ throw createTaggedError("INPUT_SCHEMA_INVALID", error.message, {
950
+ errors: error.errors,
951
+ schema: spec.inputSchema
952
+ });
953
+ }
954
+ throw error;
955
+ }
956
+ }
957
+ function enrichDefaults(spec, args, validator) {
958
+ return validator.enrichDefaults(spec.inputSchema, args);
959
+ }
960
+ function enforcePolicy(spec, args, ctx, deps) {
961
+ try {
962
+ deps.policy.enforce(spec, args, ctx);
963
+ } catch (error) {
964
+ if (error instanceof PolicyDeniedError) {
965
+ const event = {
966
+ type: "POLICY_DENIED",
967
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
968
+ requestId: ctx.requestId,
969
+ taskId: ctx.taskId,
970
+ toolName: spec.name,
971
+ traceId: ctx.traceId,
972
+ userId: ctx.userId,
973
+ reason: error.message,
974
+ missingCapabilities: error.missingCapabilities?.map(String)
975
+ };
976
+ deps.eventLog.append(event);
977
+ deps.metrics.recordPolicyDenied(spec.name, error.message);
978
+ }
979
+ throw error;
980
+ }
981
+ }
982
+ var HITL_GATED_SIDE_EFFECTS = ["external_write", "destructive"];
983
+ async function requireHumanApproval(spec, args, ctx, deps) {
984
+ const sideEffect = spec._meta?.hitl?.sideEffect ?? "none";
985
+ if (!HITL_GATED_SIDE_EFFECTS.includes(sideEffect)) return;
986
+ const onApproval = deps.onApprovalRequired;
987
+ if (!onApproval) return;
988
+ const baseEvent = {
989
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
990
+ requestId: ctx.requestId,
991
+ taskId: ctx.taskId,
992
+ toolName: spec.name,
993
+ traceId: ctx.traceId,
994
+ userId: ctx.userId
995
+ };
996
+ const requested = {
997
+ ...baseEvent,
998
+ type: "HITL_APPROVAL_REQUESTED",
999
+ sideEffect
1000
+ };
1001
+ deps.eventLog.append(requested);
1002
+ deps.logger.trace("hitl.requested", { tool: spec.name, sideEffect, requestId: ctx.requestId });
1003
+ let approved;
1004
+ try {
1005
+ approved = await onApproval(spec, args, ctx);
1006
+ } catch (err) {
1007
+ deps.eventLog.append({
1008
+ ...baseEvent,
1009
+ type: "HITL_APPROVAL_DENIED",
1010
+ sideEffect,
1011
+ reason: err instanceof Error ? err.message : String(err)
1012
+ });
1013
+ throw createTaggedError(
1014
+ "HITL_DENIED",
1015
+ `Human denied approval for ${spec.name} (${sideEffect})`,
1016
+ { reason: err instanceof Error ? err.message : String(err) }
1017
+ );
1018
+ }
1019
+ if (approved === false) {
1020
+ deps.eventLog.append({
1021
+ ...baseEvent,
1022
+ type: "HITL_APPROVAL_DENIED",
1023
+ sideEffect,
1024
+ reason: "User rejected"
1025
+ });
1026
+ throw createTaggedError("HITL_DENIED", `Human denied approval for ${spec.name} (${sideEffect})`);
1027
+ }
1028
+ deps.eventLog.append({
1029
+ ...baseEvent,
1030
+ type: "HITL_APPROVAL_GRANTED",
1031
+ sideEffect
1032
+ });
1033
+ deps.logger.trace("hitl.granted", { tool: spec.name, sideEffect, requestId: ctx.requestId });
1034
+ }
1035
+ async function executeWithBudget(spec, args, ctx, spanId, deps) {
1036
+ const adapter = deps.adapters.get(spec.kind);
1037
+ if (!adapter) {
1038
+ throw createTaggedError(
1039
+ "TOOL_NOT_FOUND",
1040
+ `No adapter registered for kind: ${spec.kind}`
1041
+ );
1042
+ }
1043
+ const timeoutMs = deps.budget.getTimeout(
1044
+ spec.name,
1045
+ ctx.budget?.timeoutMs
1046
+ );
1047
+ const maxRetries = ctx.budget?.maxRetries ?? deps.defaultMaxRetries ?? 2;
1048
+ const executeFn = async () => {
1049
+ return deps.budget.execute(spec.name, async () => {
1050
+ deps.tracing.addEvent(spanId, "execute_start");
1051
+ deps.logger.trace("execute.start", {
1052
+ tool: spec.name,
1053
+ requestId: ctx.requestId,
1054
+ timeoutMs,
1055
+ maxRetries
1056
+ });
1057
+ const result = await adapter.invoke(spec, args, ctx);
1058
+ deps.tracing.addEvent(spanId, "execute_end");
1059
+ deps.logger.trace("execute.end", {
1060
+ tool: spec.name,
1061
+ requestId: ctx.requestId
1062
+ });
1063
+ return result;
1064
+ });
1065
+ };
1066
+ const retryFn = () => withRetry(executeFn, {
1067
+ maxRetries,
1068
+ onRetry: (error, attempt) => {
1069
+ deps.metrics.recordRetry(spec.name);
1070
+ const event = {
1071
+ type: "RETRY",
1072
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1073
+ requestId: ctx.requestId,
1074
+ taskId: ctx.taskId,
1075
+ toolName: spec.name,
1076
+ traceId: ctx.traceId,
1077
+ userId: ctx.userId,
1078
+ attempt,
1079
+ maxRetries,
1080
+ reason: error.message
1081
+ };
1082
+ deps.eventLog.append(event);
1083
+ deps.tracing.addEvent(spanId, "retry", { attempt, reason: error.message });
1084
+ }
1085
+ });
1086
+ try {
1087
+ return await pTimeout(retryFn(), {
1088
+ milliseconds: timeoutMs,
1089
+ message: `Tool ${spec.name} timed out after ${timeoutMs}ms`
1090
+ });
1091
+ } catch (error) {
1092
+ if (error instanceof Error && error.message.includes("timed out")) {
1093
+ throw createTaggedError("TIMEOUT", error.message);
1094
+ }
1095
+ throw error;
1096
+ }
1097
+ }
1098
+ function validateOutput(spec, result, validator) {
1099
+ try {
1100
+ return validator.validateOrThrow(
1101
+ spec.outputSchema,
1102
+ result,
1103
+ `Output validation failed for ${spec.name}`
1104
+ );
1105
+ } catch (error) {
1106
+ if (error instanceof SchemaValidationError) {
1107
+ throw createTaggedError("OUTPUT_SCHEMA_INVALID", error.message, {
1108
+ errors: error.errors
1109
+ });
1110
+ }
1111
+ throw error;
1112
+ }
1113
+ }
1114
+
1115
+ // src/core/runtime/PTCRuntimeObservability.ts
1116
+ function emitToolCalled(intent, ctx, deps) {
1117
+ const event = {
1118
+ type: "TOOL_CALLED",
1119
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1120
+ requestId: ctx.requestId,
1121
+ taskId: ctx.taskId,
1122
+ toolName: intent.tool,
1123
+ traceId: ctx.traceId,
1124
+ userId: ctx.userId,
1125
+ argsSummary: sanitizeArgs(intent.args),
1126
+ purpose: intent.purpose,
1127
+ idempotencyKey: intent.idempotencyKey
1128
+ };
1129
+ deps.eventLog.append(event);
1130
+ }
1131
+ function recordSuccess(spec, durationMs, _evidence, spanId, deps) {
1132
+ deps.metrics.recordInvocation(spec.name, true, durationMs);
1133
+ deps.tracing.setAttributes(spanId, {
1134
+ "tool.duration_ms": durationMs,
1135
+ "tool.ok": true
1136
+ });
1137
+ deps.tracing.endSpan(spanId, "ok");
1138
+ }
1139
+ function handleError(error, intent, ctx, durationMs, spanId, deps) {
1140
+ const kind = error?.kind ?? "UPSTREAM_ERROR";
1141
+ const message = error instanceof Error ? error.message : String(error);
1142
+ const details = error?.details;
1143
+ deps.metrics.recordInvocation(intent.tool, false, durationMs);
1144
+ deps.tracing.setAttributes(spanId, {
1145
+ "tool.duration_ms": durationMs,
1146
+ "tool.ok": false,
1147
+ "tool.error_kind": kind
1148
+ });
1149
+ deps.tracing.endSpan(spanId, "error");
1150
+ const event = {
1151
+ type: "TOOL_RESULT",
1152
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1153
+ requestId: ctx.requestId,
1154
+ taskId: ctx.taskId,
1155
+ toolName: intent.tool,
1156
+ traceId: ctx.traceId,
1157
+ userId: ctx.userId,
1158
+ ok: false,
1159
+ durationMs,
1160
+ resultSummary: message,
1161
+ evidence: [],
1162
+ error: { kind, message, details }
1163
+ };
1164
+ deps.eventLog.append(event);
1165
+ deps.logger.warn("invoke.error", {
1166
+ tool: intent.tool,
1167
+ requestId: ctx.requestId,
1168
+ taskId: ctx.taskId,
1169
+ traceId: ctx.traceId,
1170
+ kind,
1171
+ message,
1172
+ durationMs,
1173
+ details: deps.logger.options.includeResults ? summarizeForLog(details) : void 0
1174
+ });
1175
+ return {
1176
+ ok: false,
1177
+ evidence: [],
1178
+ error: { kind, message, details }
1179
+ };
1180
+ }
1181
+ function sanitizeArgs(args) {
1182
+ if (!args) return "{}";
1183
+ return sanitizeForLog(args);
1184
+ }
1185
+
1186
+ // src/core/runtime/PTCRuntime.ts
1187
+ var PTCRuntime = class {
1188
+ registry;
1189
+ adapters = /* @__PURE__ */ new Map();
1190
+ validator;
1191
+ policy;
1192
+ budget;
1193
+ eventLog;
1194
+ metrics;
1195
+ tracing;
1196
+ config;
1197
+ logger;
1198
+ constructor(options = {}) {
1199
+ this.config = options.config ?? {};
1200
+ this.registry = options.registry ?? new ToolRegistry();
1201
+ this.validator = options.validator ?? new SchemaValidator();
1202
+ this.policy = options.policy ?? new PolicyEngine(this.config.policy);
1203
+ this.budget = options.budget ?? new BudgetManager(this.config.budget);
1204
+ this.eventLog = options.eventLog ?? new EventLog();
1205
+ this.metrics = options.metrics ?? new Metrics();
1206
+ this.tracing = options.tracing ?? new Tracing();
1207
+ this.logger = createLogger({ ...this.config.debug, prefix: "PTCRuntime" });
1208
+ if (this.logger.options.logEvents) {
1209
+ this.eventLog.on((entry) => {
1210
+ const event = entry.event;
1211
+ this.logger.debug("event", {
1212
+ seq: entry.seq,
1213
+ type: event.type,
1214
+ toolName: event.toolName,
1215
+ requestId: event.requestId,
1216
+ taskId: event.taskId,
1217
+ ok: "ok" in event ? event.ok : void 0
1218
+ });
1219
+ });
1220
+ }
1221
+ }
1222
+ /**
1223
+ * Register an adapter for a tool kind.
1224
+ */
1225
+ registerAdapter(adapter) {
1226
+ this.adapters.set(adapter.kind, adapter);
1227
+ }
1228
+ /**
1229
+ * Get an adapter by kind (e.g. "mcp"). Use to set MCP client via adapter.setClient().
1230
+ */
1231
+ getAdapter(kind) {
1232
+ return this.adapters.get(kind);
1233
+ }
1234
+ /**
1235
+ * Get the tool registry.
1236
+ */
1237
+ getRegistry() {
1238
+ return this.registry;
1239
+ }
1240
+ /**
1241
+ * Get the event log.
1242
+ */
1243
+ getEventLog() {
1244
+ return this.eventLog;
1245
+ }
1246
+ /**
1247
+ * Get the metrics collector.
1248
+ */
1249
+ getMetrics() {
1250
+ return this.metrics;
1251
+ }
1252
+ /**
1253
+ * Get the tracing system.
1254
+ */
1255
+ getTracing() {
1256
+ return this.tracing;
1257
+ }
1258
+ /**
1259
+ * Invoke a tool through the PTC pipeline.
1260
+ * Never throws - always returns a structured ToolResult.
1261
+ */
1262
+ async invoke(intent, ctx) {
1263
+ const startTime = Date.now();
1264
+ if (this.logger.isEnabled("debug")) {
1265
+ this.logger.debug("invoke.start", {
1266
+ tool: intent.tool,
1267
+ requestId: ctx.requestId,
1268
+ taskId: ctx.taskId,
1269
+ traceId: ctx.traceId,
1270
+ purpose: intent.purpose,
1271
+ args: this.logger.options.includeArgs ? sanitizeForLog(intent.args) : void 0
1272
+ });
1273
+ }
1274
+ const span = this.tracing.startSpan({
1275
+ name: `tool:${intent.tool}`,
1276
+ traceId: ctx.traceId,
1277
+ attributes: {
1278
+ "tool.name": intent.tool,
1279
+ "tool.purpose": intent.purpose,
1280
+ requestId: ctx.requestId,
1281
+ taskId: ctx.taskId
1282
+ }
1283
+ });
1284
+ emitToolCalled(intent, ctx, this.getObservabilityDeps());
1285
+ try {
1286
+ const spec = resolveTool(intent.tool, this.registry);
1287
+ this.tracing.addEvent(span.spanId, "resolved", {
1288
+ kind: spec.kind,
1289
+ version: spec.version
1290
+ });
1291
+ const validatedArgs = validateInput(spec, intent.args, this.validator);
1292
+ const enrichedArgs = enrichDefaults(spec, validatedArgs, this.validator);
1293
+ enforcePolicy(spec, enrichedArgs, ctx, {
1294
+ policy: this.policy,
1295
+ eventLog: this.eventLog,
1296
+ metrics: this.metrics,
1297
+ tracing: this.tracing
1298
+ });
1299
+ if (!this.budget.checkRateLimit(spec.name)) {
1300
+ throw createTaggedError(
1301
+ "BUDGET_EXCEEDED",
1302
+ `Rate limit exceeded for tool: ${spec.name}`
1303
+ );
1304
+ }
1305
+ await requireHumanApproval(spec, enrichedArgs, ctx, {
1306
+ onApprovalRequired: this.config.onApprovalRequired,
1307
+ eventLog: this.eventLog,
1308
+ logger: this.logger
1309
+ });
1310
+ if (ctx.dryRun) {
1311
+ return this.buildDryRunResult(spec, enrichedArgs, ctx, startTime, span.spanId);
1312
+ }
1313
+ const { result, raw } = await executeWithBudget(
1314
+ spec,
1315
+ enrichedArgs,
1316
+ ctx,
1317
+ span.spanId,
1318
+ this.getPipelineDeps()
1319
+ );
1320
+ const validatedOutput = validateOutput(spec, result, this.validator);
1321
+ const durationMs = Date.now() - startTime;
1322
+ const builtEvidence = buildEvidence({
1323
+ spec,
1324
+ args: enrichedArgs,
1325
+ result: validatedOutput,
1326
+ raw,
1327
+ ctx,
1328
+ durationMs
1329
+ });
1330
+ const adapterEvidence = raw && typeof raw === "object" && Array.isArray(raw.evidence) ? raw.evidence : [];
1331
+ const evidence = [...adapterEvidence, ...builtEvidence];
1332
+ recordSuccess(spec, durationMs, evidence, span.spanId, this.getObservabilityDeps());
1333
+ if (this.logger.isEnabled("debug")) {
1334
+ this.logger.debug("invoke.ok", {
1335
+ tool: spec.name,
1336
+ durationMs,
1337
+ result: this.logger.options.includeResults ? summarizeForLog(validatedOutput) : void 0,
1338
+ raw: this.logger.options.includeRaw ? summarizeForLog(raw) : void 0
1339
+ });
1340
+ }
1341
+ return {
1342
+ ok: true,
1343
+ result: validatedOutput,
1344
+ evidence,
1345
+ raw: this.config.includeRaw !== false ? raw : void 0
1346
+ };
1347
+ } catch (error) {
1348
+ const durationMs = Date.now() - startTime;
1349
+ return handleError(error, intent, ctx, durationMs, span.spanId, this.getObservabilityDeps());
1350
+ }
1351
+ }
1352
+ /**
1353
+ * Search for tools in the registry.
1354
+ */
1355
+ searchTools(query, filters) {
1356
+ return this.registry.search({
1357
+ text: query,
1358
+ kind: filters?.kind,
1359
+ capabilities: filters?.capabilities,
1360
+ tags: filters?.tags
1361
+ });
1362
+ }
1363
+ /**
1364
+ * Get the schema for a tool.
1365
+ */
1366
+ getToolSchema(toolName) {
1367
+ const spec = this.registry.get(toolName);
1368
+ if (!spec) return void 0;
1369
+ return { input: spec.inputSchema, output: spec.outputSchema };
1370
+ }
1371
+ // --- Helper Methods ---
1372
+ getPipelineDeps() {
1373
+ return {
1374
+ registry: this.registry,
1375
+ adapters: this.adapters,
1376
+ validator: this.validator,
1377
+ policy: this.policy,
1378
+ budget: this.budget,
1379
+ eventLog: this.eventLog,
1380
+ metrics: this.metrics,
1381
+ tracing: this.tracing,
1382
+ logger: this.logger,
1383
+ defaultMaxRetries: this.config.defaultMaxRetries,
1384
+ onApprovalRequired: this.config.onApprovalRequired
1385
+ };
1386
+ }
1387
+ getObservabilityDeps() {
1388
+ return {
1389
+ eventLog: this.eventLog,
1390
+ metrics: this.metrics,
1391
+ tracing: this.tracing,
1392
+ logger: this.logger
1393
+ };
1394
+ }
1395
+ buildDryRunResult(spec, args, _ctx, startTime, spanId) {
1396
+ this.tracing.endSpan(spanId, "ok");
1397
+ return {
1398
+ ok: true,
1399
+ result: {
1400
+ dryRun: true,
1401
+ tool: spec.name,
1402
+ kind: spec.kind,
1403
+ args,
1404
+ capabilities: spec.capabilities
1405
+ },
1406
+ evidence: [
1407
+ {
1408
+ type: "tool",
1409
+ ref: `${spec.name}@${spec.version}`,
1410
+ summary: `Dry-run: would execute ${spec.kind}:${spec.name}`,
1411
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1412
+ }
1413
+ ]
1414
+ };
1415
+ }
1416
+ };
1417
+
1418
+ // src/tools/util/toolDescriptor.ts
1419
+ var TOOL_PATH_REGEX = /^([a-z][a-z0-9-]*):([^/]+)\/([^#]+)(#(.+))?$/;
1420
+ function isToolPath(descriptor) {
1421
+ return TOOL_PATH_REGEX.test(descriptor.trim());
1422
+ }
1423
+ function parseToolPath(descriptor) {
1424
+ const s = descriptor.trim();
1425
+ const m = s.match(TOOL_PATH_REGEX);
1426
+ if (!m || m[1] === void 0 || m[2] === void 0 || m[3] === void 0) return null;
1427
+ return {
1428
+ protocol: m[1],
1429
+ scope: m[2],
1430
+ packageWithVersion: m[3],
1431
+ toolName: m[5] ?? ""
1432
+ };
1433
+ }
1434
+ function parsePackageVersion(packageWithVersion) {
1435
+ const at = packageWithVersion.lastIndexOf("@");
1436
+ if (at <= 0) return { package: packageWithVersion };
1437
+ const pkg = packageWithVersion.slice(0, at);
1438
+ const version = packageWithVersion.slice(at + 1);
1439
+ if (!version || /^\d/.test(version)) return { package: pkg, version };
1440
+ return { package: packageWithVersion };
1441
+ }
1442
+ function isNpmToolDescriptor(descriptor) {
1443
+ return isToolPath(descriptor) && parseToolPath(descriptor)?.protocol === "npm";
1444
+ }
1445
+ function parseNpmToolDescriptor(descriptor) {
1446
+ const parsed = parseToolPath(descriptor);
1447
+ if (!parsed || parsed.protocol !== "npm") return null;
1448
+ return {
1449
+ fullPackage: `${parsed.scope}/${parsed.packageWithVersion}`,
1450
+ toolPath: parsed.toolName
1451
+ };
1452
+ }
1453
+ var BUILTIN_NPM_PACKAGE = "@easynet/agent-tool-builtin";
1454
+ var BUILTIN_REGISTRY_PREFIX = "core/";
1455
+ var BUILTIN_DISPLAY_SCOPE_PREFIX = "npm:@easynet/agent-tool-builtin";
1456
+ function getDisplayScope(registryName, kind, toolVersion) {
1457
+ if (kind === "core" || registryName.startsWith(BUILTIN_REGISTRY_PREFIX)) {
1458
+ return toolVersion ? `${BUILTIN_DISPLAY_SCOPE_PREFIX}@${toolVersion}` : BUILTIN_DISPLAY_SCOPE_PREFIX;
1459
+ }
1460
+ const i = registryName.indexOf("/");
1461
+ return i < 0 ? registryName : registryName.slice(0, i);
1462
+ }
1463
+ function resolveNpmToolDescriptor(descriptor) {
1464
+ const parsed = parseToolPath(descriptor);
1465
+ if (!parsed || parsed.protocol !== "npm") return null;
1466
+ const pv = parsePackageVersion(parsed.packageWithVersion);
1467
+ const pkgId = `${parsed.scope}/${pv.package}`;
1468
+ if (pkgId !== BUILTIN_NPM_PACKAGE) return null;
1469
+ if (!parsed.toolName) return null;
1470
+ if (parsed.toolName.includes("*")) return null;
1471
+ return BUILTIN_REGISTRY_PREFIX + parsed.toolName;
1472
+ }
1473
+ function expandToolDescriptorsToRegistryNames(descriptors, registryNames) {
1474
+ const out = [];
1475
+ const seen = /* @__PURE__ */ new Set();
1476
+ function add(name) {
1477
+ if (registryNames.includes(name) && !seen.has(name)) {
1478
+ seen.add(name);
1479
+ out.push(name);
1480
+ }
1481
+ }
1482
+ function globMatch(pattern, name) {
1483
+ const re = new RegExp("^" + pattern.replace(/\*/g, "[^.]*").replace(/\./g, "\\.") + "$");
1484
+ return re.test(name);
1485
+ }
1486
+ for (const d of descriptors) {
1487
+ const s = d.trim();
1488
+ if (!s) continue;
1489
+ const parsed = parseToolPath(s);
1490
+ if (parsed && parsed.protocol === "npm") {
1491
+ const pv = parsePackageVersion(parsed.packageWithVersion);
1492
+ const pkgId = `${parsed.scope}/${pv.package}`;
1493
+ if (pkgId === BUILTIN_NPM_PACKAGE) {
1494
+ if (!parsed.toolName) {
1495
+ registryNames.filter((n) => n.startsWith(BUILTIN_REGISTRY_PREFIX)).forEach(add);
1496
+ continue;
1497
+ }
1498
+ if (parsed.toolName.includes("*")) {
1499
+ registryNames.filter((n) => n.startsWith(BUILTIN_REGISTRY_PREFIX) && globMatch(parsed.toolName, n.slice(BUILTIN_REGISTRY_PREFIX.length))).forEach(add);
1500
+ continue;
1501
+ }
1502
+ add(BUILTIN_REGISTRY_PREFIX + parsed.toolName);
1503
+ continue;
1504
+ }
1505
+ }
1506
+ add(s);
1507
+ }
1508
+ return out;
1509
+ }
1510
+ function resolveToolDescriptor(descriptor) {
1511
+ const s = descriptor.trim();
1512
+ const resolved = resolveNpmToolDescriptor(s);
1513
+ if (resolved !== null) return resolved;
1514
+ return s;
1515
+ }
1516
+ function normalizeToolList(descriptors) {
1517
+ const seen = /* @__PURE__ */ new Set();
1518
+ const out = [];
1519
+ for (const d of descriptors) {
1520
+ if (typeof d !== "string" || !d.trim()) continue;
1521
+ const name = resolveToolDescriptor(d);
1522
+ if (!seen.has(name)) {
1523
+ seen.add(name);
1524
+ out.push(name);
1525
+ }
1526
+ }
1527
+ return out;
1528
+ }
1529
+ function loadToolConfig(toolYamlPath) {
1530
+ const abs = resolve(toolYamlPath);
1531
+ const raw = readFileSync(abs, "utf8");
1532
+ const parsed = yaml.load(raw);
1533
+ if (!parsed || typeof parsed !== "object") return {};
1534
+ return parsed;
1535
+ }
1536
+ function resolveSandboxedPath(toolYamlPath, sandboxedPath) {
1537
+ const configDir = dirname(resolve(toolYamlPath));
1538
+ return resolve(configDir, sandboxedPath);
1539
+ }
1540
+ function findAndLoadToolConfig(dir) {
1541
+ const candidates = [join(dir, "tool.yaml"), join(dir, ".tool.yaml")];
1542
+ for (const p of candidates) {
1543
+ if (existsSync(p)) {
1544
+ const config = loadToolConfig(p);
1545
+ return { ...config, configPath: p };
1546
+ }
1547
+ }
1548
+ return {};
1549
+ }
1550
+ function createRuntimeFromConfigSync(options = {}) {
1551
+ const registry = new ToolRegistry();
1552
+ if (options.coreTools !== void 0) {
1553
+ const coreAdapter = registerCoreTools(registry, options.coreTools);
1554
+ const runtime2 = new PTCRuntime({ registry });
1555
+ runtime2.registerAdapter(coreAdapter);
1556
+ if (options.exampleTools !== void 0) {
1557
+ const exampleAdapter = registerExampleTools(registry, options.exampleTools);
1558
+ runtime2.registerAdapter(exampleAdapter);
1559
+ }
1560
+ return { runtime: runtime2, registry };
1561
+ }
1562
+ if (options.exampleTools !== void 0) {
1563
+ const exampleAdapter = registerExampleTools(registry, options.exampleTools);
1564
+ const runtime2 = new PTCRuntime({ registry });
1565
+ runtime2.registerAdapter(exampleAdapter);
1566
+ return { runtime: runtime2, registry };
1567
+ }
1568
+ const runtime = new PTCRuntime({ registry });
1569
+ return { runtime, registry };
1570
+ }
1571
+ async function createRuntimeFromConfig(options = {}) {
1572
+ return createRuntimeFromConfigSync(options);
1573
+ }
1574
+
1575
+ // src/tools/mcp/types.ts
1576
+ var MCP_KIND = "mcp";
1577
+
1578
+ // src/tools/langchain/types.ts
1579
+ var LANGCHAIN_KIND = "langchain";
1580
+ var LANGCHAIN_DIR_NAME = "langchain";
1581
+
1582
+ export { BudgetManager, EventLog, LANGCHAIN_DIR_NAME, LANGCHAIN_KIND, MCP_KIND, Metrics, PTCRuntime, PolicyDeniedError, PolicyEngine, SchemaValidationError, SchemaValidator, Tracing, buildEvidence, createLogger, createRuntimeFromConfig, createRuntimeFromConfigSync, expandToolDescriptorsToRegistryNames, findAndLoadToolConfig, getDisplayScope, isNpmToolDescriptor, loadToolConfig, normalizeToolList, parseNpmToolDescriptor, resolveNpmToolDescriptor, resolveSandboxedPath, resolveToolDescriptor, sanitizeForLog, summarizeForLog };
1583
+ //# sourceMappingURL=chunk-Q7KPGWC6.js.map
1584
+ //# sourceMappingURL=chunk-Q7KPGWC6.js.map