@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,489 @@
1
+ import type {
2
+ LLMBackend,
3
+ TaskProfile,
4
+ ArchitectureConfig,
5
+ EvolutionCandidate,
6
+ ArchitectureEvolutionConfig,
7
+ EvolutionMetrics,
8
+ } from '@cogitator-ai/types';
9
+ import { CapabilityAnalyzer } from './capability-analyzer';
10
+ import { EvolutionStrategy, type SelectionResult } from './evolution-strategy';
11
+ import {
12
+ buildCandidateGenerationPrompt,
13
+ buildPerformanceAnalysisPrompt,
14
+ parseCandidateGenerationResponse,
15
+ parsePerformanceAnalysisResponse,
16
+ } from './prompts';
17
+
18
+ export interface ParameterOptimizerOptions {
19
+ llm: LLMBackend;
20
+ config: ArchitectureEvolutionConfig;
21
+ baseConfig: ArchitectureConfig;
22
+ }
23
+
24
+ export interface OptimizationResult {
25
+ recommendedConfig: ArchitectureConfig;
26
+ candidate: EvolutionCandidate | null;
27
+ metrics: EvolutionMetrics;
28
+ shouldAdopt: boolean;
29
+ confidence: number;
30
+ reasoning: string;
31
+ }
32
+
33
+ interface HistoricalRecord {
34
+ taskProfile: TaskProfile;
35
+ config: Partial<ArchitectureConfig>;
36
+ score: number;
37
+ metrics: Record<string, number>;
38
+ timestamp: number;
39
+ }
40
+
41
+ export class ParameterOptimizer {
42
+ private readonly llm: LLMBackend;
43
+ private readonly config: ArchitectureEvolutionConfig;
44
+ private readonly baseConfig: ArchitectureConfig;
45
+ private readonly capabilityAnalyzer: CapabilityAnalyzer;
46
+ private readonly evolutionStrategy: EvolutionStrategy;
47
+
48
+ private candidates: EvolutionCandidate[] = [];
49
+ private history: HistoricalRecord[] = [];
50
+ private currentGeneration = 0;
51
+ private readonly maxHistorySize = 100;
52
+
53
+ constructor(options: ParameterOptimizerOptions) {
54
+ this.llm = options.llm;
55
+ this.config = options.config;
56
+ this.baseConfig = options.baseConfig;
57
+
58
+ this.capabilityAnalyzer = new CapabilityAnalyzer({
59
+ llm: options.llm,
60
+ enableLLMAnalysis: true,
61
+ });
62
+
63
+ this.evolutionStrategy = new EvolutionStrategy({
64
+ strategy: options.config.strategy,
65
+ explorationBonus: 2.0,
66
+ });
67
+ }
68
+
69
+ async optimize(taskDescription: string): Promise<OptimizationResult> {
70
+ const profile = await this.capabilityAnalyzer.analyzeTask(taskDescription);
71
+
72
+ if (this.candidates.length === 0) {
73
+ await this.generateInitialCandidates(profile);
74
+ }
75
+
76
+ const selection = this.evolutionStrategy.select(this.candidates);
77
+
78
+ const mergedConfig = this.mergeConfigs(this.baseConfig, selection.candidate.config);
79
+
80
+ return {
81
+ recommendedConfig: mergedConfig,
82
+ candidate: selection.candidate,
83
+ metrics: this.calculateMetrics(),
84
+ shouldAdopt: true,
85
+ confidence: selection.score,
86
+ reasoning: selection.reasoning,
87
+ };
88
+ }
89
+
90
+ async recordOutcome(
91
+ candidateId: string,
92
+ taskProfile: TaskProfile,
93
+ metrics: {
94
+ successRate: number;
95
+ latency: number;
96
+ tokenUsage: number;
97
+ qualityScore: number;
98
+ }
99
+ ): Promise<void> {
100
+ const candidate = this.candidates.find((c) => c.id === candidateId);
101
+ if (!candidate) return;
102
+
103
+ const reward = this.calculateReward(metrics);
104
+ this.evolutionStrategy.updateCandidate(candidate, reward);
105
+
106
+ this.history.push({
107
+ taskProfile,
108
+ config: candidate.config,
109
+ score: reward,
110
+ metrics: {
111
+ successRate: metrics.successRate,
112
+ latency: metrics.latency,
113
+ tokenUsage: metrics.tokenUsage,
114
+ qualityScore: metrics.qualityScore,
115
+ },
116
+ timestamp: Date.now(),
117
+ });
118
+
119
+ if (this.history.length > this.maxHistorySize) {
120
+ this.history = this.history.slice(-this.maxHistorySize);
121
+ }
122
+
123
+ if (this.shouldEvolve()) {
124
+ await this.evolve(taskProfile);
125
+ }
126
+ }
127
+
128
+ private async generateInitialCandidates(profile: TaskProfile): Promise<void> {
129
+ const prompt = buildCandidateGenerationPrompt(
130
+ profile,
131
+ this.baseConfig,
132
+ this.getRelevantHistory(profile)
133
+ );
134
+
135
+ try {
136
+ const response = await this.callLLM([
137
+ {
138
+ role: 'system',
139
+ content: 'You are an AI architecture optimizer. Generate candidate configurations.',
140
+ },
141
+ { role: 'user', content: prompt },
142
+ ], 0.5);
143
+
144
+ const generated = parseCandidateGenerationResponse(response.content);
145
+
146
+ this.candidates = [
147
+ this.createBaselineCandidate(),
148
+ ...generated.map((c) => ({
149
+ ...c,
150
+ generation: this.currentGeneration,
151
+ })),
152
+ ];
153
+ } catch {
154
+ this.candidates = [this.createBaselineCandidate()];
155
+ }
156
+ }
157
+
158
+ private createBaselineCandidate(): EvolutionCandidate {
159
+ return {
160
+ id: 'baseline',
161
+ config: {},
162
+ reasoning: 'Baseline configuration with no modifications',
163
+ expectedImprovement: 0,
164
+ risk: 'low',
165
+ generation: 0,
166
+ score: 0.5,
167
+ evaluationCount: 0,
168
+ };
169
+ }
170
+
171
+ private async evolve(currentProfile: TaskProfile): Promise<void> {
172
+ this.currentGeneration++;
173
+
174
+ const topCandidates = [...this.candidates]
175
+ .filter((c) => c.evaluationCount > 0)
176
+ .sort((a, b) => b.score - a.score)
177
+ .slice(0, 3);
178
+
179
+ if (topCandidates.length === 0) return;
180
+
181
+ const newCandidates = await this.generateOffspring(topCandidates, currentProfile);
182
+
183
+ const keepCount = Math.max(3, Math.floor(this.candidates.length * 0.5));
184
+ const survivingCandidates = [...this.candidates]
185
+ .sort((a, b) => {
186
+ const scoreA = a.score + (a.evaluationCount > 0 ? 0 : 0.1);
187
+ const scoreB = b.score + (b.evaluationCount > 0 ? 0 : 0.1);
188
+ return scoreB - scoreA;
189
+ })
190
+ .slice(0, keepCount);
191
+
192
+ this.candidates = [...survivingCandidates, ...newCandidates];
193
+
194
+ const maxCandidates = this.config.maxCandidates ?? 10;
195
+ if (this.candidates.length > maxCandidates) {
196
+ this.candidates = this.candidates.slice(0, maxCandidates);
197
+ }
198
+ }
199
+
200
+ private async generateOffspring(
201
+ parents: EvolutionCandidate[],
202
+ profile: TaskProfile
203
+ ): Promise<EvolutionCandidate[]> {
204
+ const offspring: EvolutionCandidate[] = [];
205
+
206
+ for (const parent of parents) {
207
+ const mutated = this.mutateConfig(parent.config);
208
+ offspring.push({
209
+ id: `gen${this.currentGeneration}_${offspring.length}`,
210
+ config: mutated,
211
+ reasoning: `Mutation of ${parent.id}`,
212
+ expectedImprovement: parent.score * 0.9,
213
+ risk: 'medium',
214
+ generation: this.currentGeneration,
215
+ score: 0,
216
+ evaluationCount: 0,
217
+ });
218
+ }
219
+
220
+ if (parents.length >= 2) {
221
+ const crossed = this.crossover(parents[0].config, parents[1].config);
222
+ offspring.push({
223
+ id: `gen${this.currentGeneration}_crossover`,
224
+ config: crossed,
225
+ reasoning: `Crossover of ${parents[0].id} and ${parents[1].id}`,
226
+ expectedImprovement: (parents[0].score + parents[1].score) / 2,
227
+ risk: 'medium',
228
+ generation: this.currentGeneration,
229
+ score: 0,
230
+ evaluationCount: 0,
231
+ });
232
+ }
233
+
234
+ return offspring;
235
+ }
236
+
237
+ private mutateConfig(config: Partial<ArchitectureConfig>): Partial<ArchitectureConfig> {
238
+ const mutated = { ...config };
239
+ const mutationRate = 0.3;
240
+
241
+ if (Math.random() < mutationRate && mutated.temperature !== undefined) {
242
+ mutated.temperature = Math.max(0, Math.min(2, mutated.temperature + (Math.random() - 0.5) * 0.3));
243
+ }
244
+
245
+ if (Math.random() < mutationRate && mutated.maxTokens !== undefined) {
246
+ const delta = Math.floor((Math.random() - 0.5) * 1000);
247
+ mutated.maxTokens = Math.max(100, Math.min(32000, mutated.maxTokens + delta));
248
+ }
249
+
250
+ if (Math.random() < mutationRate && mutated.reflectionDepth !== undefined) {
251
+ mutated.reflectionDepth = Math.max(0, Math.min(5, mutated.reflectionDepth + Math.round(Math.random() * 2 - 1)));
252
+ }
253
+
254
+ return mutated;
255
+ }
256
+
257
+ private crossover(
258
+ configA: Partial<ArchitectureConfig>,
259
+ configB: Partial<ArchitectureConfig>
260
+ ): Partial<ArchitectureConfig> {
261
+ const result: Partial<ArchitectureConfig> = {};
262
+
263
+ const allKeys = new Set([...Object.keys(configA), ...Object.keys(configB)]);
264
+
265
+ for (const key of allKeys) {
266
+ const typedKey = key as keyof ArchitectureConfig;
267
+ if (Math.random() < 0.5 && configA[typedKey] !== undefined) {
268
+ (result as Record<string, unknown>)[key] = configA[typedKey];
269
+ } else if (configB[typedKey] !== undefined) {
270
+ (result as Record<string, unknown>)[key] = configB[typedKey];
271
+ }
272
+ }
273
+
274
+ return result;
275
+ }
276
+
277
+ private calculateReward(metrics: {
278
+ successRate: number;
279
+ latency: number;
280
+ tokenUsage: number;
281
+ qualityScore: number;
282
+ }): number {
283
+ const weights = {
284
+ success: 0.4,
285
+ quality: 0.3,
286
+ latency: 0.15,
287
+ tokens: 0.15,
288
+ };
289
+
290
+ const successScore = metrics.successRate;
291
+ const qualityScore = metrics.qualityScore;
292
+ const latencyScore = Math.max(0, 1 - metrics.latency / 30000);
293
+ const tokenScore = Math.max(0, 1 - metrics.tokenUsage / 10000);
294
+
295
+ return (
296
+ weights.success * successScore +
297
+ weights.quality * qualityScore +
298
+ weights.latency * latencyScore +
299
+ weights.tokens * tokenScore
300
+ );
301
+ }
302
+
303
+ private shouldEvolve(): boolean {
304
+ const minEvaluations = this.candidates.reduce(
305
+ (min, c) => Math.min(min, c.evaluationCount),
306
+ Infinity
307
+ );
308
+
309
+ if (minEvaluations < 3) return false;
310
+
311
+ const evaluationsSinceEvolution = this.history.filter(
312
+ (h) => h.timestamp > this.getLastEvolutionTime()
313
+ ).length;
314
+
315
+ return evaluationsSinceEvolution >= 5;
316
+ }
317
+
318
+ private getLastEvolutionTime(): number {
319
+ const latestGenCandidate = this.candidates.find(
320
+ (c) => c.generation === this.currentGeneration && c.evaluationCount === 0
321
+ );
322
+ return latestGenCandidate ? Date.now() - 300000 : 0;
323
+ }
324
+
325
+ private getRelevantHistory(profile: TaskProfile): HistoricalRecord[] {
326
+ return this.history
327
+ .filter((h) => h.taskProfile.domain === profile.domain || h.taskProfile.complexity === profile.complexity)
328
+ .slice(-10);
329
+ }
330
+
331
+ private mergeConfigs(
332
+ base: ArchitectureConfig,
333
+ overrides: Partial<ArchitectureConfig>
334
+ ): ArchitectureConfig {
335
+ return {
336
+ ...base,
337
+ ...Object.fromEntries(
338
+ Object.entries(overrides).filter(([, v]) => v !== undefined && v !== null)
339
+ ),
340
+ } as ArchitectureConfig;
341
+ }
342
+
343
+ private calculateMetrics(): EvolutionMetrics {
344
+ const evaluatedCandidates = this.candidates.filter((c) => c.evaluationCount > 0);
345
+
346
+ if (evaluatedCandidates.length === 0) {
347
+ return {
348
+ generation: this.currentGeneration,
349
+ bestScore: 0,
350
+ averageScore: 0,
351
+ diversity: 1,
352
+ convergenceRate: 0,
353
+ };
354
+ }
355
+
356
+ const scores = evaluatedCandidates.map((c) => c.score);
357
+ const bestScore = Math.max(...scores);
358
+ const averageScore = scores.reduce((a, b) => a + b, 0) / scores.length;
359
+ const diversity = this.calculateDiversity();
360
+ const convergenceRate = this.calculateConvergenceRate();
361
+
362
+ return {
363
+ generation: this.currentGeneration,
364
+ bestScore,
365
+ averageScore,
366
+ diversity,
367
+ convergenceRate,
368
+ };
369
+ }
370
+
371
+ private calculateDiversity(): number {
372
+ if (this.candidates.length < 2) return 1;
373
+
374
+ let totalDiff = 0;
375
+ let comparisons = 0;
376
+
377
+ for (let i = 0; i < this.candidates.length; i++) {
378
+ for (let j = i + 1; j < this.candidates.length; j++) {
379
+ totalDiff += this.configDistance(this.candidates[i].config, this.candidates[j].config);
380
+ comparisons++;
381
+ }
382
+ }
383
+
384
+ return comparisons > 0 ? totalDiff / comparisons : 0;
385
+ }
386
+
387
+ private configDistance(a: Partial<ArchitectureConfig>, b: Partial<ArchitectureConfig>): number {
388
+ let distance = 0;
389
+ let fields = 0;
390
+
391
+ if (a.temperature !== undefined && b.temperature !== undefined) {
392
+ distance += Math.abs(a.temperature - b.temperature) / 2;
393
+ fields++;
394
+ }
395
+
396
+ if (a.maxTokens !== undefined && b.maxTokens !== undefined) {
397
+ distance += Math.abs(a.maxTokens - b.maxTokens) / 32000;
398
+ fields++;
399
+ }
400
+
401
+ if (a.model !== b.model) {
402
+ distance += 1;
403
+ fields++;
404
+ }
405
+
406
+ return fields > 0 ? distance / fields : 0;
407
+ }
408
+
409
+ private calculateConvergenceRate(): number {
410
+ if (this.history.length < 10) return 0;
411
+
412
+ const recentScores = this.history.slice(-10).map((h) => h.score);
413
+ const variance = this.calculateVariance(recentScores);
414
+
415
+ return Math.max(0, 1 - variance * 4);
416
+ }
417
+
418
+ private calculateVariance(values: number[]): number {
419
+ if (values.length === 0) return 0;
420
+ const mean = values.reduce((a, b) => a + b, 0) / values.length;
421
+ const squaredDiffs = values.map((v) => Math.pow(v - mean, 2));
422
+ return squaredDiffs.reduce((a, b) => a + b, 0) / values.length;
423
+ }
424
+
425
+ async analyzePerformance(): Promise<{
426
+ recommendation: string;
427
+ confidence: number;
428
+ analysis: string;
429
+ } | null> {
430
+ if (this.candidates.length === 0 || this.history.length < 5) {
431
+ return null;
432
+ }
433
+
434
+ const evaluatedCandidates = this.candidates.filter((c) => c.evaluationCount > 0);
435
+ if (evaluatedCandidates.length === 0) return null;
436
+
437
+ const results = evaluatedCandidates.map((c) => {
438
+ const records = this.history.filter((h) => JSON.stringify(h.config) === JSON.stringify(c.config));
439
+ const avgMetrics = records.length > 0
440
+ ? {
441
+ successRate: records.reduce((s, r) => s + r.metrics.successRate, 0) / records.length,
442
+ avgLatency: records.reduce((s, r) => s + r.metrics.latency, 0) / records.length,
443
+ avgTokens: records.reduce((s, r) => s + r.metrics.tokenUsage, 0) / records.length,
444
+ qualityScore: records.reduce((s, r) => s + r.metrics.qualityScore, 0) / records.length,
445
+ }
446
+ : { successRate: 0, avgLatency: 0, avgTokens: 0, qualityScore: 0 };
447
+
448
+ return { candidateId: c.id, metrics: avgMetrics };
449
+ });
450
+
451
+ const prompt = buildPerformanceAnalysisPrompt(evaluatedCandidates, results);
452
+
453
+ try {
454
+ const response = await this.callLLM([
455
+ { role: 'system', content: 'You are an AI performance analyst.' },
456
+ { role: 'user', content: prompt },
457
+ ], 0.2);
458
+
459
+ return parsePerformanceAnalysisResponse(response.content);
460
+ } catch {
461
+ return null;
462
+ }
463
+ }
464
+
465
+ private async callLLM(
466
+ messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,
467
+ temperature: number
468
+ ) {
469
+ if (this.llm.complete) {
470
+ return this.llm.complete({ messages, temperature });
471
+ }
472
+ return this.llm.chat({ model: 'default', messages, temperature });
473
+ }
474
+
475
+ getCandidates(): EvolutionCandidate[] {
476
+ return [...this.candidates];
477
+ }
478
+
479
+ getHistory(): HistoricalRecord[] {
480
+ return [...this.history];
481
+ }
482
+
483
+ reset(): void {
484
+ this.candidates = [];
485
+ this.history = [];
486
+ this.currentGeneration = 0;
487
+ this.evolutionStrategy.reset();
488
+ }
489
+ }
@@ -0,0 +1,216 @@
1
+ import type { TaskProfile, ArchitectureConfig, EvolutionCandidate } from '@cogitator-ai/types';
2
+
3
+ export const ARCHITECTURE_ANALYSIS_SYSTEM_PROMPT = `You are an expert in AI agent architecture optimization.
4
+ Your task is to analyze tasks and recommend optimal configurations.
5
+
6
+ Consider these factors:
7
+ 1. Task complexity - simple tasks need lighter models, complex need stronger
8
+ 2. Domain requirements - some domains need specific capabilities
9
+ 3. Resource constraints - balance performance vs cost
10
+ 4. Historical performance - learn from past executions
11
+
12
+ Always provide structured JSON responses.`;
13
+
14
+ export function buildTaskProfilePrompt(
15
+ taskDescription: string,
16
+ context?: {
17
+ previousTasks?: string[];
18
+ availableModels?: string[];
19
+ constraints?: { maxCost?: number; maxLatency?: number };
20
+ }
21
+ ): string {
22
+ const contextSection = context
23
+ ? `
24
+ CONTEXT:
25
+ ${context.previousTasks?.length ? `Previous tasks: ${context.previousTasks.slice(-3).join(', ')}` : ''}
26
+ ${context.availableModels?.length ? `Available models: ${context.availableModels.join(', ')}` : ''}
27
+ ${context.constraints?.maxCost ? `Max cost: $${context.constraints.maxCost}` : ''}
28
+ ${context.constraints?.maxLatency ? `Max latency: ${context.constraints.maxLatency}ms` : ''}`
29
+ : '';
30
+
31
+ return `Analyze the following task and create a profile for architecture optimization.
32
+
33
+ TASK:
34
+ ${taskDescription}
35
+ ${contextSection}
36
+
37
+ Respond with a JSON object:
38
+ {
39
+ "complexity": "trivial" | "simple" | "moderate" | "complex" | "extreme",
40
+ "domain": "general" | "coding" | "reasoning" | "creative" | "factual" | "conversational",
41
+ "estimatedTokens": number,
42
+ "requiresTools": boolean,
43
+ "toolIntensity": "none" | "light" | "moderate" | "heavy",
44
+ "reasoningDepth": "shallow" | "moderate" | "deep" | "exhaustive",
45
+ "creativityLevel": "low" | "moderate" | "high",
46
+ "accuracyRequirement": "approximate" | "moderate" | "high" | "critical",
47
+ "timeConstraint": "none" | "relaxed" | "moderate" | "strict",
48
+ "suggestedApproach": "Brief description of recommended approach",
49
+ "riskFactors": ["List of potential challenges"]
50
+ }`;
51
+ }
52
+
53
+ export function buildCandidateGenerationPrompt(
54
+ profile: TaskProfile,
55
+ currentConfig: ArchitectureConfig,
56
+ historicalPerformance?: Array<{
57
+ config: Partial<ArchitectureConfig>;
58
+ score: number;
59
+ metrics: Record<string, number>;
60
+ }>
61
+ ): string {
62
+ const historySection = historicalPerformance?.length
63
+ ? `
64
+ HISTORICAL PERFORMANCE:
65
+ ${historicalPerformance
66
+ .slice(-5)
67
+ .map(
68
+ (h, i) =>
69
+ `${i + 1}. Config: ${JSON.stringify(h.config)} → Score: ${h.score.toFixed(2)}, Metrics: ${JSON.stringify(h.metrics)}`
70
+ )
71
+ .join('\n')}`
72
+ : '';
73
+
74
+ return `Generate candidate configurations for architecture evolution.
75
+
76
+ TASK PROFILE:
77
+ ${JSON.stringify(profile, null, 2)}
78
+
79
+ CURRENT CONFIG:
80
+ ${JSON.stringify(currentConfig, null, 2)}
81
+ ${historySection}
82
+
83
+ Generate 3-5 candidate configurations that might improve performance.
84
+ Each candidate should modify 1-3 parameters from current config.
85
+
86
+ Respond with a JSON array:
87
+ [
88
+ {
89
+ "id": "candidate_1",
90
+ "config": {
91
+ "model": "model name or null to keep current",
92
+ "temperature": number or null,
93
+ "maxTokens": number or null,
94
+ "systemPromptAdditions": "additional instructions or null",
95
+ "toolStrategy": "sequential" | "parallel" | "adaptive" | null,
96
+ "reflectionDepth": number or null
97
+ },
98
+ "reasoning": "Why this configuration might help",
99
+ "expectedImprovement": 0.0-1.0,
100
+ "risk": "low" | "medium" | "high"
101
+ }
102
+ ]`;
103
+ }
104
+
105
+ export function buildPerformanceAnalysisPrompt(
106
+ candidates: EvolutionCandidate[],
107
+ results: Array<{
108
+ candidateId: string;
109
+ metrics: {
110
+ successRate: number;
111
+ avgLatency: number;
112
+ avgTokens: number;
113
+ qualityScore: number;
114
+ };
115
+ }>
116
+ ): string {
117
+ return `Analyze the performance of architecture candidates and recommend the best configuration.
118
+
119
+ CANDIDATES AND RESULTS:
120
+ ${candidates
121
+ .map((c) => {
122
+ const result = results.find((r) => r.candidateId === c.id);
123
+ return `
124
+ ${c.id}:
125
+ Config: ${JSON.stringify(c.config)}
126
+ Reasoning: ${c.reasoning}
127
+ ${result ? `Results: ${JSON.stringify(result.metrics)}` : 'Not yet tested'}`;
128
+ })
129
+ .join('\n')}
130
+
131
+ Respond with:
132
+ {
133
+ "recommendation": "candidate_id of best candidate",
134
+ "confidence": 0.0-1.0,
135
+ "analysis": "Detailed analysis of results",
136
+ "suggestedNextExperiments": ["List of additional experiments to try"],
137
+ "shouldAdopt": boolean,
138
+ "adoptionReason": "Why to adopt or not adopt the recommendation"
139
+ }`;
140
+ }
141
+
142
+ export function parseTaskProfileResponse(response: string): TaskProfile | null {
143
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
144
+ if (!jsonMatch) return null;
145
+
146
+ try {
147
+ const parsed = JSON.parse(jsonMatch[0]);
148
+
149
+ return {
150
+ complexity: parsed.complexity || 'moderate',
151
+ domain: parsed.domain || 'general',
152
+ estimatedTokens: parsed.estimatedTokens || 1000,
153
+ requiresTools: Boolean(parsed.requiresTools),
154
+ toolIntensity: parsed.toolIntensity || 'none',
155
+ reasoningDepth: parsed.reasoningDepth || 'moderate',
156
+ creativityLevel: parsed.creativityLevel || 'moderate',
157
+ accuracyRequirement: parsed.accuracyRequirement || 'moderate',
158
+ timeConstraint: parsed.timeConstraint || 'none',
159
+ };
160
+ } catch {
161
+ return null;
162
+ }
163
+ }
164
+
165
+ export function parseCandidateGenerationResponse(
166
+ response: string
167
+ ): EvolutionCandidate[] {
168
+ const jsonMatch = response.match(/\[[\s\S]*\]/);
169
+ if (!jsonMatch) return [];
170
+
171
+ try {
172
+ const parsed = JSON.parse(jsonMatch[0]);
173
+ if (!Array.isArray(parsed)) return [];
174
+
175
+ return parsed
176
+ .filter((c: Record<string, unknown>) => c && typeof c === 'object' && c.config)
177
+ .map((c: Record<string, unknown>, idx: number) => ({
178
+ id: String(c.id || `candidate_${idx}`),
179
+ config: c.config as Partial<ArchitectureConfig>,
180
+ reasoning: String(c.reasoning || ''),
181
+ expectedImprovement: typeof c.expectedImprovement === 'number' ? c.expectedImprovement : 0.5,
182
+ risk: (['low', 'medium', 'high'].includes(String(c.risk)) ? c.risk : 'medium') as
183
+ | 'low'
184
+ | 'medium'
185
+ | 'high',
186
+ generation: 0,
187
+ score: 0,
188
+ evaluationCount: 0,
189
+ }));
190
+ } catch {
191
+ return [];
192
+ }
193
+ }
194
+
195
+ export function parsePerformanceAnalysisResponse(response: string): {
196
+ recommendation: string;
197
+ confidence: number;
198
+ shouldAdopt: boolean;
199
+ analysis: string;
200
+ } | null {
201
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
202
+ if (!jsonMatch) return null;
203
+
204
+ try {
205
+ const parsed = JSON.parse(jsonMatch[0]);
206
+
207
+ return {
208
+ recommendation: String(parsed.recommendation || ''),
209
+ confidence: typeof parsed.confidence === 'number' ? parsed.confidence : 0.5,
210
+ shouldAdopt: Boolean(parsed.shouldAdopt),
211
+ analysis: String(parsed.analysis || ''),
212
+ };
213
+ } catch {
214
+ return null;
215
+ }
216
+ }