@cogitator-ai/self-modifying 0.1.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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +714 -0
  3. package/dist/architecture-evolution/capability-analyzer.d.ts +32 -0
  4. package/dist/architecture-evolution/capability-analyzer.d.ts.map +1 -0
  5. package/dist/architecture-evolution/capability-analyzer.js +264 -0
  6. package/dist/architecture-evolution/capability-analyzer.js.map +1 -0
  7. package/dist/architecture-evolution/evolution-strategy.d.ts +29 -0
  8. package/dist/architecture-evolution/evolution-strategy.d.ts.map +1 -0
  9. package/dist/architecture-evolution/evolution-strategy.js +176 -0
  10. package/dist/architecture-evolution/evolution-strategy.js.map +1 -0
  11. package/dist/architecture-evolution/index.d.ts +5 -0
  12. package/dist/architecture-evolution/index.d.ts.map +1 -0
  13. package/dist/architecture-evolution/index.js +5 -0
  14. package/dist/architecture-evolution/index.js.map +1 -0
  15. package/dist/architecture-evolution/parameter-optimizer.d.ts +67 -0
  16. package/dist/architecture-evolution/parameter-optimizer.d.ts.map +1 -0
  17. package/dist/architecture-evolution/parameter-optimizer.js +341 -0
  18. package/dist/architecture-evolution/parameter-optimizer.js.map +1 -0
  19. package/dist/architecture-evolution/prompts.d.ts +33 -0
  20. package/dist/architecture-evolution/prompts.d.ts.map +1 -0
  21. package/dist/architecture-evolution/prompts.js +169 -0
  22. package/dist/architecture-evolution/prompts.js.map +1 -0
  23. package/dist/constraints/index.d.ts +4 -0
  24. package/dist/constraints/index.d.ts.map +1 -0
  25. package/dist/constraints/index.js +4 -0
  26. package/dist/constraints/index.js.map +1 -0
  27. package/dist/constraints/modification-validator.d.ts +26 -0
  28. package/dist/constraints/modification-validator.d.ts.map +1 -0
  29. package/dist/constraints/modification-validator.js +313 -0
  30. package/dist/constraints/modification-validator.js.map +1 -0
  31. package/dist/constraints/rollback-manager.d.ts +52 -0
  32. package/dist/constraints/rollback-manager.d.ts.map +1 -0
  33. package/dist/constraints/rollback-manager.js +113 -0
  34. package/dist/constraints/rollback-manager.js.map +1 -0
  35. package/dist/constraints/safety-constraints.d.ts +11 -0
  36. package/dist/constraints/safety-constraints.d.ts.map +1 -0
  37. package/dist/constraints/safety-constraints.js +78 -0
  38. package/dist/constraints/safety-constraints.js.map +1 -0
  39. package/dist/events/event-emitter.d.ts +12 -0
  40. package/dist/events/event-emitter.d.ts.map +1 -0
  41. package/dist/events/event-emitter.js +43 -0
  42. package/dist/events/event-emitter.js.map +1 -0
  43. package/dist/events/index.d.ts +2 -0
  44. package/dist/events/index.d.ts.map +1 -0
  45. package/dist/events/index.js +2 -0
  46. package/dist/events/index.js.map +1 -0
  47. package/dist/index.d.ts +8 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +7 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/meta-reasoning/index.d.ts +5 -0
  52. package/dist/meta-reasoning/index.d.ts.map +1 -0
  53. package/dist/meta-reasoning/index.js +5 -0
  54. package/dist/meta-reasoning/index.js.map +1 -0
  55. package/dist/meta-reasoning/meta-reasoner.d.ts +53 -0
  56. package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -0
  57. package/dist/meta-reasoning/meta-reasoner.js +261 -0
  58. package/dist/meta-reasoning/meta-reasoner.js.map +1 -0
  59. package/dist/meta-reasoning/observation-collector.d.ts +37 -0
  60. package/dist/meta-reasoning/observation-collector.d.ts.map +1 -0
  61. package/dist/meta-reasoning/observation-collector.js +123 -0
  62. package/dist/meta-reasoning/observation-collector.js.map +1 -0
  63. package/dist/meta-reasoning/prompts.d.ts +31 -0
  64. package/dist/meta-reasoning/prompts.d.ts.map +1 -0
  65. package/dist/meta-reasoning/prompts.js +96 -0
  66. package/dist/meta-reasoning/prompts.js.map +1 -0
  67. package/dist/meta-reasoning/strategy-selector.d.ts +27 -0
  68. package/dist/meta-reasoning/strategy-selector.d.ts.map +1 -0
  69. package/dist/meta-reasoning/strategy-selector.js +138 -0
  70. package/dist/meta-reasoning/strategy-selector.js.map +1 -0
  71. package/dist/self-modifying-agent.d.ts +61 -0
  72. package/dist/self-modifying-agent.d.ts.map +1 -0
  73. package/dist/self-modifying-agent.js +449 -0
  74. package/dist/self-modifying-agent.js.map +1 -0
  75. package/dist/tool-generation/gap-analyzer.d.ts +25 -0
  76. package/dist/tool-generation/gap-analyzer.d.ts.map +1 -0
  77. package/dist/tool-generation/gap-analyzer.js +153 -0
  78. package/dist/tool-generation/gap-analyzer.js.map +1 -0
  79. package/dist/tool-generation/generated-tool-store.d.ts +51 -0
  80. package/dist/tool-generation/generated-tool-store.d.ts.map +1 -0
  81. package/dist/tool-generation/generated-tool-store.js +195 -0
  82. package/dist/tool-generation/generated-tool-store.js.map +1 -0
  83. package/dist/tool-generation/index.d.ts +7 -0
  84. package/dist/tool-generation/index.d.ts.map +1 -0
  85. package/dist/tool-generation/index.js +7 -0
  86. package/dist/tool-generation/index.js.map +1 -0
  87. package/dist/tool-generation/prompts.d.ts +28 -0
  88. package/dist/tool-generation/prompts.d.ts.map +1 -0
  89. package/dist/tool-generation/prompts.js +269 -0
  90. package/dist/tool-generation/prompts.js.map +1 -0
  91. package/dist/tool-generation/tool-generator.d.ts +29 -0
  92. package/dist/tool-generation/tool-generator.d.ts.map +1 -0
  93. package/dist/tool-generation/tool-generator.js +169 -0
  94. package/dist/tool-generation/tool-generator.js.map +1 -0
  95. package/dist/tool-generation/tool-sandbox.d.ts +31 -0
  96. package/dist/tool-generation/tool-sandbox.d.ts.map +1 -0
  97. package/dist/tool-generation/tool-sandbox.js +240 -0
  98. package/dist/tool-generation/tool-sandbox.js.map +1 -0
  99. package/dist/tool-generation/tool-validator.d.ts +32 -0
  100. package/dist/tool-generation/tool-validator.d.ts.map +1 -0
  101. package/dist/tool-generation/tool-validator.js +304 -0
  102. package/dist/tool-generation/tool-validator.js.map +1 -0
  103. package/dist/utils/index.d.ts +2 -0
  104. package/dist/utils/index.d.ts.map +1 -0
  105. package/dist/utils/index.js +2 -0
  106. package/dist/utils/index.js.map +1 -0
  107. package/dist/utils/llm-helper.d.ts +6 -0
  108. package/dist/utils/llm-helper.d.ts.map +1 -0
  109. package/dist/utils/llm-helper.js +18 -0
  110. package/dist/utils/llm-helper.js.map +1 -0
  111. package/package.json +61 -0
  112. package/src/__tests__/architecture-evolution.test.ts +368 -0
  113. package/src/__tests__/constraints.test.ts +266 -0
  114. package/src/__tests__/index.test.ts +99 -0
  115. package/src/__tests__/meta-reasoning.test.ts +343 -0
  116. package/src/__tests__/tool-generation.test.ts +455 -0
  117. package/src/architecture-evolution/capability-analyzer.ts +337 -0
  118. package/src/architecture-evolution/evolution-strategy.ts +224 -0
  119. package/src/architecture-evolution/index.ts +26 -0
  120. package/src/architecture-evolution/parameter-optimizer.ts +489 -0
  121. package/src/architecture-evolution/prompts.ts +216 -0
  122. package/src/constraints/index.ts +23 -0
  123. package/src/constraints/modification-validator.ts +402 -0
  124. package/src/constraints/rollback-manager.ts +173 -0
  125. package/src/constraints/safety-constraints.ts +103 -0
  126. package/src/events/event-emitter.ts +62 -0
  127. package/src/events/index.ts +1 -0
  128. package/src/index.ts +112 -0
  129. package/src/meta-reasoning/index.ts +24 -0
  130. package/src/meta-reasoning/meta-reasoner.ts +381 -0
  131. package/src/meta-reasoning/observation-collector.ts +161 -0
  132. package/src/meta-reasoning/prompts.ts +131 -0
  133. package/src/meta-reasoning/strategy-selector.ts +179 -0
  134. package/src/self-modifying-agent.ts +585 -0
  135. package/src/tool-generation/gap-analyzer.ts +234 -0
  136. package/src/tool-generation/generated-tool-store.ts +268 -0
  137. package/src/tool-generation/index.ts +19 -0
  138. package/src/tool-generation/prompts.ts +308 -0
  139. package/src/tool-generation/tool-generator.ts +243 -0
  140. package/src/tool-generation/tool-sandbox.ts +332 -0
  141. package/src/tool-generation/tool-validator.ts +365 -0
  142. package/src/utils/index.ts +1 -0
  143. package/src/utils/llm-helper.ts +24 -0
