elsabro 2.3.0 → 3.7.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 (67) hide show
  1. package/README.md +668 -20
  2. package/bin/install.js +0 -0
  3. package/flows/development-flow.json +452 -0
  4. package/flows/quick-flow.json +118 -0
  5. package/package.json +3 -2
  6. package/references/SYSTEM_INDEX.md +379 -5
  7. package/references/agent-marketplace.md +2274 -0
  8. package/references/agent-protocol.md +1126 -0
  9. package/references/ai-code-suggestions.md +2413 -0
  10. package/references/checkpointing.md +595 -0
  11. package/references/collaboration-patterns.md +851 -0
  12. package/references/collaborative-sessions.md +1081 -0
  13. package/references/configuration-management.md +1810 -0
  14. package/references/cost-tracking.md +1095 -0
  15. package/references/enterprise-sso.md +2001 -0
  16. package/references/error-contracts-v2.md +968 -0
  17. package/references/event-driven.md +1031 -0
  18. package/references/flow-orchestration.md +940 -0
  19. package/references/flow-visualization.md +1557 -0
  20. package/references/ide-integrations.md +3513 -0
  21. package/references/interrupt-system.md +681 -0
  22. package/references/kubernetes-deployment.md +3099 -0
  23. package/references/memory-system.md +683 -0
  24. package/references/mobile-companion.md +3236 -0
  25. package/references/multi-llm-providers.md +2494 -0
  26. package/references/multi-project-memory.md +1182 -0
  27. package/references/observability.md +793 -0
  28. package/references/output-schemas.md +858 -0
  29. package/references/performance-profiler.md +955 -0
  30. package/references/plugin-system.md +1526 -0
  31. package/references/prompt-management.md +292 -0
  32. package/references/sandbox-execution.md +303 -0
  33. package/references/security-system.md +1253 -0
  34. package/references/streaming.md +696 -0
  35. package/references/testing-framework.md +1151 -0
  36. package/references/time-travel.md +802 -0
  37. package/references/tool-registry.md +886 -0
  38. package/references/voice-commands.md +3296 -0
  39. package/templates/agent-marketplace-config.json +220 -0
  40. package/templates/agent-protocol-config.json +136 -0
  41. package/templates/ai-suggestions-config.json +100 -0
  42. package/templates/checkpoint-state.json +61 -0
  43. package/templates/collaboration-config.json +157 -0
  44. package/templates/collaborative-sessions-config.json +153 -0
  45. package/templates/configuration-config.json +245 -0
  46. package/templates/cost-tracking-config.json +148 -0
  47. package/templates/enterprise-sso-config.json +438 -0
  48. package/templates/events-config.json +148 -0
  49. package/templates/flow-visualization-config.json +196 -0
  50. package/templates/ide-integrations-config.json +442 -0
  51. package/templates/kubernetes-config.json +764 -0
  52. package/templates/memory-state.json +84 -0
  53. package/templates/mobile-companion-config.json +600 -0
  54. package/templates/multi-llm-config.json +544 -0
  55. package/templates/multi-project-memory-config.json +145 -0
  56. package/templates/observability-config.json +109 -0
  57. package/templates/performance-profiler-config.json +125 -0
  58. package/templates/plugin-config.json +170 -0
  59. package/templates/prompt-management-config.json +86 -0
  60. package/templates/sandbox-config.json +185 -0
  61. package/templates/schemas-config.json +65 -0
  62. package/templates/security-config.json +120 -0
  63. package/templates/streaming-config.json +72 -0
  64. package/templates/testing-config.json +81 -0
  65. package/templates/timetravel-config.json +62 -0
  66. package/templates/tool-registry-config.json +109 -0
  67. package/templates/voice-commands-config.json +658 -0
