@easynet/agent-tool 1.0.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 (157) hide show
  1. package/README.md +103 -0
  2. package/dist/chunk-3YLVPZRJ.cjs +32 -0
  3. package/dist/chunk-3YLVPZRJ.cjs.map +1 -0
  4. package/dist/chunk-AXUNV4MK.js +28 -0
  5. package/dist/chunk-AXUNV4MK.js.map +1 -0
  6. package/dist/chunk-BM4EVYI5.js +1069 -0
  7. package/dist/chunk-BM4EVYI5.js.map +1 -0
  8. package/dist/chunk-P3UEAZHK.cjs +171 -0
  9. package/dist/chunk-P3UEAZHK.cjs.map +1 -0
  10. package/dist/chunk-RPAMQCFH.js +167 -0
  11. package/dist/chunk-RPAMQCFH.js.map +1 -0
  12. package/dist/chunk-Z7TGIG77.cjs +1108 -0
  13. package/dist/chunk-Z7TGIG77.cjs.map +1 -0
  14. package/dist/cli.cjs +154 -0
  15. package/dist/cli.cjs.map +1 -0
  16. package/dist/cli.d.ts +10 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +147 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/codegen/build.d.ts +23 -0
  21. package/dist/codegen/build.d.ts.map +1 -0
  22. package/dist/codegen/generator.d.ts +15 -0
  23. package/dist/codegen/generator.d.ts.map +1 -0
  24. package/dist/codegen/index.d.ts +21 -0
  25. package/dist/codegen/index.d.ts.map +1 -0
  26. package/dist/codegen/init.d.ts +17 -0
  27. package/dist/codegen/init.d.ts.map +1 -0
  28. package/dist/codegen/run.d.ts +19 -0
  29. package/dist/codegen/run.d.ts.map +1 -0
  30. package/dist/codegen/scan/scanN8n.d.ts +17 -0
  31. package/dist/codegen/scan/scanN8n.d.ts.map +1 -0
  32. package/dist/codegen/scan/scanSkill.d.ts +17 -0
  33. package/dist/codegen/scan/scanSkill.d.ts.map +1 -0
  34. package/dist/codegen/scan/scanTools.d.ts +31 -0
  35. package/dist/codegen/scan/scanTools.d.ts.map +1 -0
  36. package/dist/codegen/scan/scanner.d.ts +26 -0
  37. package/dist/codegen/scan/scanner.d.ts.map +1 -0
  38. package/dist/codegen/scan/schemaFromTs.d.ts +16 -0
  39. package/dist/codegen/scan/schemaFromTs.d.ts.map +1 -0
  40. package/dist/codegen/types.d.ts +81 -0
  41. package/dist/codegen/types.d.ts.map +1 -0
  42. package/dist/core.cjs +20 -0
  43. package/dist/core.cjs.map +1 -0
  44. package/dist/core.d.ts +8 -0
  45. package/dist/core.d.ts.map +1 -0
  46. package/dist/core.js +3 -0
  47. package/dist/core.js.map +1 -0
  48. package/dist/discovery/MCPProcessManager.d.ts +57 -0
  49. package/dist/discovery/MCPProcessManager.d.ts.map +1 -0
  50. package/dist/discovery/errors.d.ts +13 -0
  51. package/dist/discovery/errors.d.ts.map +1 -0
  52. package/dist/discovery/load/LangChainLoader.d.ts +7 -0
  53. package/dist/discovery/load/LangChainLoader.d.ts.map +1 -0
  54. package/dist/discovery/load/MCPLoader.d.ts +8 -0
  55. package/dist/discovery/load/MCPLoader.d.ts.map +1 -0
  56. package/dist/discovery/load/N8nLoader.d.ts +25 -0
  57. package/dist/discovery/load/N8nLoader.d.ts.map +1 -0
  58. package/dist/discovery/load/SkillLoader.d.ts +20 -0
  59. package/dist/discovery/load/SkillLoader.d.ts.map +1 -0
  60. package/dist/discovery/load/SkillManifest.d.ts +79 -0
  61. package/dist/discovery/load/SkillManifest.d.ts.map +1 -0
  62. package/dist/discovery/load/SkillMdParser.d.ts +31 -0
  63. package/dist/discovery/load/SkillMdParser.d.ts.map +1 -0
  64. package/dist/discovery/load/index.d.ts +6 -0
  65. package/dist/discovery/load/index.d.ts.map +1 -0
  66. package/dist/discovery/load/resolveEntry.d.ts +7 -0
  67. package/dist/discovery/load/resolveEntry.d.ts.map +1 -0
  68. package/dist/discovery/scan/DirectoryScanner.d.ts +37 -0
  69. package/dist/discovery/scan/DirectoryScanner.d.ts.map +1 -0
  70. package/dist/discovery/scan/scanUtil.d.ts +16 -0
  71. package/dist/discovery/scan/scanUtil.d.ts.map +1 -0
  72. package/dist/discovery/types.d.ts +99 -0
  73. package/dist/discovery/types.d.ts.map +1 -0
  74. package/dist/index.cjs +3014 -0
  75. package/dist/index.cjs.map +1 -0
  76. package/dist/index.d.ts +68 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +2778 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/llm/AgentLLMAdapter.d.ts +27 -0
  81. package/dist/llm/AgentLLMAdapter.d.ts.map +1 -0
  82. package/dist/llm/LangChainToolsHub.d.ts +31 -0
  83. package/dist/llm/LangChainToolsHub.d.ts.map +1 -0
  84. package/dist/llm/OpenAICompatibleClient.d.ts +64 -0
  85. package/dist/llm/OpenAICompatibleClient.d.ts.map +1 -0
  86. package/dist/llm/ReActAgent.d.ts +35 -0
  87. package/dist/llm/ReActAgent.d.ts.map +1 -0
  88. package/dist/llm-export.cjs +20 -0
  89. package/dist/llm-export.cjs.map +1 -0
  90. package/dist/llm-export.d.ts +9 -0
  91. package/dist/llm-export.d.ts.map +1 -0
  92. package/dist/llm-export.js +3 -0
  93. package/dist/llm-export.js.map +1 -0
  94. package/dist/mcp/MCPClientAdapter.d.ts +34 -0
  95. package/dist/mcp/MCPClientAdapter.d.ts.map +1 -0
  96. package/dist/mcp/connectMCP.d.ts +47 -0
  97. package/dist/mcp/connectMCP.d.ts.map +1 -0
  98. package/dist/mcp/index.d.ts +10 -0
  99. package/dist/mcp/index.d.ts.map +1 -0
  100. package/dist/mcp/registerMCPTools.d.ts +24 -0
  101. package/dist/mcp/registerMCPTools.d.ts.map +1 -0
  102. package/dist/observability/EventLog.d.ts +60 -0
  103. package/dist/observability/EventLog.d.ts.map +1 -0
  104. package/dist/observability/Logger.d.ts +33 -0
  105. package/dist/observability/Logger.d.ts.map +1 -0
  106. package/dist/observability/Metrics.d.ts +70 -0
  107. package/dist/observability/Metrics.d.ts.map +1 -0
  108. package/dist/observability/Tracing.d.ts +69 -0
  109. package/dist/observability/Tracing.d.ts.map +1 -0
  110. package/dist/registry/ToolRegistry.d.ts +68 -0
  111. package/dist/registry/ToolRegistry.d.ts.map +1 -0
  112. package/dist/report/AgentReportGenerator.d.ts +53 -0
  113. package/dist/report/AgentReportGenerator.d.ts.map +1 -0
  114. package/dist/report/agent-report-template.html +362 -0
  115. package/dist/report/index.d.ts +3 -0
  116. package/dist/report/index.d.ts.map +1 -0
  117. package/dist/report/types.d.ts +101 -0
  118. package/dist/report/types.d.ts.map +1 -0
  119. package/dist/runAgent.d.ts +37 -0
  120. package/dist/runAgent.d.ts.map +1 -0
  121. package/dist/runtime/Budget.d.ts +63 -0
  122. package/dist/runtime/Budget.d.ts.map +1 -0
  123. package/dist/runtime/Evidence.d.ts +19 -0
  124. package/dist/runtime/Evidence.d.ts.map +1 -0
  125. package/dist/runtime/PTCRuntime.d.ts +115 -0
  126. package/dist/runtime/PTCRuntime.d.ts.map +1 -0
  127. package/dist/runtime/PTCRuntimeObservability.d.ts +26 -0
  128. package/dist/runtime/PTCRuntimeObservability.d.ts.map +1 -0
  129. package/dist/runtime/PTCRuntimePipeline.d.ts +62 -0
  130. package/dist/runtime/PTCRuntimePipeline.d.ts.map +1 -0
  131. package/dist/runtime/PolicyEngine.d.ts +67 -0
  132. package/dist/runtime/PolicyEngine.d.ts.map +1 -0
  133. package/dist/runtime/Retry.d.ts +33 -0
  134. package/dist/runtime/Retry.d.ts.map +1 -0
  135. package/dist/runtime/SchemaValidator.d.ts +42 -0
  136. package/dist/runtime/SchemaValidator.d.ts.map +1 -0
  137. package/dist/templates/mcp-server.js +48 -0
  138. package/dist/templates/n8n-invoker.js +11 -0
  139. package/dist/templates/skill-invoker.js +11 -0
  140. package/dist/templates/tool-index.js +9 -0
  141. package/dist/toolDescriptor.d.ts +38 -0
  142. package/dist/toolDescriptor.d.ts.map +1 -0
  143. package/dist/types/Events.d.ts +99 -0
  144. package/dist/types/Events.d.ts.map +1 -0
  145. package/dist/types/ToolIntent.d.ts +40 -0
  146. package/dist/types/ToolIntent.d.ts.map +1 -0
  147. package/dist/types/ToolResult.d.ts +30 -0
  148. package/dist/types/ToolResult.d.ts.map +1 -0
  149. package/dist/types/ToolSpec.d.ts +99 -0
  150. package/dist/types/ToolSpec.d.ts.map +1 -0
  151. package/dist/types/index.d.ts +6 -0
  152. package/dist/types/index.d.ts.map +1 -0
  153. package/extensions/examples/README.md +40 -0
  154. package/extensions/examples/scripts/agent-tool-react-stock.mjs +30 -0
  155. package/extensions/examples/tools/instruction-only/skill/SKILL.md +26 -0
  156. package/extensions/examples/tools/web-search/mcp/mcp.json +8 -0
  157. package/package.json +122 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,3014 @@