@@ -0,0 +1,234 @@
1
+ import type {
2
+ Tool,
3
+ LLMBackend,
4
+ CapabilityGap,
5
+ GapAnalysisResult,
6
+ ToolSelfGenerationConfig,
7
+ } from '@cogitator-ai/types';
8
+ import { buildGapAnalysisPrompt, parseGapAnalysisResponse } from './prompts';
9
+
10
+ export interface GapAnalyzerOptions {
11
+ llm: LLMBackend;
12
+ config: ToolSelfGenerationConfig;
13
+ }
14
+
15
+ export class GapAnalyzer {
16
+ private readonly llm: LLMBackend;
17
+ private readonly config: ToolSelfGenerationConfig;
18
+ private readonly analysisCache = new Map<string, GapAnalysisResult>();
19
+
20
+ constructor(options: GapAnalyzerOptions) {
21
+ this.llm = options.llm;
22
+ this.config = options.config;
23
+ }
24
+
25
+ async analyze(
26
+ userIntent: string,
27
+ availableTools: Tool[],
28
+ context?: {
29
+ failedAttempts?: string[];
30
+ previousGaps?: CapabilityGap[];
31
+ }
32
+ ): Promise<GapAnalysisResult> {
33
+ const cacheKey = this.buildCacheKey(userIntent, availableTools);
34
+ const cached = this.analysisCache.get(cacheKey);
35
+ if (cached && Date.now() - cached.timestamp.getTime() < 60000) {
36
+ return cached;
37
+ }
38
+
39
+ const toolSummaries = availableTools.map((t) => ({
40
+ name: t.name,
41
+ description: t.description,
42
+ }));
43
+
44
+ const prompt = buildGapAnalysisPrompt(
45
+ userIntent,
46
+ toolSummaries,
47
+ context?.failedAttempts
48
+ );
49
+
50
+ const response = await this.callLLM([
51
+ {
52
+ role: 'system',
53
+ content: `You are a capability analyzer for AI agents.
54
+ Identify gaps between user intent and available tools.
55
+ Be conservative - only report gaps when truly necessary.
56
+ Consider tool composition before suggesting new tools.`,
57
+ },
58
+ { role: 'user', content: prompt },
59
+ ], 0.3);
60
+
61
+ const parsed = parseGapAnalysisResponse(response.content);
62
+ const filteredGaps = this.filterAndPrioritizeGaps(
63
+ parsed.gaps,
64
+ availableTools,
65
+ context?.previousGaps
66
+ );
67
+
68
+ const result: GapAnalysisResult = {
69
+ gaps: filteredGaps,
70
+ analysis: {
71
+ intentCoverage: this.calculateCoverage(userIntent, availableTools, filteredGaps),
72
+ suggestedCompositions: this.suggestCompositions(userIntent, availableTools),
73
+ canProceedWithExisting: parsed.canProceed && filteredGaps.length === 0,
74
+ reasoning: parsed.alternativeApproach || this.generateReasoning(filteredGaps),
75
+ },
76
+ timestamp: new Date(),
77
+ };
78
+
79
+ this.analysisCache.set(cacheKey, result);
80
+
81
+ if (this.analysisCache.size > 100) {
82
+ const oldest = Array.from(this.analysisCache.entries())
83
+ .sort((a, b) => a[1].timestamp.getTime() - b[1].timestamp.getTime())
84
+ .slice(0, 20);
85
+ oldest.forEach(([key]) => this.analysisCache.delete(key));
86
+ }
87
+
88
+ return result;
89
+ }
90
+
91
+ private filterAndPrioritizeGaps(
92
+ gaps: CapabilityGap[],
93
+ availableTools: Tool[],
94
+ previousGaps?: CapabilityGap[]
95
+ ): CapabilityGap[] {
96
+ const toolNames = new Set(availableTools.map((t) => t.name.toLowerCase()));
97
+ const previousGapIds = new Set(previousGaps?.map((g) => g.id) || []);
98
+
99
+ return gaps
100
+ .filter((gap) => {
101
+ if (toolNames.has(gap.suggestedToolName.toLowerCase())) {
102
+ return false;
103
+ }
104
+
105
+ if (gap.confidence < this.config.minConfidenceForGeneration) {
106
+ return false;
107
+ }
108
+
109
+ const complexityAllowed = this.isComplexityAllowed(gap.complexity);
110
+ if (!complexityAllowed) {
111
+ return false;
112
+ }
113
+
114
+ return true;
115
+ })
116
+ .map((gap) => ({
117
+ ...gap,
118
+ priority: this.calculatePriority(gap, previousGapIds.has(gap.id)),
119
+ }))
120
+ .sort((a, b) => (b.priority || 0) - (a.priority || 0))
121
+ .slice(0, this.config.maxToolsPerSession);
122
+ }
123
+
124
+ private isComplexityAllowed(complexity: 'simple' | 'moderate' | 'complex'): boolean {
125
+ const maxComplexity = this.config.maxComplexity || 'moderate';
126
+ const levels = { simple: 1, moderate: 2, complex: 3 };
127
+ return levels[complexity] <= levels[maxComplexity];
128
+ }
129
+
130
+ private calculatePriority(gap: CapabilityGap, isPreviouslyIdentified: boolean): number {
131
+ let priority = gap.confidence;
132
+
133
+ if (isPreviouslyIdentified) {
134
+ priority += 0.2;
135
+ }
136
+
137
+ const complexityBonus = { simple: 0.1, moderate: 0, complex: -0.1 };
138
+ priority += complexityBonus[gap.complexity];
139
+
140
+ return Math.min(1, Math.max(0, priority));
141
+ }
142
+
143
+ private calculateCoverage(
144
+ userIntent: string,
145
+ availableTools: Tool[],
146
+ gaps: CapabilityGap[]
147
+ ): number {
148
+ if (gaps.length === 0) {
149
+ return 1.0;
150
+ }
151
+
152
+ const intentWords = userIntent.toLowerCase().split(/\s+/).length;
153
+ const toolDescriptionWords = availableTools
154
+ .map((t) => t.description.toLowerCase().split(/\s+/))
155
+ .flat();
156
+
157
+ const intentTokens = new Set(userIntent.toLowerCase().split(/\s+/));
158
+ let matchedTokens = 0;
159
+
160
+ intentTokens.forEach((token) => {
161
+ if (token.length > 3 && toolDescriptionWords.includes(token)) {
162
+ matchedTokens++;
163
+ }
164
+ });
165
+
166
+ const baseCoverage = matchedTokens / Math.max(1, intentTokens.size);
167
+ const gapPenalty = gaps.reduce((sum, g) => sum + g.confidence * 0.2, 0);
168
+
169
+ return Math.max(0, Math.min(1, baseCoverage - gapPenalty));
170
+ }
171
+
172
+ private suggestCompositions(
173
+ userIntent: string,
174
+ availableTools: Tool[]
175
+ ): Array<{ tools: string[]; description: string }> {
176
+ const compositions: Array<{ tools: string[]; description: string }> = [];
177
+
178
+ const intentLower = userIntent.toLowerCase();
179
+
180
+ const keywords = {
181
+ transform: ['parse', 'format', 'convert'],
182
+ analyze: ['calculate', 'validate', 'check'],
183
+ combine: ['merge', 'join', 'aggregate'],
184
+ };
185
+
186
+ for (const [action, related] of Object.entries(keywords)) {
187
+ if (intentLower.includes(action)) {
188
+ const relatedTools = availableTools.filter((t) =>
189
+ related.some((r) => t.name.toLowerCase().includes(r) || t.description.toLowerCase().includes(r))
190
+ );
191
+
192
+ if (relatedTools.length >= 2) {
193
+ compositions.push({
194
+ tools: relatedTools.slice(0, 3).map((t) => t.name),
195
+ description: `Combine ${relatedTools.map((t) => t.name).join(' + ')} for ${action}`,
196
+ });
197
+ }
198
+ }
199
+ }
200
+
201
+ return compositions.slice(0, 3);
202
+ }
203
+
204
+ private generateReasoning(gaps: CapabilityGap[]): string {
205
+ if (gaps.length === 0) {
206
+ return 'All required capabilities are available with existing tools.';
207
+ }
208
+
209
+ const gapDescriptions = gaps
210
+ .map((g) => `- ${g.description} (confidence: ${(g.confidence * 100).toFixed(0)}%)`)
211
+ .join('\n');
212
+
213
+ return `Identified ${gaps.length} capability gap(s):\n${gapDescriptions}`;
214
+ }
215
+
216
+ private buildCacheKey(userIntent: string, tools: Tool[]): string {
217
+ const toolSignature = tools.map((t) => t.name).sort().join(',');
218
+ return `${userIntent.slice(0, 100)}|${toolSignature}`;
219
+ }
220
+
221
+ clearCache(): void {
222
+ this.analysisCache.clear();
223
+ }
224
+
225
+ private async callLLM(
226
+ messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,
227
+ temperature: number
228
+ ) {
229
+ if (this.llm.complete) {
230
+ return this.llm.complete({ messages, temperature });
231
+ }
232
+ return this.llm.chat({ model: 'default', messages, temperature });
233
+ }
234
+ }
@@ -0,0 +1,268 @@
1
+ import type { GeneratedTool, GeneratedToolStore as IGeneratedToolStore } from '@cogitator-ai/types';
2
+
3
+ export interface ToolUsageRecord {
4
+ toolId: string;
5
+ timestamp: Date;
6
+ success: boolean;
7
+ executionTime: number;
8
+ inputSummary?: string;
9
+ error?: string;
10
+ }
11
+
12
+ export interface ToolMetrics {
13
+ totalUsage: number;
14
+ successCount: number;
15
+ failureCount: number;
16
+ averageExecutionTime: number;
17
+ lastUsed: Date | null;
18
+ successRate: number;
19
+ }
20
+
21
+ export class InMemoryGeneratedToolStore implements IGeneratedToolStore {
22
+ private readonly tools = new Map<string, GeneratedTool>();
23
+ private readonly usageRecords = new Map<string, ToolUsageRecord[]>();
24
+ private readonly maxUsageRecordsPerTool = 1000;
25
+
26
+ async save(tool: GeneratedTool): Promise<void> {
27
+ const existing = this.tools.get(tool.id);
28
+ if (existing) {
29
+ tool.version = existing.version + 1;
30
+ }
31
+ this.tools.set(tool.id, { ...tool, updatedAt: new Date() });
32
+ }
33
+
34
+ async get(id: string): Promise<GeneratedTool | null> {
35
+ return this.tools.get(id) || null;
36
+ }
37
+
38
+ async getByName(name: string): Promise<GeneratedTool | null> {
39
+ for (const tool of this.tools.values()) {
40
+ if (tool.name === name && tool.status !== 'deprecated') {
41
+ return tool;
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+
47
+ async list(filter?: {
48
+ status?: GeneratedTool['status'];
49
+ minScore?: number;
50
+ }): Promise<GeneratedTool[]> {
51
+ let tools = Array.from(this.tools.values());
52
+
53
+ if (filter?.status) {
54
+ tools = tools.filter((t) => t.status === filter.status);
55
+ }
56
+
57
+ if (filter?.minScore !== undefined) {
58
+ tools = tools.filter(
59
+ (t) => t.validationScore !== undefined && t.validationScore >= filter.minScore!
60
+ );
61
+ }
62
+
63
+ return tools.sort((a, b) => {
64
+ const scoreA = a.validationScore ?? 0;
65
+ const scoreB = b.validationScore ?? 0;
66
+ return scoreB - scoreA;
67
+ });
68
+ }
69
+
70
+ async delete(id: string): Promise<boolean> {
71
+ const deleted = this.tools.delete(id);
72
+ this.usageRecords.delete(id);
73
+ return deleted;
74
+ }
75
+
76
+ async updateStatus(
77
+ id: string,
78
+ status: GeneratedTool['status']
79
+ ): Promise<boolean> {
80
+ const tool = this.tools.get(id);
81
+ if (!tool) return false;
82
+
83
+ tool.status = status;
84
+ tool.updatedAt = new Date();
85
+ return true;
86
+ }
87
+
88
+ async recordUsage(record: ToolUsageRecord): Promise<void> {
89
+ const records = this.usageRecords.get(record.toolId) || [];
90
+ records.push(record);
91
+
92
+ if (records.length > this.maxUsageRecordsPerTool) {
93
+ records.splice(0, records.length - this.maxUsageRecordsPerTool);
94
+ }
95
+
96
+ this.usageRecords.set(record.toolId, records);
97
+
98
+ const tool = this.tools.get(record.toolId);
99
+ if (tool) {
100
+ tool.usageCount = (tool.usageCount || 0) + 1;
101
+ tool.lastUsed = record.timestamp;
102
+ }
103
+ }
104
+
105
+ async getMetrics(toolId: string): Promise<ToolMetrics | null> {
106
+ const records = this.usageRecords.get(toolId);
107
+ if (!records || records.length === 0) {
108
+ return null;
109
+ }
110
+
111
+ const successCount = records.filter((r) => r.success).length;
112
+ const totalTime = records.reduce((sum, r) => sum + r.executionTime, 0);
113
+
114
+ return {
115
+ totalUsage: records.length,
116
+ successCount,
117
+ failureCount: records.length - successCount,
118
+ averageExecutionTime: totalTime / records.length,
119
+ lastUsed: records.length > 0 ? records[records.length - 1].timestamp : null,
120
+ successRate: successCount / records.length,
121
+ };
122
+ }
123
+
124
+ async getTopTools(limit: number = 10): Promise<Array<{ tool: GeneratedTool; metrics: ToolMetrics }>> {
125
+ const result: Array<{ tool: GeneratedTool; metrics: ToolMetrics }> = [];
126
+
127
+ for (const tool of this.tools.values()) {
128
+ if (tool.status !== 'active') continue;
129
+
130
+ const metrics = await this.getMetrics(tool.id);
131
+ if (metrics && metrics.totalUsage > 0) {
132
+ result.push({ tool, metrics });
133
+ }
134
+ }
135
+
136
+ return result
137
+ .sort((a, b) => {
138
+ const scoreA = a.metrics.successRate * Math.log(a.metrics.totalUsage + 1);
139
+ const scoreB = b.metrics.successRate * Math.log(b.metrics.totalUsage + 1);
140
+ return scoreB - scoreA;
141
+ })
142
+ .slice(0, limit);
143
+ }
144
+
145
+ async findSimilar(description: string, limit: number = 5): Promise<GeneratedTool[]> {
146
+ const descWords = new Set(description.toLowerCase().split(/\s+/));
147
+ const scored: Array<{ tool: GeneratedTool; score: number }> = [];
148
+
149
+ for (const tool of this.tools.values()) {
150
+ if (tool.status === 'deprecated') continue;
151
+
152
+ const toolWords = new Set(
153
+ `${tool.name} ${tool.description}`.toLowerCase().split(/\s+/)
154
+ );
155
+
156
+ let matchCount = 0;
157
+ for (const word of descWords) {
158
+ if (word.length >= 3 && toolWords.has(word)) {
159
+ matchCount++;
160
+ }
161
+ }
162
+
163
+ if (matchCount > 0) {
164
+ scored.push({
165
+ tool,
166
+ score: matchCount / Math.max(descWords.size, toolWords.size),
167
+ });
168
+ }
169
+ }
170
+
171
+ return scored
172
+ .sort((a, b) => b.score - a.score)
173
+ .slice(0, limit)
174
+ .map((s) => s.tool);
175
+ }
176
+
177
+ async promoteToActive(toolId: string): Promise<boolean> {
178
+ const tool = this.tools.get(toolId);
179
+ if (!tool) return false;
180
+
181
+ if (tool.status !== 'validated') {
182
+ return false;
183
+ }
184
+
185
+ tool.status = 'active';
186
+ tool.updatedAt = new Date();
187
+ return true;
188
+ }
189
+
190
+ async deprecate(toolId: string, reason?: string): Promise<boolean> {
191
+ const tool = this.tools.get(toolId);
192
+ if (!tool) return false;
193
+
194
+ tool.status = 'deprecated';
195
+ tool.metadata = {
196
+ ...tool.metadata,
197
+ deprecationReason: reason,
198
+ deprecatedAt: new Date().toISOString(),
199
+ };
200
+ tool.updatedAt = new Date();
201
+ return true;
202
+ }
203
+
204
+ async cleanup(options: {
205
+ maxAge?: number;
206
+ minUsage?: number;
207
+ maxDeprecated?: number;
208
+ }): Promise<number> {
209
+ let removed = 0;
210
+ const now = Date.now();
211
+
212
+ for (const [id, tool] of this.tools) {
213
+ if (options.maxAge && tool.createdAt) {
214
+ const age = now - tool.createdAt.getTime();
215
+ if (age > options.maxAge && tool.status !== 'active') {
216
+ this.tools.delete(id);
217
+ this.usageRecords.delete(id);
218
+ removed++;
219
+ continue;
220
+ }
221
+ }
222
+
223
+ if (options.minUsage !== undefined) {
224
+ const usage = tool.usageCount || 0;
225
+ if (usage < options.minUsage && tool.status === 'deprecated') {
226
+ this.tools.delete(id);
227
+ this.usageRecords.delete(id);
228
+ removed++;
229
+ }
230
+ }
231
+ }
232
+
233
+ if (options.maxDeprecated !== undefined) {
234
+ const deprecated = Array.from(this.tools.values())
235
+ .filter((t) => t.status === 'deprecated')
236
+ .sort((a, b) => (a.usageCount || 0) - (b.usageCount || 0));
237
+
238
+ while (deprecated.length > options.maxDeprecated) {
239
+ const toRemove = deprecated.shift()!;
240
+ this.tools.delete(toRemove.id);
241
+ this.usageRecords.delete(toRemove.id);
242
+ removed++;
243
+ }
244
+ }
245
+
246
+ return removed;
247
+ }
248
+
249
+ getStats(): {
250
+ total: number;
251
+ byStatus: Record<string, number>;
252
+ totalUsage: number;
253
+ } {
254
+ const byStatus: Record<string, number> = {};
255
+ let totalUsage = 0;
256
+
257
+ for (const tool of this.tools.values()) {
258
+ byStatus[tool.status] = (byStatus[tool.status] || 0) + 1;
259
+ totalUsage += tool.usageCount || 0;
260
+ }
261
+
262
+ return {
263
+ total: this.tools.size,
264
+ byStatus,
265
+ totalUsage,
266
+ };
267
+ }
268
+ }
@@ -0,0 +1,19 @@
1
+ export { GapAnalyzer, type GapAnalyzerOptions } from './gap-analyzer';
2
+ export { ToolGenerator, type ToolGeneratorOptions, type GenerationResult } from './tool-generator';
3
+ export { ToolValidator, type ToolValidatorOptions } from './tool-validator';
4
+ export { ToolSandbox, DEFAULT_SANDBOX_CONFIG } from './tool-sandbox';
5
+ export {
6
+ InMemoryGeneratedToolStore,
7
+ type ToolUsageRecord,
8
+ type ToolMetrics,
9
+ } from './generated-tool-store';
10
+ export {
11
+ buildGapAnalysisPrompt,
12
+ buildToolGenerationPrompt,
13
+ buildToolValidationPrompt,
14
+ buildToolImprovementPrompt,
15
+ parseGapAnalysisResponse,
16
+ parseToolGenerationResponse,
17
+ parseValidationResponse,
18
+ TOOL_GENERATION_SYSTEM_PROMPT,
19
+ } from './prompts';