@cogitator-ai/self-modifying 17.0.18 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +112 -48
  2. package/dist/architecture-evolution/capability-analyzer.d.ts.map +1 -1
  3. package/dist/architecture-evolution/capability-analyzer.js +38 -37
  4. package/dist/architecture-evolution/capability-analyzer.js.map +1 -1
  5. package/dist/architecture-evolution/index.d.ts +2 -2
  6. package/dist/architecture-evolution/index.d.ts.map +1 -1
  7. package/dist/architecture-evolution/index.js +1 -1
  8. package/dist/architecture-evolution/index.js.map +1 -1
  9. package/dist/architecture-evolution/parameter-optimizer.d.ts +5 -4
  10. package/dist/architecture-evolution/parameter-optimizer.d.ts.map +1 -1
  11. package/dist/architecture-evolution/parameter-optimizer.js +36 -31
  12. package/dist/architecture-evolution/parameter-optimizer.js.map +1 -1
  13. package/dist/architecture-evolution/prompts.d.ts +21 -2
  14. package/dist/architecture-evolution/prompts.d.ts.map +1 -1
  15. package/dist/architecture-evolution/prompts.js +150 -36
  16. package/dist/architecture-evolution/prompts.js.map +1 -1
  17. package/dist/constraints/modification-validator.d.ts +1 -0
  18. package/dist/constraints/modification-validator.d.ts.map +1 -1
  19. package/dist/constraints/modification-validator.js +30 -14
  20. package/dist/constraints/modification-validator.js.map +1 -1
  21. package/dist/index.d.ts +4 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/meta-reasoning/meta-reasoner.d.ts +3 -0
  26. package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -1
  27. package/dist/meta-reasoning/meta-reasoner.js +101 -33
  28. package/dist/meta-reasoning/meta-reasoner.js.map +1 -1
  29. package/dist/meta-reasoning/prompts.d.ts +10 -14
  30. package/dist/meta-reasoning/prompts.d.ts.map +1 -1
  31. package/dist/meta-reasoning/prompts.js +109 -1
  32. package/dist/meta-reasoning/prompts.js.map +1 -1
  33. package/dist/self-modifying-agent.d.ts +83 -17
  34. package/dist/self-modifying-agent.d.ts.map +1 -1
  35. package/dist/self-modifying-agent.js +557 -444
  36. package/dist/self-modifying-agent.js.map +1 -1
  37. package/dist/tool-generation/gap-analyzer.d.ts +0 -1
  38. package/dist/tool-generation/gap-analyzer.d.ts.map +1 -1
  39. package/dist/tool-generation/gap-analyzer.js +14 -14
  40. package/dist/tool-generation/gap-analyzer.js.map +1 -1
  41. package/dist/tool-generation/index.d.ts +3 -3
  42. package/dist/tool-generation/index.d.ts.map +1 -1
  43. package/dist/tool-generation/index.js +2 -2
  44. package/dist/tool-generation/index.js.map +1 -1
  45. package/dist/tool-generation/prompts.d.ts +1 -0
  46. package/dist/tool-generation/prompts.d.ts.map +1 -1
  47. package/dist/tool-generation/prompts.js +33 -8
  48. package/dist/tool-generation/prompts.js.map +1 -1
  49. package/dist/tool-generation/tool-generator.d.ts +5 -5
  50. package/dist/tool-generation/tool-generator.d.ts.map +1 -1
  51. package/dist/tool-generation/tool-generator.js +41 -28
  52. package/dist/tool-generation/tool-generator.js.map +1 -1
  53. package/dist/tool-generation/tool-sandbox.d.ts +9 -6
  54. package/dist/tool-generation/tool-sandbox.d.ts.map +1 -1
  55. package/dist/tool-generation/tool-sandbox.js +257 -157
  56. package/dist/tool-generation/tool-sandbox.js.map +1 -1
  57. package/dist/tool-generation/tool-validator.d.ts +3 -8
  58. package/dist/tool-generation/tool-validator.d.ts.map +1 -1
  59. package/dist/tool-generation/tool-validator.js +53 -54
  60. package/dist/tool-generation/tool-validator.js.map +1 -1
  61. package/dist/utils/llm-helper.d.ts.map +1 -1
  62. package/dist/utils/llm-helper.js +1 -0
  63. package/dist/utils/llm-helper.js.map +1 -1
  64. package/package.json +3 -12
  65. package/src/__tests__/component-regressions.test.ts +599 -0
  66. package/src/__tests__/meta-reasoning.test.ts +5 -1
  67. package/src/__tests__/sandbox-security.test.ts +186 -0
  68. package/src/__tests__/self-modifying-agent.test.ts +363 -1
  69. package/src/architecture-evolution/capability-analyzer.ts +56 -40
  70. package/src/architecture-evolution/index.ts +2 -0
  71. package/src/architecture-evolution/parameter-optimizer.ts +52 -34
  72. package/src/architecture-evolution/prompts.ts +179 -41
  73. package/src/constraints/modification-validator.ts +30 -14
  74. package/src/index.ts +14 -0
  75. package/src/meta-reasoning/meta-reasoner.ts +105 -40
  76. package/src/meta-reasoning/prompts.ts +129 -15
  77. package/src/self-modifying-agent.ts +764 -489
  78. package/src/tool-generation/gap-analyzer.ts +19 -18
  79. package/src/tool-generation/index.ts +13 -3
  80. package/src/tool-generation/prompts.ts +41 -8
  81. package/src/tool-generation/tool-generator.ts +59 -33
  82. package/src/tool-generation/tool-sandbox.ts +306 -175
  83. package/src/tool-generation/tool-validator.ts +66 -63
  84. package/src/utils/llm-helper.ts +1 -0
@@ -3,26 +3,41 @@ import type {
3
3
  Agent,
4
4
  AgentConfig,
5
5
  Tool,
6
+ ToolCall,
7
+ ToolCallMessage,
6
8
  LLMBackend,
9
+ ChatResponse,
7
10
  SelfModifyingConfig,
11
+ ToolSelfGenerationConfig,
12
+ ToolSandboxConfig,
13
+ MetaReasoningConfig,
14
+ ArchitectureEvolutionConfig,
15
+ ModificationConstraintsConfig,
16
+ ModificationConstraints,
8
17
  ArchitectureConfig,
9
18
  GeneratedTool,
10
19
  MetaObservation,
20
+ MetaAssessment,
11
21
  MetaAdaptation,
22
+ MetaTrigger,
12
23
  ModificationCheckpoint,
13
24
  AppliedModification,
14
25
  ModificationRequest,
15
26
  SelfModifyingEvent,
27
+ SelfModifyingEventType,
16
28
  CapabilityGap,
29
+ EvolutionMetrics,
30
+ ReasoningMode,
17
31
  Message,
18
32
  ToolSchema,
19
33
  ToolContext,
20
34
  } from '@cogitator-ai/types';
35
+ import { DEFAULT_META_REASONING_CONFIG } from '@cogitator-ai/types';
21
36
 
22
37
  import { SelfModifyingEventEmitter } from './events';
23
38
  import { GapAnalyzer, ToolGenerator, InMemoryGeneratedToolStore } from './tool-generation';
24
39
  import { MetaReasoner } from './meta-reasoning';
