@easynet/agent-tool-hub 1.0.6 → 1.0.8

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.
package/dist/cli.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var chunkTIKHPRMB_cjs = require('./chunk-TIKHPRMB.cjs');
4
+ var chunkXHNKPSOO_cjs = require('./chunk-XHNKPSOO.cjs');
5
5
  require('./chunk-NTTBDQUF.cjs');
6
6
  var path = require('path');
7
7
  var url = require('url');
@@ -67,7 +67,7 @@ async function ensureConfig(configPath) {
67
67
  }
68
68
  async function runWithHub(configPath, collectErrors) {
69
69
  const errors = [];
70
- const { options } = await chunkTIKHPRMB_cjs.loadToolHubConfig(configPath);
70
+ const { options } = await chunkXHNKPSOO_cjs.loadToolHubConfig(configPath);
71
71
  const optionsWithErrorHandler = {
72
72
  ...options,
73
73
  ...{
@@ -80,7 +80,7 @@ async function runWithHub(configPath, collectErrors) {
80
80
  return { hub, errors };
81
81
  }
82
82
  async function createHubAndInit(options) {
83
- const hub = chunkTIKHPRMB_cjs.createToolHub(options);
83
+ const hub = chunkXHNKPSOO_cjs.createToolHub(options);
84
84
  await hub.initAllTools();
85
85
  return hub;
86
86
  }
@@ -89,7 +89,7 @@ function formatRoot(root) {
89
89
  return root.namespace ? `${root.path} (${root.namespace})` : root.path;
90
90
  }
91
91
  async function cmdScan(configPath) {
92
- const { options } = await chunkTIKHPRMB_cjs.loadToolHubConfig(configPath);
92
+ const { options } = await chunkXHNKPSOO_cjs.loadToolHubConfig(configPath);
93
93
  const hub = await createHubAndInit(options);
94
94
  const specs = hub.getRegistry().snapshot();
95
95
  const roots = options.roots ?? [];
@@ -141,7 +141,7 @@ function formatSpecFull(spec) {
141
141
  );
142
142
  }
143
143
  async function cmdList(configPath, detail) {
144
- const { options } = await chunkTIKHPRMB_cjs.loadToolHubConfig(configPath);
144
+ const { options } = await chunkXHNKPSOO_cjs.loadToolHubConfig(configPath);
145
145
  const hub = await createHubAndInit(options);
146
146
  const specs = hub.getRegistry().snapshot();
147
147
  const formatter = detail === "short" ? formatSpecShort : detail === "full" ? formatSpecFull : formatSpecNormal;
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { loadToolHubConfig, createToolHub } from './chunk-HPDQEW2P.js';
2
+ import { loadToolHubConfig, createToolHub } from './chunk-QSBCXLMH.js';
3
3
  import './chunk-YSYEED4K.js';
4
4
  import path from 'path';
5
5
  import { fileURLToPath } from 'url';
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk6QTWECRD_cjs = require('./chunk-6QTWECRD.cjs');
4
- var chunkTIKHPRMB_cjs = require('./chunk-TIKHPRMB.cjs');
3
+ var chunkCJZ2EWUG_cjs = require('./chunk-CJZ2EWUG.cjs');
4
+ var chunkXHNKPSOO_cjs = require('./chunk-XHNKPSOO.cjs');
5
5
  var chunkX53WXBKX_cjs = require('./chunk-X53WXBKX.cjs');
6
6
  var chunkNTTBDQUF_cjs = require('./chunk-NTTBDQUF.cjs');
7
7
  var uuid = require('uuid');
@@ -281,7 +281,7 @@ var DirectoryToolAdapter = class {
281
281
  // Required by ToolAdapter but not used for routing
282
282
  scanner;
283
283
  constructor(options) {
284
- this.scanner = new chunkTIKHPRMB_cjs.DirectoryScanner(options);
284
+ this.scanner = new chunkXHNKPSOO_cjs.DirectoryScanner(options);
285
285
  }
286
286
  /**
287
287
  * Scan directories and return discovered tool specs.
@@ -354,217 +354,288 @@ var MCPProcessManager = class {
354
354
  }
355
355
  };
356
356
 
357
+ // src/llm/OpenAICompatibleClient.ts
358
+ function createOpenAICompatibleClient(baseUrl, model, apiKey) {
359
+ return new OpenAICompatibleClient({ baseUrl, model, apiKey });
360
+ }
361
+ var OpenAICompatibleClient = class {
362
+ baseUrl;
363
+ model;
364
+ apiKey;
365
+ constructor(config) {
366
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
367
+ this.model = config.model;
368
+ this.apiKey = config.apiKey;
369
+ }
370
+ /**
371
+ * Send chat messages and return the first assistant reply.
372
+ *
373
+ * @param messages - Array of { role, content }
374
+ * @param options - Optional timeout
375
+ * @returns Promise of { content, raw }
376
+ */
377
+ async chat(messages, options) {
378
+ const timeoutMs = options?.timeoutMs ?? 6e4;
379
+ const url = `${this.baseUrl}/chat/completions`;
380
+ const headers = {
381
+ "Content-Type": "application/json"
382
+ };
383
+ if (this.apiKey) {
384
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
385
+ }
386
+ const controller = new AbortController();
387
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
388
+ let response;
389
+ try {
390
+ response = await fetch(url, {
391
+ method: "POST",
392
+ headers,
393
+ body: JSON.stringify({
394
+ model: this.model,
395
+ messages: messages.map((m) => ({ role: m.role, content: m.content }))
396
+ }),
397
+ signal: controller.signal
398
+ });
399
+ } catch (err) {
400
+ clearTimeout(timer);
401
+ if (err instanceof Error && err.name === "AbortError") {
402
+ throw new Error(`LLM request timed out after ${timeoutMs}ms`);
403
+ }
404
+ throw err;
405
+ }
406
+ clearTimeout(timer);
407
+ const raw = await response.json();
408
+ if (!response.ok) {
409
+ const errBody = typeof raw === "object" && raw !== null && "error" in raw ? raw.error : raw;
410
+ throw new Error(
411
+ `LLM API error ${response.status}: ${JSON.stringify(errBody)}`
412
+ );
413
+ }
414
+ const choices = raw.choices;
415
+ const content = Array.isArray(choices) && choices[0]?.message?.content != null ? String(choices[0].message.content) : "";
416
+ return { content, raw };
417
+ }
418
+ };
419
+
420
+ Object.defineProperty(exports, "AgentToolHub", {
421
+ enumerable: true,
422
+ get: function () { return chunkCJZ2EWUG_cjs.AgentToolHub; }
423
+ });
357
424
  Object.defineProperty(exports, "createAgentToolHub", {
358
425
  enumerable: true,
359
- get: function () { return chunk6QTWECRD_cjs.createAgentToolHub; }
426
+ get: function () { return chunkCJZ2EWUG_cjs.createAgentToolHub; }
360
427
  });
361
428
  Object.defineProperty(exports, "createToolHubAndInitFromConfig", {
362
429
  enumerable: true,
363
- get: function () { return chunk6QTWECRD_cjs.createToolHubAndInitFromConfig; }
430
+ get: function () { return chunkCJZ2EWUG_cjs.createToolHubAndInitFromConfig; }
364
431
  });
365
432
  Object.defineProperty(exports, "BudgetManager", {
366
433
  enumerable: true,
367
- get: function () { return chunkTIKHPRMB_cjs.BudgetManager; }
434
+ get: function () { return chunkXHNKPSOO_cjs.BudgetManager; }
368
435
  });
369
436
  Object.defineProperty(exports, "ComfyUIAdapter", {
370
437
  enumerable: true,
371
- get: function () { return chunkTIKHPRMB_cjs.ComfyUIAdapter; }
438
+ get: function () { return chunkXHNKPSOO_cjs.ComfyUIAdapter; }
372
439
  });
373
440
  Object.defineProperty(exports, "CoreAdapter", {
374
441
  enumerable: true,
375
- get: function () { return chunkTIKHPRMB_cjs.CoreAdapter; }
442
+ get: function () { return chunkXHNKPSOO_cjs.CoreAdapter; }
443
+ });
444
+ Object.defineProperty(exports, "DEFAULT_CONFIG_FILE", {
445
+ enumerable: true,
446
+ get: function () { return chunkXHNKPSOO_cjs.DEFAULT_CONFIG_FILE; }
376
447
  });
377
448
  Object.defineProperty(exports, "DEFAULT_CORE_TOOLS_CONFIG", {
378
449
  enumerable: true,
379
- get: function () { return chunkTIKHPRMB_cjs.DEFAULT_CORE_TOOLS_CONFIG; }
450
+ get: function () { return chunkXHNKPSOO_cjs.DEFAULT_CORE_TOOLS_CONFIG; }
380
451
  });
381
452
  Object.defineProperty(exports, "DirectoryScanner", {
382
453
  enumerable: true,
383
- get: function () { return chunkTIKHPRMB_cjs.DirectoryScanner; }
454
+ get: function () { return chunkXHNKPSOO_cjs.DirectoryScanner; }
384
455
  });
385
456
  Object.defineProperty(exports, "DiscoveryError", {
386
457
  enumerable: true,
387
- get: function () { return chunkTIKHPRMB_cjs.DiscoveryError; }
458
+ get: function () { return chunkXHNKPSOO_cjs.DiscoveryError; }
388
459
  });
389
460
  Object.defineProperty(exports, "EventLog", {
390
461
  enumerable: true,
391
- get: function () { return chunkTIKHPRMB_cjs.EventLog; }
462
+ get: function () { return chunkXHNKPSOO_cjs.EventLog; }
392
463
  });
393
464
  Object.defineProperty(exports, "LangChainAdapter", {
394
465
  enumerable: true,
395
- get: function () { return chunkTIKHPRMB_cjs.LangChainAdapter; }
466
+ get: function () { return chunkXHNKPSOO_cjs.LangChainAdapter; }
396
467
  });
397
468
  Object.defineProperty(exports, "MCPAdapter", {
398
469
  enumerable: true,
399
- get: function () { return chunkTIKHPRMB_cjs.MCPAdapter; }
470
+ get: function () { return chunkXHNKPSOO_cjs.MCPAdapter; }
400
471
  });
401
472
  Object.defineProperty(exports, "Metrics", {
402
473
  enumerable: true,
403
- get: function () { return chunkTIKHPRMB_cjs.Metrics; }
474
+ get: function () { return chunkXHNKPSOO_cjs.Metrics; }
404
475
  });
405
476
  Object.defineProperty(exports, "N8nAdapter", {
406
477
  enumerable: true,
407
- get: function () { return chunkTIKHPRMB_cjs.N8nAdapter; }
478
+ get: function () { return chunkXHNKPSOO_cjs.N8nAdapter; }
408
479
  });
409
480
  Object.defineProperty(exports, "PTCRuntime", {
410
481
  enumerable: true,
411
- get: function () { return chunkTIKHPRMB_cjs.PTCRuntime; }
482
+ get: function () { return chunkXHNKPSOO_cjs.PTCRuntime; }
412
483
  });
413
484
  Object.defineProperty(exports, "PolicyDeniedError", {
414
485
  enumerable: true,
415
- get: function () { return chunkTIKHPRMB_cjs.PolicyDeniedError; }
486
+ get: function () { return chunkXHNKPSOO_cjs.PolicyDeniedError; }
416
487
  });
417
488
  Object.defineProperty(exports, "PolicyEngine", {
418
489
  enumerable: true,
419
- get: function () { return chunkTIKHPRMB_cjs.PolicyEngine; }
490
+ get: function () { return chunkXHNKPSOO_cjs.PolicyEngine; }
420
491
  });
421
492
  Object.defineProperty(exports, "SchemaValidationError", {
422
493
  enumerable: true,
423
- get: function () { return chunkTIKHPRMB_cjs.SchemaValidationError; }
494
+ get: function () { return chunkXHNKPSOO_cjs.SchemaValidationError; }
424
495
  });
425
496
  Object.defineProperty(exports, "SchemaValidator", {
426
497
  enumerable: true,
427
- get: function () { return chunkTIKHPRMB_cjs.SchemaValidator; }
498
+ get: function () { return chunkXHNKPSOO_cjs.SchemaValidator; }
428
499
  });
429
500
  Object.defineProperty(exports, "SkillAdapter", {
430
501
  enumerable: true,
431
- get: function () { return chunkTIKHPRMB_cjs.SkillAdapter; }
502
+ get: function () { return chunkXHNKPSOO_cjs.SkillAdapter; }
432
503
  });
433
504
  Object.defineProperty(exports, "SkillManifestError", {
434
505
  enumerable: true,
435
- get: function () { return chunkTIKHPRMB_cjs.SkillManifestError; }
506
+ get: function () { return chunkXHNKPSOO_cjs.SkillManifestError; }
436
507
  });
437
508
  Object.defineProperty(exports, "ToolHub", {
438
509
  enumerable: true,
439
- get: function () { return chunkTIKHPRMB_cjs.ToolHub; }
510
+ get: function () { return chunkXHNKPSOO_cjs.ToolHub; }
440
511
  });
441
512
  Object.defineProperty(exports, "ToolRegistry", {
442
513
  enumerable: true,
443
- get: function () { return chunkTIKHPRMB_cjs.ToolRegistry; }
514
+ get: function () { return chunkXHNKPSOO_cjs.ToolRegistry; }
444
515
  });
445
516
  Object.defineProperty(exports, "Tracing", {
446
517
  enumerable: true,
447
- get: function () { return chunkTIKHPRMB_cjs.Tracing; }
518
+ get: function () { return chunkXHNKPSOO_cjs.Tracing; }
448
519
  });
449
520
  Object.defineProperty(exports, "buildEvidence", {
450
521
  enumerable: true,
451
- get: function () { return chunkTIKHPRMB_cjs.buildEvidence; }
522
+ get: function () { return chunkXHNKPSOO_cjs.buildEvidence; }
452
523
  });
453
524
  Object.defineProperty(exports, "createTaggedError", {
454
525
  enumerable: true,
455
- get: function () { return chunkTIKHPRMB_cjs.createTaggedError; }
526
+ get: function () { return chunkXHNKPSOO_cjs.createTaggedError; }
456
527
  });
457
528
  Object.defineProperty(exports, "createToolHub", {
458
529
  enumerable: true,
459
- get: function () { return chunkTIKHPRMB_cjs.createToolHub; }
530
+ get: function () { return chunkXHNKPSOO_cjs.createToolHub; }
460
531
  });
461
532
  Object.defineProperty(exports, "deletePathSpec", {
462
533
  enumerable: true,
463
- get: function () { return chunkTIKHPRMB_cjs.deletePathSpec; }
534
+ get: function () { return chunkXHNKPSOO_cjs.deletePathSpec; }
464
535
  });
465
536
  Object.defineProperty(exports, "downloadFileSpec", {
466
537
  enumerable: true,
467
- get: function () { return chunkTIKHPRMB_cjs.downloadFileSpec; }
538
+ get: function () { return chunkXHNKPSOO_cjs.downloadFileSpec; }
468
539
  });
469
540
  Object.defineProperty(exports, "fetchJsonSpec", {
470
541
  enumerable: true,
471
- get: function () { return chunkTIKHPRMB_cjs.fetchJsonSpec; }
542
+ get: function () { return chunkXHNKPSOO_cjs.fetchJsonSpec; }
472
543
  });
473
544
  Object.defineProperty(exports, "fetchTextSpec", {
474
545
  enumerable: true,
475
- get: function () { return chunkTIKHPRMB_cjs.fetchTextSpec; }
546
+ get: function () { return chunkXHNKPSOO_cjs.fetchTextSpec; }
476
547
  });
477
548
  Object.defineProperty(exports, "hashTextSpec", {
478
549
  enumerable: true,
479
- get: function () { return chunkTIKHPRMB_cjs.hashTextSpec; }
550
+ get: function () { return chunkXHNKPSOO_cjs.hashTextSpec; }
480
551
  });
481
552
  Object.defineProperty(exports, "headSpec", {
482
553
  enumerable: true,
483
- get: function () { return chunkTIKHPRMB_cjs.headSpec; }
554
+ get: function () { return chunkXHNKPSOO_cjs.headSpec; }
484
555
  });
485
556
  Object.defineProperty(exports, "isIpInBlockedCidrs", {
486
557
  enumerable: true,
487
- get: function () { return chunkTIKHPRMB_cjs.isIpInBlockedCidrs; }
558
+ get: function () { return chunkXHNKPSOO_cjs.isIpInBlockedCidrs; }
488
559
  });
489
560
  Object.defineProperty(exports, "isRetryable", {
490
561
  enumerable: true,
491
- get: function () { return chunkTIKHPRMB_cjs.isRetryable; }
562
+ get: function () { return chunkXHNKPSOO_cjs.isRetryable; }
492
563
  });
493
564
  Object.defineProperty(exports, "jsonSelectSpec", {
494
565
  enumerable: true,
495
- get: function () { return chunkTIKHPRMB_cjs.jsonSelectSpec; }
566
+ get: function () { return chunkXHNKPSOO_cjs.jsonSelectSpec; }
496
567
  });
497
568
  Object.defineProperty(exports, "listDirSpec", {
498
569
  enumerable: true,
499
- get: function () { return chunkTIKHPRMB_cjs.listDirSpec; }
570
+ get: function () { return chunkXHNKPSOO_cjs.listDirSpec; }
500
571
  });
501
572
  Object.defineProperty(exports, "loadSkillDefinition", {
502
573
  enumerable: true,
503
- get: function () { return chunkTIKHPRMB_cjs.loadSkillDefinition; }
574
+ get: function () { return chunkXHNKPSOO_cjs.loadSkillDefinition; }
504
575
  });
505
576
  Object.defineProperty(exports, "loadToolHubConfig", {
506
577
  enumerable: true,
507
- get: function () { return chunkTIKHPRMB_cjs.loadToolHubConfig; }
578
+ get: function () { return chunkXHNKPSOO_cjs.loadToolHubConfig; }
508
579
  });
509
580
  Object.defineProperty(exports, "mapToolHubConfig", {
510
581
  enumerable: true,
511
- get: function () { return chunkTIKHPRMB_cjs.mapToolHubConfig; }
582
+ get: function () { return chunkXHNKPSOO_cjs.mapToolHubConfig; }
512
583
  });
513
584
  Object.defineProperty(exports, "nowSpec", {
514
585
  enumerable: true,
515
- get: function () { return chunkTIKHPRMB_cjs.nowSpec; }
586
+ get: function () { return chunkXHNKPSOO_cjs.nowSpec; }
516
587
  });
517
588
  Object.defineProperty(exports, "parseSkillMd", {
518
589
  enumerable: true,
519
- get: function () { return chunkTIKHPRMB_cjs.parseSkillMd; }
590
+ get: function () { return chunkXHNKPSOO_cjs.parseSkillMd; }
520
591
  });
521
592
  Object.defineProperty(exports, "readTextSpec", {
522
593
  enumerable: true,
523
- get: function () { return chunkTIKHPRMB_cjs.readTextSpec; }
594
+ get: function () { return chunkXHNKPSOO_cjs.readTextSpec; }
524
595
  });
525
596
  Object.defineProperty(exports, "registerCoreTools", {
526
597
  enumerable: true,
527
- get: function () { return chunkTIKHPRMB_cjs.registerCoreTools; }
598
+ get: function () { return chunkXHNKPSOO_cjs.registerCoreTools; }
528
599
  });
529
600
  Object.defineProperty(exports, "resolveSandboxedPath", {
530
601
  enumerable: true,
531
- get: function () { return chunkTIKHPRMB_cjs.resolveSandboxedPath; }
602
+ get: function () { return chunkXHNKPSOO_cjs.resolveSandboxedPath; }
532
603
  });
533
604
  Object.defineProperty(exports, "scanSkillResources", {
534
605
  enumerable: true,
535
- get: function () { return chunkTIKHPRMB_cjs.scanSkillResources; }
606
+ get: function () { return chunkXHNKPSOO_cjs.scanSkillResources; }
536
607
  });
537
608
  Object.defineProperty(exports, "searchTextSpec", {
538
609
  enumerable: true,
539
- get: function () { return chunkTIKHPRMB_cjs.searchTextSpec; }
610
+ get: function () { return chunkXHNKPSOO_cjs.searchTextSpec; }
540
611
  });
541
612
  Object.defineProperty(exports, "sha256Spec", {
542
613
  enumerable: true,
543
- get: function () { return chunkTIKHPRMB_cjs.sha256Spec; }
614
+ get: function () { return chunkXHNKPSOO_cjs.sha256Spec; }
544
615
  });
545
616
  Object.defineProperty(exports, "templateRenderSpec", {
546
617
  enumerable: true,
547
- get: function () { return chunkTIKHPRMB_cjs.templateRenderSpec; }
618
+ get: function () { return chunkXHNKPSOO_cjs.templateRenderSpec; }
548
619
  });
549
620
  Object.defineProperty(exports, "truncateSpec", {
550
621
  enumerable: true,
551
- get: function () { return chunkTIKHPRMB_cjs.truncateSpec; }
622
+ get: function () { return chunkXHNKPSOO_cjs.truncateSpec; }
552
623
  });
553
624
  Object.defineProperty(exports, "validateFrontmatter", {
554
625
  enumerable: true,
555
- get: function () { return chunkTIKHPRMB_cjs.validateFrontmatter; }
626
+ get: function () { return chunkXHNKPSOO_cjs.validateFrontmatter; }
556
627
  });
557
628
  Object.defineProperty(exports, "validateUrl", {
558
629
  enumerable: true,
559
- get: function () { return chunkTIKHPRMB_cjs.validateUrl; }
630
+ get: function () { return chunkXHNKPSOO_cjs.validateUrl; }
560
631
  });
561
632
  Object.defineProperty(exports, "withRetry", {
562
633
  enumerable: true,
563
- get: function () { return chunkTIKHPRMB_cjs.withRetry; }
634
+ get: function () { return chunkXHNKPSOO_cjs.withRetry; }
564
635
  });
565
636
  Object.defineProperty(exports, "writeTextSpec", {
566
637
  enumerable: true,
567
- get: function () { return chunkTIKHPRMB_cjs.writeTextSpec; }
638
+ get: function () { return chunkXHNKPSOO_cjs.writeTextSpec; }
568
639
  });
569
640
  Object.defineProperty(exports, "N8nLocalAdapter", {
570
641
  enumerable: true,
@@ -587,6 +658,8 @@ exports.DirectoryToolAdapter = DirectoryToolAdapter;
587
658
  exports.Discovery = Discovery;
588
659
  exports.InMemoryJobStore = InMemoryJobStore;
589
660
  exports.MCPProcessManager = MCPProcessManager;
661
+ exports.OpenAICompatibleClient = OpenAICompatibleClient;
590
662
  exports.createDirectoryDiscoverySource = createDirectoryDiscoverySource;
663
+ exports.createOpenAICompatibleClient = createOpenAICompatibleClient;
591
664
  //# sourceMappingURL=index.cjs.map
592
665
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry/Discovery.ts","../src/jobs/AsyncJobManager.ts","../src/discovery/DirectoryDiscoverySource.ts","../src/discovery/MCPProcessManager.ts"],"names":["EventEmitter","uuidv4","DirectoryScanner"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ToolAdapter, ToolSpec } from \"../types/ToolSpec.js\";\nimport type { ToolRegistry } from \"./ToolRegistry.js\";\n\n/**\n * Discovery source configuration.\n */\nexport interface DiscoverySource {\n /** Unique identifier for this source */\n id: string;\n /** The adapter that supports listTools() */\n adapter: ToolAdapter;\n /** Refresh interval in ms (0 = manual only) */\n refreshIntervalMs?: number;\n /** Whether to auto-discover on startup */\n autoDiscover?: boolean;\n}\n\n/**\n * Discovery manager that pulls tool specs from adapters\n * and registers them into the ToolRegistry.\n */\nexport class Discovery {\n private readonly sources = new Map<string, DiscoverySource>();\n private readonly timers = new Map<string, ReturnType<typeof setInterval>>();\n private readonly registry: ToolRegistry;\n private readonly lastRefresh = new Map<string, number>();\n private readonly discoveredTools = new Map<string, Set<string>>(); // sourceId → tool names\n\n constructor(registry: ToolRegistry) {\n this.registry = registry;\n }\n\n /**\n * Add a discovery source.\n */\n addSource(source: DiscoverySource): void {\n this.sources.set(source.id, source);\n this.discoveredTools.set(source.id, new Set());\n\n // Start auto-refresh if configured\n if (source.refreshIntervalMs && source.refreshIntervalMs > 0) {\n const timer = setInterval(\n () => void this.refresh(source.id),\n source.refreshIntervalMs,\n );\n // Unref so it doesn't prevent process exit\n if (typeof timer === \"object\" && \"unref\" in timer) {\n timer.unref();\n }\n this.timers.set(source.id, timer);\n }\n\n // Auto-discover on add if configured\n if (source.autoDiscover) {\n void this.refresh(source.id);\n }\n }\n\n /**\n * Remove a discovery source and its registered tools.\n */\n removeSource(id: string): void {\n const timer = this.timers.get(id);\n if (timer) {\n clearInterval(timer);\n this.timers.delete(id);\n }\n\n // Unregister tools from this source\n const tools = this.discoveredTools.get(id);\n if (tools) {\n for (const name of tools) {\n this.registry.unregister(name);\n }\n }\n\n this.sources.delete(id);\n this.discoveredTools.delete(id);\n this.lastRefresh.delete(id);\n }\n\n /**\n * Refresh tools from a specific source (or all sources).\n */\n async refresh(sourceId?: string): Promise<ToolSpec[]> {\n if (sourceId) {\n return this.refreshSource(sourceId);\n }\n\n const allSpecs: ToolSpec[] = [];\n for (const id of this.sources.keys()) {\n const specs = await this.refreshSource(id);\n allSpecs.push(...specs);\n }\n return allSpecs;\n }\n\n /**\n * Get the last refresh timestamp for a source.\n */\n getLastRefresh(sourceId: string): number | undefined {\n return this.lastRefresh.get(sourceId);\n }\n\n /**\n * Get all registered source IDs.\n */\n getSources(): string[] {\n return [...this.sources.keys()];\n }\n\n /**\n * Stop all refresh timers.\n */\n dispose(): void {\n for (const timer of this.timers.values()) {\n clearInterval(timer);\n }\n this.timers.clear();\n }\n\n private async refreshSource(sourceId: string): Promise<ToolSpec[]> {\n const source = this.sources.get(sourceId);\n if (!source) return [];\n\n if (!source.adapter.listTools) {\n return [];\n }\n\n try {\n const specs = await source.adapter.listTools();\n const currentTools = this.discoveredTools.get(sourceId) ?? new Set();\n const newToolNames = new Set(specs.map((s) => s.name));\n\n // Unregister tools that are no longer present\n for (const name of currentTools) {\n if (!newToolNames.has(name)) {\n this.registry.unregister(name);\n }\n }\n\n // Register/update tools\n for (const spec of specs) {\n this.registry.register(spec);\n }\n\n this.discoveredTools.set(sourceId, newToolNames);\n this.lastRefresh.set(sourceId, Date.now());\n\n return specs;\n } catch (error) {\n // Log but don't throw - discovery failures shouldn't crash the system\n console.error(`Discovery refresh failed for source ${sourceId}:`, error);\n return [];\n }\n }\n}\n","import { v4 as uuidv4 } from \"uuid\";\nimport { EventEmitter } from \"eventemitter3\";\n\n/**\n * Job status in the lifecycle.\n */\nexport type JobStatus = \"queued\" | \"running\" | \"completed\" | \"failed\";\n\n/**\n * A job record representing an async tool invocation.\n */\nexport interface Job {\n jobId: string;\n toolName: string;\n requestId: string;\n taskId: string;\n status: JobStatus;\n createdAt: number; // epoch ms\n updatedAt: number;\n result?: unknown;\n error?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for submitting a job.\n */\nexport interface SubmitJobOptions {\n toolName: string;\n requestId: string;\n taskId: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Job store interface for pluggable backends.\n */\nexport interface JobStore {\n set(jobId: string, job: Job): Promise<void>;\n get(jobId: string): Promise<Job | undefined>;\n list(filter?: { toolName?: string; status?: JobStatus }): Promise<Job[]>;\n delete(jobId: string): Promise<void>;\n}\n\n/**\n * In-memory job store (default, for PoC and testing).\n */\nexport class InMemoryJobStore implements JobStore {\n private readonly jobs = new Map<string, Job>();\n\n async set(jobId: string, job: Job): Promise<void> {\n this.jobs.set(jobId, job);\n }\n\n async get(jobId: string): Promise<Job | undefined> {\n return this.jobs.get(jobId);\n }\n\n async list(filter?: { toolName?: string; status?: JobStatus }): Promise<Job[]> {\n let results = [...this.jobs.values()];\n if (filter?.toolName) {\n results = results.filter((j) => j.toolName === filter.toolName);\n }\n if (filter?.status) {\n results = results.filter((j) => j.status === filter.status);\n }\n return results;\n }\n\n async delete(jobId: string): Promise<void> {\n this.jobs.delete(jobId);\n }\n\n get size(): number {\n return this.jobs.size;\n }\n\n clear(): void {\n this.jobs.clear();\n }\n}\n\n/**\n * Async Job Manager: unified async task handling for tools.\n * Provides submit/poll/getResult pattern.\n */\nexport class AsyncJobManager {\n private readonly store: JobStore;\n private readonly emitter = new EventEmitter();\n private readonly ttlMs: number;\n private cleanupTimer?: ReturnType<typeof setInterval>;\n\n constructor(options: { store?: JobStore; ttlMs?: number } = {}) {\n this.store = options.store ?? new InMemoryJobStore();\n this.ttlMs = options.ttlMs ?? 3600_000; // 1 hour default TTL\n this.startCleanup();\n }\n\n /**\n * Submit a new async job.\n */\n async submit(options: SubmitJobOptions): Promise<Job> {\n const now = Date.now();\n const job: Job = {\n jobId: uuidv4(),\n toolName: options.toolName,\n requestId: options.requestId,\n taskId: options.taskId,\n status: \"queued\",\n createdAt: now,\n updatedAt: now,\n metadata: options.metadata,\n };\n\n await this.store.set(job.jobId, job);\n this.emitter.emit(\"submitted\", job);\n return job;\n }\n\n /**\n * Update job status to running.\n */\n async markRunning(jobId: string): Promise<Job | undefined> {\n const job = await this.store.get(jobId);\n if (!job) return undefined;\n\n job.status = \"running\";\n job.updatedAt = Date.now();\n await this.store.set(jobId, job);\n this.emitter.emit(\"running\", job);\n return job;\n }\n\n /**\n * Complete a job with a result.\n */\n async complete(jobId: string, result: unknown): Promise<Job | undefined> {\n const job = await this.store.get(jobId);\n if (!job) return undefined;\n\n job.status = \"completed\";\n job.result = result;\n job.updatedAt = Date.now();\n await this.store.set(jobId, job);\n this.emitter.emit(\"completed\", job);\n return job;\n }\n\n /**\n * Fail a job with an error message.\n */\n async fail(jobId: string, error: string): Promise<Job | undefined> {\n const job = await this.store.get(jobId);\n if (!job) return undefined;\n\n job.status = \"failed\";\n job.error = error;\n job.updatedAt = Date.now();\n await this.store.set(jobId, job);\n this.emitter.emit(\"failed\", job);\n return job;\n }\n\n /**\n * Get current job status.\n */\n async getStatus(jobId: string): Promise<JobStatus | undefined> {\n const job = await this.store.get(jobId);\n return job?.status;\n }\n\n /**\n * Get the full job record.\n */\n async getJob(jobId: string): Promise<Job | undefined> {\n return this.store.get(jobId);\n }\n\n /**\n * Get the result of a completed job.\n */\n async getResult(jobId: string): Promise<unknown | undefined> {\n const job = await this.store.get(jobId);\n if (!job || job.status !== \"completed\") return undefined;\n return job.result;\n }\n\n /**\n * List jobs with optional filter.\n */\n async list(filter?: {\n toolName?: string;\n status?: JobStatus;\n }): Promise<Job[]> {\n return this.store.list(filter);\n }\n\n /**\n * Subscribe to job events.\n */\n on(\n event: \"submitted\" | \"running\" | \"completed\" | \"failed\",\n listener: (job: Job) => void,\n ): () => void {\n this.emitter.on(event, listener);\n return () => this.emitter.off(event, listener);\n }\n\n /**\n * Stop cleanup timer.\n */\n dispose(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = undefined;\n }\n }\n\n private startCleanup(): void {\n // Run cleanup every TTL/2 interval\n const interval = Math.max(this.ttlMs / 2, 60_000);\n this.cleanupTimer = setInterval(() => void this.cleanup(), interval);\n if (typeof this.cleanupTimer === \"object\" && \"unref\" in this.cleanupTimer) {\n this.cleanupTimer.unref();\n }\n }\n\n private async cleanup(): Promise<void> {\n const now = Date.now();\n const all = await this.store.list();\n for (const job of all) {\n if (\n (job.status === \"completed\" || job.status === \"failed\") &&\n now - job.updatedAt > this.ttlMs\n ) {\n await this.store.delete(job.jobId);\n }\n }\n }\n}\n","import type { ToolAdapter, ToolSpec } from \"../types/ToolSpec.js\";\nimport type { ExecContext } from \"../types/ToolIntent.js\";\nimport type { DirectoryScannerOptions } from \"./types.js\";\nimport type { DiscoverySource } from \"../registry/Discovery.js\";\nimport { DirectoryScanner } from \"./DirectoryScanner.js\";\n\n/**\n * A ToolAdapter that discovers tools from filesystem directories.\n * Used as the adapter within a DiscoverySource for the Discovery system.\n *\n * Note: This adapter's invoke() is not called directly. Discovered tools\n * retain their original kind (mcp/langchain/skill/n8n) and are invoked\n * by the kind-specific adapter registered on PTCRuntime.\n */\nexport class DirectoryToolAdapter implements ToolAdapter {\n readonly kind = \"mcp\" as const; // Required by ToolAdapter but not used for routing\n private readonly scanner: DirectoryScanner;\n\n constructor(options: DirectoryScannerOptions) {\n this.scanner = new DirectoryScanner(options);\n }\n\n /**\n * Scan directories and return discovered tool specs.\n * Called by Discovery.refresh().\n */\n async listTools(): Promise<ToolSpec[]> {\n return this.scanner.scan();\n }\n\n /**\n * Not used — actual invocation routes through kind-specific adapters.\n */\n async invoke(\n _spec: ToolSpec,\n _args: unknown,\n _ctx: ExecContext,\n ): Promise<{ result: unknown }> {\n throw new Error(\n \"DirectoryToolAdapter.invoke() should not be called directly. \" +\n \"Tool execution is handled by the kind-specific adapter (MCPAdapter, LangChainAdapter, etc.).\",\n );\n }\n\n /**\n * Get the underlying scanner for direct usage.\n */\n getScanner(): DirectoryScanner {\n return this.scanner;\n }\n}\n\n/**\n * Options for creating a directory discovery source.\n */\nexport interface DirectoryDiscoveryOptions extends DirectoryScannerOptions {\n /** Refresh interval in ms (0 = manual only, default: 0) */\n refreshIntervalMs?: number;\n /** Whether to auto-discover on startup (default: true) */\n autoDiscover?: boolean;\n}\n\n/**\n * Factory: create a DiscoverySource for directory-based tool discovery.\n *\n * Usage:\n * ```ts\n * const discovery = new Discovery(registry);\n * discovery.addSource(\n * createDirectoryDiscoverySource(\"local-tools\", {\n * roots: [\"/path/to/tools\"],\n * namespace: \"local\",\n * refreshIntervalMs: 60_000,\n * autoDiscover: true,\n * })\n * );\n * ```\n */\nexport function createDirectoryDiscoverySource(\n id: string,\n options: DirectoryDiscoveryOptions,\n): DiscoverySource {\n const { refreshIntervalMs, autoDiscover, ...scannerOptions } = options;\n\n return {\n id,\n adapter: new DirectoryToolAdapter(scannerOptions),\n refreshIntervalMs: refreshIntervalMs ?? 0,\n autoDiscover: autoDiscover ?? true,\n };\n}\n","import type { MCPServerConfig } from \"./types.js\";\n\n/**\n * Connection info for an MCP server.\n */\nexport interface MCPConnectionInfo {\n /** Transport type: \"url\" for SSE/HTTP, \"stdio\" for command-based */\n type: \"url\" | \"stdio\";\n /** SSE/HTTP URL (when type=\"url\") */\n url?: string;\n /** Command to spawn (when type=\"stdio\") */\n command?: string;\n /** Command arguments (when type=\"stdio\") */\n args?: string[];\n /** Environment variables (when type=\"stdio\") */\n env?: Record<string, string>;\n}\n\n/**\n * Manages MCP server connection information extracted from directory discovery.\n *\n * This class provides connection configuration for MCP servers discovered\n * from mcp.json files. The actual MCP client creation and lifecycle management\n * is the consumer's responsibility (using @modelcontextprotocol/sdk or similar).\n *\n * Usage:\n * ```ts\n * const manager = new MCPProcessManager();\n * const info = manager.getConnectionInfo(\"my-tool\", mcpConfig);\n * if (info.type === \"stdio\") {\n * // Spawn process with info.command, info.args, info.env\n * } else {\n * // Connect SSE client to info.url\n * }\n * ```\n */\nexport class MCPProcessManager {\n private readonly connections = new Map<string, MCPConnectionInfo>();\n\n /**\n * Get connection info for an MCP tool based on its config.\n * Caches the result by tool name.\n */\n getConnectionInfo(toolName: string, config: MCPServerConfig): MCPConnectionInfo {\n const cached = this.connections.get(toolName);\n if (cached) return cached;\n\n const info: MCPConnectionInfo = config.url\n ? { type: \"url\", url: config.url }\n : {\n type: \"stdio\",\n command: config.command!,\n args: config.args,\n env: config.env,\n };\n\n this.connections.set(toolName, info);\n return info;\n }\n\n /**\n * Remove cached connection info for a tool.\n */\n remove(toolName: string): boolean {\n return this.connections.delete(toolName);\n }\n\n /**\n * Get all registered tool names.\n */\n getToolNames(): string[] {\n return [...this.connections.keys()];\n }\n\n /**\n * Clear all cached connection info.\n */\n dispose(): void {\n this.connections.clear();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/registry/Discovery.ts","../src/jobs/AsyncJobManager.ts","../src/discovery/DirectoryDiscoverySource.ts","../src/discovery/MCPProcessManager.ts","../src/llm/OpenAICompatibleClient.ts"],"names":["EventEmitter","uuidv4","DirectoryScanner"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ToolAdapter, ToolSpec } from \"../types/ToolSpec.js\";\nimport type { ToolRegistry } from \"./ToolRegistry.js\";\n\n/**\n * Discovery source configuration.\n */\nexport interface DiscoverySource {\n /** Unique identifier for this source */\n id: string;\n /** The adapter that supports listTools() */\n adapter: ToolAdapter;\n /** Refresh interval in ms (0 = manual only) */\n refreshIntervalMs?: number;\n /** Whether to auto-discover on startup */\n autoDiscover?: boolean;\n}\n\n/**\n * Discovery manager that pulls tool specs from adapters\n * and registers them into the ToolRegistry.\n */\nexport class Discovery {\n private readonly sources = new Map<string, DiscoverySource>();\n private readonly timers = new Map<string, ReturnType<typeof setInterval>>();\n private readonly registry: ToolRegistry;\n private readonly lastRefresh = new Map<string, number>();\n private readonly discoveredTools = new Map<string, Set<string>>(); // sourceId → tool names\n\n constructor(registry: ToolRegistry) {\n this.registry = registry;\n }\n\n /**\n * Add a discovery source.\n */\n addSource(source: DiscoverySource): void {\n this.sources.set(source.id, source);\n this.discoveredTools.set(source.id, new Set());\n\n // Start auto-refresh if configured\n if (source.refreshIntervalMs && source.refreshIntervalMs > 0) {\n const timer = setInterval(\n () => void this.refresh(source.id),\n source.refreshIntervalMs,\n );\n // Unref so it doesn't prevent process exit\n if (typeof timer === \"object\" && \"unref\" in timer) {\n timer.unref();\n }\n this.timers.set(source.id, timer);\n }\n\n // Auto-discover on add if configured\n if (source.autoDiscover) {\n void this.refresh(source.id);\n }\n }\n\n /**\n * Remove a discovery source and its registered tools.\n */\n removeSource(id: string): void {\n const timer = this.timers.get(id);\n if (timer) {\n clearInterval(timer);\n this.timers.delete(id);\n }\n\n // Unregister tools from this source\n const tools = this.discoveredTools.get(id);\n if (tools) {\n for (const name of tools) {\n this.registry.unregister(name);\n }\n }\n\n this.sources.delete(id);\n this.discoveredTools.delete(id);\n this.lastRefresh.delete(id);\n }\n\n /**\n * Refresh tools from a specific source (or all sources).\n */\n async refresh(sourceId?: string): Promise<ToolSpec[]> {\n if (sourceId) {\n return this.refreshSource(sourceId);\n }\n\n const allSpecs: ToolSpec[] = [];\n for (const id of this.sources.keys()) {\n const specs = await this.refreshSource(id);\n allSpecs.push(...specs);\n }\n return allSpecs;\n }\n\n /**\n * Get the last refresh timestamp for a source.\n */\n getLastRefresh(sourceId: string): number | undefined {\n return this.lastRefresh.get(sourceId);\n }\n\n /**\n * Get all registered source IDs.\n */\n getSources(): string[] {\n return [...this.sources.keys()];\n }\n\n /**\n * Stop all refresh timers.\n */\n dispose(): void {\n for (const timer of this.timers.values()) {\n clearInterval(timer);\n }\n this.timers.clear();\n }\n\n private async refreshSource(sourceId: string): Promise<ToolSpec[]> {\n const source = this.sources.get(sourceId);\n if (!source) return [];\n\n if (!source.adapter.listTools) {\n return [];\n }\n\n try {\n const specs = await source.adapter.listTools();\n const currentTools = this.discoveredTools.get(sourceId) ?? new Set();\n const newToolNames = new Set(specs.map((s) => s.name));\n\n // Unregister tools that are no longer present\n for (const name of currentTools) {\n if (!newToolNames.has(name)) {\n this.registry.unregister(name);\n }\n }\n\n // Register/update tools\n for (const spec of specs) {\n this.registry.register(spec);\n }\n\n this.discoveredTools.set(sourceId, newToolNames);\n this.lastRefresh.set(sourceId, Date.now());\n\n return specs;\n } catch (error) {\n // Log but don't throw - discovery failures shouldn't crash the system\n console.error(`Discovery refresh failed for source ${sourceId}:`, error);\n return [];\n }\n }\n}\n","import { v4 as uuidv4 } from \"uuid\";\nimport { EventEmitter } from \"eventemitter3\";\n\n/**\n * Job status in the lifecycle.\n */\nexport type JobStatus = \"queued\" | \"running\" | \"completed\" | \"failed\";\n\n/**\n * A job record representing an async tool invocation.\n */\nexport interface Job {\n jobId: string;\n toolName: string;\n requestId: string;\n taskId: string;\n status: JobStatus;\n createdAt: number; // epoch ms\n updatedAt: number;\n result?: unknown;\n error?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for submitting a job.\n */\nexport interface SubmitJobOptions {\n toolName: string;\n requestId: string;\n taskId: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Job store interface for pluggable backends.\n */\nexport interface JobStore {\n set(jobId: string, job: Job): Promise<void>;\n get(jobId: string): Promise<Job | undefined>;\n list(filter?: { toolName?: string; status?: JobStatus }): Promise<Job[]>;\n delete(jobId: string): Promise<void>;\n}\n\n/**\n * In-memory job store (default, for PoC and testing).\n */\nexport class InMemoryJobStore implements JobStore {\n private readonly jobs = new Map<string, Job>();\n\n async set(jobId: string, job: Job): Promise<void> {\n this.jobs.set(jobId, job);\n }\n\n async get(jobId: string): Promise<Job | undefined> {\n return this.jobs.get(jobId);\n }\n\n async list(filter?: { toolName?: string; status?: JobStatus }): Promise<Job[]> {\n let results = [...this.jobs.values()];\n if (filter?.toolName) {\n results = results.filter((j) => j.toolName === filter.toolName);\n }\n if (filter?.status) {\n results = results.filter((j) => j.status === filter.status);\n }\n return results;\n }\n\n async delete(jobId: string): Promise<void> {\n this.jobs.delete(jobId);\n }\n\n get size(): number {\n return this.jobs.size;\n }\n\n clear(): void {\n this.jobs.clear();\n }\n}\n\n/**\n * Async Job Manager: unified async task handling for tools.\n * Provides submit/poll/getResult pattern.\n */\nexport class AsyncJobManager {\n private readonly store: JobStore;\n private readonly emitter = new EventEmitter();\n private readonly ttlMs: number;\n private cleanupTimer?: ReturnType<typeof setInterval>;\n\n constructor(options: { store?: JobStore; ttlMs?: number } = {}) {\n this.store = options.store ?? new InMemoryJobStore();\n this.ttlMs = options.ttlMs ?? 3600_000; // 1 hour default TTL\n this.startCleanup();\n }\n\n /**\n * Submit a new async job.\n */\n async submit(options: SubmitJobOptions): Promise<Job> {\n const now = Date.now();\n const job: Job = {\n jobId: uuidv4(),\n toolName: options.toolName,\n requestId: options.requestId,\n taskId: options.taskId,\n status: \"queued\",\n createdAt: now,\n updatedAt: now,\n metadata: options.metadata,\n };\n\n await this.store.set(job.jobId, job);\n this.emitter.emit(\"submitted\", job);\n return job;\n }\n\n /**\n * Update job status to running.\n */\n async markRunning(jobId: string): Promise<Job | undefined> {\n const job = await this.store.get(jobId);\n if (!job) return undefined;\n\n job.status = \"running\";\n job.updatedAt = Date.now();\n await this.store.set(jobId, job);\n this.emitter.emit(\"running\", job);\n return job;\n }\n\n /**\n * Complete a job with a result.\n */\n async complete(jobId: string, result: unknown): Promise<Job | undefined> {\n const job = await this.store.get(jobId);\n if (!job) return undefined;\n\n job.status = \"completed\";\n job.result = result;\n job.updatedAt = Date.now();\n await this.store.set(jobId, job);\n this.emitter.emit(\"completed\", job);\n return job;\n }\n\n /**\n * Fail a job with an error message.\n */\n async fail(jobId: string, error: string): Promise<Job | undefined> {\n const job = await this.store.get(jobId);\n if (!job) return undefined;\n\n job.status = \"failed\";\n job.error = error;\n job.updatedAt = Date.now();\n await this.store.set(jobId, job);\n this.emitter.emit(\"failed\", job);\n return job;\n }\n\n /**\n * Get current job status.\n */\n async getStatus(jobId: string): Promise<JobStatus | undefined> {\n const job = await this.store.get(jobId);\n return job?.status;\n }\n\n /**\n * Get the full job record.\n */\n async getJob(jobId: string): Promise<Job | undefined> {\n return this.store.get(jobId);\n }\n\n /**\n * Get the result of a completed job.\n */\n async getResult(jobId: string): Promise<unknown | undefined> {\n const job = await this.store.get(jobId);\n if (!job || job.status !== \"completed\") return undefined;\n return job.result;\n }\n\n /**\n * List jobs with optional filter.\n */\n async list(filter?: {\n toolName?: string;\n status?: JobStatus;\n }): Promise<Job[]> {\n return this.store.list(filter);\n }\n\n /**\n * Subscribe to job events.\n */\n on(\n event: \"submitted\" | \"running\" | \"completed\" | \"failed\",\n listener: (job: Job) => void,\n ): () => void {\n this.emitter.on(event, listener);\n return () => this.emitter.off(event, listener);\n }\n\n /**\n * Stop cleanup timer.\n */\n dispose(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = undefined;\n }\n }\n\n private startCleanup(): void {\n // Run cleanup every TTL/2 interval\n const interval = Math.max(this.ttlMs / 2, 60_000);\n this.cleanupTimer = setInterval(() => void this.cleanup(), interval);\n if (typeof this.cleanupTimer === \"object\" && \"unref\" in this.cleanupTimer) {\n this.cleanupTimer.unref();\n }\n }\n\n private async cleanup(): Promise<void> {\n const now = Date.now();\n const all = await this.store.list();\n for (const job of all) {\n if (\n (job.status === \"completed\" || job.status === \"failed\") &&\n now - job.updatedAt > this.ttlMs\n ) {\n await this.store.delete(job.jobId);\n }\n }\n }\n}\n","import type { ToolAdapter, ToolSpec } from \"../types/ToolSpec.js\";\nimport type { ExecContext } from \"../types/ToolIntent.js\";\nimport type { DirectoryScannerOptions } from \"./types.js\";\nimport type { DiscoverySource } from \"../registry/Discovery.js\";\nimport { DirectoryScanner } from \"./DirectoryScanner.js\";\n\n/**\n * A ToolAdapter that discovers tools from filesystem directories.\n * Used as the adapter within a DiscoverySource for the Discovery system.\n *\n * Note: This adapter's invoke() is not called directly. Discovered tools\n * retain their original kind (mcp/langchain/skill/n8n) and are invoked\n * by the kind-specific adapter registered on PTCRuntime.\n */\nexport class DirectoryToolAdapter implements ToolAdapter {\n readonly kind = \"mcp\" as const; // Required by ToolAdapter but not used for routing\n private readonly scanner: DirectoryScanner;\n\n constructor(options: DirectoryScannerOptions) {\n this.scanner = new DirectoryScanner(options);\n }\n\n /**\n * Scan directories and return discovered tool specs.\n * Called by Discovery.refresh().\n */\n async listTools(): Promise<ToolSpec[]> {\n return this.scanner.scan();\n }\n\n /**\n * Not used — actual invocation routes through kind-specific adapters.\n */\n async invoke(\n _spec: ToolSpec,\n _args: unknown,\n _ctx: ExecContext,\n ): Promise<{ result: unknown }> {\n throw new Error(\n \"DirectoryToolAdapter.invoke() should not be called directly. \" +\n \"Tool execution is handled by the kind-specific adapter (MCPAdapter, LangChainAdapter, etc.).\",\n );\n }\n\n /**\n * Get the underlying scanner for direct usage.\n */\n getScanner(): DirectoryScanner {\n return this.scanner;\n }\n}\n\n/**\n * Options for creating a directory discovery source.\n */\nexport interface DirectoryDiscoveryOptions extends DirectoryScannerOptions {\n /** Refresh interval in ms (0 = manual only, default: 0) */\n refreshIntervalMs?: number;\n /** Whether to auto-discover on startup (default: true) */\n autoDiscover?: boolean;\n}\n\n/**\n * Factory: create a DiscoverySource for directory-based tool discovery.\n *\n * Usage:\n * ```ts\n * const discovery = new Discovery(registry);\n * discovery.addSource(\n * createDirectoryDiscoverySource(\"local-tools\", {\n * roots: [\"/path/to/tools\"],\n * namespace: \"local\",\n * refreshIntervalMs: 60_000,\n * autoDiscover: true,\n * })\n * );\n * ```\n */\nexport function createDirectoryDiscoverySource(\n id: string,\n options: DirectoryDiscoveryOptions,\n): DiscoverySource {\n const { refreshIntervalMs, autoDiscover, ...scannerOptions } = options;\n\n return {\n id,\n adapter: new DirectoryToolAdapter(scannerOptions),\n refreshIntervalMs: refreshIntervalMs ?? 0,\n autoDiscover: autoDiscover ?? true,\n };\n}\n","import type { MCPServerConfig } from \"./types.js\";\n\n/**\n * Connection info for an MCP server.\n */\nexport interface MCPConnectionInfo {\n /** Transport type: \"url\" for SSE/HTTP, \"stdio\" for command-based */\n type: \"url\" | \"stdio\";\n /** SSE/HTTP URL (when type=\"url\") */\n url?: string;\n /** Command to spawn (when type=\"stdio\") */\n command?: string;\n /** Command arguments (when type=\"stdio\") */\n args?: string[];\n /** Environment variables (when type=\"stdio\") */\n env?: Record<string, string>;\n}\n\n/**\n * Manages MCP server connection information extracted from directory discovery.\n *\n * This class provides connection configuration for MCP servers discovered\n * from mcp.json files. The actual MCP client creation and lifecycle management\n * is the consumer's responsibility (using @modelcontextprotocol/sdk or similar).\n *\n * Usage:\n * ```ts\n * const manager = new MCPProcessManager();\n * const info = manager.getConnectionInfo(\"my-tool\", mcpConfig);\n * if (info.type === \"stdio\") {\n * // Spawn process with info.command, info.args, info.env\n * } else {\n * // Connect SSE client to info.url\n * }\n * ```\n */\nexport class MCPProcessManager {\n private readonly connections = new Map<string, MCPConnectionInfo>();\n\n /**\n * Get connection info for an MCP tool based on its config.\n * Caches the result by tool name.\n */\n getConnectionInfo(toolName: string, config: MCPServerConfig): MCPConnectionInfo {\n const cached = this.connections.get(toolName);\n if (cached) return cached;\n\n const info: MCPConnectionInfo = config.url\n ? { type: \"url\", url: config.url }\n : {\n type: \"stdio\",\n command: config.command!,\n args: config.args,\n env: config.env,\n };\n\n this.connections.set(toolName, info);\n return info;\n }\n\n /**\n * Remove cached connection info for a tool.\n */\n remove(toolName: string): boolean {\n return this.connections.delete(toolName);\n }\n\n /**\n * Get all registered tool names.\n */\n getToolNames(): string[] {\n return [...this.connections.keys()];\n }\n\n /**\n * Clear all cached connection info.\n */\n dispose(): void {\n this.connections.clear();\n }\n}\n","/**\n * Minimal client for OpenAI-compatible chat completions API.\n * Use createOpenAICompatibleClient(baseUrl, model, apiKey?) and then .chat(messages).\n */\n\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface ChatOptions {\n /** Request timeout in milliseconds. Default 60000. */\n timeoutMs?: number;\n}\n\nexport interface ChatResult {\n /** Content of the first assistant reply. */\n content: string;\n /** Raw response from the API (for debugging or advanced use). */\n raw: unknown;\n}\n\nexport interface OpenAICompatibleClientConfig {\n /** Base URL of the API (e.g. https://api.openai.com/v1). Trailing slash is optional. */\n baseUrl: string;\n /** Model name (e.g. gpt-4o-mini). */\n model: string;\n /** API key; optional if the provider does not require it. */\n apiKey?: string;\n}\n\n/**\n * Creates an OpenAI-compatible LLM client.\n *\n * @param baseUrl - LLM API base URL (e.g. https://api.openai.com/v1)\n * @param model - Model name (e.g. gpt-4o-mini)\n * @param apiKey - Optional API key\n * @returns Client instance with .chat(messages, options?)\n */\nexport function createOpenAICompatibleClient(\n baseUrl: string,\n model: string,\n apiKey?: string\n): OpenAICompatibleClient {\n return new OpenAICompatibleClient({ baseUrl, model, apiKey });\n}\n\nexport class OpenAICompatibleClient {\n private readonly baseUrl: string;\n private readonly model: string;\n private readonly apiKey?: string;\n\n constructor(config: OpenAICompatibleClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.model = config.model;\n this.apiKey = config.apiKey;\n }\n\n /**\n * Send chat messages and return the first assistant reply.\n *\n * @param messages - Array of { role, content }\n * @param options - Optional timeout\n * @returns Promise of { content, raw }\n */\n async chat(\n messages: ChatMessage[],\n options?: ChatOptions\n ): Promise<ChatResult> {\n const timeoutMs = options?.timeoutMs ?? 60_000;\n const url = `${this.baseUrl}/chat/completions`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n model: this.model,\n messages: messages.map((m) => ({ role: m.role, content: m.content })),\n }),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new Error(`LLM request timed out after ${timeoutMs}ms`);\n }\n throw err;\n }\n clearTimeout(timer);\n\n const raw = (await response.json()) as unknown;\n if (!response.ok) {\n const errBody =\n typeof raw === \"object\" && raw !== null && \"error\" in (raw as object)\n ? (raw as { error: unknown }).error\n : raw;\n throw new Error(\n `LLM API error ${response.status}: ${JSON.stringify(errBody)}`\n );\n }\n\n const choices = (raw as { choices?: Array<{ message?: { content?: string } }> }).choices;\n const content =\n Array.isArray(choices) && choices[0]?.message?.content != null\n ? String(choices[0].message.content)\n : \"\";\n\n return { content, raw };\n }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ToolSpec, E as ExecContext, a as Evidence, b as ToolRegistry, c as ToolAdapter, S as SkillDefinition, d as SkillFrontmatter, e as SkillResource, f as ToolKind, C as Capability, g as CostHints, h as ToolHubInitOptions } from './toolhub-runtime-CQkP4QVW.cjs';
2
- export { A as AnyToolEvent, B as BudgetConfig, i as BudgetManager, j as BudgetOptions, k as ComfyUIAdapter, l as ComfyUIAdapterOptions, m as ComfyUIHistoryEntry, n as ComfyUIHttpClient, o as ComfyUIQueueResponse, p as CoreAdapter, q as CoreToolContext, r as CoreToolHandler, s as CoreToolResult, t as CoreToolsConfig, u as CoreToolsUserConfig, v as CounterValue, D as DEFAULT_CORE_TOOLS_CONFIG, w as DebugOptions, x as EventListener, y as EventLog, H as HistogramValue, z as HttpClient, I as InvokeOptions, J as JobCompletedEvent, F as JobFailedEvent, G as JobSubmittedEvent, L as LangChainAdapter, K as LangChainAdapterOptions, M as LangChainToolLike, N as LogEntry, O as LogLevel, P as Logger, Q as MCPAdapter, R as MCPAdapterOptions, U as MCPCallResult, V as MCPClientLike, W as MCPToolDefinition, X as Metrics, Y as N8nAdapter, Z as N8nAdapterOptions, _ as N8nInvokeMode, $ as N8nLocalAdapter, a0 as N8nLocalAdapterOptions, a1 as PTCRuntime, a2 as PTCRuntimeConfig, a3 as PolicyCheckResult, a4 as PolicyConfig, a5 as PolicyDeniedError, a6 as PolicyDeniedEvent, a7 as PolicyEngine, a8 as ResolvedDebugOptions, a9 as RetryEvent, aa as SchemaValidationError, ab as SchemaValidator, ac as SkillAdapter, ad as SkillAdapterOptions, ae as SkillContext, af as SkillHandler, ag as SkillInstructionResult, ah as SkillInvocationContext, ai as SkillManifestError, aj as SkillOutput, ak as Span, al as SpanEvent, am as ToolCalledEvent, an as ToolDescription, ao as ToolError, ap as ToolEvent, aq as ToolEventType, ar as ToolHub, as as ToolIntent, at as ToolMetadata, au as ToolResult, av as ToolResultEvent, aw as ToolSearchQuery, ax as Tracing, ay as ValidationResult, az as createAgentToolHub, aA as createLogger, aB as createToolHub, aC as createToolHubAndInitFromConfig, aD as registerCoreTools, aE as sanitizeForLog, aF as summarizeForLog, aG as validateFrontmatter } from './toolhub-runtime-CQkP4QVW.cjs';
1
+ import { T as ToolSpec, E as ExecContext, a as Evidence, b as ToolRegistry, c as ToolAdapter, S as SkillDefinition, d as SkillFrontmatter, e as SkillResource, f as ToolKind, C as Capability, g as CostHints, h as ToolHubInitOptions } from './toolhub-runtime-Du3j3gS3.cjs';
2
+ export { A as AgentToolHub, i as AnyToolEvent, B as BudgetConfig, j as BudgetManager, k as BudgetOptions, l as ComfyUIAdapter, m as ComfyUIAdapterOptions, n as ComfyUIHistoryEntry, o as ComfyUIHttpClient, p as ComfyUIQueueResponse, q as CoreAdapter, r as CoreToolContext, s as CoreToolHandler, t as CoreToolResult, u as CoreToolsConfig, v as CoreToolsUserConfig, w as CounterValue, D as DEFAULT_CORE_TOOLS_CONFIG, x as DebugOptions, y as EventListener, z as EventLog, H as HistogramValue, F as HttpClient, I as InvokeOptions, J as JobCompletedEvent, G as JobFailedEvent, K as JobSubmittedEvent, L as LangChainAdapter, M as LangChainAdapterOptions, N as LangChainToolLike, O as LogEntry, P as LogLevel, Q as Logger, R as MCPAdapter, U as MCPAdapterOptions, V as MCPCallResult, W as MCPClientLike, X as MCPToolDefinition, Y as Metrics, Z as N8nAdapter, _ as N8nAdapterOptions, $ as N8nInvokeMode, a0 as N8nLocalAdapter, a1 as N8nLocalAdapterOptions, a2 as PTCRuntime, a3 as PTCRuntimeConfig, a4 as PolicyCheckResult, a5 as PolicyConfig, a6 as PolicyDeniedError, a7 as PolicyDeniedEvent, a8 as PolicyEngine, a9 as ResolvedDebugOptions, aa as RetryEvent, ab as SchemaValidationError, ac as SchemaValidator, ad as SkillAdapter, ae as SkillAdapterOptions, af as SkillContext, ag as SkillHandler, ah as SkillInstructionResult, ai as SkillInvocationContext, aj as SkillManifestError, ak as SkillOutput, al as Span, am as SpanEvent, an as ToolCalledEvent, ao as ToolDescription, ap as ToolError, aq as ToolEvent, ar as ToolEventType, as as ToolHub, at as ToolIntent, au as ToolMetadata, av as ToolResult, aw as ToolResultEvent, ax as ToolSearchQuery, ay as Tracing, az as ValidationResult, aA as createAgentToolHub, aB as createLogger, aC as createToolHub, aD as createToolHubAndInitFromConfig, aE as registerCoreTools, aF as sanitizeForLog, aG as summarizeForLog, aH as validateFrontmatter } from './toolhub-runtime-Du3j3gS3.cjs';
3
3
  import '@easynet/n8n-local';
4
4
  import 'ajv';
5
5
  import 'cockatiel';
@@ -541,6 +541,58 @@ declare class DiscoveryError extends Error {
541
541
  constructor(toolDir: string, phase: "manifest" | "load" | "validate", message: string, cause?: Error);
542
542
  }
543
543
 
544
+ /**
545
+ * Minimal client for OpenAI-compatible chat completions API.
546
+ * Use createOpenAICompatibleClient(baseUrl, model, apiKey?) and then .chat(messages).
547
+ */
548
+ interface ChatMessage {
549
+ role: "system" | "user" | "assistant";
550
+ content: string;
551
+ }
552
+ interface ChatOptions {
553
+ /** Request timeout in milliseconds. Default 60000. */
554
+ timeoutMs?: number;
555
+ }
556
+ interface ChatResult {
557
+ /** Content of the first assistant reply. */
558
+ content: string;
559
+ /** Raw response from the API (for debugging or advanced use). */
560
+ raw: unknown;
561
+ }
562
+ interface OpenAICompatibleClientConfig {
563
+ /** Base URL of the API (e.g. https://api.openai.com/v1). Trailing slash is optional. */
564
+ baseUrl: string;
565
+ /** Model name (e.g. gpt-4o-mini). */
566
+ model: string;
567
+ /** API key; optional if the provider does not require it. */
568
+ apiKey?: string;
569
+ }
570
+ /**
571
+ * Creates an OpenAI-compatible LLM client.
572
+ *
573
+ * @param baseUrl - LLM API base URL (e.g. https://api.openai.com/v1)
574
+ * @param model - Model name (e.g. gpt-4o-mini)
575
+ * @param apiKey - Optional API key
576
+ * @returns Client instance with .chat(messages, options?)
577
+ */
578
+ declare function createOpenAICompatibleClient(baseUrl: string, model: string, apiKey?: string): OpenAICompatibleClient;
579
+ declare class OpenAICompatibleClient {
580
+ private readonly baseUrl;
581
+ private readonly model;
582
+ private readonly apiKey?;
583
+ constructor(config: OpenAICompatibleClientConfig);
584
+ /**
585
+ * Send chat messages and return the first assistant reply.
586
+ *
587
+ * @param messages - Array of { role, content }
588
+ * @param options - Optional timeout
589
+ * @returns Promise of { content, raw }
590
+ */
591
+ chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResult>;
592
+ }
593
+
594
+ /** Default config filename used when no path is given (e.g. AgentToolHub(), CLI). */
595
+ declare const DEFAULT_CONFIG_FILE = "toolhub.yaml";
544
596
  interface ToolHubConfigLoadResult {
545
597
  configPath: string;
546
598
  rawConfig: unknown;
@@ -549,4 +601,4 @@ interface ToolHubConfigLoadResult {
549
601
  declare function mapToolHubConfig(raw: unknown, configDir: string): ToolHubInitOptions;
550
602
  declare function loadToolHubConfig(configPath: string): Promise<ToolHubConfigLoadResult>;
551
603
 
552
- export { AsyncJobManager, type BuildEvidenceOptions, Capability, CostHints, type DirectoryDiscoveryOptions, DirectoryScanner, type DirectoryScannerOptions, DirectoryToolAdapter, type DiscoverableKind, Discovery, DiscoveryError, type DiscoverySource, Evidence, ExecContext, InMemoryJobStore, type Job, type JobStatus, type JobStore, type LoadedTool, type MCPConnectionInfo, MCPProcessManager, type MCPServerConfig, type RetryOptions, SkillDefinition, SkillFrontmatter, SkillResource, type SubmitJobOptions, ToolAdapter, type ToolHubConfigLoadResult, ToolHubInitOptions, ToolKind, type ToolManifest, ToolRegistry, ToolSpec, buildEvidence, createDirectoryDiscoverySource, createTaggedError, deletePathSpec, downloadFileSpec, fetchJsonSpec, fetchTextSpec, hashTextSpec, headSpec, isIpInBlockedCidrs, isRetryable, jsonSelectSpec, listDirSpec, loadSkillDefinition, loadToolHubConfig, mapToolHubConfig, nowSpec, parseSkillMd, readTextSpec, resolveSandboxedPath, scanSkillResources, searchTextSpec, sha256Spec, templateRenderSpec, truncateSpec, validateUrl, withRetry, writeTextSpec };
604
+ export { AsyncJobManager, type BuildEvidenceOptions, Capability, type ChatMessage, type ChatOptions, type ChatResult, CostHints, DEFAULT_CONFIG_FILE, type DirectoryDiscoveryOptions, DirectoryScanner, type DirectoryScannerOptions, DirectoryToolAdapter, type DiscoverableKind, Discovery, DiscoveryError, type DiscoverySource, Evidence, ExecContext, InMemoryJobStore, type Job, type JobStatus, type JobStore, type LoadedTool, type MCPConnectionInfo, MCPProcessManager, type MCPServerConfig, OpenAICompatibleClient, type OpenAICompatibleClientConfig, type RetryOptions, SkillDefinition, SkillFrontmatter, SkillResource, type SubmitJobOptions, ToolAdapter, type ToolHubConfigLoadResult, ToolHubInitOptions, ToolKind, type ToolManifest, ToolRegistry, ToolSpec, buildEvidence, createDirectoryDiscoverySource, createOpenAICompatibleClient, createTaggedError, deletePathSpec, downloadFileSpec, fetchJsonSpec, fetchTextSpec, hashTextSpec, headSpec, isIpInBlockedCidrs, isRetryable, jsonSelectSpec, listDirSpec, loadSkillDefinition, loadToolHubConfig, mapToolHubConfig, nowSpec, parseSkillMd, readTextSpec, resolveSandboxedPath, scanSkillResources, searchTextSpec, sha256Spec, templateRenderSpec, truncateSpec, validateUrl, withRetry, writeTextSpec };