@@ -0,0 +1,886 @@
1
+ # Tool Registry System (v3.3)
2
+
3
+ Sistema de registro dinámico de herramientas con discovery, versionado, y capability matching.
4
+
5
+ ## Arquitectura
6
+
7
+ ```
8
+ ┌─────────────────────────────────────────────────────────────────────────┐
9
+ │ TOOL REGISTRY SYSTEM │
10
+ ├─────────────────────────────────────────────────────────────────────────┤
11
+ │ │
12
+ │ ┌─────────────────────────────────────────────────────────────────┐ │
13
+ │ │ TOOL REGISTRY │ │
14
+ │ │ ┌─────────────────────────────────────────────────────────┐ │ │
15
+ │ │ │ Registered Tools │ │ │
16
+ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
17
+ │ │ │ │ Bash │ │ Read │ │ Write │ │ MCP │ │ │ │
18
+ │ │ │ │ v1.2.0 │ │ v1.0.0 │ │ v1.0.0 │ │ v2.0.0 │ │ │ │
19
+ │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
20
+ │ │ └─────────────────────────────────────────────────────────┘ │ │
21
+ │ └─────────────────────────────────────────────────────────────────┘ │
22
+ │ │ │
23
+ │ ▼ │
24
+ │ ┌─────────────────────────────────────────────────────────────────┐ │
25
+ │ │ TOOL DISCOVERY │ │
26
+ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
27
+ │ │ │ By Name │ │ By Category │ │By Capability│ │ │
28
+ │ │ │ "Bash" │ │ "file-ops" │ │ "can:write" │ │ │
29
+ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
30
+ │ └─────────────────────────────────────────────────────────────────┘ │
31
+ │ │ │
32
+ │ ▼ │
33
+ │ ┌─────────────────────────────────────────────────────────────────┐ │
34
+ │ │ CAPABILITY MATCHER │ │
35
+ │ │ ┌───────────────────────────────────────────────────────────┐ │ │
36
+ │ │ │ Agent Request → Matching Tools │ │ │
37
+ │ │ │ "Need to read files" → [Read, Glob, Grep, WebFetch] │ │ │
38
+ │ │ └───────────────────────────────────────────────────────────┘ │ │
39
+ │ └─────────────────────────────────────────────────────────────────┘ │
40
+ │ │ │
41
+ │ ▼ │
42
+ │ ┌─────────────────────────────────────────────────────────────────┐ │
43
+ │ │ VERSION MANAGER │ │
44
+ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
45
+ │ │ │ Versioning │ │ Deprecation │ │ Migration │ │ │
46
+ │ │ │ semver │ │ warnings │ │ paths │ │ │
47
+ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
48
+ │ └─────────────────────────────────────────────────────────────────┘ │
49
+ │ │
50
+ └─────────────────────────────────────────────────────────────────────────┘
51
+ ```
52
+
53
+ ---
54
+
55
+ ## ToolRegistry
56
+
57
+ ### API Principal
58
+
59
+ ```typescript
60
+ interface ToolDefinition {
61
+ name: string;
62
+ version: string;
63
+ description: string;
64
+ category: string;
65
+ capabilities: string[];
66
+ parameters: ToolParameter[];
67
+ returns: ToolReturn;
68
+ examples?: ToolExample[];
69
+ metadata?: Record<string, unknown>;
70
+ }
71
+
72
+ interface ToolParameter {
73
+ name: string;
74
+ type: 'string' | 'number' | 'boolean' | 'object' | 'array';
75
+ description: string;
76
+ required: boolean;
77
+ default?: unknown;
78
+ enum?: unknown[];
79
+ schema?: JSONSchema;
80
+ }
81
+
82
+ interface ToolReturn {
83
+ type: string;
84
+ description: string;
85
+ schema?: JSONSchema;
86
+ }
87
+
88
+ interface ToolExample {
89
+ description: string;
90
+ input: Record<string, unknown>;
91
+ output: unknown;
92
+ }
93
+
94
+ interface RegisteredTool extends ToolDefinition {
95
+ id: string;
96
+ registered_at: string;
97
+ updated_at: string;
98
+ status: 'active' | 'deprecated' | 'disabled';
99
+ deprecation?: {
100
+ message: string;
101
+ replacement?: string;
102
+ remove_at?: string;
103
+ };
104
+ usage: {
105
+ total_calls: number;
106
+ success_rate: number;
107
+ avg_duration_ms: number;
108
+ };
109
+ }
110
+
111
+ class ToolRegistry {
112
+ private tools: Map<string, RegisteredTool>;
113
+ private categories: Map<string, Set<string>>;
114
+ private capabilities: Map<string, Set<string>>;
115
+ private config: ToolRegistryConfig;
116
+
117
+ constructor(config: ToolRegistryConfig) {
118
+ this.config = config;
119
+ this.tools = new Map();
120
+ this.categories = new Map();
121
+ this.capabilities = new Map();
122
+ this.loadBuiltinTools();
123
+ }
124
+
125
+ // Register new tool
126
+ register(definition: ToolDefinition): RegisteredTool {
127
+ const existing = this.tools.get(definition.name);
128
+
129
+ // Version conflict check
130
+ if (existing && !this.isNewerVersion(definition.version, existing.version)) {
131
+ throw new Error(
132
+ `Tool ${definition.name} v${existing.version} already registered. ` +
133
+ `Provided v${definition.version} is not newer.`
134
+ );
135
+ }
136
+
137
+ const tool: RegisteredTool = {
138
+ ...definition,
139
+ id: this.generateId(),
140
+ registered_at: new Date().toISOString(),
141
+ updated_at: new Date().toISOString(),
142
+ status: 'active',
143
+ usage: {
144
+ total_calls: existing?.usage.total_calls || 0,
145
+ success_rate: existing?.usage.success_rate || 100,
146
+ avg_duration_ms: existing?.usage.avg_duration_ms || 0
147
+ }
148
+ };
149
+
150
+ // Register tool
151
+ this.tools.set(definition.name, tool);
152
+
153
+ // Index by category
154
+ if (!this.categories.has(definition.category)) {
155
+ this.categories.set(definition.category, new Set());
156
+ }
157
+ this.categories.get(definition.category)!.add(definition.name);
158
+
159
+ // Index by capabilities
160
+ for (const capability of definition.capabilities) {
161
+ if (!this.capabilities.has(capability)) {
162
+ this.capabilities.set(capability, new Set());
163
+ }
164
+ this.capabilities.get(capability)!.add(definition.name);
165
+ }
166
+
167
+ // Emit event
168
+ EventBus.publish('tool.registered', {
169
+ name: definition.name,
170
+ version: definition.version,
171
+ category: definition.category
172
+ });
173
+
174
+ return tool;
175
+ }
176
+
177
+ // Get tool by name
178
+ get(name: string): RegisteredTool | undefined {
179
+ return this.tools.get(name);
180
+ }
181
+
182
+ // Get tool with version check
183
+ getVersion(name: string, version?: string): RegisteredTool | undefined {
184
+ const tool = this.tools.get(name);
185
+ if (!tool) return undefined;
186
+
187
+ if (version && !this.satisfiesVersion(tool.version, version)) {
188
+ return undefined;
189
+ }
190
+
191
+ return tool;
192
+ }
193
+
194
+ // List all tools
195
+ list(options?: ListOptions): RegisteredTool[] {
196
+ let tools = Array.from(this.tools.values());
197
+
198
+ if (options?.category) {
199
+ tools = tools.filter(t => t.category === options.category);
200
+ }
201
+
202
+ if (options?.status) {
203
+ tools = tools.filter(t => t.status === options.status);
204
+ }
205
+
206
+ if (options?.capability) {
207
+ const toolNames = this.capabilities.get(options.capability);
208
+ if (toolNames) {
209
+ tools = tools.filter(t => toolNames.has(t.name));
210
+ } else {
211
+ tools = [];
212
+ }
213
+ }
214
+
215
+ return tools;
216
+ }
217
+
218
+ // Search tools
219
+ search(query: string): RegisteredTool[] {
220
+ const lowerQuery = query.toLowerCase();
221
+
222
+ return Array.from(this.tools.values()).filter(tool =>
223
+ tool.name.toLowerCase().includes(lowerQuery) ||
224
+ tool.description.toLowerCase().includes(lowerQuery) ||
225
+ tool.capabilities.some(c => c.toLowerCase().includes(lowerQuery))
226
+ );
227
+ }
228
+
229
+ // Deprecate tool
230
+ deprecate(name: string, message: string, replacement?: string): void {
231
+ const tool = this.tools.get(name);
232
+ if (!tool) throw new Error(`Tool not found: ${name}`);
233
+
234
+ tool.status = 'deprecated';
235
+ tool.deprecation = {
236
+ message,
237
+ replacement,
238
+ remove_at: this.calculateRemovalDate()
239
+ };
240
+ tool.updated_at = new Date().toISOString();
241
+
242
+ EventBus.publish('tool.deprecated', {
243
+ name,
244
+ message,
245
+ replacement
246
+ });
247
+ }
248
+
249
+ // Disable tool
250
+ disable(name: string): void {
251
+ const tool = this.tools.get(name);
252
+ if (!tool) throw new Error(`Tool not found: ${name}`);
253
+
254
+ tool.status = 'disabled';
255
+ tool.updated_at = new Date().toISOString();
256
+
257
+ EventBus.publish('tool.disabled', { name });
258
+ }
259
+
260
+ // Enable tool
261
+ enable(name: string): void {
262
+ const tool = this.tools.get(name);
263
+ if (!tool) throw new Error(`Tool not found: ${name}`);
264
+
265
+ tool.status = 'active';
266
+ tool.deprecation = undefined;
267
+ tool.updated_at = new Date().toISOString();
268
+
269
+ EventBus.publish('tool.enabled', { name });
270
+ }
271
+
272
+ // Unregister tool
273
+ unregister(name: string): boolean {
274
+ const tool = this.tools.get(name);
275
+ if (!tool) return false;
276
+
277
+ // Remove from indices
278
+ this.categories.get(tool.category)?.delete(name);
279
+ for (const capability of tool.capabilities) {
280
+ this.capabilities.get(capability)?.delete(name);
281
+ }
282
+
283
+ this.tools.delete(name);
284
+
285
+ EventBus.publish('tool.unregistered', { name });
286
+
287
+ return true;
288
+ }
289
+
290
+ // Record tool usage
291
+ recordUsage(name: string, success: boolean, duration_ms: number): void {
292
+ const tool = this.tools.get(name);
293
+ if (!tool) return;
294
+
295
+ tool.usage.total_calls++;
296
+
297
+ // Update success rate (rolling average)
298
+ const successValue = success ? 100 : 0;
299
+ tool.usage.success_rate =
300
+ (tool.usage.success_rate * (tool.usage.total_calls - 1) + successValue) /
301
+ tool.usage.total_calls;
302
+
303
+ // Update average duration (rolling average)
304
+ tool.usage.avg_duration_ms =
305
+ (tool.usage.avg_duration_ms * (tool.usage.total_calls - 1) + duration_ms) /
306
+ tool.usage.total_calls;
307
+ }
308
+
309
+ // Get categories
310
+ getCategories(): string[] {
311
+ return Array.from(this.categories.keys());
312
+ }
313
+
314
+ // Get capabilities
315
+ getCapabilities(): string[] {
316
+ return Array.from(this.capabilities.keys());
317
+ }
318
+
319
+ // Export registry
320
+ export(): ToolRegistryExport {
321
+ return {
322
+ version: '1.0.0',
323
+ exported_at: new Date().toISOString(),
324
+ tools: Array.from(this.tools.values())
325
+ };
326
+ }
327
+
328
+ // Import registry
329
+ import(data: ToolRegistryExport): number {
330
+ let imported = 0;
331
+ for (const tool of data.tools) {
332
+ try {
333
+ this.register(tool);
334
+ imported++;
335
+ } catch {
336
+ // Skip conflicts
337
+ }
338
+ }
339
+ return imported;
340
+ }
341
+
342
+ private loadBuiltinTools(): void {
343
+ // Register Claude Code built-in tools
344
+ const builtins: ToolDefinition[] = [
345
+ {
346
+ name: 'Bash',
347
+ version: '1.0.0',
348
+ description: 'Execute bash commands',
349
+ category: 'system',
350
+ capabilities: ['execute', 'shell', 'git', 'npm'],
351
+ parameters: [
352
+ { name: 'command', type: 'string', description: 'Command to execute', required: true },
353
+ { name: 'timeout', type: 'number', description: 'Timeout in ms', required: false }
354
+ ],
355
+ returns: { type: 'string', description: 'Command output' }
356
+ },
357
+ {
358
+ name: 'Read',
359
+ version: '1.0.0',
360
+ description: 'Read file contents',
361
+ category: 'file-ops',
362
+ capabilities: ['read', 'file', 'content'],
363
+ parameters: [
364
+ { name: 'file_path', type: 'string', description: 'Path to file', required: true },
365
+ { name: 'offset', type: 'number', description: 'Start line', required: false },
366
+ { name: 'limit', type: 'number', description: 'Max lines', required: false }
367
+ ],
368
+ returns: { type: 'string', description: 'File content' }
369
+ },
370
+ {
371
+ name: 'Write',
372
+ version: '1.0.0',
373
+ description: 'Write file contents',
374
+ category: 'file-ops',
375
+ capabilities: ['write', 'file', 'create'],
376
+ parameters: [
377
+ { name: 'file_path', type: 'string', description: 'Path to file', required: true },
378
+ { name: 'content', type: 'string', description: 'Content to write', required: true }
379
+ ],
380
+ returns: { type: 'boolean', description: 'Success status' }
381
+ },
382
+ {
383
+ name: 'Edit',
384
+ version: '1.0.0',
385
+ description: 'Edit file with replacements',
386
+ category: 'file-ops',
387
+ capabilities: ['edit', 'file', 'modify'],
388
+ parameters: [
389
+ { name: 'file_path', type: 'string', description: 'Path to file', required: true },
390
+ { name: 'old_string', type: 'string', description: 'Text to replace', required: true },
391
+ { name: 'new_string', type: 'string', description: 'Replacement text', required: true }
392
+ ],
393
+ returns: { type: 'boolean', description: 'Success status' }
394
+ },
395
+ {
396
+ name: 'Glob',
397
+ version: '1.0.0',
398
+ description: 'Find files by pattern',
399
+ category: 'search',
400
+ capabilities: ['search', 'find', 'pattern'],
401
+ parameters: [
402
+ { name: 'pattern', type: 'string', description: 'Glob pattern', required: true },
403
+ { name: 'path', type: 'string', description: 'Base path', required: false }
404
+ ],
405
+ returns: { type: 'array', description: 'Matching file paths' }
406
+ },
407
+ {
408
+ name: 'Grep',
409
+ version: '1.0.0',
410
+ description: 'Search file contents',
411
+ category: 'search',
412
+ capabilities: ['search', 'content', 'regex'],
413
+ parameters: [
414
+ { name: 'pattern', type: 'string', description: 'Search pattern', required: true },
415
+ { name: 'path', type: 'string', description: 'Search path', required: false }
416
+ ],
417
+ returns: { type: 'array', description: 'Matching lines' }
418
+ },
419
+ {
420
+ name: 'Task',
421
+ version: '1.0.0',
422
+ description: 'Launch subagent for complex tasks',
423
+ category: 'agent',
424
+ capabilities: ['delegate', 'parallel', 'subagent'],
425
+ parameters: [
426
+ { name: 'prompt', type: 'string', description: 'Task description', required: true },
427
+ { name: 'subagent_type', type: 'string', description: 'Agent type', required: true }
428
+ ],
429
+ returns: { type: 'object', description: 'Agent result' }
430
+ },
431
+ {
432
+ name: 'WebFetch',
433
+ version: '1.0.0',
434
+ description: 'Fetch and process web content',
435
+ category: 'web',
436
+ capabilities: ['fetch', 'http', 'web'],
437
+ parameters: [
438
+ { name: 'url', type: 'string', description: 'URL to fetch', required: true },
439
+ { name: 'prompt', type: 'string', description: 'Processing prompt', required: true }
440
+ ],
441
+ returns: { type: 'string', description: 'Processed content' }
442
+ },
443
+ {
444
+ name: 'WebSearch',
445
+ version: '1.0.0',
446
+ description: 'Search the web',
447
+ category: 'web',
448
+ capabilities: ['search', 'web', 'query'],
449
+ parameters: [
450
+ { name: 'query', type: 'string', description: 'Search query', required: true }
451
+ ],
452
+ returns: { type: 'array', description: 'Search results' }
453
+ }
454
+ ];
455
+
456
+ for (const tool of builtins) {
457
+ this.register(tool);
458
+ }
459
+ }
460
+
461
+ private isNewerVersion(newVersion: string, oldVersion: string): boolean {
462
+ const parse = (v: string) => v.split('.').map(Number);
463
+ const [newMajor, newMinor, newPatch] = parse(newVersion);
464
+ const [oldMajor, oldMinor, oldPatch] = parse(oldVersion);
465
+
466
+ if (newMajor > oldMajor) return true;
467
+ if (newMajor < oldMajor) return false;
468
+ if (newMinor > oldMinor) return true;
469
+ if (newMinor < oldMinor) return false;
470
+ return newPatch > oldPatch;
471
+ }
472
+
473
+ private satisfiesVersion(actual: string, required: string): boolean {
474
+ // Simple semver satisfaction check
475
+ if (required.startsWith('^')) {
476
+ const base = required.slice(1);
477
+ const [reqMajor] = base.split('.').map(Number);
478
+ const [actMajor] = actual.split('.').map(Number);
479
+ return actMajor === reqMajor && this.isNewerVersion(actual, base);
480
+ }
481
+ if (required.startsWith('~')) {
482
+ const base = required.slice(1);
483
+ const [reqMajor, reqMinor] = base.split('.').map(Number);
484
+ const [actMajor, actMinor] = actual.split('.').map(Number);
485
+ return actMajor === reqMajor && actMinor === reqMinor;
486
+ }
487
+ return actual === required;
488
+ }
489
+
490
+ private calculateRemovalDate(): string {
491
+ const date = new Date();
492
+ date.setMonth(date.getMonth() + 3);
493
+ return date.toISOString();
494
+ }
495
+
496
+ private generateId(): string {
497
+ return `tool_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
498
+ }
499
+ }
500
+ ```
501
+
502
+ ---
503
+
504
+ ## ToolDiscovery
505
+
506
+ ```typescript
507
+ interface DiscoveryQuery {
508
+ text?: string;
509
+ capabilities?: string[];
510
+ category?: string;
511
+ minVersion?: string;
512
+ includeDeprecated?: boolean;
513
+ }
514
+
515
+ interface DiscoveryResult {
516
+ tool: RegisteredTool;
517
+ score: number;
518
+ matchedCapabilities: string[];
519
+ matchReason: string;
520
+ }
521
+
522
+ class ToolDiscovery {
523
+ private registry: ToolRegistry;
524
+ private cache: Map<string, DiscoveryResult[]>;
525
+
526
+ constructor(registry: ToolRegistry) {
527
+ this.registry = registry;
528
+ this.cache = new Map();
529
+ }
530
+
531
+ // Discover tools matching query
532
+ discover(query: DiscoveryQuery): DiscoveryResult[] {
533
+ const cacheKey = JSON.stringify(query);
534
+ if (this.cache.has(cacheKey)) {
535
+ return this.cache.get(cacheKey)!;
536
+ }
537
+
538
+ let candidates = this.registry.list({
539
+ status: query.includeDeprecated ? undefined : 'active'
540
+ });
541
+
542
+ const results: DiscoveryResult[] = [];
543
+
544
+ for (const tool of candidates) {
545
+ const score = this.calculateScore(tool, query);
546
+ if (score > 0) {
547
+ results.push({
548
+ tool,
549
+ score,
550
+ matchedCapabilities: this.getMatchedCapabilities(tool, query),
551
+ matchReason: this.getMatchReason(tool, query, score)
552
+ });
553
+ }
554
+ }
555
+
556
+ // Sort by score descending
557
+ results.sort((a, b) => b.score - a.score);
558
+
559
+ // Cache results
560
+ this.cache.set(cacheKey, results);
561
+
562
+ return results;
563
+ }
564
+
565
+ // Find best tool for capability
566
+ findBest(capability: string): RegisteredTool | undefined {
567
+ const results = this.discover({ capabilities: [capability] });
568
+ return results[0]?.tool;
569
+ }
570
+
571
+ // Find all tools for category
572
+ findByCategory(category: string): RegisteredTool[] {
573
+ return this.registry.list({ category });
574
+ }
575
+
576
+ // Suggest tools for task description
577
+ suggest(taskDescription: string): DiscoveryResult[] {
578
+ // Extract likely capabilities from description
579
+ const capabilities = this.extractCapabilities(taskDescription);
580
+
581
+ return this.discover({
582
+ text: taskDescription,
583
+ capabilities
584
+ });
585
+ }
586
+
587
+ // Clear discovery cache
588
+ clearCache(): void {
589
+ this.cache.clear();
590
+ }
591
+
592
+ private calculateScore(tool: RegisteredTool, query: DiscoveryQuery): number {
593
+ let score = 0;
594
+
595
+ // Text match
596
+ if (query.text) {
597
+ const text = query.text.toLowerCase();
598
+ if (tool.name.toLowerCase().includes(text)) score += 50;
599
+ if (tool.description.toLowerCase().includes(text)) score += 30;
600
+ }
601
+
602
+ // Capability match
603
+ if (query.capabilities) {
604
+ for (const cap of query.capabilities) {
605
+ if (tool.capabilities.includes(cap)) score += 25;
606
+ }
607
+ }
608
+
609
+ // Category match
610
+ if (query.category && tool.category === query.category) {
611
+ score += 20;
612
+ }
613
+
614
+ // Version match
615
+ if (query.minVersion) {
616
+ if (this.satisfiesMinVersion(tool.version, query.minVersion)) {
617
+ score += 10;
618
+ } else {
619
+ score = 0; // Exclude if version doesn't satisfy
620
+ }
621
+ }
622
+
623
+ // Usage bonus (more used = more trusted)
624
+ if (tool.usage.total_calls > 100) score += 5;
625
+ if (tool.usage.success_rate > 95) score += 5;
626
+
627
+ // Penalty for deprecated
628
+ if (tool.status === 'deprecated') score -= 20;
629
+
630
+ return Math.max(0, score);
631
+ }
632
+
633
+ private getMatchedCapabilities(tool: RegisteredTool, query: DiscoveryQuery): string[] {
634
+ if (!query.capabilities) return [];
635
+ return query.capabilities.filter(c => tool.capabilities.includes(c));
636
+ }
637
+
638
+ private getMatchReason(tool: RegisteredTool, query: DiscoveryQuery, score: number): string {
639
+ const reasons: string[] = [];
640
+
641
+ if (query.text && tool.name.toLowerCase().includes(query.text.toLowerCase())) {
642
+ reasons.push('name match');
643
+ }
644
+
645
+ if (query.capabilities) {
646
+ const matched = this.getMatchedCapabilities(tool, query);
647
+ if (matched.length > 0) {
648
+ reasons.push(`capabilities: ${matched.join(', ')}`);
649
+ }
650
+ }
651
+
652
+ if (query.category && tool.category === query.category) {
653
+ reasons.push('category match');
654
+ }
655
+
656
+ return reasons.join('; ') || 'general match';
657
+ }
658
+
659
+ private extractCapabilities(description: string): string[] {
660
+ const keywords: Record<string, string[]> = {
661
+ 'read': ['read', 'file', 'content'],
662
+ 'write': ['write', 'create', 'save'],
663
+ 'edit': ['edit', 'modify', 'change', 'update'],
664
+ 'search': ['search', 'find', 'look', 'grep'],
665
+ 'execute': ['run', 'execute', 'command', 'bash', 'shell'],
666
+ 'fetch': ['fetch', 'download', 'http', 'api', 'web'],
667
+ 'delegate': ['agent', 'task', 'parallel', 'complex']
668
+ };
669
+
670
+ const lower = description.toLowerCase();
671
+ const capabilities: string[] = [];
672
+
673
+ for (const [capability, triggers] of Object.entries(keywords)) {
674
+ if (triggers.some(t => lower.includes(t))) {
675
+ capabilities.push(capability);
676
+ }
677
+ }
678
+
679
+ return capabilities;
680
+ }
681
+
682
+ private satisfiesMinVersion(actual: string, min: string): boolean {
683
+ const parse = (v: string) => v.split('.').map(Number);
684
+ const [actMajor, actMinor, actPatch] = parse(actual);
685
+ const [minMajor, minMinor, minPatch] = parse(min);
686
+
687
+ if (actMajor > minMajor) return true;
688
+ if (actMajor < minMajor) return false;
689
+ if (actMinor > minMinor) return true;
690
+ if (actMinor < minMinor) return false;
691
+ return actPatch >= minPatch;
692
+ }
693
+ }
694
+ ```
695
+
696
+ ---
697
+
698
+ ## CapabilityMatcher
699
+
700
+ ```typescript
701
+ interface CapabilityRequirement {
702
+ capability: string;
703
+ required: boolean;
704
+ priority: number;
705
+ }
706
+
707
+ interface MatchResult {
708
+ tool: RegisteredTool;
709
+ matchedCapabilities: string[];
710
+ missingCapabilities: string[];
711
+ matchPercentage: number;
712
+ }
713
+
714
+ class CapabilityMatcher {
715
+ private registry: ToolRegistry;
716
+
717
+ constructor(registry: ToolRegistry) {
718
+ this.registry = registry;
719
+ }
720
+
721
+ // Match tools to required capabilities
722
+ match(requirements: CapabilityRequirement[]): MatchResult[] {
723
+ const tools = this.registry.list({ status: 'active' });
724
+ const results: MatchResult[] = [];
725
+
726
+ for (const tool of tools) {
727
+ const matched: string[] = [];
728
+ const missing: string[] = [];
729
+
730
+ for (const req of requirements) {
731
+ if (tool.capabilities.includes(req.capability)) {
732
+ matched.push(req.capability);
733
+ } else if (req.required) {
734
+ missing.push(req.capability);
735
+ }
736
+ }
737
+
738
+ // Skip if missing required capabilities
739
+ if (missing.length > 0 && requirements.some(r => r.required && missing.includes(r.capability))) {
740
+ continue;
741
+ }
742
+
743
+ const matchPercentage = (matched.length / requirements.length) * 100;
744
+
745
+ results.push({
746
+ tool,
747
+ matchedCapabilities: matched,
748
+ missingCapabilities: missing,
749
+ matchPercentage
750
+ });
751
+ }
752
+
753
+ // Sort by match percentage
754
+ return results.sort((a, b) => b.matchPercentage - a.matchPercentage);
755
+ }
756
+
757
+ // Find minimum set of tools covering all capabilities
758
+ findMinimalSet(capabilities: string[]): RegisteredTool[] {
759
+ const uncovered = new Set(capabilities);
760
+ const selected: RegisteredTool[] = [];
761
+
762
+ while (uncovered.size > 0) {
763
+ // Find tool that covers most uncovered capabilities
764
+ let best: RegisteredTool | undefined;
765
+ let bestCoverage = 0;
766
+
767
+ for (const tool of this.registry.list({ status: 'active' })) {
768
+ const coverage = tool.capabilities.filter(c => uncovered.has(c)).length;
769
+ if (coverage > bestCoverage) {
770
+ best = tool;
771
+ bestCoverage = coverage;
772
+ }
773
+ }
774
+
775
+ if (!best || bestCoverage === 0) break;
776
+
777
+ selected.push(best);
778
+ for (const cap of best.capabilities) {
779
+ uncovered.delete(cap);
780
+ }
781
+ }
782
+
783
+ return selected;
784
+ }
785
+
786
+ // Check if capabilities are satisfiable
787
+ canSatisfy(capabilities: string[]): boolean {
788
+ const available = new Set(this.registry.getCapabilities());
789
+ return capabilities.every(c => available.has(c));
790
+ }
791
+
792
+ // Get missing capabilities
793
+ getMissing(capabilities: string[]): string[] {
794
+ const available = new Set(this.registry.getCapabilities());
795
+ return capabilities.filter(c => !available.has(c));
796
+ }
797
+ }
798
+ ```
799
+
800
+ ---
801
+
802
+ ## Integración con Agentes
803
+
804
+ ```typescript
805
+ // Uso en agentes
806
+ class SmartAgent {
807
+ private discovery: ToolDiscovery;
808
+
809
+ async selectTools(taskDescription: string): Promise<RegisteredTool[]> {
810
+ // Discover relevant tools
811
+ const results = this.discovery.suggest(taskDescription);
812
+
813
+ // Filter to top matches
814
+ const topTools = results
815
+ .filter(r => r.score > 30)
816
+ .slice(0, 5)
817
+ .map(r => r.tool);
818
+
819
+ return topTools;
820
+ }
821
+
822
+ async execute(task: Task): Promise<Result> {
823
+ // Get available tools for this task
824
+ const tools = await this.selectTools(task.description);
825
+
826
+ // Build tool context for prompt
827
+ const toolContext = tools.map(t => ({
828
+ name: t.name,
829
+ description: t.description,
830
+ parameters: t.parameters
831
+ }));
832
+
833
+ // Execute with selected tools
834
+ return this.runWithTools(task, toolContext);
835
+ }
836
+ }
837
+ ```
838
+
839
+ ---
840
+
841
+ ## Comandos
842
+
843
+ ```bash
844
+ /elsabro:tools # Listar todas las herramientas
845
+ /elsabro:tools search "file" # Buscar herramientas
846
+ /elsabro:tools info Bash # Ver detalles de herramienta
847
+ /elsabro:tools stats # Ver estadísticas de uso
848
+ /elsabro:tools register ./tool.json # Registrar nueva herramienta
849
+ /elsabro:tools deprecate OldTool # Marcar como deprecated
850
+ ```
851
+
852
+ ---
853
+
854
+ ## Configuración
855
+
856
+ ```json
857
+ {
858
+ "toolRegistry": {
859
+ "enabled": true,
860
+ "autoLoadBuiltins": true,
861
+ "customToolsPath": ".elsabro/tools",
862
+ "caching": {
863
+ "enabled": true,
864
+ "ttl": 300000
865
+ },
866
+ "validation": {
867
+ "strictSchema": true,
868
+ "requireExamples": false
869
+ },
870
+ "deprecation": {
871
+ "warningPeriod": "30d",
872
+ "removalPeriod": "90d"
873
+ }
874
+ }
875
+ }
876
+ ```
877
+
878
+ ---
879
+
880
+ ## Changelog
881
+
882
+ - **v3.3.0**: Initial Tool Registry System
883
+ - ToolRegistry with registration/versioning
884
+ - ToolDiscovery for smart tool finding
885
+ - CapabilityMatcher for requirements matching
886
+ - Built-in tool definitions