1
+ 'use strict';
2
+
3
+ var chunkZ7TGIG77_cjs = require('./chunk-Z7TGIG77.cjs');
4
+ var chunk3YLVPZRJ_cjs = require('./chunk-3YLVPZRJ.cjs');
5
+ var chunkP3UEAZHK_cjs = require('./chunk-P3UEAZHK.cjs');
6
+ var Ajv = require('ajv');
7
+ var addFormats = require('ajv-formats');
8
+ var cockatiel = require('cockatiel');
9
+ var eventemitter3 = require('eventemitter3');
10
+ var uuid = require('uuid');
11
+ var pRetry = require('p-retry');
12
+ var pTimeout = require('p-timeout');
13
+ var agentToolBuiltinTools = require('@easynet/agent-tool-builtin-tools');
14
+ var agentToolExampleTools = require('@easynet/agent-tool-example-tools');
15
+ var promises = require('fs/promises');
16
+ var path = require('path');
17
+ var url = require('url');
18
+ var tools = require('@langchain/core/tools');
19
+ var fs = require('fs');
20
+ var yaml = require('js-yaml');
21
+ var agentLlm = require('@easynet/agent-llm');
22
+
23
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
24
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
25
+
26
+ var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
27
+ var addFormats__default = /*#__PURE__*/_interopDefault(addFormats);
28
+ var pRetry__default = /*#__PURE__*/_interopDefault(pRetry);
29
+ var pTimeout__default = /*#__PURE__*/_interopDefault(pTimeout);
30
+ var yaml__default = /*#__PURE__*/_interopDefault(yaml);
31
+
32
+ // src/registry/ToolRegistry.ts
33
+ var ToolRegistry = class {
34
+ tools = /* @__PURE__ */ new Map();
35
+ tagIndex = /* @__PURE__ */ new Map();
36
+ // tag → tool names
37
+ kindIndex = /* @__PURE__ */ new Map();
38
+ // kind → tool names
39
+ /**
40
+ * Register a single tool spec.
41
+ * Overwrites if same name already exists.
42
+ */
43
+ register(spec) {
44
+ this.validateSpec(spec);
45
+ this.tools.set(spec.name, spec);
46
+ this.indexTool(spec);
47
+ }
48
+ /**
49
+ * Register multiple tool specs at once.
50
+ */
51
+ bulkRegister(specs) {
52
+ for (const spec of specs) {
53
+ this.register(spec);
54
+ }
55
+ }
56
+ /**
57
+ * Unregister a tool by name.
58
+ */
59
+ unregister(name) {
60
+ const spec = this.tools.get(name);
61
+ if (!spec) return false;
62
+ this.tools.delete(name);
63
+ this.deindexTool(spec);
64
+ return true;
65
+ }
66
+ /**
67
+ * Get a tool spec by name.
68
+ */
69
+ get(name) {
70
+ return this.tools.get(name);
71
+ }
72
+ /**
73
+ * Check if a tool exists.
74
+ */
75
+ has(name) {
76
+ return this.tools.has(name);
77
+ }
78
+ /**
79
+ * Search tools by query.
80
+ */
81
+ search(query) {
82
+ let candidates;
83
+ if (query.kind) {
84
+ const names = this.kindIndex.get(query.kind);
85
+ if (!names || names.size === 0) return [];
86
+ candidates = [...names].map((n) => this.tools.get(n)).filter((s) => s !== void 0);
87
+ } else {
88
+ candidates = [...this.tools.values()];
89
+ }
90
+ if (query.tags && query.tags.length > 0) {
91
+ candidates = candidates.filter(
92
+ (spec) => query.tags.some((tag) => spec.tags?.includes(tag))
93
+ );
94
+ }
95
+ if (query.capabilities && query.capabilities.length > 0) {
96
+ candidates = candidates.filter(
97
+ (spec) => query.capabilities.every((cap) => spec.capabilities.includes(cap))
98
+ );
99
+ }
100
+ if (query.text) {
101
+ const lower = query.text.toLowerCase();
102
+ candidates = candidates.filter(
103
+ (spec) => spec.name.toLowerCase().includes(lower) || spec.description?.toLowerCase().includes(lower) || spec.tags?.some((t) => t.toLowerCase().includes(lower))
104
+ );
105
+ }
106
+ return candidates;
107
+ }
108
+ /**
109
+ * List all registered tool names.
110
+ */
111
+ list() {
112
+ return [...this.tools.keys()];
113
+ }
114
+ /**
115
+ * Get count of registered tools.
116
+ */
117
+ get size() {
118
+ return this.tools.size;
119
+ }
120
+ /**
121
+ * Export a snapshot of all registered tools (for debugging/routing).
122
+ */
123
+ snapshot() {
124
+ return [...this.tools.values()];
125
+ }
126
+ /**
127
+ * Clear all registered tools.
128
+ */
129
+ clear() {
130
+ this.tools.clear();
131
+ this.tagIndex.clear();
132
+ this.kindIndex.clear();
133
+ }
134
+ validateSpec(spec) {
135
+ if (!spec.name) throw new Error("ToolSpec.name is required");
136
+ if (!spec.version) throw new Error("ToolSpec.version is required");
137
+ if (!spec.kind) throw new Error("ToolSpec.kind is required");
138
+ if (!spec.inputSchema) throw new Error("ToolSpec.inputSchema is required");
139
+ if (!spec.outputSchema) throw new Error("ToolSpec.outputSchema is required");
140
+ if (!spec.capabilities) throw new Error("ToolSpec.capabilities is required");
141
+ }
142
+ indexTool(spec) {
143
+ let kindSet = this.kindIndex.get(spec.kind);
144
+ if (!kindSet) {
145
+ kindSet = /* @__PURE__ */ new Set();
146
+ this.kindIndex.set(spec.kind, kindSet);
147
+ }
148
+ kindSet.add(spec.name);
149
+ if (spec.tags) {
150
+ for (const tag of spec.tags) {
151
+ let tagSet = this.tagIndex.get(tag);
152
+ if (!tagSet) {
153
+ tagSet = /* @__PURE__ */ new Set();
154
+ this.tagIndex.set(tag, tagSet);
155
+ }
156
+ tagSet.add(spec.name);
157
+ }
158
+ }
159
+ }
160
+ deindexTool(spec) {
161
+ this.kindIndex.get(spec.kind)?.delete(spec.name);
162
+ if (spec.tags) {
163
+ for (const tag of spec.tags) {
164
+ this.tagIndex.get(tag)?.delete(spec.name);
165
+ }
166
+ }
167
+ }
168
+ };
169
+ var SchemaValidator = class {
170
+ ajv;
171
+ cache = /* @__PURE__ */ new Map();
172
+ constructor() {
173
+ this.ajv = new Ajv__default.default({
174
+ allErrors: true,
175
+ coerceTypes: true,
176
+ useDefaults: true,
177
+ removeAdditional: "failing",
178
+ strict: false
179
+ });
180
+ addFormats__default.default(this.ajv);
181
+ }
182
+ /**
183
+ * Validate data against a JSON Schema.
184
+ * Coerces types and applies defaults in-place.
185
+ */
186
+ validate(schema, data) {
187
+ const validate = this.getOrCompile(schema);
188
+ const cloned = structuredClone(data);
189
+ const valid = validate(cloned);
190
+ if (valid) {
191
+ return { valid: true, data: cloned };
192
+ }
193
+ return {
194
+ valid: false,
195
+ errors: validate.errors ?? void 0
196
+ };
197
+ }
198
+ /**
199
+ * Validate and return coerced data, or throw a descriptive error.
200
+ */
201
+ validateOrThrow(schema, data, context) {
202
+ const result = this.validate(schema, data);
203
+ if (!result.valid) {
204
+ const messages = (result.errors ?? []).map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ");
205
+ throw new SchemaValidationError(
206
+ `${context}: ${messages}`,
207
+ result.errors ?? []
208
+ );
209
+ }
210
+ return result.data;
211
+ }
212
+ /**
213
+ * Apply default values from schema to data without full validation.
214
+ */
215
+ enrichDefaults(schema, data) {
216
+ const validate = this.getOrCompile(schema);
217
+ const cloned = structuredClone(data);
218
+ validate(cloned);
219
+ return cloned;
220
+ }
221
+ getOrCompile(schema) {
222
+ const normalized = this.normalizeSchema(schema);
223
+ const key = JSON.stringify(normalized);
224
+ let cached = this.cache.get(key);
225
+ if (!cached) {
226
+ cached = this.ajv.compile(normalized);
227
+ this.cache.set(key, cached);
228
+ }
229
+ return cached;
230
+ }
231
+ /** Ensure schema is AJV-compatible (required = string[], nullable handled via type). */
232
+ normalizeSchema(schema) {
233
+ return this.normalizeSchemaRec(schema);
234
+ }
235
+ normalizeSchemaRec(s) {
236
+ const out = {};
237
+ for (const [key, value] of Object.entries(s)) {
238
+ if (key === "required") {
239
+ const raw = value;
240
+ out.required = Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : typeof raw === "string" ? [raw] : [];
241
+ continue;
242
+ }
243
+ if (key === "nullable") {
244
+ continue;
245
+ }
246
+ if (key === "properties" && value !== null && typeof value === "object") {
247
+ const props = {};
248
+ for (const [pk, pv] of Object.entries(value)) {
249
+ if (pv !== null && typeof pv === "object" && !Array.isArray(pv)) {
250
+ props[pk] = this.normalizeSchemaRec(pv);
251
+ } else {
252
+ props[pk] = pv;
253
+ }
254
+ }
255
+ out.properties = props;
256
+ continue;
257
+ }
258
+ if ((key === "items" || key === "additionalProperties") && value !== null && typeof value === "object" && !Array.isArray(value)) {
259
+ out[key] = this.normalizeSchemaRec(value);
260
+ continue;
261
+ }
262
+ if ((key === "oneOf" || key === "anyOf" || key === "allOf") && Array.isArray(value)) {
263
+ out[key] = value.map(
264
+ (item) => item !== null && typeof item === "object" && !Array.isArray(item) ? this.normalizeSchemaRec(item) : item
265
+ );
266
+ continue;
267
+ }
268
+ out[key] = value;
269
+ }
270
+ if (s.nullable === true) {
271
+ const existingType = out.type;
272
+ if (existingType === void 0) {
273
+ out.type = "object";
274
+ } else if (Array.isArray(existingType)) {
275
+ if (!existingType.includes("null")) out.type = [...existingType, "null"];
276
+ } else {
277
+ out.type = [existingType, "null"];
278
+ }
279
+ }
280
+ return out;
281
+ }
282
+ };
283
+ var SchemaValidationError = class extends Error {
284
+ constructor(message, errors) {
285
+ super(message);
286
+ this.errors = errors;
287
+ this.name = "SchemaValidationError";
288
+ }
289
+ };
290
+
291
+ // src/runtime/PolicyEngine.ts
292
+ var PolicyEngine = class {
293
+ config;
294
+ constructor(config = {}) {
295
+ this.config = {
296
+ requireExplicitDangerPermission: true,
297
+ deniedSqlPatterns: ["DROP\\s", "TRUNCATE\\s", "DELETE\\s+FROM\\s+\\w+\\s*$"],
298
+ ...config
299
+ };
300
+ }
301
+ /**
302
+ * Enforce all policy checks. Throws PolicyDeniedError if denied.
303
+ */
304
+ enforce(spec, args, ctx) {
305
+ const result = this.check(spec, args, ctx);
306
+ if (!result.allowed) {
307
+ throw new PolicyDeniedError(
308
+ result.reason ?? "Policy denied",
309
+ result.missingCapabilities
310
+ );
311
+ }
312
+ }
313
+ /**
314
+ * Check all policies without throwing.
315
+ */
316
+ check(spec, args, ctx) {
317
+ const capResult = this.checkCapabilities(spec, ctx);
318
+ if (!capResult.allowed) return capResult;
319
+ const paramResult = this.checkParameters(spec, args);
320
+ if (!paramResult.allowed) return paramResult;
321
+ return { allowed: true };
322
+ }
323
+ /**
324
+ * Check that context permissions cover tool capabilities.
325
+ */
326
+ checkCapabilities(spec, ctx) {
327
+ const missing = [];
328
+ for (const cap of spec.capabilities) {
329
+ if (cap === "danger:destructive") {
330
+ if (this.config.requireExplicitDangerPermission && !ctx.permissions.includes("danger:destructive")) {
331
+ missing.push(cap);
332
+ }
333
+ } else if (!ctx.permissions.includes(cap)) {
334
+ missing.push(cap);
335
+ }
336
+ }
337
+ if (missing.length > 0) {
338
+ return {
339
+ allowed: false,
340
+ reason: `Missing capabilities: ${missing.join(", ")}`,
341
+ missingCapabilities: missing
342
+ };
343
+ }
344
+ return { allowed: true };
345
+ }
346
+ /**
347
+ * Check parameter-level security constraints.
348
+ */
349
+ checkParameters(spec, args) {
350
+ if (!args || typeof args !== "object") return { allowed: true };
351
+ const argsObj = args;
352
+ if (spec.capabilities.includes("write:fs") && this.config.sandboxPaths) {
353
+ const pathResult = this.checkFilePaths(argsObj);
354
+ if (!pathResult.allowed) return pathResult;
355
+ }
356
+ if (spec.capabilities.includes("network") || spec.capabilities.includes("read:web")) {
357
+ const urlResult = this.checkUrls(argsObj);
358
+ if (!urlResult.allowed) return urlResult;
359
+ }
360
+ if (spec.capabilities.includes("write:db") || spec.capabilities.includes("read:db")) {
361
+ const sqlResult = this.checkSql(argsObj);
362
+ if (!sqlResult.allowed) return sqlResult;
363
+ }
364
+ if (spec.capabilities.includes("network") && this.config.allowedDomains) {
365
+ const domainResult = this.checkDomains(argsObj);
366
+ if (!domainResult.allowed) return domainResult;
367
+ }
368
+ return { allowed: true };
369
+ }
370
+ checkFilePaths(args) {
371
+ const paths = this.extractStringValues(args, ["path", "file", "filepath", "filename", "dir", "directory"]);
372
+ for (const p of paths) {
373
+ const normalized = p.replace(/\.\./g, "");
374
+ if (p.includes("..")) {
375
+ return {
376
+ allowed: false,
377
+ reason: `Path traversal detected: ${p}`
378
+ };
379
+ }
380
+ if (this.config.sandboxPaths && this.config.sandboxPaths.length > 0) {
381
+ const inSandbox = this.config.sandboxPaths.some(
382
+ (sp) => normalized.startsWith(sp)
383
+ );
384
+ if (!inSandbox) {
385
+ return {
386
+ allowed: false,
387
+ reason: `Path outside sandbox: ${p}. Allowed: ${this.config.sandboxPaths.join(", ")}`
388
+ };
389
+ }
390
+ }
391
+ }
392
+ return { allowed: true };
393
+ }
394
+ checkUrls(args) {
395
+ const urls = this.extractStringValues(args, ["url", "endpoint", "href", "uri"]);
396
+ for (const url of urls) {
397
+ if (this.config.urlDenylist) {
398
+ for (const pattern of this.config.urlDenylist) {
399
+ if (new RegExp(pattern, "i").test(url)) {
400
+ return {
401
+ allowed: false,
402
+ reason: `URL denied by policy: ${url}`
403
+ };
404
+ }
405
+ }
406
+ }
407
+ if (this.config.urlAllowlist && this.config.urlAllowlist.length > 0) {
408
+ const allowed = this.config.urlAllowlist.some(
409
+ (pattern) => new RegExp(pattern, "i").test(url)
410
+ );
411
+ if (!allowed) {
412
+ return {
413
+ allowed: false,
414
+ reason: `URL not in allowlist: ${url}`
415
+ };
416
+ }
417
+ }
418
+ }
419
+ return { allowed: true };
420
+ }
421
+ checkSql(args) {
422
+ const sqls = this.extractStringValues(args, ["sql", "query", "statement"]);
423
+ for (const sql of sqls) {
424
+ if (this.config.deniedSqlPatterns) {
425
+ for (const pattern of this.config.deniedSqlPatterns) {
426
+ if (new RegExp(pattern, "i").test(sql)) {
427
+ return {
428
+ allowed: false,
429
+ reason: `SQL pattern denied: ${sql.slice(0, 50)}...`
430
+ };
431
+ }
432
+ }
433
+ }
434
+ }
435
+ return { allowed: true };
436
+ }
437
+ checkDomains(args) {
438
+ const urls = this.extractStringValues(args, ["url", "endpoint", "href", "host", "domain"]);
439
+ for (const url of urls) {
440
+ try {
441
+ const hostname = url.includes("://") ? new URL(url).hostname : url;
442
+ if (this.config.allowedDomains && !this.config.allowedDomains.some(
443
+ (d) => hostname === d || hostname.endsWith(`.${d}`)
444
+ )) {
445
+ return {
446
+ allowed: false,
447
+ reason: `Domain not allowed: ${hostname}`
448
+ };
449
+ }
450
+ } catch {
451
+ }
452
+ }
453
+ return { allowed: true };
454
+ }
455
+ /**
456
+ * Extract string values from args matching given key patterns.
457
+ */
458
+ extractStringValues(args, keyPatterns) {
459
+ const results = [];
460
+ const walk = (obj) => {
461
+ for (const [key, val] of Object.entries(obj)) {
462
+ const lowerKey = key.toLowerCase();
463
+ if (typeof val === "string" && keyPatterns.some((p) => lowerKey.includes(p))) {
464
+ results.push(val);
465
+ } else if (val && typeof val === "object" && !Array.isArray(val)) {
466
+ walk(val);
467
+ }
468
+ }
469
+ };
470
+ walk(args);
471
+ return results;
472
+ }
473
+ };
474
+ var PolicyDeniedError = class extends Error {
475
+ constructor(message, missingCapabilities) {
476
+ super(message);
477
+ this.missingCapabilities = missingCapabilities;
478
+ this.name = "PolicyDeniedError";
479
+ }
480
+ kind = "POLICY_DENIED";
481
+ };
482
+ var RateLimiter = class {
483
+ constructor(maxCalls, windowMs) {
484
+ this.maxCalls = maxCalls;
485
+ this.windowMs = windowMs;
486
+ }
487
+ timestamps = [];
488
+ tryAcquire() {
489
+ const now = Date.now();
490
+ while (this.timestamps.length > 0 && this.timestamps[0] <= now - this.windowMs) {
491
+ this.timestamps.shift();
492
+ }
493
+ if (this.timestamps.length >= this.maxCalls) {
494
+ return false;
495
+ }
496
+ this.timestamps.push(now);
497
+ return true;
498
+ }
499
+ get remaining() {
500
+ const now = Date.now();
501
+ const active = this.timestamps.filter((t) => t > now - this.windowMs);
502
+ return Math.max(0, this.maxCalls - active.length);
503
+ }
504
+ };
505
+ var BudgetManager = class {
506
+ defaultTimeoutMs;
507
+ bulkheads = /* @__PURE__ */ new Map();
508
+ circuitBreakers = /* @__PURE__ */ new Map();
509
+ rateLimiters = /* @__PURE__ */ new Map();
510
+ options;
511
+ constructor(options = {}) {
512
+ this.options = options;
513
+ this.defaultTimeoutMs = options.defaultTimeoutMs ?? 3e4;
514
+ }
515
+ /**
516
+ * Get effective timeout for a tool invocation.
517
+ */
518
+ getTimeout(_toolName, contextTimeoutMs) {
519
+ return contextTimeoutMs ?? this.defaultTimeoutMs;
520
+ }
521
+ /**
522
+ * Check rate limit for a tool. Returns true if allowed.
523
+ */
524
+ checkRateLimit(toolName) {
525
+ if (!this.options.rateLimit) return true;
526
+ let limiter = this.rateLimiters.get(toolName);
527
+ if (!limiter) {
528
+ limiter = new RateLimiter(
529
+ this.options.rateLimit.maxCalls,
530
+ this.options.rateLimit.windowMs
531
+ );
532
+ this.rateLimiters.set(toolName, limiter);
533
+ }
534
+ return limiter.tryAcquire();
535
+ }
536
+ /**
537
+ * Get or create a bulkhead (concurrency limiter) for a tool.
538
+ */
539
+ getBulkhead(toolName) {
540
+ if (!this.options.maxConcurrency) return void 0;
541
+ let bh = this.bulkheads.get(toolName);
542
+ if (!bh) {
543
+ bh = cockatiel.bulkhead(this.options.maxConcurrency, 0);
544
+ this.bulkheads.set(toolName, bh);
545
+ }
546
+ return bh;
547
+ }
548
+ /**
549
+ * Get or create a circuit breaker for a tool.
550
+ */
551
+ getCircuitBreaker(toolName) {
552
+ if (!this.options.circuitBreaker) return void 0;
553
+ let breaker = this.circuitBreakers.get(toolName);
554
+ if (!breaker) {
555
+ breaker = cockatiel.circuitBreaker(cockatiel.handleAll, {
556
+ breaker: new cockatiel.ConsecutiveBreaker(this.options.circuitBreaker.threshold),
557
+ halfOpenAfter: this.options.circuitBreaker.halfOpenAfterMs
558
+ });
559
+ this.circuitBreakers.set(toolName, breaker);
560
+ }
561
+ return breaker;
562
+ }
563
+ /**
564
+ * Execute a function within budget constraints (bulkhead + circuit breaker).
565
+ */
566
+ async execute(toolName, fn) {
567
+ const bh = this.getBulkhead(toolName);
568
+ const breaker = this.getCircuitBreaker(toolName);
569
+ let wrapped = fn;
570
+ if (breaker) {
571
+ const prevWrapped = wrapped;
572
+ wrapped = () => breaker.execute(() => prevWrapped());
573
+ }
574
+ if (bh) {
575
+ const prevWrapped = wrapped;
576
+ wrapped = () => bh.execute(() => prevWrapped());
577
+ }
578
+ return wrapped();
579
+ }
580
+ /**
581
+ * Reset all policies for a tool (useful for testing).
582
+ */
583
+ reset(toolName) {
584
+ this.bulkheads.delete(toolName);
585
+ this.circuitBreakers.delete(toolName);
586
+ this.rateLimiters.delete(toolName);
587
+ }
588
+ /**
589
+ * Reset all policies globally.
590
+ */
591
+ resetAll() {
592
+ this.bulkheads.clear();
593
+ this.circuitBreakers.clear();
594
+ this.rateLimiters.clear();
595
+ }
596
+ };
597
+
598
+ // src/runtime/Evidence.ts
599
+ function buildEvidence(options) {
600
+ const { spec, args, result, ctx, durationMs } = options;
601
+ const now = (/* @__PURE__ */ new Date()).toISOString();
602
+ const evidence = [];
603
+ evidence.push({
604
+ type: "tool",
605
+ ref: `${spec.name}@${spec.version}`,
606
+ summary: summarizeToolCall(spec, args, result, durationMs),
607
+ createdAt: now
608
+ });
609
+ if (result && typeof result === "object") {
610
+ const urls = extractUrls(result);
611
+ for (const url of urls) {
612
+ evidence.push({
613
+ type: "url",
614
+ ref: url,
615
+ summary: `Output URL from ${spec.name}`,
616
+ createdAt: now
617
+ });
618
+ }
619
+ const files = extractFilePaths(result);
620
+ for (const file of files) {
621
+ evidence.push({
622
+ type: "file",
623
+ ref: file,
624
+ summary: `Output file from ${spec.name}`,
625
+ createdAt: now
626
+ });
627
+ }
628
+ }
629
+ if (durationMs !== void 0 && durationMs > 0) {
630
+ evidence.push({
631
+ type: "metric",
632
+ ref: `latency:${spec.name}`,
633
+ summary: `Completed in ${durationMs}ms (request: ${ctx.requestId})`,
634
+ createdAt: now
635
+ });
636
+ }
637
+ return evidence;
638
+ }
639
+ function summarizeToolCall(spec, args, result, durationMs) {
640
+ const argKeys = args && typeof args === "object" ? Object.keys(args).join(", ") : "none";
641
+ const duration = durationMs ? ` in ${durationMs}ms` : "";
642
+ const resultPreview = summarizeValue(result, 100);
643
+ return `${spec.kind}:${spec.name} called with [${argKeys}]${duration} \u2192 ${resultPreview}`;
644
+ }
645
+ function summarizeValue(value, maxLen) {
646
+ if (value === null || value === void 0) return "null";
647
+ if (typeof value === "string") {
648
+ return value.length > maxLen ? value.slice(0, maxLen) + "..." : value;
649
+ }
650
+ const str = JSON.stringify(value);
651
+ return str.length > maxLen ? str.slice(0, maxLen) + "..." : str;
652
+ }
653
+ function extractUrls(obj) {
654
+ const urls = [];
655
+ const walk = (val) => {
656
+ if (typeof val === "string" && /^https?:\/\//i.test(val)) {
657
+ urls.push(val);
658
+ } else if (val && typeof val === "object") {
659
+ for (const v of Object.values(val)) {
660
+ walk(v);
661
+ }
662
+ }
663
+ };
664
+ walk(obj);
665
+ return urls.slice(0, 10);
666
+ }
667
+ function extractFilePaths(obj) {
668
+ const paths = [];
669
+ const walk = (val) => {
670
+ if (typeof val === "string" && (val.startsWith("/") || val.startsWith("./")) && val.includes(".")) {
671
+ paths.push(val);
672
+ } else if (val && typeof val === "object") {
673
+ for (const v of Object.values(val)) {
674
+ walk(v);
675
+ }
676
+ }
677
+ };
678
+ walk(obj);
679
+ return paths.slice(0, 10);
680
+ }
681
+ var EventLog = class {
682
+ entries = [];
683
+ seq = 0;
684
+ maxEntries;
685
+ emitter = new eventemitter3.EventEmitter();
686
+ constructor(options = {}) {
687
+ this.maxEntries = options.maxEntries ?? 1e4;
688
+ }
689
+ /**
690
+ * Append an event to the log.
691
+ */
692
+ append(event) {
693
+ const entry = { seq: ++this.seq, event };
694
+ this.entries.push(entry);
695
+ if (this.entries.length > this.maxEntries) {
696
+ this.entries.shift();
697
+ }
698
+ this.emitter.emit("event", entry);
699
+ this.emitter.emit(event.type, entry);
700
+ return entry;
701
+ }
702
+ /**
703
+ * Subscribe to all events.
704
+ */
705
+ on(listener) {
706
+ this.emitter.on("event", listener);
707
+ return () => this.emitter.off("event", listener);
708
+ }
709
+ /**
710
+ * Subscribe to events of a specific type.
711
+ */
712
+ onType(type, listener) {
713
+ this.emitter.on(type, listener);
714
+ return () => this.emitter.off(type, listener);
715
+ }
716
+ /**
717
+ * Query events by filter.
718
+ */
719
+ query(filter) {
720
+ let results = this.entries;
721
+ if (filter.since !== void 0) {
722
+ results = results.filter((e) => e.seq > filter.since);
723
+ }
724
+ if (filter.type) {
725
+ results = results.filter((e) => e.event.type === filter.type);
726
+ }
727
+ if (filter.toolName) {
728
+ results = results.filter((e) => e.event.toolName === filter.toolName);
729
+ }
730
+ if (filter.requestId) {
731
+ results = results.filter((e) => e.event.requestId === filter.requestId);
732
+ }
733
+ if (filter.limit) {
734
+ results = results.slice(-filter.limit);
735
+ }
736
+ return results;
737
+ }
738
+ /**
739
+ * Get all entries.
740
+ */
741
+ getAll() {
742
+ return this.entries;
743
+ }
744
+ /**
745
+ * Get entry count.
746
+ */
747
+ get size() {
748
+ return this.entries.length;
749
+ }
750
+ /**
751
+ * Clear all entries (for testing).
752
+ */
753
+ clear() {
754
+ this.entries.length = 0;
755
+ this.seq = 0;
756
+ }
757
+ };
758
+
759
+ // src/observability/Logger.ts
760
+ var LEVEL_ORDER = {
761
+ silent: 0,
762
+ error: 1,
763
+ warn: 2,
764
+ info: 3,
765
+ debug: 4,
766
+ trace: 5
767
+ };
768
+ function createLogger(options = {}) {
769
+ const resolved = resolveDebugOptions(options);
770
+ const log = (level, message, meta) => {
771
+ if (!resolved.enabled) return;
772
+ if (LEVEL_ORDER[level] > LEVEL_ORDER[resolved.level]) return;
773
+ const prefix = `[${resolved.prefix}]`;
774
+ const levelTag = `[${level.toUpperCase()}]`;
775
+ const metaText = meta ? ` ${safeStringify(meta, 1e3)}` : "";
776
+ switch (level) {
777
+ case "error":
778
+ console.error(`${prefix} ${levelTag} ${message}${metaText}`);
779
+ break;
780
+ case "warn":
781
+ console.warn(`${prefix} ${levelTag} ${message}${metaText}`);
782
+ break;
783
+ case "info":
784
+ console.info(`${prefix} ${levelTag} ${message}${metaText}`);
785
+ break;
786
+ default:
787
+ console.log(`${prefix} ${levelTag} ${message}${metaText}`);
788
+ break;
789
+ }
790
+ };
791
+ return {
792
+ options: resolved,
793
+ isEnabled: (level) => resolved.enabled && LEVEL_ORDER[level] <= LEVEL_ORDER[resolved.level],
794
+ error: (message, meta) => log("error", message, meta),
795
+ warn: (message, meta) => log("warn", message, meta),
796
+ info: (message, meta) => log("info", message, meta),
797
+ debug: (message, meta) => log("debug", message, meta),
798
+ trace: (message, meta) => log("trace", message, meta)
799
+ };
800
+ }
801
+ function resolveDebugOptions(options = {}) {
802
+ const envLevel = parseEnvLogLevel();
803
+ const enabledFromEnv = envLevel !== void 0 && envLevel !== "silent";
804
+ const enabled = options.enabled ?? enabledFromEnv ?? false;
805
+ const level = options.level ?? envLevel ?? (enabled ? "debug" : "silent");
806
+ return {
807
+ enabled,
808
+ level,
809
+ includeArgs: options.includeArgs ?? false,
810
+ includeResults: options.includeResults ?? false,
811
+ includeRaw: options.includeRaw ?? false,
812
+ logEvents: options.logEvents ?? false,
813
+ prefix: options.prefix ?? "agent-tool"
814
+ };
815
+ }
816
+ function sanitizeForLog(value, maxLen = 500) {
817
+ const str = safeStringify(value, maxLen);
818
+ return str.replace(
819
+ /"(password|token|secret|key|auth)":\s*"[^"]*"/gi,
820
+ '"$1":"[REDACTED]"'
821
+ );
822
+ }
823
+ function summarizeForLog(value, maxLen = 200) {
824
+ if (value === null) return "null";
825
+ if (value === void 0) return "undefined";
826
+ if (typeof value === "string") {
827
+ return value.length > maxLen ? `${value.slice(0, maxLen)}...` : value;
828
+ }
829
+ if (typeof value === "number" || typeof value === "boolean") {
830
+ return String(value);
831
+ }
832
+ if (Array.isArray(value)) {
833
+ return `Array(${value.length})`;
834
+ }
835
+ if (typeof value === "object") {
836
+ const keys = Object.keys(value);
837
+ const shown = keys.slice(0, 5).join(", ");
838
+ return `Object(keys: ${shown}${keys.length > 5 ? ", ..." : ""})`;
839
+ }
840
+ return String(value);
841
+ }
842
+ function safeStringify(value, maxLen) {
843
+ try {
844
+ const json = JSON.stringify(value);
845
+ if (!json) return String(value);
846
+ return json.length > maxLen ? `${json.slice(0, maxLen)}...` : json;
847
+ } catch {
848
+ const fallback = String(value);
849
+ return fallback.length > maxLen ? `${fallback.slice(0, maxLen)}...` : fallback;
850
+ }
851
+ }
852
+ function parseEnvLogLevel() {
853
+ const raw = process.env.TOOLHUB_LOG_LEVEL ?? process.env.TOOLHUB_DEBUG ?? process.env.DEBUG;
854
+ if (!raw) return void 0;
855
+ const value = raw.trim().toLowerCase();
856
+ if (!value || value === "0" || value === "false" || value === "off") {
857
+ return "silent";
858
+ }
859
+ if (value.includes("trace")) return "trace";
860
+ if (value.includes("debug") || value === "1" || value === "true" || value === "yes") {
861
+ return "debug";
862
+ }
863
+ if (value.includes("info")) return "info";
864
+ if (value.includes("warn")) return "warn";
865
+ if (value.includes("error")) return "error";
866
+ if (value.includes("silent")) return "silent";
867
+ return "debug";
868
+ }
869
+
870
+ // src/observability/Metrics.ts
871
+ var Metrics = class {
872
+ counters = /* @__PURE__ */ new Map();
873
+ histograms = /* @__PURE__ */ new Map();
874
+ defaultBuckets = [
875
+ 5,
876
+ 10,
877
+ 25,
878
+ 50,
879
+ 100,
880
+ 250,
881
+ 500,
882
+ 1e3,
883
+ 2500,
884
+ 5e3,
885
+ 1e4
886
+ ];
887
+ /**
888
+ * Increment a counter.
889
+ */
890
+ increment(name, labels = {}, value = 1) {
891
+ const key = this.makeKey(name, labels);
892
+ this.counters.set(key, (this.counters.get(key) ?? 0) + value);
893
+ }
894
+ /**
895
+ * Record a value in a histogram.
896
+ */
897
+ observe(name, labels, value) {
898
+ const key = this.makeKey(name, labels);
899
+ let hist = this.histograms.get(key);
900
+ if (!hist) {
901
+ hist = { count: 0, sum: 0, values: [] };
902
+ this.histograms.set(key, hist);
903
+ }
904
+ hist.count++;
905
+ hist.sum += value;
906
+ hist.values.push(value);
907
+ }
908
+ /**
909
+ * Get a counter value.
910
+ */
911
+ getCounter(name, labels = {}) {
912
+ return this.counters.get(this.makeKey(name, labels)) ?? 0;
913
+ }
914
+ /**
915
+ * Get histogram stats.
916
+ */
917
+ getHistogram(name, labels) {
918
+ const key = this.makeKey(name, labels);
919
+ const hist = this.histograms.get(key);
920
+ if (!hist) return void 0;
921
+ const buckets = /* @__PURE__ */ new Map();
922
+ for (const bound of this.defaultBuckets) {
923
+ buckets.set(bound, hist.values.filter((v) => v <= bound).length);
924
+ }
925
+ return { name, labels, count: hist.count, sum: hist.sum, buckets };
926
+ }
927
+ /**
928
+ * Get all counter values.
929
+ */
930
+ getAllCounters() {
931
+ const results = [];
932
+ for (const [key, value] of this.counters) {
933
+ const { name, labels } = this.parseKey(key);
934
+ results.push({ name, labels, value });
935
+ }
936
+ return results;
937
+ }
938
+ /**
939
+ * Get all histogram values.
940
+ */
941
+ getAllHistograms() {
942
+ const results = [];
943
+ for (const [key, hist] of this.histograms) {
944
+ const { name, labels } = this.parseKey(key);
945
+ const buckets = /* @__PURE__ */ new Map();
946
+ for (const bound of this.defaultBuckets) {
947
+ buckets.set(bound, hist.values.filter((v) => v <= bound).length);
948
+ }
949
+ results.push({ name, labels, count: hist.count, sum: hist.sum, buckets });
950
+ }
951
+ return results;
952
+ }
953
+ /**
954
+ * Record standard tool invocation metrics.
955
+ */
956
+ recordInvocation(toolName, ok, durationMs) {
957
+ this.increment("tool_invocations_total", {
958
+ toolName,
959
+ ok: String(ok)
960
+ });
961
+ this.observe("tool_latency_ms", { toolName }, durationMs);
962
+ }
963
+ /**
964
+ * Record a retry event.
965
+ */
966
+ recordRetry(toolName) {
967
+ this.increment("tool_retries_total", { toolName });
968
+ }
969
+ /**
970
+ * Record a policy denial.
971
+ */
972
+ recordPolicyDenied(toolName, reason) {
973
+ this.increment("policy_denied_total", { toolName, reason });
974
+ }
975
+ /**
976
+ * Reset all metrics (for testing).
977
+ */
978
+ reset() {
979
+ this.counters.clear();
980
+ this.histograms.clear();
981
+ }
982
+ makeKey(name, labels) {
983
+ const sortedLabels = Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
984
+ return `${name}{${sortedLabels}}`;
985
+ }
986
+ parseKey(key) {
987
+ const match = key.match(/^(.+?)\{(.*)\}$/);
988
+ if (!match) return { name: key, labels: {} };
989
+ const labels = {};
990
+ if (match[2]) {
991
+ for (const part of match[2].split(",")) {
992
+ const [k, v] = part.split("=");
993
+ if (k && v !== void 0) labels[k] = v;
994
+ }
995
+ }
996
+ return { name: match[1], labels };
997
+ }
998
+ };
999
+ var Tracing = class {
1000
+ spans = /* @__PURE__ */ new Map();
1001
+ traceSpans = /* @__PURE__ */ new Map();
1002
+ // traceId → spanIds
1003
+ /**
1004
+ * Start a new span.
1005
+ */
1006
+ startSpan(options) {
1007
+ const span = {
1008
+ spanId: uuid.v4(),
1009
+ traceId: options.traceId ?? uuid.v4(),
1010
+ parentSpanId: options.parentSpanId,
1011
+ name: options.name,
1012
+ startTime: Date.now(),
1013
+ status: "in_progress",
1014
+ attributes: options.attributes ?? {},
1015
+ events: []
1016
+ };
1017
+ this.spans.set(span.spanId, span);
1018
+ const traceList = this.traceSpans.get(span.traceId) ?? [];
1019
+ traceList.push(span.spanId);
1020
+ this.traceSpans.set(span.traceId, traceList);
1021
+ return span;
1022
+ }
1023
+ /**
1024
+ * End a span and calculate duration.
1025
+ */
1026
+ endSpan(spanId, status = "ok") {
1027
+ const span = this.spans.get(spanId);
1028
+ if (!span) return void 0;
1029
+ span.endTime = Date.now();
1030
+ span.durationMs = span.endTime - span.startTime;
1031
+ span.status = status;
1032
+ return span;
1033
+ }
1034
+ /**
1035
+ * Add an event to a span.
1036
+ */
1037
+ addEvent(spanId, name, attributes) {
1038
+ const span = this.spans.get(spanId);
1039
+ if (!span) return;
1040
+ span.events.push({ name, timestamp: Date.now(), attributes });
1041
+ }
1042
+ /**
1043
+ * Set attributes on a span.
1044
+ */
1045
+ setAttributes(spanId, attributes) {
1046
+ const span = this.spans.get(spanId);
1047
+ if (!span) return;
1048
+ Object.assign(span.attributes, attributes);
1049
+ }
1050
+ /**
1051
+ * Get a span by ID.
1052
+ */
1053
+ getSpan(spanId) {
1054
+ return this.spans.get(spanId);
1055
+ }
1056
+ /**
1057
+ * Get all spans for a trace.
1058
+ */
1059
+ getTrace(traceId) {
1060
+ const spanIds = this.traceSpans.get(traceId) ?? [];
1061
+ return spanIds.map((id) => this.spans.get(id)).filter((s) => s !== void 0);
1062
+ }
1063
+ /**
1064
+ * Create a child span from a parent.
1065
+ */
1066
+ createChildSpan(parentSpanId, name, attributes) {
1067
+ const parent = this.spans.get(parentSpanId);
1068
+ if (!parent) return void 0;
1069
+ return this.startSpan({
1070
+ name,
1071
+ traceId: parent.traceId,
1072
+ parentSpanId: parent.spanId,
1073
+ attributes
1074
+ });
1075
+ }
1076
+ /**
1077
+ * Clear all traces (for testing).
1078
+ */
1079
+ clear() {
1080
+ this.spans.clear();
1081
+ this.traceSpans.clear();
1082
+ }
1083
+ };
1084
+ var NON_RETRYABLE_ERRORS = /* @__PURE__ */ new Set([
1085
+ "TOOL_NOT_FOUND",
1086
+ "INPUT_SCHEMA_INVALID",
1087
+ "POLICY_DENIED",
1088
+ "HITL_DENIED",
1089
+ "OUTPUT_SCHEMA_INVALID",
1090
+ "PATH_OUTSIDE_SANDBOX",
1091
+ "FILE_TOO_LARGE",
1092
+ "HTTP_DISALLOWED_HOST",
1093
+ "HTTP_TOO_LARGE"
1094
+ ]);
1095
+ function isRetryable(error) {
1096
+ if (error instanceof Error) {
1097
+ const kind = error.kind;
1098
+ if (kind && NON_RETRYABLE_ERRORS.has(kind)) return false;
1099
+ }
1100
+ return true;
1101
+ }
1102
+ async function withRetry(fn, options = {}) {
1103
+ const {
1104
+ maxRetries = 2,
1105
+ baseDelayMs = 1e3,
1106
+ maxDelayMs = 1e4,
1107
+ jitter = 0.1,
1108
+ shouldRetry,
1109
+ onRetry
1110
+ } = options;
1111
+ if (maxRetries <= 0) {
1112
+ return fn();
1113
+ }
1114
+ const pRetryOptions = {
1115
+ retries: maxRetries,
1116
+ minTimeout: baseDelayMs,
1117
+ maxTimeout: maxDelayMs,
1118
+ randomize: true,
1119
+ factor: 2,
1120
+ onFailedAttempt: (error) => {
1121
+ if (jitter > 0 && error.retriesLeft > 0) ;
1122
+ if (shouldRetry && !shouldRetry(error)) {
1123
+ throw error;
1124
+ }
1125
+ if (!isRetryable(error)) {
1126
+ throw error;
1127
+ }
1128
+ onRetry?.(error, maxRetries - error.retriesLeft);
1129
+ }
1130
+ };
1131
+ return pRetry__default.default(fn, pRetryOptions);
1132
+ }
1133
+ function createTaggedError(kind, message, details) {
1134
+ const error = new Error(message);
1135
+ error.kind = kind;
1136
+ error.details = details;
1137
+ return error;
1138
+ }
1139
+ function resolveTool(toolName, registry) {
1140
+ const spec = registry.get(toolName);
1141
+ if (!spec) {
1142
+ throw createTaggedError(
1143
+ "TOOL_NOT_FOUND",
1144
+ `Tool not found: ${toolName}`,
1145
+ { availableTools: registry.snapshot().slice(0, 20).map((s) => s.name) }
1146
+ );
1147
+ }
1148
+ return spec;
1149
+ }
1150
+ function validateInput(spec, args, validator) {
1151
+ try {
1152
+ return validator.validateOrThrow(
1153
+ spec.inputSchema,
1154
+ args,
1155
+ `Input validation failed for ${spec.name}`
1156
+ );
1157
+ } catch (error) {
1158
+ if (error instanceof SchemaValidationError) {
1159
+ throw createTaggedError("INPUT_SCHEMA_INVALID", error.message, {
1160
+ errors: error.errors,
1161
+ schema: spec.inputSchema
1162
+ });
1163
+ }
1164
+ throw error;
1165
+ }
1166
+ }
1167
+ function enrichDefaults(spec, args, validator) {
1168
+ return validator.enrichDefaults(spec.inputSchema, args);
1169
+ }
1170
+ function enforcePolicy(spec, args, ctx, deps) {
1171
+ try {
1172
+ deps.policy.enforce(spec, args, ctx);
1173
+ } catch (error) {
1174
+ if (error instanceof PolicyDeniedError) {
1175
+ const event = {
1176
+ type: "POLICY_DENIED",
1177
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1178
+ requestId: ctx.requestId,
1179
+ taskId: ctx.taskId,
1180
+ toolName: spec.name,
1181
+ traceId: ctx.traceId,
1182
+ userId: ctx.userId,
1183
+ reason: error.message,
1184
+ missingCapabilities: error.missingCapabilities?.map(String)
1185
+ };
1186
+ deps.eventLog.append(event);
1187
+ deps.metrics.recordPolicyDenied(spec.name, error.message);
1188
+ }
1189
+ throw error;
1190
+ }
1191
+ }
1192
+ var HITL_GATED_SIDE_EFFECTS = ["external_write", "destructive"];
1193
+ async function requireHumanApproval(spec, args, ctx, deps) {
1194
+ const sideEffect = spec._meta?.hitl?.sideEffect ?? "none";
1195
+ if (!HITL_GATED_SIDE_EFFECTS.includes(sideEffect)) return;
1196
+ const onApproval = deps.onApprovalRequired;
1197
+ if (!onApproval) return;
1198
+ const baseEvent = {
1199
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1200
+ requestId: ctx.requestId,
1201
+ taskId: ctx.taskId,
1202
+ toolName: spec.name,
1203
+ traceId: ctx.traceId,
1204
+ userId: ctx.userId
1205
+ };
1206
+ const requested = {
1207
+ ...baseEvent,
1208
+ type: "HITL_APPROVAL_REQUESTED",
1209
+ sideEffect
1210
+ };
1211
+ deps.eventLog.append(requested);
1212
+ deps.logger.trace("hitl.requested", { tool: spec.name, sideEffect, requestId: ctx.requestId });
1213
+ let approved;
1214
+ try {
1215
+ approved = await onApproval(spec, args, ctx);
1216
+ } catch (err) {
1217
+ deps.eventLog.append({
1218
+ ...baseEvent,
1219
+ type: "HITL_APPROVAL_DENIED",
1220
+ sideEffect,
1221
+ reason: err instanceof Error ? err.message : String(err)
1222
+ });
1223
+ throw createTaggedError(
1224
+ "HITL_DENIED",
1225
+ `Human denied approval for ${spec.name} (${sideEffect})`,
1226
+ { reason: err instanceof Error ? err.message : String(err) }
1227
+ );
1228
+ }
1229
+ if (approved === false) {
1230
+ deps.eventLog.append({
1231
+ ...baseEvent,
1232
+ type: "HITL_APPROVAL_DENIED",
1233
+ sideEffect,
1234
+ reason: "User rejected"
1235
+ });
1236
+ throw createTaggedError("HITL_DENIED", `Human denied approval for ${spec.name} (${sideEffect})`);
1237
+ }
1238
+ deps.eventLog.append({
1239
+ ...baseEvent,
1240
+ type: "HITL_APPROVAL_GRANTED",
1241
+ sideEffect
1242
+ });
1243
+ deps.logger.trace("hitl.granted", { tool: spec.name, sideEffect, requestId: ctx.requestId });
1244
+ }
1245
+ async function executeWithBudget(spec, args, ctx, spanId, deps) {
1246
+ const adapter = deps.adapters.get(spec.kind);
1247
+ if (!adapter) {
1248
+ throw createTaggedError(
1249
+ "TOOL_NOT_FOUND",
1250
+ `No adapter registered for kind: ${spec.kind}`
1251
+ );
1252
+ }
1253
+ const timeoutMs = deps.budget.getTimeout(
1254
+ spec.name,
1255
+ ctx.budget?.timeoutMs
1256
+ );
1257
+ const maxRetries = ctx.budget?.maxRetries ?? deps.defaultMaxRetries ?? 2;
1258
+ const executeFn = async () => {
1259
+ return deps.budget.execute(spec.name, async () => {
1260
+ deps.tracing.addEvent(spanId, "execute_start");
1261
+ deps.logger.trace("execute.start", {
1262
+ tool: spec.name,
1263
+ requestId: ctx.requestId,
1264
+ timeoutMs,
1265
+ maxRetries
1266
+ });
1267
+ const result = await adapter.invoke(spec, args, ctx);
1268
+ deps.tracing.addEvent(spanId, "execute_end");
1269
+ deps.logger.trace("execute.end", {
1270
+ tool: spec.name,
1271
+ requestId: ctx.requestId
1272
+ });
1273
+ return result;
1274
+ });
1275
+ };
1276
+ const retryFn = () => withRetry(executeFn, {
1277
+ maxRetries,
1278
+ onRetry: (error, attempt) => {
1279
+ deps.metrics.recordRetry(spec.name);
1280
+ const event = {
1281
+ type: "RETRY",
1282
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1283
+ requestId: ctx.requestId,
1284
+ taskId: ctx.taskId,
1285
+ toolName: spec.name,
1286
+ traceId: ctx.traceId,
1287
+ userId: ctx.userId,
1288
+ attempt,
1289
+ maxRetries,
1290
+ reason: error.message
1291
+ };
1292
+ deps.eventLog.append(event);
1293
+ deps.tracing.addEvent(spanId, "retry", { attempt, reason: error.message });
1294
+ }
1295
+ });
1296
+ try {
1297
+ return await pTimeout__default.default(retryFn(), {
1298
+ milliseconds: timeoutMs,
1299
+ message: `Tool ${spec.name} timed out after ${timeoutMs}ms`
1300
+ });
1301
+ } catch (error) {
1302
+ if (error instanceof Error && error.message.includes("timed out")) {
1303
+ throw createTaggedError("TIMEOUT", error.message);
1304
+ }
1305
+ throw error;
1306
+ }
1307
+ }
1308
+ function validateOutput(spec, result, validator) {
1309
+ try {
1310
+ return validator.validateOrThrow(
1311
+ spec.outputSchema,
1312
+ result,
1313
+ `Output validation failed for ${spec.name}`
1314
+ );
1315
+ } catch (error) {
1316
+ if (error instanceof SchemaValidationError) {
1317
+ throw createTaggedError("OUTPUT_SCHEMA_INVALID", error.message, {
1318
+ errors: error.errors
1319
+ });
1320
+ }
1321
+ throw error;
1322
+ }
1323
+ }
1324
+
1325
+ // src/runtime/PTCRuntimeObservability.ts
1326
+ function emitToolCalled(intent, ctx, deps) {
1327
+ const event = {
1328
+ type: "TOOL_CALLED",
1329
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1330
+ requestId: ctx.requestId,
1331
+ taskId: ctx.taskId,
1332
+ toolName: intent.tool,
1333
+ traceId: ctx.traceId,
1334
+ userId: ctx.userId,
1335
+ argsSummary: sanitizeArgs(intent.args),
1336
+ purpose: intent.purpose,
1337
+ idempotencyKey: intent.idempotencyKey
1338
+ };
1339
+ deps.eventLog.append(event);
1340
+ }
1341
+ function recordSuccess(spec, durationMs, _evidence, spanId, deps) {
1342
+ deps.metrics.recordInvocation(spec.name, true, durationMs);
1343
+ deps.tracing.setAttributes(spanId, {
1344
+ "tool.duration_ms": durationMs,
1345
+ "tool.ok": true
1346
+ });
1347
+ deps.tracing.endSpan(spanId, "ok");
1348
+ }
1349
+ function handleError(error, intent, ctx, durationMs, spanId, deps) {
1350
+ const kind = error?.kind ?? "UPSTREAM_ERROR";
1351
+ const message = error instanceof Error ? error.message : String(error);
1352
+ const details = error?.details;
1353
+ deps.metrics.recordInvocation(intent.tool, false, durationMs);
1354
+ deps.tracing.setAttributes(spanId, {
1355
+ "tool.duration_ms": durationMs,
1356
+ "tool.ok": false,
1357
+ "tool.error_kind": kind
1358
+ });
1359
+ deps.tracing.endSpan(spanId, "error");
1360
+ const event = {
1361
+ type: "TOOL_RESULT",
1362
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1363
+ requestId: ctx.requestId,
1364
+ taskId: ctx.taskId,
1365
+ toolName: intent.tool,
1366
+ traceId: ctx.traceId,
1367
+ userId: ctx.userId,
1368
+ ok: false,
1369
+ durationMs,
1370
+ resultSummary: message,
1371
+ evidence: [],
1372
+ error: { kind, message, details }
1373
+ };
1374
+ deps.eventLog.append(event);
1375
+ deps.logger.warn("invoke.error", {
1376
+ tool: intent.tool,
1377
+ requestId: ctx.requestId,
1378
+ taskId: ctx.taskId,
1379
+ traceId: ctx.traceId,
1380
+ kind,
1381
+ message,
1382
+ durationMs,
1383
+ details: deps.logger.options.includeResults ? summarizeForLog(details) : void 0
1384
+ });
1385
+ return {
1386
+ ok: false,
1387
+ evidence: [],
1388
+ error: { kind, message, details }
1389
+ };
1390
+ }
1391
+ function sanitizeArgs(args) {
1392
+ if (!args) return "{}";
1393
+ return sanitizeForLog(args);
1394
+ }
1395
+
1396
+ // src/runtime/PTCRuntime.ts
1397
+ var PTCRuntime = class {
1398
+ registry;
1399
+ adapters = /* @__PURE__ */ new Map();
1400
+ validator;
1401
+ policy;
1402
+ budget;
1403
+ eventLog;
1404
+ metrics;
1405
+ tracing;
1406
+ config;
1407
+ logger;
1408
+ constructor(options = {}) {
1409
+ this.config = options.config ?? {};
1410
+ this.registry = options.registry ?? new ToolRegistry();
1411
+ this.validator = options.validator ?? new SchemaValidator();
1412
+ this.policy = options.policy ?? new PolicyEngine(this.config.policy);
1413
+ this.budget = options.budget ?? new BudgetManager(this.config.budget);
1414
+ this.eventLog = options.eventLog ?? new EventLog();
1415
+ this.metrics = options.metrics ?? new Metrics();
1416
+ this.tracing = options.tracing ?? new Tracing();
1417
+ this.logger = createLogger({ ...this.config.debug, prefix: "PTCRuntime" });
1418
+ if (this.logger.options.logEvents) {
1419
+ this.eventLog.on((entry) => {
1420
+ const event = entry.event;
1421
+ this.logger.debug("event", {
1422
+ seq: entry.seq,
1423
+ type: event.type,
1424
+ toolName: event.toolName,
1425
+ requestId: event.requestId,
1426
+ taskId: event.taskId,
1427
+ ok: "ok" in event ? event.ok : void 0
1428
+ });
1429
+ });
1430
+ }
1431
+ }
1432
+ /**
1433
+ * Register an adapter for a tool kind.
1434
+ */
1435
+ registerAdapter(adapter) {
1436
+ this.adapters.set(adapter.kind, adapter);
1437
+ }
1438
+ /**
1439
+ * Get an adapter by kind (e.g. "mcp"). Use to set MCP client via adapter.setClient().
1440
+ */
1441
+ getAdapter(kind) {
1442
+ return this.adapters.get(kind);
1443
+ }
1444
+ /**
1445
+ * Get the tool registry.
1446
+ */
1447
+ getRegistry() {
1448
+ return this.registry;
1449
+ }
1450
+ /**
1451
+ * Get the event log.
1452
+ */
1453
+ getEventLog() {
1454
+ return this.eventLog;
1455
+ }
1456
+ /**
1457
+ * Get the metrics collector.
1458
+ */
1459
+ getMetrics() {
1460
+ return this.metrics;
1461
+ }
1462
+ /**
1463
+ * Get the tracing system.
1464
+ */
1465
+ getTracing() {
1466
+ return this.tracing;
1467
+ }
1468
+ /**
1469
+ * Invoke a tool through the PTC pipeline.
1470
+ * Never throws - always returns a structured ToolResult.
1471
+ */
1472
+ async invoke(intent, ctx) {
1473
+ const startTime = Date.now();
1474
+ if (this.logger.isEnabled("debug")) {
1475
+ this.logger.debug("invoke.start", {
1476
+ tool: intent.tool,
1477
+ requestId: ctx.requestId,
1478
+ taskId: ctx.taskId,
1479
+ traceId: ctx.traceId,
1480
+ purpose: intent.purpose,
1481
+ args: this.logger.options.includeArgs ? sanitizeForLog(intent.args) : void 0
1482
+ });
1483
+ }
1484
+ const span = this.tracing.startSpan({
1485
+ name: `tool:${intent.tool}`,
1486
+ traceId: ctx.traceId,
1487
+ attributes: {
1488
+ "tool.name": intent.tool,
1489
+ "tool.purpose": intent.purpose,
1490
+ requestId: ctx.requestId,
1491
+ taskId: ctx.taskId
1492
+ }
1493
+ });
1494
+ emitToolCalled(intent, ctx, this.getObservabilityDeps());
1495
+ try {
1496
+ const spec = resolveTool(intent.tool, this.registry);
1497
+ this.tracing.addEvent(span.spanId, "resolved", {
1498
+ kind: spec.kind,
1499
+ version: spec.version
1500
+ });
1501
+ const validatedArgs = validateInput(spec, intent.args, this.validator);
1502
+ const enrichedArgs = enrichDefaults(spec, validatedArgs, this.validator);
1503
+ enforcePolicy(spec, enrichedArgs, ctx, {
1504
+ policy: this.policy,
1505
+ eventLog: this.eventLog,
1506
+ metrics: this.metrics,
1507
+ tracing: this.tracing
1508
+ });
1509
+ if (!this.budget.checkRateLimit(spec.name)) {
1510
+ throw createTaggedError(
1511
+ "BUDGET_EXCEEDED",
1512
+ `Rate limit exceeded for tool: ${spec.name}`
1513
+ );
1514
+ }
1515
+ await requireHumanApproval(spec, enrichedArgs, ctx, {
1516
+ onApprovalRequired: this.config.onApprovalRequired,
1517
+ eventLog: this.eventLog,
1518
+ logger: this.logger
1519
+ });
1520
+ if (ctx.dryRun) {
1521
+ return this.buildDryRunResult(spec, enrichedArgs, ctx, startTime, span.spanId);
1522
+ }
1523
+ const { result, raw } = await executeWithBudget(
1524
+ spec,
1525
+ enrichedArgs,
1526
+ ctx,
1527
+ span.spanId,
1528
+ this.getPipelineDeps()
1529
+ );
1530
+ const validatedOutput = validateOutput(spec, result, this.validator);
1531
+ const durationMs = Date.now() - startTime;
1532
+ const builtEvidence = buildEvidence({
1533
+ spec,
1534
+ args: enrichedArgs,
1535
+ result: validatedOutput,
1536
+ raw,
1537
+ ctx,
1538
+ durationMs
1539
+ });
1540
+ const adapterEvidence = raw && typeof raw === "object" && Array.isArray(raw.evidence) ? raw.evidence : [];
1541
+ const evidence = [...adapterEvidence, ...builtEvidence];
1542
+ recordSuccess(spec, durationMs, evidence, span.spanId, this.getObservabilityDeps());
1543
+ if (this.logger.isEnabled("debug")) {
1544
+ this.logger.debug("invoke.ok", {
1545
+ tool: spec.name,
1546
+ durationMs,
1547
+ result: this.logger.options.includeResults ? summarizeForLog(validatedOutput) : void 0,
1548
+ raw: this.logger.options.includeRaw ? summarizeForLog(raw) : void 0
1549
+ });
1550
+ }
1551
+ return {
1552
+ ok: true,
1553
+ result: validatedOutput,
1554
+ evidence,
1555
+ raw: this.config.includeRaw !== false ? raw : void 0
1556
+ };
1557
+ } catch (error) {
1558
+ const durationMs = Date.now() - startTime;
1559
+ return handleError(error, intent, ctx, durationMs, span.spanId, this.getObservabilityDeps());
1560
+ }
1561
+ }
1562
+ /**
1563
+ * Search for tools in the registry.
1564
+ */
1565
+ searchTools(query, filters) {
1566
+ return this.registry.search({
1567
+ text: query,
1568
+ kind: filters?.kind,
1569
+ capabilities: filters?.capabilities,
1570
+ tags: filters?.tags
1571
+ });
1572
+ }
1573
+ /**
1574
+ * Get the schema for a tool.
1575
+ */
1576
+ getToolSchema(toolName) {
1577
+ const spec = this.registry.get(toolName);
1578
+ if (!spec) return void 0;
1579
+ return { input: spec.inputSchema, output: spec.outputSchema };
1580
+ }
1581
+ // --- Helper Methods ---
1582
+ getPipelineDeps() {
1583
+ return {
1584
+ registry: this.registry,
1585
+ adapters: this.adapters,
1586
+ validator: this.validator,
1587
+ policy: this.policy,
1588
+ budget: this.budget,
1589
+ eventLog: this.eventLog,
1590
+ metrics: this.metrics,
1591
+ tracing: this.tracing,
1592
+ logger: this.logger,
1593
+ defaultMaxRetries: this.config.defaultMaxRetries,
1594
+ onApprovalRequired: this.config.onApprovalRequired
1595
+ };
1596
+ }
1597
+ getObservabilityDeps() {
1598
+ return {
1599
+ eventLog: this.eventLog,
1600
+ metrics: this.metrics,
1601
+ tracing: this.tracing,
1602
+ logger: this.logger
1603
+ };
1604
+ }
1605
+ buildDryRunResult(spec, args, _ctx, startTime, spanId) {
1606
+ this.tracing.endSpan(spanId, "ok");
1607
+ return {
1608
+ ok: true,
1609
+ result: {
1610
+ dryRun: true,
1611
+ tool: spec.name,
1612
+ kind: spec.kind,
1613
+ args,
1614
+ capabilities: spec.capabilities
1615
+ },
1616
+ evidence: [
1617
+ {
1618
+ type: "tool",
1619
+ ref: `${spec.name}@${spec.version}`,
1620
+ summary: `Dry-run: would execute ${spec.kind}:${spec.name}`,
1621
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1622
+ }
1623
+ ]
1624
+ };
1625
+ }
1626
+ };
1627
+
1628
+ // src/toolDescriptor.ts
1629
+ var NPM_TOOL_DESCRIPTOR_REGEX = /^npm:(@[\w.-]+\/[\w.-]+)#(.+)$/;
1630
+ function isNpmToolDescriptor(descriptor) {
1631
+ return NPM_TOOL_DESCRIPTOR_REGEX.test(descriptor.trim());
1632
+ }
1633
+ function parseNpmToolDescriptor(descriptor) {
1634
+ const s = descriptor.trim();
1635
+ const m = s.match(NPM_TOOL_DESCRIPTOR_REGEX);
1636
+ if (!m) return null;
1637
+ return { fullPackage: m[1], toolPath: m[2] };
1638
+ }
1639
+ var KNOWN_PACKAGE_PREFIX = {
1640
+ "@easynet/agent-tool-builtin-tools": "core/",
1641
+ "@easynet/agent-tool-buildin-tools": "core/",
1642
+ // alias (e.g. npm:@easynet/agent-tool-buildin#fs.readText)
1643
+ "@easynet/agent-tool-buildin": "core/",
1644
+ // shorthand
1645
+ "@easynet/agent-tool-example-tools": "example/"
1646
+ };
1647
+ function resolveNpmToolDescriptor(descriptor) {
1648
+ const parsed = parseNpmToolDescriptor(descriptor);
1649
+ if (!parsed) return null;
1650
+ const prefix = KNOWN_PACKAGE_PREFIX[parsed.fullPackage];
1651
+ if (!prefix) return null;
1652
+ const path = parsed.toolPath;
1653
+ if (path.startsWith(prefix)) return path;
1654
+ return prefix + path;
1655
+ }
1656
+ function resolveToolDescriptor(descriptor) {
1657
+ const s = descriptor.trim();
1658
+ const resolved = resolveNpmToolDescriptor(s);
1659
+ if (resolved !== null) return resolved;
1660
+ return s;
1661
+ }
1662
+ function normalizeToolList(descriptors) {
1663
+ const seen = /* @__PURE__ */ new Set();
1664
+ const out = [];
1665
+ for (const d of descriptors) {
1666
+ if (typeof d !== "string" || !d.trim()) continue;
1667
+ const name = resolveToolDescriptor(d);
1668
+ if (!seen.has(name)) {
1669
+ seen.add(name);
1670
+ out.push(name);
1671
+ }
1672
+ }
1673
+ return out;
1674
+ }
1675
+ function isCursorFormat(obj) {
1676
+ return typeof obj === "object" && obj !== null && "mcpServers" in obj && typeof obj.mcpServers === "object" && obj.mcpServers !== null;
1677
+ }
1678
+ function extractMCPConfig(parsed, toolName) {
1679
+ if (isCursorFormat(parsed)) {
1680
+ const servers = parsed.mcpServers;
1681
+ const keys = Object.keys(servers);
1682
+ if (keys.length === 0) {
1683
+ return {};
1684
+ }
1685
+ const name = toolName && keys.includes(toolName) ? toolName : keys[0];
1686
+ return servers[name];
1687
+ }
1688
+ return parsed;
1689
+ }
1690
+ async function loadMCPTool(dirPath, manifest) {
1691
+ const mcpPath = path.join(dirPath, manifest.entryPoint ?? "mcp.json");
1692
+ let raw;
1693
+ try {
1694
+ raw = await promises.readFile(mcpPath, "utf-8");
1695
+ } catch (err) {
1696
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1697
+ dirPath,
1698
+ "load",
1699
+ `Failed to read MCP config: ${mcpPath}`,
1700
+ err
1701
+ );
1702
+ }
1703
+ let parsed;
1704
+ try {
1705
+ parsed = JSON.parse(raw);
1706
+ } catch (err) {
1707
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1708
+ dirPath,
1709
+ "load",
1710
+ `Invalid JSON in ${mcpPath}`,
1711
+ err
1712
+ );
1713
+ }
1714
+ const baseName = manifest.name?.split("/").pop();
1715
+ const config = extractMCPConfig(parsed, baseName);
1716
+ if (!config.command && !config.url) {
1717
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1718
+ dirPath,
1719
+ "validate",
1720
+ `mcp.json must have either "command" or "url" field`
1721
+ );
1722
+ }
1723
+ return { manifest, dirPath, mcpConfig: config };
1724
+ }
1725
+ var DEFAULT_EXTENSIONS = [".js", ".mjs"];
1726
+ async function resolveEntryPoint(dirPath, baseName, extensions = DEFAULT_EXTENSIONS) {
1727
+ if (extensions.some((ext) => baseName.endsWith(ext))) {
1728
+ const fullPath = path.join(dirPath, baseName);
1729
+ await promises.stat(fullPath);
1730
+ return fullPath;
1731
+ }
1732
+ for (const ext of extensions) {
1733
+ const fullPath = path.join(dirPath, `${baseName}${ext}`);
1734
+ try {
1735
+ await promises.stat(fullPath);
1736
+ return fullPath;
1737
+ } catch {
1738
+ }
1739
+ }
1740
+ throw new Error(
1741
+ `Could not find entry point in ${dirPath}. Tried: ${extensions.map((e) => baseName + e).join(", ")}`
1742
+ );
1743
+ }
1744
+
1745
+ // src/discovery/load/LangChainLoader.ts
1746
+ async function loadLangChainTool(dirPath, manifest, extensions) {
1747
+ let entryFile;
1748
+ try {
1749
+ entryFile = await resolveEntryPoint(
1750
+ dirPath,
1751
+ manifest.entryPoint ?? "index",
1752
+ extensions
1753
+ );
1754
+ } catch (err) {
1755
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1756
+ dirPath,
1757
+ "load",
1758
+ `Cannot find LangChain entry point`,
1759
+ err
1760
+ );
1761
+ }
1762
+ let mod;
1763
+ try {
1764
+ mod = await import(url.pathToFileURL(entryFile).href);
1765
+ } catch (err) {
1766
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1767
+ dirPath,
1768
+ "load",
1769
+ `Failed to import ${entryFile}`,
1770
+ err
1771
+ );
1772
+ }
1773
+ const tool = mod.default ?? mod.tool ?? mod;
1774
+ if (!tool || typeof tool.invoke !== "function") {
1775
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1776
+ dirPath,
1777
+ "validate",
1778
+ `Entry point must export an object with invoke() method (LangChainToolLike)`
1779
+ );
1780
+ }
1781
+ return { manifest, dirPath, impl: tool };
1782
+ }
1783
+ var DEFAULT_EXTENSIONS2 = [".js", ".mjs"];
1784
+ async function listSkillProgramFiles(dirPath, extensions = DEFAULT_EXTENSIONS2) {
1785
+ let entries;
1786
+ try {
1787
+ const dirEntries = await promises.readdir(dirPath, { withFileTypes: true });
1788
+ entries = dirEntries.map((entry) => ({
1789
+ name: entry.name,
1790
+ isFile: entry.isFile()
1791
+ }));
1792
+ } catch {
1793
+ return [];
1794
+ }
1795
+ return entries.filter((e) => e.isFile).map((e) => e.name).filter((name) => {
1796
+ if (name.startsWith(".") || name.startsWith("_")) return false;
1797
+ if (name.includes(".test.") || name.includes(".spec.")) return false;
1798
+ return extensions.some((ext) => name.endsWith(ext));
1799
+ }).sort((a, b) => {
1800
+ if (a === "handler.js" || a === "index.js") return -1;
1801
+ if (b === "handler.js" || b === "index.js") return 1;
1802
+ return a.localeCompare(b);
1803
+ });
1804
+ }
1805
+ function isLangChainLikeTool(val) {
1806
+ return val != null && typeof val === "object" && "invoke" in val && typeof val.invoke === "function";
1807
+ }
1808
+ function isConstructable(val) {
1809
+ return typeof val === "function" && typeof val.prototype === "object";
1810
+ }
1811
+ async function loadOneSkillProgram(dirPath, manifest, entryFile, skillDef, programKey, extensions) {
1812
+ let impl;
1813
+ try {
1814
+ const fullPath = await resolveEntryPoint(dirPath, entryFile, extensions ?? [".js", ".mjs"]);
1815
+ const mod = await import(url.pathToFileURL(fullPath).href);
1816
+ const fn = mod.default ?? mod.handler ?? mod.Tool;
1817
+ if (isLangChainLikeTool(fn)) {
1818
+ impl = fn;
1819
+ } else if (isConstructable(fn)) {
1820
+ const instance = new fn();
1821
+ if (isLangChainLikeTool(instance)) impl = instance;
1822
+ } else if (typeof fn === "function") {
1823
+ impl = fn;
1824
+ }
1825
+ } catch {
1826
+ }
1827
+ return {
1828
+ manifest,
1829
+ dirPath,
1830
+ impl,
1831
+ skillDefinition: skillDef,
1832
+ programKey
1833
+ };
1834
+ }
1835
+ async function loadSkillTools(dirPath, manifest, extensions) {
1836
+ let skillDef;
1837
+ try {
1838
+ skillDef = await chunkZ7TGIG77_cjs.loadSkillDefinition(dirPath);
1839
+ } catch (err) {
1840
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
1841
+ dirPath,
1842
+ "load",
1843
+ `Failed to parse SKILL.md: ${err.message}`,
1844
+ err
1845
+ );
1846
+ }
1847
+ const programs = manifest.programs;
1848
+ if (programs && typeof programs === "object" && Object.keys(programs).length > 0) {
1849
+ const result = [];
1850
+ for (const [programKey, entryFile2] of Object.entries(programs)) {
1851
+ const loaded2 = await loadOneSkillProgram(
1852
+ dirPath,
1853
+ manifest,
1854
+ entryFile2,
1855
+ skillDef,
1856
+ programKey,
1857
+ extensions
1858
+ );
1859
+ result.push(loaded2);
1860
+ }
1861
+ return result;
1862
+ }
1863
+ const exts = extensions ?? DEFAULT_EXTENSIONS2;
1864
+ const files = await listSkillProgramFiles(dirPath, exts);
1865
+ if (files.length >= 2) {
1866
+ const result = [];
1867
+ for (let i = 0; i < files.length; i++) {
1868
+ const file = files[i];
1869
+ const programKey = i === 0 ? "default" : file.replace(/\.[^.]+$/, "");
1870
+ const loaded2 = await loadOneSkillProgram(
1871
+ dirPath,
1872
+ manifest,
1873
+ file,
1874
+ skillDef,
1875
+ programKey,
1876
+ extensions
1877
+ );
1878
+ result.push(loaded2);
1879
+ }
1880
+ return result;
1881
+ }
1882
+ const entryFile = manifest.entryPoint ?? files[0] ?? "handler";
1883
+ const loaded = await loadOneSkillProgram(
1884
+ dirPath,
1885
+ manifest,
1886
+ entryFile,
1887
+ skillDef,
1888
+ void 0,
1889
+ extensions
1890
+ );
1891
+ return [loaded];
1892
+ }
1893
+
1894
+ // src/discovery/scan/DirectoryScanner.ts
1895
+ var DEFAULT_EXTENSIONS3 = [".js", ".mjs"];
1896
+ var DirectoryScanner = class {
1897
+ roots;
1898
+ extensions;
1899
+ onError;
1900
+ constructor(options) {
1901
+ const defaultNamespace = options.namespace ?? "dir";
1902
+ this.roots = options.roots.map((root) => {
1903
+ if (typeof root === "string") {
1904
+ return { path: root, namespace: defaultNamespace };
1905
+ }
1906
+ return {
1907
+ path: root.path,
1908
+ namespace: root.namespace ?? defaultNamespace
1909
+ };
1910
+ });
1911
+ this.extensions = options.extensions ?? DEFAULT_EXTENSIONS3;
1912
+ this.onError = options.onError;
1913
+ }
1914
+ /**
1915
+ * Scan all root directories and return discovered ToolSpecs.
1916
+ * Errors in individual tool directories are reported via onError
1917
+ * and do not prevent other tools from loading.
1918
+ */
1919
+ async scan() {
1920
+ const specs = [];
1921
+ for (const root of this.roots) {
1922
+ const rootSpecs = await this.scanRoot(root.path, root.namespace);
1923
+ specs.push(...rootSpecs);
1924
+ }
1925
+ return specs;
1926
+ }
1927
+ async scanRoot(rootPath, namespace) {
1928
+ return this.scanRecursive(rootPath, namespace);
1929
+ }
1930
+ /**
1931
+ * Recursively scan directories for tool definitions.
1932
+ * Directories can be detected via tool.json or inferred markers.
1933
+ */
1934
+ async scanRecursive(dirPath, namespace) {
1935
+ const specs = [];
1936
+ let dirEntries;
1937
+ try {
1938
+ const entries = await promises.readdir(dirPath, { withFileTypes: true });
1939
+ dirEntries = entries.map((entry) => ({
1940
+ name: entry.name,
1941
+ isDirectory: entry.isDirectory()
1942
+ }));
1943
+ } catch (error) {
1944
+ this.onError?.(dirPath, error);
1945
+ return specs;
1946
+ }
1947
+ const dirName = path.basename(dirPath);
1948
+ try {
1949
+ const loadedSpecs = await this.loadToolDir(dirPath, dirName, namespace);
1950
+ if (loadedSpecs.length > 0) {
1951
+ specs.push(...loadedSpecs);
1952
+ }
1953
+ } catch (error) {
1954
+ this.onError?.(dirPath, error);
1955
+ }
1956
+ for (const entry of dirEntries) {
1957
+ if (!entry.isDirectory) {
1958
+ continue;
1959
+ }
1960
+ const childPath = path.join(dirPath, entry.name);
1961
+ try {
1962
+ const childSpecs = await this.scanRecursive(childPath, namespace);
1963
+ specs.push(...childSpecs);
1964
+ } catch (error) {
1965
+ this.onError?.(childPath, error);
1966
+ }
1967
+ }
1968
+ return specs;
1969
+ }
1970
+ async loadToolDir(dirPath, dirName, namespace) {
1971
+ const manifestPath = path.join(dirPath, "tool.json");
1972
+ let manifestRaw;
1973
+ try {
1974
+ manifestRaw = await promises.readFile(manifestPath, "utf-8");
1975
+ } catch {
1976
+ const inferred = await this.inferManifest(dirPath, dirName);
1977
+ if (!inferred) {
1978
+ return [];
1979
+ }
1980
+ if (inferred.kind === "langchain") {
1981
+ if (inferred.entryPoint) {
1982
+ const loaded3 = await loadLangChainTool(dirPath, inferred, this.extensions);
1983
+ return [this.toToolSpec(loaded3, dirName, dirPath, namespace)];
1984
+ }
1985
+ return this.loadLangChainTools(dirPath, dirName, inferred, false, namespace);
1986
+ }
1987
+ if (inferred.kind === "skill") {
1988
+ const loadedList = await loadSkillTools(dirPath, inferred, this.extensions);
1989
+ return loadedList.map(
1990
+ (loaded3) => this.toToolSpec(loaded3, dirName, dirPath, namespace)
1991
+ );
1992
+ }
1993
+ const loaded2 = await this.loadByKind(dirPath, inferred);
1994
+ return [this.toToolSpec(loaded2, dirName, dirPath, namespace)];
1995
+ }
1996
+ let manifest;
1997
+ try {
1998
+ manifest = JSON.parse(manifestRaw);
1999
+ } catch (err) {
2000
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
2001
+ dirPath,
2002
+ "manifest",
2003
+ "Invalid JSON in tool.json",
2004
+ err
2005
+ );
2006
+ }
2007
+ if (!manifest.kind) {
2008
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
2009
+ dirPath,
2010
+ "manifest",
2011
+ `tool.json must have a "kind" field`
2012
+ );
2013
+ }
2014
+ if (manifest.enabled === false) {
2015
+ return [];
2016
+ }
2017
+ if (manifest.kind === "langchain") {
2018
+ if (manifest.entryPoint) {
2019
+ const loaded2 = await loadLangChainTool(dirPath, manifest, this.extensions);
2020
+ return [this.toToolSpec(loaded2, dirName, dirPath, namespace)];
2021
+ }
2022
+ return this.loadLangChainTools(dirPath, dirName, manifest, true, namespace);
2023
+ }
2024
+ if (manifest.kind === "skill") {
2025
+ const loadedList = await loadSkillTools(dirPath, manifest, this.extensions);
2026
+ return loadedList.map(
2027
+ (loaded2) => this.toToolSpec(loaded2, dirName, dirPath, namespace)
2028
+ );
2029
+ }
2030
+ const loaded = await this.loadByKind(dirPath, manifest);
2031
+ return [this.toToolSpec(loaded, dirName, dirPath, namespace)];
2032
+ }
2033
+ async inferManifest(dirPath, dirName) {
2034
+ const hasSkill = await this.fileExists(path.join(dirPath, "SKILL.md"));
2035
+ const hasN8n = await this.fileExists(path.join(dirPath, "workflow.json"));
2036
+ const hasMcp = await this.fileExists(path.join(dirPath, "mcp.json"));
2037
+ const isLangchainDir = dirName === "langchain";
2038
+ const hasLangchain = isLangchainDir ? await this.hasLangchainFiles(dirPath) : dirName !== "skill" && await this.hasEntryPoint(dirPath, "index");
2039
+ const kinds = [
2040
+ hasSkill ? "skill" : null,
2041
+ hasN8n ? "n8n" : null,
2042
+ hasMcp ? "mcp" : null,
2043
+ hasLangchain ? "langchain" : null
2044
+ ].filter(Boolean);
2045
+ if (kinds.length === 0) return null;
2046
+ if (kinds.length > 1) {
2047
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
2048
+ dirPath,
2049
+ "manifest",
2050
+ `Ambiguous tool kind (found ${kinds.join(", ")}). Add tool.json to disambiguate.`
2051
+ );
2052
+ }
2053
+ const kind = kinds[0];
2054
+ const manifest = { kind };
2055
+ if (kind === "n8n") manifest.entryPoint = "workflow.json";
2056
+ if (kind === "mcp") manifest.entryPoint = "mcp.json";
2057
+ if (kind === "langchain" && !isLangchainDir) manifest.entryPoint = "index";
2058
+ if (kind === "skill") manifest.entryPoint = "handler";
2059
+ return manifest;
2060
+ }
2061
+ async fileExists(path) {
2062
+ try {
2063
+ await promises.access(path);
2064
+ return true;
2065
+ } catch {
2066
+ return false;
2067
+ }
2068
+ }
2069
+ async hasEntryPoint(dirPath, baseName) {
2070
+ try {
2071
+ await resolveEntryPoint(dirPath, baseName, this.extensions);
2072
+ return true;
2073
+ } catch {
2074
+ return false;
2075
+ }
2076
+ }
2077
+ async hasLangchainFiles(dirPath) {
2078
+ const entryFiles = await this.listLangchainEntryFiles(dirPath);
2079
+ return entryFiles.length > 0;
2080
+ }
2081
+ async listLangchainEntryFiles(dirPath) {
2082
+ let entries;
2083
+ try {
2084
+ const dirEntries = await promises.readdir(dirPath, { withFileTypes: true });
2085
+ entries = dirEntries.map((entry) => ({
2086
+ name: entry.name,
2087
+ isFile: entry.isFile()
2088
+ }));
2089
+ } catch {
2090
+ return [];
2091
+ }
2092
+ return entries.filter((entry) => entry.isFile).map((entry) => entry.name).filter((name) => {
2093
+ if (name.startsWith(".") || name.startsWith("_")) return false;
2094
+ if (name.endsWith(".d.ts")) return false;
2095
+ if (name.includes(".test.") || name.includes(".spec.")) return false;
2096
+ return this.extensions.some((ext) => name.endsWith(ext));
2097
+ });
2098
+ }
2099
+ async loadByKind(dirPath, manifest) {
2100
+ switch (manifest.kind) {
2101
+ case "mcp":
2102
+ return loadMCPTool(dirPath, manifest);
2103
+ case "langchain":
2104
+ return loadLangChainTool(dirPath, manifest, this.extensions);
2105
+ case "skill": {
2106
+ const list = await loadSkillTools(dirPath, manifest, this.extensions);
2107
+ if (list.length === 0) {
2108
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(dirPath, "load", "No skill programs loaded", new Error("empty"));
2109
+ }
2110
+ return list[0];
2111
+ }
2112
+ case "n8n":
2113
+ return chunkZ7TGIG77_cjs.loadN8nTool(dirPath, manifest);
2114
+ default:
2115
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
2116
+ dirPath,
2117
+ "manifest",
2118
+ `Unknown tool kind: "${manifest.kind}"`
2119
+ );
2120
+ }
2121
+ }
2122
+ async loadLangChainTools(dirPath, dirName, manifest, strict, namespace) {
2123
+ const entryFiles = await this.listLangchainEntryFiles(dirPath);
2124
+ if (entryFiles.length === 0) {
2125
+ if (strict) {
2126
+ throw new chunkZ7TGIG77_cjs.DiscoveryError(
2127
+ dirPath,
2128
+ "load",
2129
+ "No LangChain entry files found"
2130
+ );
2131
+ }
2132
+ return [];
2133
+ }
2134
+ const specs = [];
2135
+ const useDirNameForSingle = dirName !== "langchain";
2136
+ for (const entryFile of entryFiles) {
2137
+ const fileManifest = {
2138
+ ...manifest,
2139
+ entryPoint: entryFile
2140
+ };
2141
+ try {
2142
+ const loaded = await loadLangChainTool(dirPath, fileManifest, this.extensions);
2143
+ const fileBase = path.basename(entryFile).replace(/\.[^.]+$/, "");
2144
+ const nameHint = entryFiles.length === 1 && useDirNameForSingle ? dirName : fileBase;
2145
+ specs.push(this.toToolSpec(loaded, nameHint, dirPath, namespace));
2146
+ } catch (error) {
2147
+ const err = error;
2148
+ if (err instanceof chunkZ7TGIG77_cjs.DiscoveryError && err.phase === "validate") {
2149
+ if (strict) {
2150
+ throw err;
2151
+ }
2152
+ continue;
2153
+ }
2154
+ this.onError?.(path.join(dirPath, entryFile), err);
2155
+ if (strict) {
2156
+ throw err;
2157
+ }
2158
+ }
2159
+ }
2160
+ return specs;
2161
+ }
2162
+ toToolSpec(loaded, dirName, dirPath, namespace) {
2163
+ const { manifest } = loaded;
2164
+ const kindDirNames = /* @__PURE__ */ new Set(["mcp", "langchain", "skill", "n8n"]);
2165
+ const parentName = path.basename(path.join(dirPath, ".."));
2166
+ const isKindDir = kindDirNames.has(dirName);
2167
+ const defaultDirName = isKindDir ? parentName : dirName;
2168
+ const inferredName = isKindDir ? `${namespace}/${defaultDirName}-${dirName}` : `${namespace}/${defaultDirName}`;
2169
+ const name = manifest.name ?? inferredName;
2170
+ const spec = this.buildBaseSpec(manifest, name, dirName);
2171
+ this.applyKindSpecificFields(spec, loaded, manifest, defaultDirName, namespace);
2172
+ return spec;
2173
+ }
2174
+ buildBaseSpec(manifest, name, dirName) {
2175
+ return {
2176
+ name,
2177
+ version: manifest.version ?? "1.0.0",
2178
+ kind: manifest.kind,
2179
+ description: manifest.description ?? `${manifest.kind} tool: ${dirName}`,
2180
+ tags: manifest.tags,
2181
+ inputSchema: manifest.inputSchema ?? {
2182
+ type: "object",
2183
+ additionalProperties: true
2184
+ },
2185
+ outputSchema: manifest.outputSchema ?? {
2186
+ type: "object",
2187
+ additionalProperties: true
2188
+ },
2189
+ capabilities: manifest.capabilities ?? [],
2190
+ costHints: manifest.costHints
2191
+ };
2192
+ }
2193
+ applyKindSpecificFields(spec, loaded, manifest, defaultDirName, namespace) {
2194
+ switch (manifest.kind) {
2195
+ case "mcp":
2196
+ if (loaded.mcpConfig?.url) {
2197
+ spec.endpoint = loaded.mcpConfig.url;
2198
+ }
2199
+ spec.impl = loaded.mcpConfig;
2200
+ break;
2201
+ case "langchain":
2202
+ spec.impl = loaded.impl;
2203
+ if (!manifest.name) {
2204
+ const toolName = loaded.impl?.name;
2205
+ if (toolName) {
2206
+ spec.name = `${namespace}/${toolName}`;
2207
+ }
2208
+ }
2209
+ if (!manifest.description) {
2210
+ const toolDescription = loaded.impl?.description;
2211
+ if (toolDescription) {
2212
+ spec.description = toolDescription;
2213
+ }
2214
+ }
2215
+ if (!manifest.inputSchema && loaded.impl) {
2216
+ const tool = loaded.impl;
2217
+ if (tool.schema) {
2218
+ spec.inputSchema = tool.schema;
2219
+ }
2220
+ }
2221
+ break;
2222
+ case "skill": {
2223
+ if (loaded.skillDefinition) {
2224
+ spec.name = manifest.name ?? loaded.skillDefinition.frontmatter.name;
2225
+ spec.description = loaded.skillDefinition.frontmatter.description;
2226
+ if (loaded.programKey === "default") {
2227
+ spec.name = `${namespace}/${defaultDirName}`;
2228
+ } else if (loaded.programKey) {
2229
+ spec.name = `${namespace}/${defaultDirName}/${loaded.programKey}`;
2230
+ }
2231
+ const impl = loaded.impl;
2232
+ if (impl && typeof impl === "object" && typeof impl.invoke === "function") {
2233
+ if (impl.description != null && impl.description !== "") spec.description = impl.description;
2234
+ if (impl.schema != null && typeof impl.schema === "object") spec.inputSchema = impl.schema;
2235
+ }
2236
+ spec.impl = {
2237
+ ...loaded.skillDefinition,
2238
+ handler: loaded.impl
2239
+ };
2240
+ } else {
2241
+ spec.impl = loaded.impl;
2242
+ }
2243
+ break;
2244
+ }
2245
+ case "n8n": {
2246
+ const workflow = loaded.workflowDef;
2247
+ if (workflow?.id) {
2248
+ spec.resourceId = String(workflow.id);
2249
+ }
2250
+ if (!manifest.description && workflow) {
2251
+ const workflowDesc = workflow.description ?? workflow.meta?.description ?? (typeof workflow.name === "string" ? workflow.name : void 0);
2252
+ if (workflowDesc) {
2253
+ spec.description = workflowDesc;
2254
+ }
2255
+ }
2256
+ spec.impl = loaded.workflowDef;
2257
+ break;
2258
+ }
2259
+ }
2260
+ }
2261
+ };
2262
+
2263
+ // src/discovery/MCPProcessManager.ts
2264
+ var MCPProcessManager = class {
2265
+ connections = /* @__PURE__ */ new Map();
2266
+ /**
2267
+ * Get connection info for an MCP tool based on its config.
2268
+ * Caches the result by tool name.
2269
+ */
2270
+ getConnectionInfo(toolName, config) {
2271
+ const cached = this.connections.get(toolName);
2272
+ if (cached) return cached;
2273
+ const info = config.url ? { type: "url", url: config.url } : {
2274
+ type: "stdio",
2275
+ command: config.command,
2276
+ args: config.args,
2277
+ env: config.env,
2278
+ cwd: config.cwd
2279
+ };
2280
+ this.connections.set(toolName, info);
2281
+ return info;
2282
+ }
2283
+ /**
2284
+ * Remove cached connection info for a tool.
2285
+ */
2286
+ remove(toolName) {
2287
+ return this.connections.delete(toolName);
2288
+ }
2289
+ /**
2290
+ * Get all registered tool names.
2291
+ */
2292
+ getToolNames() {
2293
+ return [...this.connections.keys()];
2294
+ }
2295
+ /**
2296
+ * Clear all cached connection info.
2297
+ */
2298
+ dispose() {
2299
+ this.connections.clear();
2300
+ }
2301
+ };
2302
+
2303
+ // src/mcp/MCPClientAdapter.ts
2304
+ function textFromCallToolResult(result) {
2305
+ if (result.content?.length) {
2306
+ const parts = result.content.filter((c) => c.type === "text" && c.text != null).map((c) => c.text);
2307
+ if (parts.length) return parts.join("\n");
2308
+ }
2309
+ if (result.toolResult !== void 0) return JSON.stringify(result.toolResult);
2310
+ return JSON.stringify(result);
2311
+ }
2312
+ var MCPClientAdapter = class {
2313
+ constructor(client) {
2314
+ this.client = client;
2315
+ }
2316
+ kind = "mcp";
2317
+ async invoke(spec, args, _ctx) {
2318
+ const params = args != null && typeof args === "object" && !Array.isArray(args) ? args : {};
2319
+ const result = await this.client.callTool({ name: spec.name, arguments: params });
2320
+ const text = textFromCallToolResult(result);
2321
+ let resultValue = text;
2322
+ try {
2323
+ resultValue = JSON.parse(text);
2324
+ } catch {
2325
+ }
2326
+ return { result: resultValue, raw: result };
2327
+ }
2328
+ };
2329
+
2330
+ // src/mcp/connectMCP.ts
2331
+ async function connectMCP(connectionInfo) {
2332
+ if (connectionInfo.type !== "stdio" || !connectionInfo.command) {
2333
+ throw new Error(
2334
+ `MCP stdio requires connectionInfo.type "stdio" and command; got type=${connectionInfo.type}`
2335
+ );
2336
+ }
2337
+ const { Client } = await import('@modelcontextprotocol/sdk/client');
2338
+ const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js');
2339
+ const serverParams = {
2340
+ command: connectionInfo.command,
2341
+ args: connectionInfo.args ?? [],
2342
+ env: connectionInfo.env,
2343
+ cwd: connectionInfo.cwd
2344
+ };
2345
+ const transport = new StdioClientTransport(serverParams);
2346
+ const client = new Client({ name: "agent-tool", version: "1.0.0" });
2347
+ await client.connect(transport);
2348
+ return {
2349
+ client,
2350
+ transport
2351
+ };
2352
+ }
2353
+ function mcpToolsToSpecs(tools) {
2354
+ return tools.map((t) => ({
2355
+ name: t.name,
2356
+ version: "1.0.0",
2357
+ kind: "mcp",
2358
+ description: t.description ?? `MCP tool: ${t.name}`,
2359
+ inputSchema: t.inputSchema ?? chunk3YLVPZRJ_cjs.DEFAULT_INPUT_SCHEMA,
2360
+ outputSchema: chunk3YLVPZRJ_cjs.DEFAULT_OUTPUT_SCHEMA,
2361
+ capabilities: []
2362
+ }));
2363
+ }
2364
+ async function registerMCPToolsFromConfig(runtime, registry, options = {}) {
2365
+ const configPath = options.configPath ?? process.env.MCP_CONFIG_PATH ?? path.join(process.cwd(), "mcp.json");
2366
+ const dirPath = path.dirname(configPath);
2367
+ const entryPoint = path.basename(configPath);
2368
+ const toolName = options.toolName ?? "mcp";
2369
+ const loaded = await loadMCPTool(dirPath, { kind: "mcp", name: toolName, entryPoint });
2370
+ if (!loaded.mcpConfig) {
2371
+ throw new Error("mcp.json must have command or url");
2372
+ }
2373
+ const manager = new MCPProcessManager();
2374
+ const connectionInfo = manager.getConnectionInfo(toolName, loaded.mcpConfig);
2375
+ const { client, transport } = await connectMCP(connectionInfo);
2376
+ const { tools } = await client.listTools();
2377
+ const specs = mcpToolsToSpecs(tools);
2378
+ registry.bulkRegister(specs);
2379
+ runtime.registerAdapter(new MCPClientAdapter(client));
2380
+ return { transport };
2381
+ }
2382
+ var DEFAULT_CTX_FACTORY = () => ({
2383
+ requestId: `lc-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
2384
+ taskId: `task-${Date.now()}`,
2385
+ permissions: [
2386
+ "read:web",
2387
+ "read:fs",
2388
+ "write:fs",
2389
+ "read:db",
2390
+ "write:db",
2391
+ "network",
2392
+ "workflow",
2393
+ "danger:destructive"
2394
+ ]
2395
+ });
2396
+ var LangChainToolsHub = class {
2397
+ constructor(runtime, ctxFactory = DEFAULT_CTX_FACTORY) {
2398
+ this.runtime = runtime;
2399
+ this.ctxFactory = ctxFactory;
2400
+ }
2401
+ /**
2402
+ * Returns all registered tools as LangChain tools (DynamicTool[]).
2403
+ * Each tool invokes the runtime through the full pipeline (policy, HITL, etc.).
2404
+ */
2405
+ getLangChainTools() {
2406
+ const registry = this.runtime.getRegistry();
2407
+ const specs = registry.snapshot();
2408
+ return specs.map((spec) => this.specToLangChainTool(spec));
2409
+ }
2410
+ /**
2411
+ * Returns LangChain tools for a subset of tools (by name or query).
2412
+ */
2413
+ getLangChainToolsForNames(toolNames) {
2414
+ const registry = this.runtime.getRegistry();
2415
+ const set = new Set(toolNames);
2416
+ const specs = registry.snapshot().filter((s) => set.has(s.name));
2417
+ return specs.map((spec) => this.specToLangChainTool(spec));
2418
+ }
2419
+ specToLangChainTool(spec) {
2420
+ const runtime = this.runtime;
2421
+ const ctxFactory = this.ctxFactory;
2422
+ return new tools.DynamicTool({
2423
+ name: spec.name,
2424
+ description: spec.description ?? `Tool: ${spec.name}`,
2425
+ func: async (input) => {
2426
+ const args = parseToolInput(input);
2427
+ const intent = {
2428
+ tool: spec.name,
2429
+ args,
2430
+ purpose: "langchain"
2431
+ };
2432
+ const ctx = ctxFactory();
2433
+ const result = await runtime.invoke(intent, ctx);
2434
+ if (result.ok) {
2435
+ return typeof result.result === "string" ? result.result : JSON.stringify(result.result);
2436
+ }
2437
+ const err = result.error;
2438
+ const message = err?.message ?? "Tool failed";
2439
+ const details = err?.details;
2440
+ return JSON.stringify(
2441
+ details != null ? { error: message, details } : { error: message }
2442
+ );
2443
+ }
2444
+ });
2445
+ }
2446
+ };
2447
+ function parseToolInput(input) {
2448
+ const s = input.trim();
2449
+ if (!s) return {};
2450
+ try {
2451
+ const parsed = JSON.parse(s);
2452
+ if (parsed != null && typeof parsed === "object" && !Array.isArray(parsed)) {
2453
+ return parsed;
2454
+ }
2455
+ } catch {
2456
+ }
2457
+ const lastBrace = s.lastIndexOf("{");
2458
+ if (lastBrace !== -1) {
2459
+ try {
2460
+ const parsed = JSON.parse(s.slice(lastBrace));
2461
+ if (parsed != null && typeof parsed === "object" && !Array.isArray(parsed)) {
2462
+ return parsed;
2463
+ }
2464
+ } catch {
2465
+ }
2466
+ }
2467
+ return {};
2468
+ }
2469
+
2470
+ // src/llm/AgentLLMAdapter.ts
2471
+ function createAgentLLMAdapter(client) {
2472
+ if (!client.chatWithTools) {
2473
+ throw new Error(
2474
+ `agent-llm client "${client.id}" does not support chatWithTools; ReAct agent requires tool-calling.`
2475
+ );
2476
+ }
2477
+ return new AgentLLMAdapter(client);
2478
+ }
2479
+ var AgentLLMAdapter = class {
2480
+ constructor(client) {
2481
+ this.client = client;
2482
+ }
2483
+ async chat(messages, options) {
2484
+ const result = await this.client.chat(messages);
2485
+ return { content: result.content, raw: result.usage ?? {} };
2486
+ }
2487
+ async chatWithTools(messages, tools, options) {
2488
+ const agentLlmTools = tools.map((t) => ({
2489
+ type: "function",
2490
+ function: {
2491
+ name: t.function.name,
2492
+ description: t.function.description,
2493
+ parameters: t.function.parameters
2494
+ }
2495
+ }));
2496
+ const result = await this.client.chatWithTools(messages, agentLlmTools, {
2497
+ timeoutMs: options?.timeoutMs
2498
+ });
2499
+ return {
2500
+ message: result.message,
2501
+ raw: result.usage ?? {}
2502
+ };
2503
+ }
2504
+ };
2505
+ var DEFAULT_ALLOWED_HOSTS = ["*"];
2506
+ var DEFAULT_SANDBOX_ROOT = process.cwd();
2507
+ function loadAgentConfig(configPath) {
2508
+ const abs = path.resolve(configPath);
2509
+ const raw = fs.readFileSync(abs, "utf8");
2510
+ const parsed = yaml__default.default.load(raw);
2511
+ if (!parsed || typeof parsed !== "object") return {};
2512
+ return parsed;
2513
+ }
2514
+ function createRuntimeWithTools(options) {
2515
+ const sandboxRoot = options.sandboxRoot ?? DEFAULT_SANDBOX_ROOT;
2516
+ const allowedHosts = options.allowedHosts ?? DEFAULT_ALLOWED_HOSTS;
2517
+ const registry = new ToolRegistry();
2518
+ const coreConfig = { sandboxRoot, allowedHosts };
2519
+ const coreAdapter = agentToolBuiltinTools.registerCoreTools(registry, coreConfig);
2520
+ const exampleConfig = { sandboxRoot, allowedHosts };
2521
+ const exampleAdapter = agentToolExampleTools.registerExampleTools(registry, exampleConfig);
2522
+ const runtime = new PTCRuntime({ registry });
2523
+ runtime.registerAdapter(coreAdapter);
2524
+ runtime.registerAdapter(exampleAdapter);
2525
+ return { runtime, coreAdapter, exampleAdapter };
2526
+ }
2527
+ async function runAgent(configPath, task, options) {
2528
+ const config = loadAgentConfig(configPath);
2529
+ const llmSection = config.llm ?? null;
2530
+ const registry = agentLlm.createLLMRegistry({ llmSection });
2531
+ const defaultId = registry.defaultId();
2532
+ if (!defaultId) {
2533
+ throw new Error(
2534
+ "agent.yaml has no llm section or no LLM instances. Add an llm block (see agent.yaml.example)."
2535
+ );
2536
+ }
2537
+ const client = registry.get(defaultId);
2538
+ if (!client) {
2539
+ throw new Error(`LLM "${defaultId}" not found in registry.`);
2540
+ }
2541
+ const adapter = createAgentLLMAdapter(client);
2542
+ const sandboxRoot = options?.sandboxRoot ?? DEFAULT_SANDBOX_ROOT;
2543
+ const allowedHosts = options?.allowedHosts ?? DEFAULT_ALLOWED_HOSTS;
2544
+ const { runtime } = createRuntimeWithTools({ sandboxRoot, allowedHosts });
2545
+ const ctxFactory = () => ({
2546
+ requestId: `run-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
2547
+ taskId: `task-${Date.now()}`,
2548
+ permissions: [
2549
+ "read:web",
2550
+ "read:fs",
2551
+ "write:fs",
2552
+ "read:db",
2553
+ "write:db",
2554
+ "network",
2555
+ "workflow",
2556
+ "danger:destructive",
2557
+ "exec"
2558
+ ]
2559
+ });
2560
+ const hub = {
2561
+ getRegistry: () => runtime.getRegistry(),
2562
+ invokeTool: async (name, args) => {
2563
+ const ctx = ctxFactory();
2564
+ const result = await runtime.invoke(
2565
+ { tool: name, args, purpose: "langchain" },
2566
+ ctx
2567
+ );
2568
+ return result;
2569
+ }
2570
+ };
2571
+ const agent = new chunkP3UEAZHK_cjs.ReActAgent(adapter, hub);
2572
+ const toolNames = Array.isArray(config.tools) && config.tools.length > 0 ? normalizeToolList(config.tools) : void 0;
2573
+ return agent.run(task, {
2574
+ systemPrompt: options?.systemPrompt,
2575
+ toolNames,
2576
+ ...options?.runOptions
2577
+ });
2578
+ }
2579
+ var PLACEHOLDER = "__REPORT_DATA__";
2580
+ function getReportTemplateDir() {
2581
+ if (typeof __dirname !== "undefined") return __dirname;
2582
+ return path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
2583
+ }
2584
+ var DEFAULT_REPORT_TEMPLATE_PATH = (() => {
2585
+ const dir = getReportTemplateDir();
2586
+ const nextToModule = path.join(dir, "agent-report-template.html");
2587
+ if (fs.existsSync(nextToModule)) return nextToModule;
2588
+ return path.join(dir, "report", "agent-report-template.html");
2589
+ })();
2590
+ function generateAgentReport(data, options) {
2591
+ const templatePath = options.templatePath ?? DEFAULT_REPORT_TEMPLATE_PATH;
2592
+ const template = fs.readFileSync(templatePath, "utf8");
2593
+ let json = JSON.stringify(data);
2594
+ json = json.replace(/<\/script/gi, "<\\/script");
2595
+ const html = template.replace(PLACEHOLDER, json);
2596
+ const outPath = path.resolve(options.outputPath);
2597
+ fs.writeFileSync(outPath, html, "utf8");
2598
+ return outPath;
2599
+ }
2600
+ function serializeStepOutput(value) {
2601
+ if (value === null || value === void 0) return value;
2602
+ if (typeof value !== "object") return value;
2603
+ const v = value;
2604
+ const out = {};
2605
+ if (Array.isArray(v.messages)) {
2606
+ out.messages = v.messages.map((m) => serializeMessage(m));
2607
+ }
2608
+ if (v.__state__ && typeof v.__state__ === "object") {
2609
+ const state = v.__state__;
2610
+ if (Array.isArray(state.messages)) {
2611
+ out.messages = state.messages.map((m) => serializeMessage(m));
2612
+ }
2613
+ }
2614
+ if (Object.keys(out).length === 0) {
2615
+ try {
2616
+ return JSON.parse(JSON.stringify(value));
2617
+ } catch {
2618
+ return { _raw: String(value) };
2619
+ }
2620
+ }
2621
+ return out;
2622
+ }
2623
+ function serializeMessage(msg) {
2624
+ if (msg === null || typeof msg !== "object") return { content: String(msg) };
2625
+ const m = msg;
2626
+ const out = {
2627
+ type: m.type ?? "message",
2628
+ content: m.content ?? ""
2629
+ };
2630
+ if (m.tool_calls) out.tool_calls = m.tool_calls;
2631
+ if (m.usage_metadata) out.usage_metadata = m.usage_metadata;
2632
+ if (m.name) out.name = m.name;
2633
+ return out;
2634
+ }
2635
+ function formatStepProgress(step) {
2636
+ const parts = [` [${step.stepIndex}] ${step.node}`];
2637
+ if (step.toolCalls?.length) {
2638
+ const toolParts = step.toolCalls.map((tc) => {
2639
+ const argStr = tc.args && Object.keys(tc.args).length ? " " + JSON.stringify(tc.args) : "";
2640
+ return `${tc.name}${argStr}`;
2641
+ });
2642
+ parts.push(`tools \u2192 ${toolParts.join("; ")}`);
2643
+ }
2644
+ if (step.usage) {
2645
+ const inN = step.usage.input_tokens ?? 0;
2646
+ const outN = step.usage.output_tokens ?? 0;
2647
+ const total = step.usage.total_tokens ?? inN + outN;
2648
+ parts.push(`tokens: in=${inN} out=${outN} total=${total}`);
2649
+ }
2650
+ return parts.join(" | ");
2651
+ }
2652
+ function buildStep(stepIndex, node, value) {
2653
+ const v = value;
2654
+ const messages = v?.messages ?? v?.__state__?.messages;
2655
+ const lastMsg = Array.isArray(messages) ? messages.slice(-1)[0] : void 0;
2656
+ const last = lastMsg;
2657
+ const toolCalls = last?.tool_calls;
2658
+ const usage = last?.usage_metadata;
2659
+ return {
2660
+ stepIndex,
2661
+ node,
2662
+ input: void 0,
2663
+ // filled later from previous step's output
2664
+ output: serializeStepOutput(value),
2665
+ toolCalls: toolCalls?.map((tc) => ({ name: tc.name, args: tc.args ?? {} })),
2666
+ usage: usage ? {
2667
+ input_tokens: usage.input_tokens ?? usage.prompt_tokens,
2668
+ output_tokens: usage.output_tokens ?? usage.completion_tokens,
2669
+ total_tokens: usage.total_tokens
2670
+ } : void 0
2671
+ };
2672
+ }
2673
+ function isAiMessage(msg) {
2674
+ if (!msg || typeof msg !== "object") return false;
2675
+ if (msg.type === "ai" || msg.type === "assistant") return true;
2676
+ const getType = msg._getType;
2677
+ if (typeof getType === "function" && getType.call(msg) === "ai") return true;
2678
+ const lcId = msg.lc_id;
2679
+ if (Array.isArray(lcId) && lcId[lcId.length - 1] === "AIMessage") return true;
2680
+ return false;
2681
+ }
2682
+ function getMessageContent(msg) {
2683
+ if (!msg || typeof msg !== "object") return "";
2684
+ let c = msg.content ?? msg.kwargs?.content;
2685
+ if (typeof c === "string") return c;
2686
+ if (Array.isArray(c)) {
2687
+ return c.map((p) => p && typeof p === "object" && "text" in p ? p.text : String(p)).filter(Boolean).join("");
2688
+ }
2689
+ return "";
2690
+ }
2691
+ function extractAiContent(msg) {
2692
+ if (!msg || !isAiMessage(msg)) return "";
2693
+ return getMessageContent(msg);
2694
+ }
2695
+ async function collectStreamSteps(stream, options) {
2696
+ const steps = [];
2697
+ let stepIndex = 0;
2698
+ let lastAiContent = "";
2699
+ for await (const chunk of stream) {
2700
+ const nodeMap = Array.isArray(chunk) && chunk.length >= 2 && typeof chunk[chunk.length - 1] === "object" && chunk[chunk.length - 1] !== null && !Array.isArray(chunk[chunk.length - 1]) ? chunk[chunk.length - 1] : chunk;
2701
+ for (const [node, value] of Object.entries(nodeMap)) {
2702
+ if (value === void 0 || value === null) continue;
2703
+ stepIndex += 1;
2704
+ const step = buildStep(stepIndex, node, value);
2705
+ steps.push(step);
2706
+ options?.onStep?.(step);
2707
+ const v = value;
2708
+ const messages = v?.messages ?? v?.__state__?.messages;
2709
+ const lastMsg = Array.isArray(messages) ? messages.slice(-1)[0] : void 0;
2710
+ let content = extractAiContent(lastMsg);
2711
+ if (!content && node === "agent" && lastMsg && typeof lastMsg === "object" && !("tool_call_id" in lastMsg && lastMsg.tool_call_id)) {
2712
+ content = getMessageContent(lastMsg);
2713
+ }
2714
+ if (content) lastAiContent = content;
2715
+ }
2716
+ }
2717
+ for (let i = 1; i < steps.length; i++) {
2718
+ const prev = steps[i - 1];
2719
+ const curr = steps[i];
2720
+ if (prev && curr) curr.input = prev.output;
2721
+ }
2722
+ const first = steps[0];
2723
+ if (first && first.input === void 0) {
2724
+ first.input = { __info: "Initial state (see System and User Prompt above)" };
2725
+ }
2726
+ return { steps, lastAiContent };
2727
+ }
2728
+ async function runAgentWithReport(agent, input, options) {
2729
+ const stream = await agent.stream(input, options.streamConfig ?? {});
2730
+ const { steps, lastAiContent } = await collectStreamSteps(stream, { onStep: options.onStep });
2731
+ let reportMarkdown = lastAiContent;
2732
+ if (options.reportPath) {
2733
+ const reportPath = path.resolve(options.reportPath);
2734
+ if (fs.existsSync(reportPath)) {
2735
+ reportMarkdown = fs.readFileSync(reportPath, "utf8");
2736
+ }
2737
+ }
2738
+ let htmlPath;
2739
+ if (options.htmlReportPath) {
2740
+ htmlPath = generateAgentReport(
2741
+ {
2742
+ systemPrompt: options.systemPrompt,
2743
+ userPrompt: options.userPrompt,
2744
+ reportMarkdown,
2745
+ steps
2746
+ },
2747
+ {
2748
+ outputPath: options.htmlReportPath,
2749
+ templatePath: options.templatePath
2750
+ }
2751
+ );
2752
+ }
2753
+ return { steps, reportMarkdown, htmlPath };
2754
+ }
2755
+ async function writeReportFromStream(stream, options) {
2756
+ const { steps, lastAiContent } = await collectStreamSteps(stream, { onStep: options.onStep });
2757
+ let reportMarkdown = lastAiContent;
2758
+ if (options.reportPath) {
2759
+ const reportPath = path.resolve(options.reportPath);
2760
+ if (fs.existsSync(reportPath)) {
2761
+ reportMarkdown = fs.readFileSync(reportPath, "utf8");
2762
+ }
2763
+ }
2764
+ let htmlPath;
2765
+ if (options.htmlReportPath) {
2766
+ htmlPath = generateAgentReport(
2767
+ {
2768
+ systemPrompt: options.systemPrompt,
2769
+ userPrompt: options.userPrompt,
2770
+ reportMarkdown,
2771
+ steps
2772
+ },
2773
+ {
2774
+ outputPath: options.htmlReportPath,
2775
+ templatePath: options.templatePath
2776
+ }
2777
+ );
2778
+ }
2779
+ return { steps, reportMarkdown, htmlPath };
2780
+ }
2781
+
2782
+ Object.defineProperty(exports, "DiscoveryError", {
2783
+ enumerable: true,
2784
+ get: function () { return chunkZ7TGIG77_cjs.DiscoveryError; }
2785
+ });
2786
+ Object.defineProperty(exports, "SkillManifestError", {
2787
+ enumerable: true,
2788
+ get: function () { return chunkZ7TGIG77_cjs.SkillManifestError; }
2789
+ });
2790
+ Object.defineProperty(exports, "buildFunctionToTool", {
2791
+ enumerable: true,
2792
+ get: function () { return chunkZ7TGIG77_cjs.buildFunctionToTool; }
2793
+ });
2794
+ Object.defineProperty(exports, "buildMcpPackage", {
2795
+ enumerable: true,
2796
+ get: function () { return chunkZ7TGIG77_cjs.buildMcpPackage; }
2797
+ });
2798
+ Object.defineProperty(exports, "initProject", {
2799
+ enumerable: true,
2800
+ get: function () { return chunkZ7TGIG77_cjs.initProject; }
2801
+ });
2802
+ Object.defineProperty(exports, "loadSkillDefinition", {
2803
+ enumerable: true,
2804
+ get: function () { return chunkZ7TGIG77_cjs.loadSkillDefinition; }
2805
+ });
2806
+ Object.defineProperty(exports, "parseSkillMd", {
2807
+ enumerable: true,
2808
+ get: function () { return chunkZ7TGIG77_cjs.parseSkillMd; }
2809
+ });
2810
+ Object.defineProperty(exports, "runGeneratedMCP", {
2811
+ enumerable: true,
2812
+ get: function () { return chunkZ7TGIG77_cjs.runGeneratedMCP; }
2813
+ });
2814
+ Object.defineProperty(exports, "runMcpServer", {
2815
+ enumerable: true,
2816
+ get: function () { return chunkZ7TGIG77_cjs.runMcpServer; }
2817
+ });
2818
+ Object.defineProperty(exports, "scanForTools", {
2819
+ enumerable: true,
2820
+ get: function () { return chunkZ7TGIG77_cjs.scanForTools; }
2821
+ });
2822
+ Object.defineProperty(exports, "scanSkillResources", {
2823
+ enumerable: true,
2824
+ get: function () { return chunkZ7TGIG77_cjs.scanSkillResources; }
2825
+ });
2826
+ Object.defineProperty(exports, "validateFrontmatter", {
2827
+ enumerable: true,
2828
+ get: function () { return chunkZ7TGIG77_cjs.validateFrontmatter; }
2829
+ });
2830
+ Object.defineProperty(exports, "DEFAULT_INPUT_SCHEMA", {
2831
+ enumerable: true,
2832
+ get: function () { return chunk3YLVPZRJ_cjs.DEFAULT_INPUT_SCHEMA; }
2833
+ });
2834
+ Object.defineProperty(exports, "DEFAULT_OUTPUT_SCHEMA", {
2835
+ enumerable: true,
2836
+ get: function () { return chunk3YLVPZRJ_cjs.DEFAULT_OUTPUT_SCHEMA; }
2837
+ });
2838
+ Object.defineProperty(exports, "createToolSpec", {
2839
+ enumerable: true,
2840
+ get: function () { return chunk3YLVPZRJ_cjs.createToolSpec; }
2841
+ });
2842
+ Object.defineProperty(exports, "LangChainAgent", {
2843
+ enumerable: true,
2844
+ get: function () { return chunkP3UEAZHK_cjs.ReActAgent; }
2845
+ });
2846
+ Object.defineProperty(exports, "OpenAICompatibleClient", {
2847
+ enumerable: true,
2848
+ get: function () { return chunkP3UEAZHK_cjs.OpenAICompatibleClient; }
2849
+ });
2850
+ Object.defineProperty(exports, "ReActAgent", {
2851
+ enumerable: true,
2852
+ get: function () { return chunkP3UEAZHK_cjs.ReActAgent; }
2853
+ });
2854
+ Object.defineProperty(exports, "createOpenAICompatibleClient", {
2855
+ enumerable: true,
2856
+ get: function () { return chunkP3UEAZHK_cjs.createOpenAICompatibleClient; }
2857
+ });
2858
+ Object.defineProperty(exports, "CoreAdapter", {
2859
+ enumerable: true,
2860
+ get: function () { return agentToolBuiltinTools.CoreAdapter; }
2861
+ });
2862
+ Object.defineProperty(exports, "DEFAULT_CORE_TOOLS_CONFIG", {
2863
+ enumerable: true,
2864
+ get: function () { return agentToolBuiltinTools.DEFAULT_CORE_TOOLS_CONFIG; }
2865
+ });
2866
+ Object.defineProperty(exports, "deletePathSpec", {
2867
+ enumerable: true,
2868
+ get: function () { return agentToolBuiltinTools.deletePathSpec; }
2869
+ });
2870
+ Object.defineProperty(exports, "downloadFileSpec", {
2871
+ enumerable: true,
2872
+ get: function () { return agentToolBuiltinTools.downloadFileSpec; }
2873
+ });
2874
+ Object.defineProperty(exports, "duckduckgoSearchSpec", {
2875
+ enumerable: true,
2876
+ get: function () { return agentToolBuiltinTools.duckduckgoSearchSpec; }
2877
+ });
2878
+ Object.defineProperty(exports, "fetchJsonSpec", {
2879
+ enumerable: true,
2880
+ get: function () { return agentToolBuiltinTools.fetchJsonSpec; }
2881
+ });
2882
+ Object.defineProperty(exports, "fetchPageMainContentSpec", {
2883
+ enumerable: true,
2884
+ get: function () { return agentToolBuiltinTools.fetchPageMainContentSpec; }
2885
+ });
2886
+ Object.defineProperty(exports, "fetchTextSpec", {
2887
+ enumerable: true,
2888
+ get: function () { return agentToolBuiltinTools.fetchTextSpec; }
2889
+ });
2890
+ Object.defineProperty(exports, "hashTextSpec", {
2891
+ enumerable: true,
2892
+ get: function () { return agentToolBuiltinTools.hashTextSpec; }
2893
+ });
2894
+ Object.defineProperty(exports, "headSpec", {
2895
+ enumerable: true,
2896
+ get: function () { return agentToolBuiltinTools.headSpec; }
2897
+ });
2898
+ Object.defineProperty(exports, "isIpInBlockedCidrs", {
2899
+ enumerable: true,
2900
+ get: function () { return agentToolBuiltinTools.isIpInBlockedCidrs; }
2901
+ });
2902
+ Object.defineProperty(exports, "jsonSelectSpec", {
2903
+ enumerable: true,
2904
+ get: function () { return agentToolBuiltinTools.jsonSelectSpec; }
2905
+ });
2906
+ Object.defineProperty(exports, "listDirSpec", {
2907
+ enumerable: true,
2908
+ get: function () { return agentToolBuiltinTools.listDirSpec; }
2909
+ });
2910
+ Object.defineProperty(exports, "nowSpec", {
2911
+ enumerable: true,
2912
+ get: function () { return agentToolBuiltinTools.nowSpec; }
2913
+ });
2914
+ Object.defineProperty(exports, "readTextSpec", {
2915
+ enumerable: true,
2916
+ get: function () { return agentToolBuiltinTools.readTextSpec; }
2917
+ });
2918
+ Object.defineProperty(exports, "registerCoreTools", {
2919
+ enumerable: true,
2920
+ get: function () { return agentToolBuiltinTools.registerCoreTools; }
2921
+ });
2922
+ Object.defineProperty(exports, "resolveSandboxedPath", {
2923
+ enumerable: true,
2924
+ get: function () { return agentToolBuiltinTools.resolveSandboxedPath; }
2925
+ });
2926
+ Object.defineProperty(exports, "runCommandSpec", {
2927
+ enumerable: true,
2928
+ get: function () { return agentToolBuiltinTools.runCommandSpec; }
2929
+ });
2930
+ Object.defineProperty(exports, "searchTextSpec", {
2931
+ enumerable: true,
2932
+ get: function () { return agentToolBuiltinTools.searchTextSpec; }
2933
+ });
2934
+ Object.defineProperty(exports, "sha256Spec", {
2935
+ enumerable: true,
2936
+ get: function () { return agentToolBuiltinTools.sha256Spec; }
2937
+ });
2938
+ Object.defineProperty(exports, "templateRenderSpec", {
2939
+ enumerable: true,
2940
+ get: function () { return agentToolBuiltinTools.templateRenderSpec; }
2941
+ });
2942
+ Object.defineProperty(exports, "truncateSpec", {
2943
+ enumerable: true,
2944
+ get: function () { return agentToolBuiltinTools.truncateSpec; }
2945
+ });
2946
+ Object.defineProperty(exports, "validateUrl", {
2947
+ enumerable: true,
2948
+ get: function () { return agentToolBuiltinTools.validateUrl; }
2949
+ });
2950
+ Object.defineProperty(exports, "writeTextSpec", {
2951
+ enumerable: true,
2952
+ get: function () { return agentToolBuiltinTools.writeTextSpec; }
2953
+ });
2954
+ Object.defineProperty(exports, "ExampleAdapter", {
2955
+ enumerable: true,
2956
+ get: function () { return agentToolExampleTools.ExampleAdapter; }
2957
+ });
2958
+ Object.defineProperty(exports, "isHostAllowed", {
2959
+ enumerable: true,
2960
+ get: function () { return agentToolExampleTools.isHostAllowed; }
2961
+ });
2962
+ Object.defineProperty(exports, "registerExampleTools", {
2963
+ enumerable: true,
2964
+ get: function () { return agentToolExampleTools.registerExampleTools; }
2965
+ });
2966
+ Object.defineProperty(exports, "yahooChartSpec", {
2967
+ enumerable: true,
2968
+ get: function () { return agentToolExampleTools.yahooChartSpec; }
2969
+ });
2970
+ Object.defineProperty(exports, "yahooQuoteSpec", {
2971
+ enumerable: true,
2972
+ get: function () { return agentToolExampleTools.yahooQuoteSpec; }
2973
+ });
2974
+ exports.BudgetManager = BudgetManager;
2975
+ exports.DirectoryScanner = DirectoryScanner;
2976
+ exports.EventLog = EventLog;
2977
+ exports.LangChainToolsHub = LangChainToolsHub;
2978
+ exports.MCPClientAdapter = MCPClientAdapter;
2979
+ exports.MCPProcessManager = MCPProcessManager;
2980
+ exports.Metrics = Metrics;
2981
+ exports.PTCRuntime = PTCRuntime;
2982
+ exports.PolicyDeniedError = PolicyDeniedError;
2983
+ exports.PolicyEngine = PolicyEngine;
2984
+ exports.SchemaValidationError = SchemaValidationError;
2985
+ exports.SchemaValidator = SchemaValidator;
2986
+ exports.ToolRegistry = ToolRegistry;
2987
+ exports.Tracing = Tracing;
2988
+ exports.buildEvidence = buildEvidence;
2989
+ exports.collectStreamSteps = collectStreamSteps;
2990
+ exports.connectMCP = connectMCP;
2991
+ exports.createAgentLLMAdapter = createAgentLLMAdapter;
2992
+ exports.createLogger = createLogger;
2993
+ exports.createTaggedError = createTaggedError;
2994
+ exports.formatStepProgress = formatStepProgress;
2995
+ exports.generateAgentReport = generateAgentReport;
2996
+ exports.isNpmToolDescriptor = isNpmToolDescriptor;
2997
+ exports.isRetryable = isRetryable;
2998
+ exports.loadAgentConfig = loadAgentConfig;
2999
+ exports.loadMCPTool = loadMCPTool;
3000
+ exports.mcpToolsToSpecs = mcpToolsToSpecs;
3001
+ exports.normalizeToolList = normalizeToolList;
3002
+ exports.parseNpmToolDescriptor = parseNpmToolDescriptor;
3003
+ exports.registerMCPToolsFromConfig = registerMCPToolsFromConfig;
3004
+ exports.resolveNpmToolDescriptor = resolveNpmToolDescriptor;
3005
+ exports.resolveToolDescriptor = resolveToolDescriptor;
3006
+ exports.runAgent = runAgent;
3007
+ exports.runAgentWithReport = runAgentWithReport;
3008
+ exports.sanitizeForLog = sanitizeForLog;
3009
+ exports.serializeStepOutput = serializeStepOutput;
3010
+ exports.summarizeForLog = summarizeForLog;
3011
+ exports.withRetry = withRetry;
3012
+ exports.writeReportFromStream = writeReportFromStream;
3013
+ //# sourceMappingURL=index.cjs.map
3014
+ //# sourceMappingURL=index.cjs.map