25
- import { ParameterOptimizer, CapabilityAnalyzer } from './architecture-evolution';
40
+ import { ParameterOptimizer, type OptimizationResult } from './architecture-evolution';
26
41
  import {
27
42
  ModificationValidator,
28
43
  RollbackManager,
@@ -31,12 +46,63 @@ import {
31
46
  DEFAULT_RESOURCE_CONSTRAINTS,
32
47
  } from './constraints';
33
48
 
49
+ export interface SelfModifyingAgentConfig {
50
+ enabled?: boolean;
51
+ toolGeneration?: Partial<Omit<ToolSelfGenerationConfig, 'sandboxConfig'>> & {
52
+ sandboxConfig?: Partial<ToolSandboxConfig>;
53
+ };
54
+ metaReasoning?: Partial<MetaReasoningConfig>;
55
+ architectureEvolution?: Partial<ArchitectureEvolutionConfig>;
56
+ constraints?: Partial<ModificationConstraintsConfig>;
57
+ }
58
+
34
59
  export interface SelfModifyingAgentOptions {
35
60
  agent: Agent;
36
61
  llm: LLMBackend;
37
- config?: Partial<SelfModifyingConfig>;
62
+ config?: SelfModifyingAgentConfig;
63
+ /** Additional or overriding constraint sets used to validate every self-modification. */
64
+ modificationConstraints?: Partial<ModificationConstraints>;
65
+ /** Models architecture evolution may switch to. Model changes are never proposed when empty. */
66
+ availableModels?: string[];
67
+ }
68
+
69
+ export interface SelfModifyingEventDataMap {
70
+ run_started: { input: string };
71
+ run_completed: {
72
+ success: boolean;
73
+ toolsGenerated?: number;
74
+ adaptationsMade?: number;
75
+ error?: string;
76
+ };
77
+ tool_generation_started: { gap: CapabilityGap };
78
+ tool_generation_completed: {
79
+ toolId: string;
80
+ name: string;
81
+ success: boolean;
82
+ iterations?: number;
83
+ error?: string;
84
+ };
85
+ meta_assessment: { observation: MetaObservation; assessment: MetaAssessment };
86
+ strategy_changed: { previousMode: ReasoningMode; newMode: ReasoningMode; reason: string };
87
+ architecture_evolved: {
88
+ success: boolean;
89
+ candidateId?: string;
90
+ changes?: ArchitectureConfig;
91
+ metrics?: EvolutionMetrics;
92
+ error?: string;
93
+ };
94
+ checkpoint_created: { checkpointId: string };
95
+ rollback_performed: { checkpointId: string; reason: string };
38
96
  }
39
97
 
98
+ export type TypedSelfModifyingEvent<K extends SelfModifyingEventType> = Omit<
99
+ SelfModifyingEvent,
100
+ 'type' | 'data'
101
+ > & {
102
+ type: K;
103
+ data: SelfModifyingEventDataMap[K];
104
+ };
105
+
40
106
  export interface RunContext {
41
107
  runId: string;
42
108
  input: string;
@@ -49,34 +115,73 @@ export interface RunContext {
49
115
  checkpoints: ModificationCheckpoint[];
50
116
  modificationsCount: number;
51
117
  appliedModifications: AppliedModification[];
118
+ tokensUsed: number;
52
119
  }
53
120
 
121
+ interface StepOptions {
122
+ temperature: number;
123
+ contextAdditions: string[];
124
+ }
125
+
126
+ interface StepResult {
127
+ content: string;
128
+ finishReason: ChatResponse['finishReason'];
129
+ tokensUsed: number;
130
+ toolCalls: number;
131
+ toolErrors: number;
132
+ complete: boolean;
133
+ }
134
+
135
+ interface ExecutionResult {
136
+ output: string;
137
+ confidence: number;
138
+ }
139
+
140
+ interface ToolCallOutcome {
141
+ call: ToolCall;
142
+ content: string;
143
+ failed: boolean;
144
+ }
145
+
146
+ const DEFAULT_TOOL_TIMEOUT_MS = 30_000;
147
+
148
+ function resolveModelName(model: string | undefined, provider: string): string {
149
+ if (!model) return 'default';
150
+ const prefix = `${provider}/`;
151
+ return model.startsWith(prefix) ? model.slice(prefix.length) : model;
152
+ }
153
+ const DEFAULT_MAX_TOOL_ROUNDS = 10;
154
+
54
155
  export class SelfModifyingAgent {
55
156
  private readonly agent: Agent;
56
157
  private readonly llm: LLMBackend;
158
+ private readonly modelName: string;
57
159
  private readonly config: SelfModifyingConfig;
58
160
  private readonly emitter = new SelfModifyingEventEmitter();
161
+ private readonly listenerWrappers = new Map<
162
+ SelfModifyingEventType,
163
+ Map<(event: never) => void, (event: SelfModifyingEvent) => void>
164
+ >();
59
165
 
60
166
  private readonly gapAnalyzer: GapAnalyzer;
61
167
  private readonly toolGenerator: ToolGenerator;
62
168
  private readonly toolStore: InMemoryGeneratedToolStore;
63
169
  private readonly metaReasoner: MetaReasoner;
64
170
  private readonly parameterOptimizer: ParameterOptimizer;
65
- private readonly capabilityAnalyzer: CapabilityAnalyzer;
66
171
  private readonly modificationValidator: ModificationValidator;
67
172
  private readonly rollbackManager: RollbackManager;
68
173
 
69
174
  private currentContext: RunContext | null = null;
70
- private isInitialized = false;
71
- private storedExecutableTools: Tool[] = [];
175
+ private runQueue: Promise<unknown> = Promise.resolve();
72
176
 
73
177
  constructor(options: SelfModifyingAgentOptions) {
74
178
  this.agent = options.agent;
75
179
  this.llm = options.llm;
180
+ this.modelName = resolveModelName(options.agent.model, options.llm.provider);
76
181
  this.config = this.mergeConfig(options.config);
77
182
 
78
183
  const toolGenConfig = this.config.toolGeneration;
79
- const agentModel = this.agent.model;
184
+ const agentModel = this.modelName;
80
185
  this.gapAnalyzer = new GapAnalyzer({ llm: this.llm, config: toolGenConfig, model: agentModel });
81
186
  this.toolGenerator = new ToolGenerator({
82
187
  llm: this.llm,
@@ -87,36 +192,30 @@ export class SelfModifyingAgent {
87
192
 
88
193
  this.metaReasoner = new MetaReasoner({
89
194
  llm: this.llm,
90
- model: agentModel ?? 'default',
195
+ model: agentModel,
91
196
  config: this.config.metaReasoning,
92
197
  });
93
198
 
94
- const baseArchConfig: ArchitectureConfig = {
95
- model: agentModel ?? 'default',
96
- temperature: 0.7,
97
- maxTokens: 4096,
98
- toolStrategy: 'sequential',
99
- reflectionDepth: 1,
100
- };
101
-
102
199
  this.parameterOptimizer = new ParameterOptimizer({
103
200
  llm: this.llm,
104
201
  config: this.config.architectureEvolution,
105
- baseConfig: baseArchConfig,
106
- model: agentModel,
107
- });
108
-
109
- this.capabilityAnalyzer = new CapabilityAnalyzer({
110
- llm: this.llm,
111
- enableLLMAnalysis: true,
202
+ baseConfig: this.createBaseArchitectureConfig(),
112
203
  model: agentModel,
204
+ availableModels: options.availableModels,
113
205
  });
114
206
 
115
207
  this.modificationValidator = new ModificationValidator({
116
208
  constraints: {
117
- safety: DEFAULT_SAFETY_CONSTRAINTS,
118
- capability: DEFAULT_CAPABILITY_CONSTRAINTS,
119
- resource: DEFAULT_RESOURCE_CONSTRAINTS,
209
+ safety: [...DEFAULT_SAFETY_CONSTRAINTS, ...(options.modificationConstraints?.safety ?? [])],
210
+ capability: [
211
+ ...DEFAULT_CAPABILITY_CONSTRAINTS,
212
+ ...(options.modificationConstraints?.capability ?? []),
213
+ ],
214
+ resource: [
215
+ ...DEFAULT_RESOURCE_CONSTRAINTS,
216
+ ...(options.modificationConstraints?.resource ?? []),
217
+ ],
218
+ custom: options.modificationConstraints?.custom,
120
219
  },
121
220
  });
122
221
 
@@ -125,120 +224,204 @@ export class SelfModifyingAgent {
125
224
  });
126
225
  }
127
226
 
128
- on<K extends SelfModifyingEvent['type']>(
227
+ on<K extends SelfModifyingEventType>(
129
228
  event: K,
130
- handler: (event: Extract<SelfModifyingEvent, { type: K }>) => void
131
- ): void {
132
- this.emitter.on(event, handler as (event: SelfModifyingEvent) => void);
229
+ handler: (event: TypedSelfModifyingEvent<K>) => void
230
+ ): () => void {
231
+ let wrappers = this.listenerWrappers.get(event);
232
+ if (!wrappers) {
233
+ wrappers = new Map();
234
+ this.listenerWrappers.set(event, wrappers);
235
+ }
236
+ const existing = wrappers.get(handler);
237
+ if (existing) this.emitter.off(event, existing);
238
+
239
+ const wrapped = (e: SelfModifyingEvent) => handler(e as TypedSelfModifyingEvent<K>);
240
+ wrappers.set(handler, wrapped);
241
+ this.emitter.on(event, wrapped);
242
+ return () => this.off(event, handler);
133
243
  }
134
244
 
135
- off<K extends SelfModifyingEvent['type']>(
245
+ off<K extends SelfModifyingEventType>(
136
246
  event: K,
137
- handler: (event: Extract<SelfModifyingEvent, { type: K }>) => void
247
+ handler: (event: TypedSelfModifyingEvent<K>) => void
138
248
  ): void {
139
- this.emitter.off(event, handler as (event: SelfModifyingEvent) => void);
249
+ const wrappers = this.listenerWrappers.get(event);
250
+ const wrapped = wrappers?.get(handler);
251
+ if (!wrappers || !wrapped) return;
252
+ this.emitter.off(event, wrapped);
253
+ wrappers.delete(handler);
140
254
  }
141
255
 
142
- async run(input: string): Promise<{
256
+ run(input: string): Promise<{
143
257
  output: string;
144
258
  toolsGenerated: GeneratedTool[];
145
259
  adaptationsMade: MetaAdaptation[];
146
260
  finalConfig: ArchitectureConfig;
147
261
  }> {
148
- await this.ensureInitialized();
262
+ const result = this.runQueue.then(() => this.executeRun(input));
263
+ this.runQueue = result.catch(() => undefined);
264
+ return result;
265
+ }
149
266
 
150
- const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
151
- const tools = this.getAvailableTools();
267
+ async generateTool(gap: CapabilityGap): Promise<GeneratedTool | null> {
268
+ if (!this.config.toolGeneration.enabled) {
269
+ return null;
270
+ }
152
271
 
153
- const baseConfig: ArchitectureConfig = {
154
- model: this.agent.model ?? 'default',
155
- temperature: 0.7,
156
- maxTokens: 4096,
157
- toolStrategy: 'sequential',
158
- reflectionDepth: 1,
272
+ return this.generateAndRegisterTool(gap, this.currentContext?.tools ?? this.getAgentTools());
273
+ }
274
+
275
+ async recordToolUsage(toolId: string, success: boolean, executionTime: number): Promise<void> {
276
+ await this.toolStore.recordUsage({
277
+ toolId,
278
+ timestamp: new Date(),
279
+ success,
280
+ executionTime,
281
+ });
282
+ }
283
+
284
+ getGeneratedTools(): Promise<GeneratedTool[]> {
285
+ return this.toolStore.list({ status: 'active' });
286
+ }
287
+
288
+ async createCheckpoint(): Promise<ModificationCheckpoint | null> {
289
+ const ctx = this.currentContext;
290
+ if (!ctx) return null;
291
+
292
+ const agentConfig: AgentConfig = {
293
+ name: this.agent.name || 'agent',
294
+ model: ctx.currentConfig.model,
295
+ instructions: this.agent.instructions || '',
296
+ temperature: ctx.currentConfig.temperature,
297
+ maxTokens: ctx.currentConfig.maxTokens,
159
298
  };
160
299
 
161
- this.currentContext = {
300
+ const checkpoint = await this.rollbackManager.createCheckpoint(
301
+ this.agent.name || 'agent',
302
+ agentConfig,
303
+ ctx.tools,
304
+ [...ctx.appliedModifications]
305
+ );
306
+
307
+ ctx.checkpoints.push(checkpoint);
308
+ this.emit('checkpoint_created', ctx.runId, { checkpointId: checkpoint.id });
309
+
310
+ return checkpoint;
311
+ }
312
+
313
+ async rollbackToCheckpoint(checkpointId: string, reason = 'Manual rollback'): Promise<boolean> {
314
+ const checkpoint = await this.rollbackManager.getCheckpoint(checkpointId);
315
+ const restored = await this.rollbackManager.rollbackTo(checkpointId);
316
+ if (!checkpoint || !restored) return false;
317
+
318
+ const ctx = this.currentContext;
319
+ if (ctx) {
320
+ ctx.tools = restored.tools;
321
+ ctx.currentConfig = {
322
+ ...ctx.currentConfig,
323
+ model: restored.agentConfig.model ?? ctx.currentConfig.model,
324
+ temperature: restored.agentConfig.temperature ?? ctx.currentConfig.temperature,
325
+ maxTokens: restored.agentConfig.maxTokens ?? ctx.currentConfig.maxTokens,
326
+ };
327
+ ctx.appliedModifications = [...checkpoint.modifications];
328
+
329
+ const restoredNames = new Set(restored.tools.map((t) => t.name));
330
+ const discarded = ctx.generatedTools.filter((t) => !restoredNames.has(t.name));
331
+ for (const tool of discarded) {
332
+ await this.toolStore.deprecate(tool.id, `Rolled back to checkpoint ${checkpointId}`);
333
+ }
334
+ ctx.generatedTools = ctx.generatedTools.filter((t) => restoredNames.has(t.name));
335
+ }
336
+
337
+ this.emit('rollback_performed', ctx?.runId ?? 'manual', { checkpointId, reason });
338
+
339
+ return true;
340
+ }
341
+
342
+ private async executeRun(input: string): Promise<{
343
+ output: string;
344
+ toolsGenerated: GeneratedTool[];
345
+ adaptationsMade: MetaAdaptation[];
346
+ finalConfig: ArchitectureConfig;
347
+ }> {
348
+ const runId = `run_${nanoid(12)}`;
349
+ const selfModification = this.config.enabled;
350
+ const tools = selfModification ? await this.loadAvailableTools() : this.getAgentTools();
351
+
352
+ const ctx: RunContext = {
162
353
  runId,
163
354
  input,
164
355
  startTime: Date.now(),
165
- tools: [...tools],
166
- currentConfig: baseConfig,
356
+ tools,
357
+ currentConfig: this.createBaseArchitectureConfig(),
167
358
  generatedTools: [],
168
359
  observations: [],
169
360
  adaptations: [],
170
361
  checkpoints: [],
171
362
  modificationsCount: 0,
172
363
  appliedModifications: [],
364
+ tokensUsed: 0,
173
365
  };
366
+ this.currentContext = ctx;
174
367
 
175
- void this.emitter.emit({
176
- type: 'run_started',
177
- runId,
178
- timestamp: new Date(),
179
- data: { input },
180
- });
368
+ this.emit('run_started', runId, { input });
369
+
370
+ let optimization: { result: OptimizationResult; candidateId: string } | null = null;
181
371
 
182
372
  try {
183
- if (this.config.constraints.enabled && this.config.constraints.autoRollback) {
373
+ if (
374
+ selfModification &&
375
+ this.config.constraints.enabled &&
376
+ this.config.constraints.autoRollback
377
+ ) {
184
378
  await this.createCheckpoint();
185
379
  }
186
380
 
187
- if (this.config.architectureEvolution.enabled) {
188
- await this.optimizeArchitecture(input);
381
+ if (selfModification && this.config.architectureEvolution.enabled) {
382
+ optimization = await this.optimizeArchitecture(ctx);
189
383
  }
190
384
 
191
- if (this.config.toolGeneration.enabled && this.config.toolGeneration.autoGenerate) {
192
- await this.analyzeAndGenerateTools(input);
385
+ if (
386
+ selfModification &&
387
+ this.config.toolGeneration.enabled &&
388
+ this.config.toolGeneration.autoGenerate
389
+ ) {
390
+ await this.analyzeAndGenerateTools(ctx);
193
391
  }
194
392
 
195
- const modeConfig = this.metaReasoner.initializeRun(runId);
196
-
197
- void this.emitter.emit({
198
- type: 'strategy_changed',
199
- runId,
200
- timestamp: new Date(),
201
- data: {
202
- previousMode: 'analytical',
203
- newMode: modeConfig.mode,
204
- reason: 'Initial mode selection',
205
- },
206
- });
393
+ const execution = await this.executeWithMetaReasoning(ctx, selfModification);
207
394
 
208
- const output = await this.executeWithMetaReasoning(input, runId);
395
+ await this.recordArchitectureOutcome(ctx, optimization, true, execution.confidence);
209
396
 
210
397
  const result = {
211
- output,
212
- toolsGenerated: [...this.currentContext.generatedTools],
213
- adaptationsMade: [...this.currentContext.adaptations],
214
- finalConfig: { ...this.currentContext.currentConfig },
398
+ output: execution.output,
399
+ toolsGenerated: [...ctx.generatedTools],
400
+ adaptationsMade: [...ctx.adaptations],
401
+ finalConfig: { ...ctx.currentConfig },
215
402
  };
216
403
 
217
- void this.emitter.emit({
218
- type: 'run_completed',
219
- runId,
220
- timestamp: new Date(),
221
- data: {
222
- success: true,
223
- toolsGenerated: result.toolsGenerated.length,
224
- adaptationsMade: result.adaptationsMade.length,
225
- },
404
+ this.emit('run_completed', runId, {
405
+ success: true,
406
+ toolsGenerated: result.toolsGenerated.length,
407
+ adaptationsMade: result.adaptationsMade.length,
226
408
  });
227
409
 
228
410
  return result;
229
411
  } catch (error) {
230
- if (this.config.constraints.enabled && this.config.constraints.autoRollback) {
231
- await this.autoRollbackOnError();
412
+ await this.recordArchitectureOutcome(ctx, optimization, false, 0).catch(() => undefined);
413
+
414
+ if (
415
+ selfModification &&
416
+ this.config.constraints.enabled &&
417
+ this.config.constraints.autoRollback
418
+ ) {
419
+ await this.autoRollback(ctx, 'Run failed');
232
420
  }
233
421
 
234
- void this.emitter.emit({
235
- type: 'run_completed',
236
- runId,
237
- timestamp: new Date(),
238
- data: {
239
- success: false,
240
- error: error instanceof Error ? error.message : String(error),
241
- },
422
+ this.emit('run_completed', runId, {
423
+ success: false,
424
+ error: error instanceof Error ? error.message : String(error),
242
425
  });
243
426
 
244
427
  throw error;
@@ -248,128 +431,31 @@ export class SelfModifyingAgent {
248
431
  }
249
432
  }
250
433
 
251
- async generateTool(gap: CapabilityGap): Promise<GeneratedTool | null> {
252
- if (!this.config.toolGeneration.enabled) {
253
- return null;
254
- }
255
-
256
- const tools = this.getAvailableTools();
257
- const result = await this.toolGenerator.generate(gap, tools);
258
-
259
- if (result.success && result.tool) {
260
- await this.toolStore.save(result.tool);
261
-
262
- void this.emitter.emit({
263
- type: 'tool_generation_completed',
264
- runId: this.currentContext?.runId || 'manual',
265
- timestamp: new Date(),
266
- data: {
267
- toolId: result.tool.id,
268
- name: result.tool.name,
269
- success: true,
270
- iterations: result.iterations,
271
- },
272
- });
273
-
274
- return result.tool;
275
- }
276
-
434
+ private emit<K extends SelfModifyingEventType>(
435
+ type: K,
436
+ runId: string,
437
+ data: SelfModifyingEventDataMap[K]
438
+ ): void {
277
439
  void this.emitter.emit({
278
- type: 'tool_generation_completed',
279
- runId: this.currentContext?.runId || 'manual',
280
- timestamp: new Date(),
281
- data: {
282
- toolId: '',
283
- name: gap.suggestedToolName,
284
- success: false,
285
- error: result.error,
286
- },
287
- });
288
-
289
- return null;
290
- }
291
-
292
- async recordToolUsage(toolId: string, success: boolean, executionTime: number): Promise<void> {
293
- await this.toolStore.recordUsage({
294
- toolId,
440
+ type,
441
+ runId,
442
+ agentId: this.agent.id,
295
443
  timestamp: new Date(),
296
- success,
297
- executionTime,
444
+ data,
298
445
  });
299
446
  }
300
447
 
301
- getGeneratedTools(): Promise<GeneratedTool[]> {
302
- return this.toolStore.list({ status: 'active' });
303
- }
304
-
305
- async createCheckpoint(): Promise<ModificationCheckpoint | null> {
306
- if (!this.currentContext) return null;
307
-
308
- const agentConfig: AgentConfig = {
309
- name: this.agent.name || 'agent',
310
- model: this.currentContext.currentConfig.model,
311
- instructions: this.agent.instructions || '',
312
- temperature: this.currentContext.currentConfig.temperature,
313
- maxTokens: this.currentContext.currentConfig.maxTokens,
448
+ private createBaseArchitectureConfig(): ArchitectureConfig {
449
+ return {
450
+ model: this.modelName,
451
+ temperature: this.agent.config?.temperature ?? 0.7,
452
+ maxTokens: this.agent.config?.maxTokens ?? 4096,
453
+ toolStrategy: 'sequential',
454
+ reflectionDepth: 0,
314
455
  };
315
-
316
- const checkpoint = await this.rollbackManager.createCheckpoint(
317
- this.agent.name || 'agent',
318
- agentConfig,
319
- this.currentContext.tools,
320
- [...this.currentContext.appliedModifications]
321
- );
322
-
323
- this.currentContext.checkpoints.push(checkpoint);
324
-
325
- void this.emitter.emit({
326
- type: 'checkpoint_created',
327
- runId: this.currentContext.runId,
328
- timestamp: new Date(),
329
- data: { checkpointId: checkpoint.id },
330
- });
331
-
332
- return checkpoint;
333
456
  }
334
457
 
335
- async rollbackToCheckpoint(checkpointId: string): Promise<boolean> {
336
- const restored = await this.rollbackManager.rollbackTo(checkpointId);
337
- if (!restored) return false;
338
-
339
- if (this.currentContext) {
340
- this.currentContext.tools = restored.tools;
341
- this.currentContext.currentConfig = {
342
- ...this.currentContext.currentConfig,
343
- model: restored.agentConfig.model ?? this.currentContext.currentConfig.model,
344
- temperature:
345
- restored.agentConfig.temperature ?? this.currentContext.currentConfig.temperature,
346
- maxTokens: restored.agentConfig.maxTokens ?? this.currentContext.currentConfig.maxTokens,
347
- };
348
- }
349
-
350
- void this.emitter.emit({
351
- type: 'rollback_performed',
352
- runId: this.currentContext?.runId || 'manual',
353
- timestamp: new Date(),
354
- data: {
355
- checkpointId,
356
- reason: 'Manual rollback',
357
- },
358
- });
359
-
360
- return true;
361
- }
362
-
363
- private async ensureInitialized(): Promise<void> {
364
- if (this.isInitialized) return;
365
-
366
- const activeTools = await this.toolStore.list({ status: 'active' });
367
- this.storedExecutableTools = activeTools.map((t) => this.toolGenerator.createExecutableTool(t));
368
-
369
- this.isInitialized = true;
370
- }
371
-
372
- private mergeConfig(partial?: Partial<SelfModifyingConfig>): SelfModifyingConfig {
458
+ private mergeConfig(partial?: SelfModifyingAgentConfig): SelfModifyingConfig {
373
459
  const defaults: SelfModifyingConfig = {
374
460
  enabled: true,
375
461
  toolGeneration: {
@@ -387,40 +473,7 @@ export class SelfModifyingAgent {
387
473
  isolationLevel: 'strict',
388
474
  },
389
475
  },
390
- metaReasoning: {
391
- enabled: true,
392
- defaultMode: 'analytical',
393
- allowedModes: [
394
- 'analytical',
395
- 'creative',
396
- 'systematic',
397
- 'intuitive',
398
- 'reflective',
399
- 'exploratory',
400
- ],
401
- modeProfiles: {
402
- analytical: { mode: 'analytical', temperature: 0.3, depth: 3 },
403
- creative: { mode: 'creative', temperature: 0.9, depth: 2 },
404
- systematic: { mode: 'systematic', temperature: 0.2, depth: 4 },
405
- intuitive: { mode: 'intuitive', temperature: 0.6, depth: 1 },
406
- reflective: { mode: 'reflective', temperature: 0.4, depth: 3 },
407
- exploratory: { mode: 'exploratory', temperature: 0.7, depth: 2 },
408
- },
409
- maxMetaAssessments: 5,
410
- maxAdaptations: 3,
411
- metaAssessmentCooldown: 10000,
412
- adaptationCooldown: 15000,
413
- triggers: ['on_failure', 'on_low_confidence', 'periodic'],
414
- triggerAfterIterations: 3,
415
- triggerOnConfidenceDrop: 0.3,
416
- triggerOnProgressStall: 2,
417
- tokenBudget: 2000,
418
- maxMetaTokens: 1000,
419
- minConfidenceToAdapt: 0.6,
420
- enableRollback: true,
421
- rollbackWindow: 30000,
422
- rollbackOnDecline: true,
423
- },
476
+ metaReasoning: { ...DEFAULT_META_REASONING_CONFIG },
424
477
  architectureEvolution: {
425
478
  enabled: true,
426
479
  strategy: { type: 'ucb', explorationConstant: 2 },
@@ -439,14 +492,20 @@ export class SelfModifyingAgent {
439
492
 
440
493
  if (!partial) return defaults;
441
494
 
495
+ const defaultSandbox = defaults.toolGeneration.sandboxConfig ?? {
496
+ enabled: true,
497
+ maxExecutionTime: 5000,
498
+ maxMemory: 50 * 1024 * 1024,
499
+ allowedModules: [],
500
+ isolationLevel: 'strict' as const,
501
+ };
502
+
442
503
  return {
443
504
  enabled: partial.enabled ?? defaults.enabled,
444
505
  toolGeneration: {
445
506
  ...defaults.toolGeneration,
446
507
  ...partial.toolGeneration,
447
- sandboxConfig: partial.toolGeneration?.sandboxConfig
448
- ? { ...defaults.toolGeneration.sandboxConfig, ...partial.toolGeneration.sandboxConfig }
449
- : defaults.toolGeneration.sandboxConfig,
508
+ sandboxConfig: { ...defaultSandbox, ...partial.toolGeneration?.sandboxConfig },
450
509
  },
451
510
  metaReasoning: {
452
511
  ...defaults.metaReasoning,
@@ -459,327 +518,557 @@ export class SelfModifyingAgent {
459
518
  architectureEvolution: {
460
519
  ...defaults.architectureEvolution,
461
520
  ...partial.architectureEvolution,
462
- strategy: partial.architectureEvolution?.strategy
463
- ? {
464
- ...defaults.architectureEvolution.strategy,
465
- ...partial.architectureEvolution.strategy,
466
- }
467
- : defaults.architectureEvolution.strategy,
521
+ strategy: {
522
+ ...defaults.architectureEvolution.strategy,
523
+ ...partial.architectureEvolution?.strategy,
524
+ },
468
525
  },
469
526
  constraints: { ...defaults.constraints, ...partial.constraints },
470
527
  };
471
528
  }
472
529
 
473
- private getAvailableTools(): Tool[] {
474
- return [...(this.agent.tools ?? []), ...this.storedExecutableTools];
530
+ private getAgentTools(): Tool[] {
531
+ return [...(this.agent.tools ?? [])];
475
532
  }
476
533
 
477
- private async optimizeArchitecture(input: string): Promise<void> {
478
- if (!this.currentContext) return;
534
+ private async loadAvailableTools(): Promise<Tool[]> {
535
+ const tools = this.getAgentTools();
536
+ const names = new Set(tools.map((t) => t.name));
537
+ const stored = await this.toolStore.list({ status: 'active' });
538
+
539
+ for (const generated of stored) {
540
+ if (names.has(generated.name)) continue;
541
+ names.add(generated.name);
542
+ tools.push(this.toolGenerator.createExecutableTool(generated));
543
+ }
544
+
545
+ return tools;
546
+ }
479
547
 
548
+ private async optimizeArchitecture(
549
+ ctx: RunContext
550
+ ): Promise<{ result: OptimizationResult; candidateId: string } | null> {
480
551
  try {
481
- const result = await this.parameterOptimizer.optimize(input);
482
-
483
- if (result.shouldAdopt && result.confidence > 0.6 && this.canApplyModification()) {
484
- const validation = await this.validateModification({
485
- type: 'config_change',
486
- target: 'architecture',
487
- changes: result.recommendedConfig,
488
- reason: result.reasoning,
489
- });
552
+ const result = await this.parameterOptimizer.optimize(ctx.input);
553
+ const candidate = result.candidate;
554
+ if (!candidate) return null;
490
555
 
491
- if (validation) {
492
- this.currentContext.currentConfig = result.recommendedConfig;
493
- this.recordModification('config_change', result.recommendedConfig);
494
-
495
- void this.emitter.emit({
496
- type: 'architecture_evolved',
497
- runId: this.currentContext.runId,
498
- timestamp: new Date(),
499
- data: {
500
- success: true,
501
- candidateId: result.candidate?.id,
502
- changes: result.recommendedConfig,
503
- metrics: result.metrics,
504
- },
505
- });
506
- }
556
+ const isNoop = Object.keys(candidate.config).length === 0;
557
+ if (isNoop) {
558
+ return { result, candidateId: candidate.id };
559
+ }
560
+
561
+ if (!result.shouldAdopt || !this.canApplyModification(ctx)) {
562
+ return { result, candidateId: 'baseline' };
563
+ }
564
+
565
+ const valid = await this.validateModification(ctx, {
566
+ type: 'config_change',
567
+ target: 'architecture',
568
+ changes: result.recommendedConfig,
569
+ reason: result.reasoning,
570
+ payload: { candidateId: candidate.id, changedKeys: Object.keys(candidate.config) },
571
+ });
572
+
573
+ if (!valid) {
574
+ return { result, candidateId: 'baseline' };
507
575
  }
576
+
577
+ ctx.currentConfig = { ...result.recommendedConfig };
578
+ this.recordModification(ctx, 'config_change', {
579
+ candidateId: candidate.id,
580
+ config: result.recommendedConfig,
581
+ });
582
+
583
+ this.emit('architecture_evolved', ctx.runId, {
584
+ success: true,
585
+ candidateId: candidate.id,
586
+ changes: result.recommendedConfig,
587
+ metrics: result.metrics,
588
+ });
589
+
590
+ return { result, candidateId: candidate.id };
508
591
  } catch (error) {
509
- void this.emitter.emit({
510
- type: 'architecture_evolved',
511
- runId: this.currentContext.runId,
512
- timestamp: new Date(),
513
- data: {
514
- success: false,
515
- error: error instanceof Error ? error.message : String(error),
516
- },
592
+ this.emit('architecture_evolved', ctx.runId, {
593
+ success: false,
594
+ error: error instanceof Error ? error.message : String(error),
517
595
  });
596
+ return null;
518
597
  }
519
598
  }
520
599
 
521
- private async analyzeAndGenerateTools(input: string): Promise<void> {
522
- if (!this.currentContext) return;
600
+ private async recordArchitectureOutcome(
601
+ ctx: RunContext,
602
+ optimization: { result: OptimizationResult; candidateId: string } | null,
603
+ success: boolean,
604
+ quality: number
605
+ ): Promise<void> {
606
+ if (!optimization) return;
607
+
608
+ await this.parameterOptimizer.recordOutcome(
609
+ optimization.candidateId,
610
+ optimization.result.taskProfile,
611
+ {
612
+ successRate: success ? 1 : 0,
613
+ latency: Date.now() - ctx.startTime,
614
+ tokenUsage: ctx.tokensUsed,
615
+ qualityScore: quality,
616
+ }
617
+ );
618
+ }
523
619
 
620
+ private async analyzeAndGenerateTools(ctx: RunContext): Promise<void> {
524
621
  try {
525
- const analysis = await this.gapAnalyzer.analyze(input, this.currentContext.tools);
622
+ const analysis = await this.gapAnalyzer.analyze(ctx.input, ctx.tools);
526
623
 
527
624
  for (const gap of analysis.gaps) {
528
- if (
529
- this.currentContext.generatedTools.length >= this.config.toolGeneration.maxToolsPerSession
530
- ) {
531
- break;
532
- }
625
+ if (ctx.generatedTools.length >= this.config.toolGeneration.maxToolsPerSession) break;
626
+ if (!this.canApplyModification(ctx)) break;
627
+ if (gap.confidence < this.config.toolGeneration.minConfidenceForGeneration) continue;
533
628
 
534
- if (gap.confidence >= this.config.toolGeneration.minConfidenceForGeneration) {
535
- void this.emitter.emit({
536
- type: 'tool_generation_started',
537
- runId: this.currentContext.runId,
538
- timestamp: new Date(),
539
- data: { gap },
540
- });
541
-
542
- const tool = await this.generateTool(gap);
543
-
544
- if (!tool) continue;
545
-
546
- const linesOfCode = tool.implementation.split('\n').length;
547
- const validated = await this.validateModification({
548
- type: 'tool_generation',
549
- target: tool.name,
550
- changes: { name: tool.name, implementation: tool.implementation },
551
- reason: `Generated tool for gap: ${gap.suggestedToolName}`,
552
- payload: {
553
- sandboxExecution: this.config.toolGeneration.sandboxConfig?.enabled ?? false,
554
- linesOfCode,
555
- complexity: linesOfCode,
556
- modificationDepth: 1,
557
- },
558
- });
559
-
560
- if (!validated || !this.canApplyModification()) {
561
- void this.emitter.emit({
562
- type: 'tool_generation_completed',
563
- runId: this.currentContext.runId,
564
- timestamp: new Date(),
565
- data: {
566
- toolId: tool.id,
567
- name: tool.name,
568
- success: false,
569
- error: 'Rejected by safety constraints or modification limit',
570
- },
571
- });
572
- continue;
573
- }
629
+ const tool = await this.generateAndRegisterTool(gap, ctx.tools);
630
+ if (!tool) continue;
574
631
 
575
- this.currentContext.generatedTools.push(tool);
576
- const executableTool = this.toolGenerator.createExecutableTool(tool);
577
- this.currentContext.tools.push(executableTool);
578
- this.recordModification('tool_generation', { toolId: tool.id, name: tool.name });
579
- }
632
+ ctx.generatedTools.push(tool);
633
+ ctx.tools.push(this.toolGenerator.createExecutableTool(tool));
634
+ this.recordModification(ctx, 'tool_generation', { toolId: tool.id, name: tool.name });
580
635
  }
581
636
  } catch (error) {
582
- void this.emitter.emit({
583
- type: 'tool_generation_completed',
584
- runId: this.currentContext.runId,
585
- timestamp: new Date(),
586
- data: {
587
- toolId: '',
588
- name: '',
589
- success: false,
590
- error: error instanceof Error ? error.message : String(error),
591
- },
637
+ this.emit('tool_generation_completed', ctx.runId, {
638
+ toolId: '',
639
+ name: '',
640
+ success: false,
641
+ error: error instanceof Error ? error.message : String(error),
642
+ });
643
+ }
644
+ }
645
+
646
+ private async generateAndRegisterTool(
647
+ gap: CapabilityGap,
648
+ existingTools: Tool[]
649
+ ): Promise<GeneratedTool | null> {
650
+ const ctx = this.currentContext;
651
+ const runId = ctx?.runId ?? 'manual';
652
+
653
+ this.emit('tool_generation_started', runId, { gap });
654
+
655
+ const result = await this.toolGenerator.generate(gap, existingTools);
656
+ const generated = result.tool;
657
+
658
+ if (!result.success || !generated) {
659
+ this.emit('tool_generation_completed', runId, {
660
+ toolId: generated?.id ?? '',
661
+ name: generated?.name ?? gap.suggestedToolName,
662
+ success: false,
663
+ iterations: result.iterations,
664
+ error: result.error,
665
+ });
666
+ return null;
667
+ }
668
+
669
+ const rejection = await this.checkGeneratedTool(generated, existingTools);
670
+ if (rejection) {
671
+ this.emit('tool_generation_completed', runId, {
672
+ toolId: generated.id,
673
+ name: generated.name,
674
+ success: false,
675
+ iterations: result.iterations,
676
+ error: rejection,
592
677
  });
678
+ return null;
679
+ }
680
+
681
+ const activeTool: GeneratedTool = { ...generated, status: 'active' };
682
+ await this.toolStore.save(activeTool);
683
+ const saved = (await this.toolStore.get(activeTool.id)) ?? activeTool;
684
+
685
+ this.emit('tool_generation_completed', runId, {
686
+ toolId: saved.id,
687
+ name: saved.name,
688
+ success: true,
689
+ iterations: result.iterations,
690
+ });
691
+
692
+ return saved;
693
+ }
694
+
695
+ private async checkGeneratedTool(
696
+ tool: GeneratedTool,
697
+ existingTools: Tool[]
698
+ ): Promise<string | null> {
699
+ if (existingTools.some((t) => t.name === tool.name)) {
700
+ return `A tool named "${tool.name}" already exists`;
593
701
  }
702
+
703
+ const linesOfCode = tool.implementation.split('\n').length;
704
+ const valid = await this.validateModification(this.currentContext, {
705
+ type: 'tool_generation',
706
+ target: tool.name,
707
+ changes: { name: tool.name, implementation: tool.implementation },
708
+ reason: `Generated tool for capability gap: ${tool.name}`,
709
+ payload: {
710
+ sandboxExecution: this.config.toolGeneration.sandboxConfig?.enabled ?? false,
711
+ linesOfCode,
712
+ complexity: linesOfCode,
713
+ modificationDepth: 1,
714
+ },
715
+ });
716
+
717
+ return valid ? null : 'Rejected by modification constraints';
594
718
  }
595
719
 
596
- private async executeWithMetaReasoning(input: string, runId: string): Promise<string> {
597
- if (!this.currentContext) {
598
- throw new Error('No active run context');
720
+ private async executeWithMetaReasoning(
721
+ ctx: RunContext,
722
+ selfModification: boolean
723
+ ): Promise<ExecutionResult> {
724
+ const runId = ctx.runId;
725
+ const metaEnabled = selfModification && this.config.metaReasoning.enabled;
726
+ const maxAttempts = metaEnabled ? Math.max(1, this.config.metaReasoning.maxAdaptations + 1) : 1;
727
+ const contextAdditions: string[] = [];
728
+ let modeAdapted = false;
729
+ let pendingAdaptation: { adaptation: MetaAdaptation; confidence: number } | null = null;
730
+
731
+ if (metaEnabled) {
732
+ const modeConfig = this.metaReasoner.initializeRun(runId);
733
+ this.emit('strategy_changed', runId, {
734
+ previousMode: this.config.metaReasoning.defaultMode,
735
+ newMode: modeConfig.mode,
736
+ reason: 'Initial mode selection',
737
+ });
599
738
  }
600
739
 
601
- let output = '';
602
- let iteration = 0;
603
- const maxIterations = 10;
740
+ let step: StepResult | null = null;
741
+ let confidence = 0;
742
+
743
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
744
+ const temperature = modeAdapted
745
+ ? this.metaReasoner.getCurrentConfig(runId).temperature
746
+ : ctx.currentConfig.temperature;
747
+
748
+ step = await this.executeAgentStep(ctx, { temperature, contextAdditions });
749
+ ctx.tokensUsed += step.tokensUsed;
750
+ confidence = this.stepConfidence(step);
751
+
752
+ if (!metaEnabled) break;
604
753
 
605
- while (iteration < maxIterations) {
606
- iteration++;
754
+ this.metaReasoner.recordConfidence(runId, confidence);
755
+
756
+ if (pendingAdaptation) {
757
+ this.metaReasoner.recordOutcome(runId, pendingAdaptation.adaptation.id, {
758
+ improved: step.complete || confidence > pendingAdaptation.confidence,
759
+ progressDelta: step.complete ? 1 : 0,
760
+ confidenceDelta: confidence - pendingAdaptation.confidence,
761
+ });
762
+ pendingAdaptation = null;
763
+ }
764
+
765
+ if (step.complete || attempt === maxAttempts) break;
607
766
 
608
- const currentMode = this.metaReasoner.getCurrentMode(runId);
609
767
  const observation = this.metaReasoner.observe(
610
768
  {
611
769
  runId,
612
- iteration,
613
- goal: input,
614
- currentMode,
615
- tokensUsed: Math.round(output.length * 1.3),
616
- timeElapsed: Date.now() - this.currentContext.startTime,
617
- iterationsRemaining: maxIterations - iteration,
618
- budgetRemaining: 10000 - Math.round(output.length * 1.3),
770
+ iteration: attempt,
771
+ goal: ctx.input,
772
+ currentMode: this.metaReasoner.getCurrentMode(runId),
773
+ tokensUsed: ctx.tokensUsed,
774
+ timeElapsed: Date.now() - ctx.startTime,
775
+ iterationsRemaining: maxAttempts - attempt,
776
+ budgetRemaining: (maxAttempts - attempt) / maxAttempts,
619
777
  },
620
778
  []
621
779
  );
780
+ ctx.observations.push(observation);
622
781
 
623
- this.currentContext.observations.push(observation);
782
+ if (!this.selectTrigger(runId, attempt, confidence, observation)) continue;
624
783
 
625
- if (
626
- this.metaReasoner.shouldTrigger(runId, 'periodic', {
627
- iteration,
628
- confidence: this.estimateConfidence(output),
629
- progressDelta: output.length > 0 ? 0.1 : 0,
630
- stagnationCount: 0,
631
- })
632
- ) {
633
- const assessment = await this.metaReasoner.assess(observation);
784
+ const assessment = await this.metaReasoner.assess(observation);
785
+ this.emit('meta_assessment', runId, { observation, assessment });
634
786
 
635
- void this.emitter.emit({
636
- type: 'meta_assessment',
637
- runId,
638
- timestamp: new Date(),
639
- data: {
640
- observation,
641
- assessment,
642
- },
643
- });
787
+ if (!assessment.requiresAdaptation) continue;
788
+ if (assessment.recommendation.action === 'abort') break;
644
789
 
645
- if (assessment.requiresAdaptation) {
646
- const adaptation = await this.metaReasoner.adapt(runId, assessment);
647
-
648
- if (adaptation) {
649
- this.currentContext.adaptations.push(adaptation);
650
-
651
- void this.emitter.emit({
652
- type: 'strategy_changed',
653
- runId,
654
- timestamp: new Date(),
655
- data: {
656
- previousMode: adaptation.before?.mode || 'analytical',
657
- newMode: adaptation.after?.mode || 'analytical',
658
- reason: adaptation.type,
659
- },
660
- });
661
- }
662
- }
663
- }
790
+ const adaptation = await this.metaReasoner.adapt(runId, assessment);
791
+ if (!adaptation) continue;
664
792
 
665
- output = await this.executeAgentStep(input);
793
+ ctx.adaptations.push(adaptation);
794
+ pendingAdaptation = { adaptation, confidence };
666
795
 
667
- if (this.isTaskComplete(output)) {
668
- break;
796
+ if (adaptation.type === 'context_injection' && assessment.recommendation.contextAddition) {
797
+ contextAdditions.push(assessment.recommendation.contextAddition);
798
+ } else {
799
+ modeAdapted = true;
669
800
  }
801
+
802
+ this.emit('strategy_changed', runId, {
803
+ previousMode: adaptation.previousMode ?? this.metaReasoner.getCurrentMode(runId),
804
+ newMode: adaptation.newMode ?? this.metaReasoner.getCurrentMode(runId),
805
+ reason: adaptation.reason ?? adaptation.type,
806
+ });
670
807
  }
671
808
 
672
- return output;
809
+ return { output: step?.content ?? '', confidence };
673
810
  }
674
811
 
675
- private async executeAgentStep(input: string): Promise<string> {
676
- const tools = this.currentContext?.tools ?? [];
677
- const toolSchemas = this.buildToolSchemas(tools);
678
- const toolMap = new Map<string, Tool>();
679
- for (const t of tools) {
680
- toolMap.set(t.name, t);
812
+ private selectTrigger(
813
+ runId: string,
814
+ iteration: number,
815
+ confidence: number,
816
+ observation: MetaObservation
817
+ ): MetaTrigger | null {
818
+ const context = {
819
+ iteration,
820
+ confidence,
821
+ progressDelta: observation.progressDelta,
822
+ stagnationCount: observation.stagnationCount,
823
+ };
824
+ const candidates: MetaTrigger[] = [
825
+ 'on_failure',
826
+ 'on_low_confidence',
827
+ 'on_stagnation',
828
+ 'iteration_complete',
829
+ 'periodic',
830
+ ];
831
+ return candidates.find((t) => this.metaReasoner.shouldTrigger(runId, t, context)) ?? null;
832
+ }
833
+
834
+ private async executeAgentStep(ctx: RunContext, options: StepOptions): Promise<StepResult> {
835
+ const toolMap = new Map<string, Tool>(ctx.tools.map((t) => [t.name, t]));
836
+ const toolSchemas = this.buildToolSchemas(ctx.tools);
837
+ const generatedIds = new Map(ctx.generatedTools.map((t) => [t.name, t.id]));
838
+ for (const stored of await this.toolStore.list({ status: 'active' })) {
839
+ if (!generatedIds.has(stored.name)) generatedIds.set(stored.name, stored.id);
681
840
  }
682
841
 
683
- const model = this.currentContext?.currentConfig.model ?? this.agent.model ?? 'default';
842
+ const model = ctx.currentConfig.model;
843
+ const maxTokens = ctx.currentConfig.maxTokens;
684
844
  const messages: Message[] = [
685
845
  ...(this.agent.instructions
686
846
  ? [{ role: 'system' as const, content: this.agent.instructions }]
687
847
  : []),
688
- { role: 'user' as const, content: input },
848
+ ...options.contextAdditions.map((content) => ({ role: 'system' as const, content })),
849
+ { role: 'user' as const, content: ctx.input },
689
850
  ];
690
851
 
691
- const maxToolRounds = 10;
852
+ let tokensUsed = 0;
853
+ let toolCalls = 0;
854
+ let toolErrors = 0;
855
+ let response: ChatResponse | null = null;
856
+
857
+ const maxToolRounds = this.agent.config?.maxIterations ?? DEFAULT_MAX_TOOL_ROUNDS;
692
858
  for (let round = 0; round < maxToolRounds; round++) {
693
- const response = await this.llm.chat({
859
+ response = await this.llm.chat({
694
860
  model,
695
861
  messages,
696
862
  tools: toolSchemas.length > 0 ? toolSchemas : undefined,
697
- temperature: this.currentContext?.currentConfig.temperature,
698
- maxTokens: this.currentContext?.currentConfig.maxTokens,
863
+ temperature: options.temperature,
864
+ maxTokens,
699
865
  });
866
+ tokensUsed += response.usage?.totalTokens ?? 0;
700
867
 
701
868
  if (response.finishReason !== 'tool_calls' || !response.toolCalls?.length) {
702
- return response.content;
869
+ break;
703
870
  }
704
871
 
705
- messages.push({
872
+ const assistantMessage: ToolCallMessage = {
706
873
  role: 'assistant',
707
874
  content: response.content,
708
875
  toolCalls: response.toolCalls,
709
- } as Message);
710
-
711
- for (const toolCall of response.toolCalls) {
712
- const t = toolMap.get(toolCall.name);
713
- let result: unknown;
714
-
715
- if (!t) {
716
- result = { error: `Tool "${toolCall.name}" not found` };
717
- } else {
718
- try {
719
- const ctx: ToolContext = {
720
- agentId: this.agent.name || 'self-modifying',
721
- runId: this.currentContext?.runId || 'unknown',
722
- signal: AbortSignal.timeout(30_000),
723
- };
724
- result = await t.execute(toolCall.arguments, ctx);
725
- } catch (err) {
726
- result = { error: err instanceof Error ? err.message : String(err) };
727
- }
728
- }
876
+ };
877
+ messages.push(assistantMessage);
729
878
 
879
+ const outcomes = await this.executeToolCalls(ctx, response.toolCalls, toolMap, generatedIds);
880
+ for (const outcome of outcomes) {
881
+ toolCalls++;
882
+ if (outcome.failed) toolErrors++;
730
883
  messages.push({
731
- role: 'tool' as const,
732
- content: typeof result === 'string' ? result : JSON.stringify(result),
733
- toolCallId: toolCall.id,
734
- name: toolCall.name,
884
+ role: 'tool',
885
+ content: outcome.content,
886
+ toolCallId: outcome.call.id,
887
+ name: outcome.call.name,
735
888
  });
736
889
  }
890
+ response = null;
737
891
  }
738
892
 
739
- const finalResponse = await this.llm.chat({
740
- model,
741
- messages,
742
- temperature: this.currentContext?.currentConfig.temperature,
743
- maxTokens: this.currentContext?.currentConfig.maxTokens,
744
- });
745
- return finalResponse.content;
893
+ if (!response) {
894
+ response = await this.llm.chat({
895
+ model,
896
+ messages,
897
+ temperature: options.temperature,
898
+ maxTokens,
899
+ });
900
+ tokensUsed += response.usage?.totalTokens ?? 0;
901
+ }
902
+
903
+ let content = response.content;
904
+ let finishReason = response.finishReason;
905
+
906
+ for (let depth = 0; depth < ctx.currentConfig.reflectionDepth && content.trim(); depth++) {
907
+ const reflection = await this.llm.chat({
908
+ model,
909
+ messages: [
910
+ ...messages,
911
+ { role: 'assistant', content },
912
+ {
913
+ role: 'user',
914
+ content:
915
+ 'Review your previous answer for mistakes or omissions. Reply with the final, corrected answer only. If it is already correct, repeat it unchanged.',
916
+ },
917
+ ],
918
+ temperature: options.temperature,
919
+ maxTokens,
920
+ });
921
+ tokensUsed += reflection.usage?.totalTokens ?? 0;
922
+ if (!reflection.content.trim() || reflection.finishReason === 'error') break;
923
+ content = reflection.content;
924
+ finishReason = reflection.finishReason;
925
+ }
926
+
927
+ return {
928
+ content,
929
+ finishReason,
930
+ tokensUsed,
931
+ toolCalls,
932
+ toolErrors,
933
+ complete: content.trim().length > 0 && finishReason !== 'length' && finishReason !== 'error',
934
+ };
746
935
  }
747
936
 
748
- private buildToolSchemas(tools: Tool[]): ToolSchema[] {
749
- return tools.map((t) => {
750
- if (typeof t.toJSON === 'function') {
751
- return t.toJSON() as ToolSchema;
937
+ private async executeToolCalls(
938
+ ctx: RunContext,
939
+ calls: ToolCall[],
940
+ toolMap: Map<string, Tool>,
941
+ generatedIds: Map<string, string>
942
+ ): Promise<ToolCallOutcome[]> {
943
+ const strategy = ctx.currentConfig.toolStrategy;
944
+ const parallel =
945
+ strategy === 'parallel' ||
946
+ (strategy === 'adaptive' && new Set(calls.map((c) => c.name)).size === calls.length);
947
+
948
+ if (parallel) {
949
+ return Promise.all(
950
+ calls.map((call) => this.executeToolCall(ctx, call, toolMap, generatedIds))
951
+ );
952
+ }
953
+
954
+ const outcomes: ToolCallOutcome[] = [];
955
+ for (const call of calls) {
956
+ outcomes.push(await this.executeToolCall(ctx, call, toolMap, generatedIds));
957
+ }
958
+ return outcomes;
959
+ }
960
+
961
+ private async executeToolCall(
962
+ ctx: RunContext,
963
+ call: ToolCall,
964
+ toolMap: Map<string, Tool>,
965
+ generatedIds: Map<string, string>
966
+ ): Promise<ToolCallOutcome> {
967
+ const t = toolMap.get(call.name);
968
+ const startedAt = Date.now();
969
+ let result: unknown;
970
+ let error: string | undefined;
971
+
972
+ if (!t) {
973
+ error = `Tool "${call.name}" not found`;
974
+ } else {
975
+ const parsed = t.parameters.safeParse(call.arguments);
976
+ if (!parsed.success) {
977
+ error = `Invalid arguments for "${call.name}": ${parsed.error.issues
978
+ .map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`)
979
+ .join('; ')}`;
980
+ } else {
981
+ try {
982
+ const toolContext: ToolContext = {
983
+ agentId: this.agent.id ?? this.agent.name ?? 'self-modifying',
984
+ runId: ctx.runId,
985
+ signal: AbortSignal.timeout(t.timeout ?? DEFAULT_TOOL_TIMEOUT_MS),
986
+ };
987
+ result = await t.execute(parsed.data, toolContext);
988
+ } catch (err) {
989
+ error = err instanceof Error ? err.message : String(err);
990
+ }
752
991
  }
753
- return {
754
- name: t.name,
755
- description: t.description,
756
- parameters: { type: 'object' as const, properties: {} },
757
- };
758
- });
992
+ }
993
+
994
+ const duration = Date.now() - startedAt;
995
+ const generatedId = generatedIds.get(call.name);
996
+ if (generatedId) {
997
+ await this.toolStore.recordUsage({
998
+ toolId: generatedId,
999
+ timestamp: new Date(),
1000
+ success: error === undefined,
1001
+ executionTime: duration,
1002
+ error,
1003
+ });
1004
+ }
1005
+
1006
+ if (this.config.enabled && this.config.metaReasoning.enabled) {
1007
+ this.metaReasoner.recordAction(ctx.runId, {
1008
+ type: 'tool_call',
1009
+ toolName: call.name,
1010
+ input: call.arguments,
1011
+ output: error === undefined ? result : undefined,
1012
+ error,
1013
+ duration,
1014
+ timestamp: startedAt,
1015
+ });
1016
+ }
1017
+
1018
+ if (error !== undefined) {
1019
+ return { call, content: JSON.stringify({ error }), failed: true };
1020
+ }
1021
+
1022
+ return {
1023
+ call,
1024
+ content: typeof result === 'string' ? result : (JSON.stringify(result) ?? 'null'),
1025
+ failed: false,
1026
+ };
1027
+ }
1028
+
1029
+ private buildToolSchemas(tools: Tool[]): ToolSchema[] {
1030
+ return tools.map((t) =>
1031
+ typeof t.toJSON === 'function'
1032
+ ? t.toJSON()
1033
+ : {
1034
+ name: t.name,
1035
+ description: t.description,
1036
+ parameters: { type: 'object' as const, properties: {} },
1037
+ }
1038
+ );
1039
+ }
1040
+
1041
+ private stepConfidence(step: StepResult): number {
1042
+ if (!step.complete) return 0.2;
1043
+ if (step.toolCalls > 0 && step.toolErrors > 0) {
1044
+ return step.toolErrors >= step.toolCalls ? 0.4 : 0.6;
1045
+ }
1046
+ return 0.9;
759
1047
  }
760
1048
 
761
- private async validateModification(request: ModificationRequest): Promise<boolean> {
1049
+ private async validateModification(
1050
+ ctx: RunContext | null,
1051
+ request: ModificationRequest
1052
+ ): Promise<boolean> {
762
1053
  if (!this.config.constraints.enabled) return true;
763
1054
 
764
1055
  const validation = await this.modificationValidator.validate(request);
765
1056
 
766
- if (validation.rollbackRequired && this.config.constraints.autoRollback) {
767
- await this.autoRollbackOnError();
1057
+ if (validation.rollbackRequired && this.config.constraints.autoRollback && ctx) {
1058
+ await this.autoRollback(ctx, `Critical constraint violation: ${request.type}`);
768
1059
  }
769
1060
 
770
1061
  return validation.valid;
771
1062
  }
772
1063
 
773
- private canApplyModification(): boolean {
1064
+ private canApplyModification(ctx: RunContext): boolean {
774
1065
  if (!this.config.constraints.enabled) return true;
775
- if (!this.currentContext) return true;
776
- return this.currentContext.modificationsCount < this.config.constraints.maxModificationsPerRun;
1066
+ return ctx.modificationsCount < this.config.constraints.maxModificationsPerRun;
777
1067
  }
778
1068
 
779
- private recordModification(type: string, data: unknown): void {
780
- if (!this.currentContext) return;
781
- this.currentContext.modificationsCount++;
782
- this.currentContext.appliedModifications.push({
1069
+ private recordModification(ctx: RunContext, type: string, data: unknown): void {
1070
+ ctx.modificationsCount++;
1071
+ ctx.appliedModifications.push({
783
1072
  id: `mod_${nanoid(8)}`,
784
1073
  type,
785
1074
  appliedAt: new Date(),
@@ -787,29 +1076,15 @@ export class SelfModifyingAgent {
787
1076
  });
788
1077
  }
789
1078
 
790
- private async autoRollbackOnError(): Promise<void> {
791
- if (!this.currentContext) return;
792
-
1079
+ private async autoRollback(ctx: RunContext, reason: string): Promise<void> {
793
1080
  const now = Date.now();
794
1081
  const window = this.config.constraints.rollbackWindow;
795
- const target = this.currentContext.checkpoints
1082
+ const target = ctx.checkpoints
796
1083
  .filter((c) => now - c.timestamp.getTime() <= window)
797
1084
  .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())[0];
798
1085
 
799
1086
  if (target) {
800
- await this.rollbackToCheckpoint(target.id);
1087
+ await this.rollbackToCheckpoint(target.id, reason);
801
1088
  }
802
1089
  }
803
-
804
- private estimateConfidence(output: string): number {
805
- if (!output) return 0.3;
806
- if (output.length < 50) return 0.4;
807
- if (output.length < 200) return 0.6;
808
- return 0.8;
809
- }
810
-
811
- private isTaskComplete(output: string): boolean {
812
- if (!output.trim()) return false;
813
- return this.estimateConfidence(output) >= 0.6;
814
- }
815
1090
  }