@cogitator-ai/self-modifying 17.0.17 → 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 (114) 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 +44 -40
  4. package/dist/architecture-evolution/capability-analyzer.js.map +1 -1
  5. package/dist/architecture-evolution/evolution-strategy.d.ts.map +1 -1
  6. package/dist/architecture-evolution/evolution-strategy.js +4 -2
  7. package/dist/architecture-evolution/evolution-strategy.js.map +1 -1
  8. package/dist/architecture-evolution/index.d.ts +2 -2
  9. package/dist/architecture-evolution/index.d.ts.map +1 -1
  10. package/dist/architecture-evolution/index.js +1 -1
  11. package/dist/architecture-evolution/index.js.map +1 -1
  12. package/dist/architecture-evolution/parameter-optimizer.d.ts +5 -4
  13. package/dist/architecture-evolution/parameter-optimizer.d.ts.map +1 -1
  14. package/dist/architecture-evolution/parameter-optimizer.js +62 -34
  15. package/dist/architecture-evolution/parameter-optimizer.js.map +1 -1
  16. package/dist/architecture-evolution/prompts.d.ts +21 -2
  17. package/dist/architecture-evolution/prompts.d.ts.map +1 -1
  18. package/dist/architecture-evolution/prompts.js +189 -37
  19. package/dist/architecture-evolution/prompts.js.map +1 -1
  20. package/dist/constraints/modification-validator.d.ts +1 -0
  21. package/dist/constraints/modification-validator.d.ts.map +1 -1
  22. package/dist/constraints/modification-validator.js +45 -18
  23. package/dist/constraints/modification-validator.js.map +1 -1
  24. package/dist/constraints/rollback-manager.d.ts +1 -0
  25. package/dist/constraints/rollback-manager.d.ts.map +1 -1
  26. package/dist/constraints/rollback-manager.js +25 -1
  27. package/dist/constraints/rollback-manager.js.map +1 -1
  28. package/dist/events/event-emitter.d.ts +0 -1
  29. package/dist/events/event-emitter.d.ts.map +1 -1
  30. package/dist/events/event-emitter.js +6 -10
  31. package/dist/events/event-emitter.js.map +1 -1
  32. package/dist/index.d.ts +4 -4
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +3 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/meta-reasoning/meta-reasoner.d.ts +4 -1
  37. package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -1
  38. package/dist/meta-reasoning/meta-reasoner.js +120 -43
  39. package/dist/meta-reasoning/meta-reasoner.js.map +1 -1
  40. package/dist/meta-reasoning/observation-collector.d.ts.map +1 -1
  41. package/dist/meta-reasoning/observation-collector.js +6 -2
  42. package/dist/meta-reasoning/observation-collector.js.map +1 -1
  43. package/dist/meta-reasoning/prompts.d.ts +10 -14
  44. package/dist/meta-reasoning/prompts.d.ts.map +1 -1
  45. package/dist/meta-reasoning/prompts.js +108 -33
  46. package/dist/meta-reasoning/prompts.js.map +1 -1
  47. package/dist/meta-reasoning/strategy-selector.d.ts.map +1 -1
  48. package/dist/meta-reasoning/strategy-selector.js +6 -0
  49. package/dist/meta-reasoning/strategy-selector.js.map +1 -1
  50. package/dist/self-modifying-agent.d.ts +88 -15
  51. package/dist/self-modifying-agent.d.ts.map +1 -1
  52. package/dist/self-modifying-agent.js +583 -376
  53. package/dist/self-modifying-agent.js.map +1 -1
  54. package/dist/tool-generation/gap-analyzer.d.ts +0 -1
  55. package/dist/tool-generation/gap-analyzer.d.ts.map +1 -1
  56. package/dist/tool-generation/gap-analyzer.js +16 -15
  57. package/dist/tool-generation/gap-analyzer.js.map +1 -1
  58. package/dist/tool-generation/generated-tool-store.d.ts.map +1 -1
  59. package/dist/tool-generation/generated-tool-store.js +90 -10
  60. package/dist/tool-generation/generated-tool-store.js.map +1 -1
  61. package/dist/tool-generation/index.d.ts +3 -3
  62. package/dist/tool-generation/index.d.ts.map +1 -1
  63. package/dist/tool-generation/index.js +2 -2
  64. package/dist/tool-generation/index.js.map +1 -1
  65. package/dist/tool-generation/prompts.d.ts +4 -3
  66. package/dist/tool-generation/prompts.d.ts.map +1 -1
  67. package/dist/tool-generation/prompts.js +96 -18
  68. package/dist/tool-generation/prompts.js.map +1 -1
  69. package/dist/tool-generation/tool-generator.d.ts +6 -6
  70. package/dist/tool-generation/tool-generator.d.ts.map +1 -1
  71. package/dist/tool-generation/tool-generator.js +88 -23
  72. package/dist/tool-generation/tool-generator.js.map +1 -1
  73. package/dist/tool-generation/tool-sandbox.d.ts +10 -11
  74. package/dist/tool-generation/tool-sandbox.d.ts.map +1 -1
  75. package/dist/tool-generation/tool-sandbox.js +346 -156
  76. package/dist/tool-generation/tool-sandbox.js.map +1 -1
  77. package/dist/tool-generation/tool-validator.d.ts +4 -8
  78. package/dist/tool-generation/tool-validator.d.ts.map +1 -1
  79. package/dist/tool-generation/tool-validator.js +74 -28
  80. package/dist/tool-generation/tool-validator.js.map +1 -1
  81. package/dist/utils/index.d.ts.map +1 -1
  82. package/dist/utils/index.js +30 -5
  83. package/dist/utils/index.js.map +1 -1
  84. package/dist/utils/llm-helper.d.ts.map +1 -1
  85. package/dist/utils/llm-helper.js +1 -0
  86. package/dist/utils/llm-helper.js.map +1 -1
  87. package/package.json +3 -12
  88. package/src/__tests__/component-regressions.test.ts +599 -0
  89. package/src/__tests__/meta-reasoning.test.ts +5 -1
  90. package/src/__tests__/sandbox-security.test.ts +186 -0
  91. package/src/__tests__/self-modifying-agent.test.ts +405 -11
  92. package/src/architecture-evolution/capability-analyzer.ts +63 -44
  93. package/src/architecture-evolution/evolution-strategy.ts +5 -2
  94. package/src/architecture-evolution/index.ts +2 -0
  95. package/src/architecture-evolution/parameter-optimizer.ts +82 -40
  96. package/src/architecture-evolution/prompts.ts +224 -42
  97. package/src/constraints/modification-validator.ts +48 -21
  98. package/src/constraints/rollback-manager.ts +20 -1
  99. package/src/events/event-emitter.ts +6 -15
  100. package/src/index.ts +14 -0
  101. package/src/meta-reasoning/meta-reasoner.ts +124 -52
  102. package/src/meta-reasoning/observation-collector.ts +6 -2
  103. package/src/meta-reasoning/prompts.ts +131 -56
  104. package/src/meta-reasoning/strategy-selector.ts +6 -0
  105. package/src/self-modifying-agent.ts +797 -413
  106. package/src/tool-generation/gap-analyzer.ts +21 -19
  107. package/src/tool-generation/generated-tool-store.ts +97 -10
  108. package/src/tool-generation/index.ts +13 -3
  109. package/src/tool-generation/prompts.ts +120 -18
  110. package/src/tool-generation/tool-generator.ts +120 -26
  111. package/src/tool-generation/tool-sandbox.ts +408 -206
  112. package/src/tool-generation/tool-validator.ts +90 -37
  113. package/src/utils/index.ts +29 -5
  114. package/src/utils/llm-helper.ts +1 -0
@@ -1,25 +1,43 @@
1
+ import { nanoid } from 'nanoid';
1
2
  import type {
2
3
  Agent,
3
4
  AgentConfig,
4
5
  Tool,
6
+ ToolCall,
7
+ ToolCallMessage,
5
8
  LLMBackend,
9
+ ChatResponse,
6
10
  SelfModifyingConfig,
11
+ ToolSelfGenerationConfig,
12
+ ToolSandboxConfig,
13
+ MetaReasoningConfig,
14
+ ArchitectureEvolutionConfig,
15
+ ModificationConstraintsConfig,
16
+ ModificationConstraints,
7
17
  ArchitectureConfig,
8
18
  GeneratedTool,
9
19
  MetaObservation,
20
+ MetaAssessment,
10
21
  MetaAdaptation,
22
+ MetaTrigger,
11
23
  ModificationCheckpoint,
24
+ AppliedModification,
25
+ ModificationRequest,
12
26
  SelfModifyingEvent,
27
+ SelfModifyingEventType,
13
28
  CapabilityGap,
29
+ EvolutionMetrics,
30
+ ReasoningMode,
14
31
  Message,
15
32
  ToolSchema,
16
33
  ToolContext,
17
34
  } from '@cogitator-ai/types';
35
+ import { DEFAULT_META_REASONING_CONFIG } from '@cogitator-ai/types';
18
36
 
19
37
  import { SelfModifyingEventEmitter } from './events';
20
38
  import { GapAnalyzer, ToolGenerator, InMemoryGeneratedToolStore } from './tool-generation';
21
39
  import { MetaReasoner } from './meta-reasoning';
22
- import { ParameterOptimizer, CapabilityAnalyzer } from './architecture-evolution';
40
+ import { ParameterOptimizer, type OptimizationResult } from './architecture-evolution';
23
41
  import {
24
42
  ModificationValidator,
25
43
  RollbackManager,
@@ -28,12 +46,63 @@ import {
28
46
  DEFAULT_RESOURCE_CONSTRAINTS,
29
47
  } from './constraints';
30
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
+
31
59
  export interface SelfModifyingAgentOptions {
32
60
  agent: Agent;
33
61
  llm: LLMBackend;
34
- 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[];
35
67
  }
36
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 };
96
+ }
97
+
98
+ export type TypedSelfModifyingEvent<K extends SelfModifyingEventType> = Omit<
99
+ SelfModifyingEvent,
100
+ 'type' | 'data'
101
+ > & {
102
+ type: K;
103
+ data: SelfModifyingEventDataMap[K];
104
+ };
105
+
37
106
  export interface RunContext {
38
107
  runId: string;
39
108
  input: string;
@@ -44,33 +113,75 @@ export interface RunContext {
44
113
  observations: MetaObservation[];
45
114
  adaptations: MetaAdaptation[];
46
115
  checkpoints: ModificationCheckpoint[];
116
+ modificationsCount: number;
117
+ appliedModifications: AppliedModification[];
118
+ tokensUsed: number;
119
+ }
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;
47
133
  }
48
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
+
49
155
  export class SelfModifyingAgent {
50
156
  private readonly agent: Agent;
51
157
  private readonly llm: LLMBackend;
158
+ private readonly modelName: string;
52
159
  private readonly config: SelfModifyingConfig;
53
160
  private readonly emitter = new SelfModifyingEventEmitter();
161
+ private readonly listenerWrappers = new Map<
162
+ SelfModifyingEventType,
163
+ Map<(event: never) => void, (event: SelfModifyingEvent) => void>
164
+ >();
54
165
 
55
166
  private readonly gapAnalyzer: GapAnalyzer;
56
167
  private readonly toolGenerator: ToolGenerator;
57
168
  private readonly toolStore: InMemoryGeneratedToolStore;
58
169
  private readonly metaReasoner: MetaReasoner;
59
170
  private readonly parameterOptimizer: ParameterOptimizer;
60
- private readonly capabilityAnalyzer: CapabilityAnalyzer;
61
171
  private readonly modificationValidator: ModificationValidator;
62
172
  private readonly rollbackManager: RollbackManager;
63
173
 
64
174
  private currentContext: RunContext | null = null;
65
- private isInitialized = false;
175
+ private runQueue: Promise<unknown> = Promise.resolve();
66
176
 
67
177
  constructor(options: SelfModifyingAgentOptions) {
68
178
  this.agent = options.agent;
69
179
  this.llm = options.llm;
180
+ this.modelName = resolveModelName(options.agent.model, options.llm.provider);
70
181
  this.config = this.mergeConfig(options.config);
71
182
 
72
183
  const toolGenConfig = this.config.toolGeneration;
73
- const agentModel = this.agent.model;
184
+ const agentModel = this.modelName;
74
185
  this.gapAnalyzer = new GapAnalyzer({ llm: this.llm, config: toolGenConfig, model: agentModel });
75
186
  this.toolGenerator = new ToolGenerator({
76
187
  llm: this.llm,
@@ -81,36 +192,30 @@ export class SelfModifyingAgent {
81
192
 
82
193
  this.metaReasoner = new MetaReasoner({
83
194
  llm: this.llm,
84
- model: agentModel ?? 'default',
195
+ model: agentModel,
85
196
  config: this.config.metaReasoning,
86
197
  });
87
198
 
88
- const baseArchConfig: ArchitectureConfig = {
89
- model: agentModel ?? 'default',
90
- temperature: 0.7,
91
- maxTokens: 4096,
92
- toolStrategy: 'sequential',
93
- reflectionDepth: 1,
94
- };
95
-
96
199
  this.parameterOptimizer = new ParameterOptimizer({
97
200
  llm: this.llm,
98
201
  config: this.config.architectureEvolution,
99
- baseConfig: baseArchConfig,
100
- model: agentModel,
101
- });
102
-
103
- this.capabilityAnalyzer = new CapabilityAnalyzer({
104
- llm: this.llm,
105
- enableLLMAnalysis: true,
202
+ baseConfig: this.createBaseArchitectureConfig(),
106
203
  model: agentModel,
204
+ availableModels: options.availableModels,
107
205
  });
108
206
 
109
207
  this.modificationValidator = new ModificationValidator({
110
208
  constraints: {
111
- safety: DEFAULT_SAFETY_CONSTRAINTS,
112
- capability: DEFAULT_CAPABILITY_CONSTRAINTS,
113
- 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,
114
219
  },
115
220
  });
116
221
 
@@ -119,117 +224,44 @@ export class SelfModifyingAgent {
119
224
  });
120
225
  }
121
226
 
122
- on<K extends SelfModifyingEvent['type']>(
227
+ on<K extends SelfModifyingEventType>(
123
228
  event: K,
124
- handler: (event: Extract<SelfModifyingEvent, { type: K }>) => void
125
- ): void {
126
- 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);
127
243
  }
128
244
 
129
- off<K extends SelfModifyingEvent['type']>(
245
+ off<K extends SelfModifyingEventType>(
130
246
  event: K,
131
- handler: (event: Extract<SelfModifyingEvent, { type: K }>) => void
247
+ handler: (event: TypedSelfModifyingEvent<K>) => void
132
248
  ): void {
133
- 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);
134
254
  }
135
255
 
136
- async run(input: string): Promise<{
256
+ run(input: string): Promise<{
137
257
  output: string;
138
258
  toolsGenerated: GeneratedTool[];
139
259
  adaptationsMade: MetaAdaptation[];
140
260
  finalConfig: ArchitectureConfig;
141
261
  }> {
142
- await this.ensureInitialized();
143
-
144
- const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
145
- const tools = this.getAvailableTools();
146
-
147
- const baseConfig: ArchitectureConfig = {
148
- model: 'default',
149
- temperature: 0.7,
150
- maxTokens: 4096,
151
- toolStrategy: 'sequential',
152
- reflectionDepth: 1,
153
- };
154
-
155
- this.currentContext = {
156
- runId,
157
- input,
158
- startTime: Date.now(),
159
- tools: [...tools],
160
- currentConfig: baseConfig,
161
- generatedTools: [],
162
- observations: [],
163
- adaptations: [],
164
- checkpoints: [],
165
- };
166
-
167
- void this.emitter.emit({
168
- type: 'run_started',
169
- runId,
170
- timestamp: new Date(),
171
- data: { input },
172
- });
173
-
174
- try {
175
- if (this.config.architectureEvolution.enabled) {
176
- await this.optimizeArchitecture(input);
177
- }
178
-
179
- if (this.config.toolGeneration.enabled && this.config.toolGeneration.autoGenerate) {
180
- await this.analyzeAndGenerateTools(input);
181
- }
182
-
183
- const modeConfig = this.metaReasoner.initializeRun(runId);
184
-
185
- void this.emitter.emit({
186
- type: 'strategy_changed',
187
- runId,
188
- timestamp: new Date(),
189
- data: {
190
- previousMode: 'analytical',
191
- newMode: modeConfig.mode,
192
- reason: 'Initial mode selection',
193
- },
194
- });
195
-
196
- const output = await this.executeWithMetaReasoning(input, runId);
197
-
198
- const result = {
199
- output,
200
- toolsGenerated: [...this.currentContext.generatedTools],
201
- adaptationsMade: [...this.currentContext.adaptations],
202
- finalConfig: { ...this.currentContext.currentConfig },
203
- };
204
-
205
- void this.emitter.emit({
206
- type: 'run_completed',
207
- runId,
208
- timestamp: new Date(),
209
- data: {
210
- success: true,
211
- toolsGenerated: result.toolsGenerated.length,
212
- adaptationsMade: result.adaptationsMade.length,
213
- },
214
- });
215
-
216
- return result;
217
- } catch (error) {
218
- void this.emitter.emit({
219
- type: 'run_completed',
220
- runId,
221
- timestamp: new Date(),
222
- data: {
223
- success: false,
224
- error: error instanceof Error ? error.message : String(error),
225
- },
226
- });
227
-
228
- throw error;
229
- } finally {
230
- this.metaReasoner.cleanupRun(runId);
231
- this.currentContext = null;
232
- }
262
+ const result = this.runQueue.then(() => this.executeRun(input));
263
+ this.runQueue = result.catch(() => undefined);
264
+ return result;
233
265
  }
234
266
 
235
267
  async generateTool(gap: CapabilityGap): Promise<GeneratedTool | null> {
@@ -237,40 +269,7 @@ export class SelfModifyingAgent {
237
269
  return null;
238
270
  }
239
271
 
240
- const tools = this.getAvailableTools();
241
- const result = await this.toolGenerator.generate(gap, tools);
242
-
243
- if (result.success && result.tool) {
244
- await this.toolStore.save(result.tool);
245
-
246
- void this.emitter.emit({
247
- type: 'tool_generation_completed',
248
- runId: this.currentContext?.runId || 'manual',
249
- timestamp: new Date(),
250
- data: {
251
- toolId: result.tool.id,
252
- name: result.tool.name,
253
- success: true,
254
- iterations: result.iterations,
255
- },
256
- });
257
-
258
- return result.tool;
259
- }
260
-
261
- void this.emitter.emit({
262
- type: 'tool_generation_completed',
263
- runId: this.currentContext?.runId || 'manual',
264
- timestamp: new Date(),
265
- data: {
266
- toolId: '',
267
- name: gap.suggestedToolName,
268
- success: false,
269
- error: result.error,
270
- },
271
- });
272
-
273
- return null;
272
+ return this.generateAndRegisterTool(gap, this.currentContext?.tools ?? this.getAgentTools());
274
273
  }
275
274
 
276
275
  async recordToolUsage(toolId: string, success: boolean, executionTime: number): Promise<void> {
@@ -287,65 +286,176 @@ export class SelfModifyingAgent {
287
286
  }
288
287
 
289
288
  async createCheckpoint(): Promise<ModificationCheckpoint | null> {
290
- if (!this.currentContext) return null;
289
+ const ctx = this.currentContext;
290
+ if (!ctx) return null;
291
291
 
292
292
  const agentConfig: AgentConfig = {
293
293
  name: this.agent.name || 'agent',
294
- model: this.currentContext.currentConfig.model,
294
+ model: ctx.currentConfig.model,
295
295
  instructions: this.agent.instructions || '',
296
- temperature: this.currentContext.currentConfig.temperature,
297
- maxTokens: this.currentContext.currentConfig.maxTokens,
296
+ temperature: ctx.currentConfig.temperature,
297
+ maxTokens: ctx.currentConfig.maxTokens,
298
298
  };
299
299
 
300
300
  const checkpoint = await this.rollbackManager.createCheckpoint(
301
301
  this.agent.name || 'agent',
302
302
  agentConfig,
303
- this.currentContext.tools,
304
- []
303
+ ctx.tools,
304
+ [...ctx.appliedModifications]
305
305
  );
306
306
 
307
- this.currentContext.checkpoints.push(checkpoint);
308
-
309
- void this.emitter.emit({
310
- type: 'checkpoint_created',
311
- runId: this.currentContext.runId,
312
- timestamp: new Date(),
313
- data: { checkpointId: checkpoint.id },
314
- });
307
+ ctx.checkpoints.push(checkpoint);
308
+ this.emit('checkpoint_created', ctx.runId, { checkpointId: checkpoint.id });
315
309
 
316
310
  return checkpoint;
317
311
  }
318
312
 
319
- async rollbackToCheckpoint(checkpointId: string): Promise<boolean> {
313
+ async rollbackToCheckpoint(checkpointId: string, reason = 'Manual rollback'): Promise<boolean> {
314
+ const checkpoint = await this.rollbackManager.getCheckpoint(checkpointId);
320
315
  const restored = await this.rollbackManager.rollbackTo(checkpointId);
321
- if (!restored) return false;
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];
322
328
 
323
- if (this.currentContext) {
324
- this.currentContext.tools = restored.tools;
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));
325
335
  }
326
336
 
327
- void this.emitter.emit({
328
- type: 'rollback_performed',
329
- runId: this.currentContext?.runId || 'manual',
330
- timestamp: new Date(),
331
- data: {
332
- checkpointId,
333
- reason: 'Manual rollback',
334
- },
335
- });
337
+ this.emit('rollback_performed', ctx?.runId ?? 'manual', { checkpointId, reason });
336
338
 
337
339
  return true;
338
340
  }
339
341
 
340
- private async ensureInitialized(): Promise<void> {
341
- if (this.isInitialized) return;
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 = {
353
+ runId,
354
+ input,
355
+ startTime: Date.now(),
356
+ tools,
357
+ currentConfig: this.createBaseArchitectureConfig(),
358
+ generatedTools: [],
359
+ observations: [],
360
+ adaptations: [],
361
+ checkpoints: [],
362
+ modificationsCount: 0,
363
+ appliedModifications: [],
364
+ tokensUsed: 0,
365
+ };
366
+ this.currentContext = ctx;
367
+
368
+ this.emit('run_started', runId, { input });
342
369
 
343
- await this.toolStore.list({ status: 'active' });
370
+ let optimization: { result: OptimizationResult; candidateId: string } | null = null;
371
+
372
+ try {
373
+ if (
374
+ selfModification &&
375
+ this.config.constraints.enabled &&
376
+ this.config.constraints.autoRollback
377
+ ) {
378
+ await this.createCheckpoint();
379
+ }
380
+
381
+ if (selfModification && this.config.architectureEvolution.enabled) {
382
+ optimization = await this.optimizeArchitecture(ctx);
383
+ }
384
+
385
+ if (
386
+ selfModification &&
387
+ this.config.toolGeneration.enabled &&
388
+ this.config.toolGeneration.autoGenerate
389
+ ) {
390
+ await this.analyzeAndGenerateTools(ctx);
391
+ }
392
+
393
+ const execution = await this.executeWithMetaReasoning(ctx, selfModification);
394
+
395
+ await this.recordArchitectureOutcome(ctx, optimization, true, execution.confidence);
396
+
397
+ const result = {
398
+ output: execution.output,
399
+ toolsGenerated: [...ctx.generatedTools],
400
+ adaptationsMade: [...ctx.adaptations],
401
+ finalConfig: { ...ctx.currentConfig },
402
+ };
403
+
404
+ this.emit('run_completed', runId, {
405
+ success: true,
406
+ toolsGenerated: result.toolsGenerated.length,
407
+ adaptationsMade: result.adaptationsMade.length,
408
+ });
409
+
410
+ return result;
411
+ } catch (error) {
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');
420
+ }
421
+
422
+ this.emit('run_completed', runId, {
423
+ success: false,
424
+ error: error instanceof Error ? error.message : String(error),
425
+ });
426
+
427
+ throw error;
428
+ } finally {
429
+ this.metaReasoner.cleanupRun(runId);
430
+ this.currentContext = null;
431
+ }
432
+ }
433
+
434
+ private emit<K extends SelfModifyingEventType>(
435
+ type: K,
436
+ runId: string,
437
+ data: SelfModifyingEventDataMap[K]
438
+ ): void {
439
+ void this.emitter.emit({
440
+ type,
441
+ runId,
442
+ agentId: this.agent.id,
443
+ timestamp: new Date(),
444
+ data,
445
+ });
446
+ }
344
447
 
345
- this.isInitialized = true;
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,
455
+ };
346
456
  }
347
457
 
348
- private mergeConfig(partial?: Partial<SelfModifyingConfig>): SelfModifyingConfig {
458
+ private mergeConfig(partial?: SelfModifyingAgentConfig): SelfModifyingConfig {
349
459
  const defaults: SelfModifyingConfig = {
350
460
  enabled: true,
351
461
  toolGeneration: {
@@ -363,40 +473,7 @@ export class SelfModifyingAgent {
363
473
  isolationLevel: 'strict',
364
474
  },
365
475
  },
366
- metaReasoning: {
367
- enabled: true,
368
- defaultMode: 'analytical',
369
- allowedModes: [
370
- 'analytical',
371
- 'creative',
372
- 'systematic',
373
- 'intuitive',
374
- 'reflective',
375
- 'exploratory',
376
- ],
377
- modeProfiles: {
378
- analytical: { mode: 'analytical', temperature: 0.3, depth: 3 },
379
- creative: { mode: 'creative', temperature: 0.9, depth: 2 },
380
- systematic: { mode: 'systematic', temperature: 0.2, depth: 4 },
381
- intuitive: { mode: 'intuitive', temperature: 0.6, depth: 1 },
382
- reflective: { mode: 'reflective', temperature: 0.4, depth: 3 },
383
- exploratory: { mode: 'exploratory', temperature: 0.7, depth: 2 },
384
- },
385
- maxMetaAssessments: 5,
386
- maxAdaptations: 3,
387
- metaAssessmentCooldown: 10000,
388
- adaptationCooldown: 15000,
389
- triggers: ['on_failure', 'on_low_confidence', 'periodic'],
390
- triggerAfterIterations: 3,
391
- triggerOnConfidenceDrop: 0.3,
392
- triggerOnProgressStall: 2,
393
- tokenBudget: 2000,
394
- maxMetaTokens: 1000,
395
- minConfidenceToAdapt: 0.6,
396
- enableRollback: true,
397
- rollbackWindow: 30000,
398
- rollbackOnDecline: true,
399
- },
476
+ metaReasoning: { ...DEFAULT_META_REASONING_CONFIG },
400
477
  architectureEvolution: {
401
478
  enabled: true,
402
479
  strategy: { type: 'ucb', explorationConstant: 2 },
@@ -415,14 +492,20 @@ export class SelfModifyingAgent {
415
492
 
416
493
  if (!partial) return defaults;
417
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
+
418
503
  return {
419
504
  enabled: partial.enabled ?? defaults.enabled,
420
505
  toolGeneration: {
421
506
  ...defaults.toolGeneration,
422
507
  ...partial.toolGeneration,
423
- sandboxConfig: partial.toolGeneration?.sandboxConfig
424
- ? { ...defaults.toolGeneration.sandboxConfig, ...partial.toolGeneration.sandboxConfig }
425
- : defaults.toolGeneration.sandboxConfig,
508
+ sandboxConfig: { ...defaultSandbox, ...partial.toolGeneration?.sandboxConfig },
426
509
  },
427
510
  metaReasoning: {
428
511
  ...defaults.metaReasoning,
@@ -435,272 +518,573 @@ export class SelfModifyingAgent {
435
518
  architectureEvolution: {
436
519
  ...defaults.architectureEvolution,
437
520
  ...partial.architectureEvolution,
438
- strategy: partial.architectureEvolution?.strategy
439
- ? {
440
- ...defaults.architectureEvolution.strategy,
441
- ...partial.architectureEvolution.strategy,
442
- }
443
- : defaults.architectureEvolution.strategy,
521
+ strategy: {
522
+ ...defaults.architectureEvolution.strategy,
523
+ ...partial.architectureEvolution?.strategy,
524
+ },
444
525
  },
445
526
  constraints: { ...defaults.constraints, ...partial.constraints },
446
527
  };
447
528
  }
448
529
 
449
- private getAvailableTools(): Tool[] {
450
- return this.agent.tools ?? [];
530
+ private getAgentTools(): Tool[] {
531
+ return [...(this.agent.tools ?? [])];
451
532
  }
452
533
 
453
- private async optimizeArchitecture(input: string): Promise<void> {
454
- 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
+ }
455
547
 
548
+ private async optimizeArchitecture(
549
+ ctx: RunContext
550
+ ): Promise<{ result: OptimizationResult; candidateId: string } | null> {
456
551
  try {
457
- const result = await this.parameterOptimizer.optimize(input);
458
-
459
- if (result.shouldAdopt && result.confidence > 0.6) {
460
- const validation = await this.modificationValidator.validate({
461
- type: 'config_change',
462
- target: 'architecture',
463
- changes: result.recommendedConfig,
464
- reason: result.reasoning,
465
- });
552
+ const result = await this.parameterOptimizer.optimize(ctx.input);
553
+ const candidate = result.candidate;
554
+ if (!candidate) return null;
466
555
 
467
- if (validation.valid) {
468
- this.currentContext.currentConfig = result.recommendedConfig;
469
-
470
- void this.emitter.emit({
471
- type: 'architecture_evolved',
472
- runId: this.currentContext.runId,
473
- timestamp: new Date(),
474
- data: {
475
- candidateId: result.candidate?.id,
476
- changes: result.recommendedConfig,
477
- metrics: result.metrics,
478
- },
479
- });
480
- }
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' };
481
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 };
482
591
  } catch (error) {
483
- void this.emitter.emit({
484
- type: 'architecture_evolved',
485
- runId: this.currentContext.runId,
486
- timestamp: new Date(),
487
- data: { error: error instanceof Error ? error.message : String(error) },
592
+ this.emit('architecture_evolved', ctx.runId, {
593
+ success: false,
594
+ error: error instanceof Error ? error.message : String(error),
488
595
  });
596
+ return null;
489
597
  }
490
598
  }
491
599
 
492
- private async analyzeAndGenerateTools(input: string): Promise<void> {
493
- 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
+ }
494
619
 
620
+ private async analyzeAndGenerateTools(ctx: RunContext): Promise<void> {
495
621
  try {
496
- const analysis = await this.gapAnalyzer.analyze(input, this.currentContext.tools);
622
+ const analysis = await this.gapAnalyzer.analyze(ctx.input, ctx.tools);
497
623
 
498
624
  for (const gap of analysis.gaps) {
499
- if (gap.confidence >= this.config.toolGeneration.minConfidenceForGeneration) {
500
- void this.emitter.emit({
501
- type: 'tool_generation_started',
502
- runId: this.currentContext.runId,
503
- timestamp: new Date(),
504
- data: { gap },
505
- });
506
-
507
- const tool = await this.generateTool(gap);
508
-
509
- if (tool) {
510
- this.currentContext.generatedTools.push(tool);
511
- const executableTool = this.toolGenerator.createExecutableTool(tool);
512
- this.currentContext.tools.push(executableTool);
513
- }
514
- }
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;
628
+
629
+ const tool = await this.generateAndRegisterTool(gap, ctx.tools);
630
+ if (!tool) continue;
631
+
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 });
515
635
  }
516
636
  } catch (error) {
517
- void this.emitter.emit({
518
- type: 'tool_generation_completed',
519
- runId: this.currentContext.runId,
520
- timestamp: new Date(),
521
- data: {
522
- toolId: '',
523
- name: '',
524
- success: false,
525
- error: error instanceof Error ? error.message : String(error),
526
- },
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,
527
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`;
528
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';
529
718
  }
530
719
 
531
- private async executeWithMetaReasoning(input: string, runId: string): Promise<string> {
532
- if (!this.currentContext) {
533
- 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
+ });
534
738
  }
535
739
 
536
- let output = '';
537
- let iteration = 0;
538
- 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;
753
+
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
+ }
539
764
 
540
- while (iteration < maxIterations) {
541
- iteration++;
765
+ if (step.complete || attempt === maxAttempts) break;
542
766
 
543
- const currentMode = this.metaReasoner.getCurrentMode(runId);
544
767
  const observation = this.metaReasoner.observe(
545
768
  {
546
769
  runId,
547
- iteration,
548
- goal: input,
549
- currentMode,
550
- tokensUsed: Math.round(output.length * 1.3),
551
- timeElapsed: Date.now() - this.currentContext.startTime,
552
- iterationsRemaining: maxIterations - iteration,
553
- 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,
554
777
  },
555
778
  []
556
779
  );
780
+ ctx.observations.push(observation);
557
781
 
558
- this.currentContext.observations.push(observation);
782
+ if (!this.selectTrigger(runId, attempt, confidence, observation)) continue;
559
783
 
560
- if (
561
- this.metaReasoner.shouldTrigger(runId, 'periodic', {
562
- iteration,
563
- confidence: this.estimateConfidence(output),
564
- progressDelta: output.length > 0 ? 0.1 : 0,
565
- stagnationCount: 0,
566
- })
567
- ) {
568
- const assessment = await this.metaReasoner.assess(observation);
784
+ const assessment = await this.metaReasoner.assess(observation);
785
+ this.emit('meta_assessment', runId, { observation, assessment });
569
786
 
570
- void this.emitter.emit({
571
- type: 'meta_assessment',
572
- runId,
573
- timestamp: new Date(),
574
- data: {
575
- observation,
576
- assessment,
577
- },
578
- });
787
+ if (!assessment.requiresAdaptation) continue;
788
+ if (assessment.recommendation.action === 'abort') break;
579
789
 
580
- if (assessment.requiresAdaptation) {
581
- const adaptation = await this.metaReasoner.adapt(runId, assessment);
582
-
583
- if (adaptation) {
584
- this.currentContext.adaptations.push(adaptation);
585
-
586
- void this.emitter.emit({
587
- type: 'strategy_changed',
588
- runId,
589
- timestamp: new Date(),
590
- data: {
591
- previousMode: adaptation.before?.mode || 'analytical',
592
- newMode: adaptation.after?.mode || 'analytical',
593
- reason: adaptation.type,
594
- },
595
- });
596
- }
597
- }
598
- }
790
+ const adaptation = await this.metaReasoner.adapt(runId, assessment);
791
+ if (!adaptation) continue;
599
792
 
600
- output = await this.executeAgentStep(input);
793
+ ctx.adaptations.push(adaptation);
794
+ pendingAdaptation = { adaptation, confidence };
601
795
 
602
- if (this.isTaskComplete(output)) {
603
- break;
796
+ if (adaptation.type === 'context_injection' && assessment.recommendation.contextAddition) {
797
+ contextAdditions.push(assessment.recommendation.contextAddition);
798
+ } else {
799
+ modeAdapted = true;
604
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
+ });
605
807
  }
606
808
 
607
- return output;
809
+ return { output: step?.content ?? '', confidence };
810
+ }
811
+
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;
608
832
  }
609
833
 
610
- private async executeAgentStep(input: string): Promise<string> {
611
- const tools = this.currentContext?.tools ?? [];
612
- const toolSchemas = this.buildToolSchemas(tools);
613
- const toolMap = new Map<string, Tool>();
614
- for (const t of tools) {
615
- toolMap.set(t.name, t);
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);
616
840
  }
617
841
 
618
- const model = this.currentContext?.currentConfig.model ?? this.agent.model ?? 'default';
842
+ const model = ctx.currentConfig.model;
843
+ const maxTokens = ctx.currentConfig.maxTokens;
619
844
  const messages: Message[] = [
620
845
  ...(this.agent.instructions
621
846
  ? [{ role: 'system' as const, content: this.agent.instructions }]
622
847
  : []),
623
- { role: 'user' as const, content: input },
848
+ ...options.contextAdditions.map((content) => ({ role: 'system' as const, content })),
849
+ { role: 'user' as const, content: ctx.input },
624
850
  ];
625
851
 
626
- 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;
627
858
  for (let round = 0; round < maxToolRounds; round++) {
628
- const response = await this.llm.chat({
859
+ response = await this.llm.chat({
629
860
  model,
630
861
  messages,
631
862
  tools: toolSchemas.length > 0 ? toolSchemas : undefined,
632
- temperature: this.currentContext?.currentConfig.temperature,
633
- maxTokens: this.currentContext?.currentConfig.maxTokens,
863
+ temperature: options.temperature,
864
+ maxTokens,
634
865
  });
866
+ tokensUsed += response.usage?.totalTokens ?? 0;
635
867
 
636
868
  if (response.finishReason !== 'tool_calls' || !response.toolCalls?.length) {
637
- return response.content;
869
+ break;
638
870
  }
639
871
 
640
- messages.push({
872
+ const assistantMessage: ToolCallMessage = {
641
873
  role: 'assistant',
642
874
  content: response.content,
643
875
  toolCalls: response.toolCalls,
644
- } as Message);
645
-
646
- for (const toolCall of response.toolCalls) {
647
- const t = toolMap.get(toolCall.name);
648
- let result: unknown;
649
-
650
- if (!t) {
651
- result = { error: `Tool "${toolCall.name}" not found` };
652
- } else {
653
- try {
654
- const ctx: ToolContext = {
655
- agentId: this.agent.name || 'self-modifying',
656
- runId: this.currentContext?.runId || 'unknown',
657
- signal: AbortSignal.timeout(30_000),
658
- };
659
- result = await t.execute(toolCall.arguments, ctx);
660
- } catch (err) {
661
- result = { error: err instanceof Error ? err.message : String(err) };
662
- }
663
- }
876
+ };
877
+ messages.push(assistantMessage);
664
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++;
665
883
  messages.push({
666
- role: 'tool' as const,
667
- content: typeof result === 'string' ? result : JSON.stringify(result),
668
- toolCallId: toolCall.id,
669
- name: toolCall.name,
884
+ role: 'tool',
885
+ content: outcome.content,
886
+ toolCallId: outcome.call.id,
887
+ name: outcome.call.name,
670
888
  });
671
889
  }
890
+ response = null;
672
891
  }
673
892
 
674
- const finalResponse = await this.llm.chat({
675
- model,
676
- messages,
677
- temperature: this.currentContext?.currentConfig.temperature,
678
- maxTokens: this.currentContext?.currentConfig.maxTokens,
679
- });
680
- 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
+ };
681
935
  }
682
936
 
683
- private buildToolSchemas(tools: Tool[]): ToolSchema[] {
684
- return tools.map((t) => {
685
- if (typeof t.toJSON === 'function') {
686
- 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
+ }
687
991
  }
688
- return {
689
- name: t.name,
690
- description: t.description,
691
- parameters: { type: 'object' as const, properties: {} },
692
- };
693
- });
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
+ };
694
1027
  }
695
1028
 
696
- private estimateConfidence(output: string): number {
697
- if (!output) return 0.3;
698
- if (output.length < 50) return 0.4;
699
- if (output.length < 200) return 0.6;
700
- return 0.8;
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
+ );
701
1039
  }
702
1040
 
703
- private isTaskComplete(_output: string): boolean {
704
- return true;
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;
1047
+ }
1048
+
1049
+ private async validateModification(
1050
+ ctx: RunContext | null,
1051
+ request: ModificationRequest
1052
+ ): Promise<boolean> {
1053
+ if (!this.config.constraints.enabled) return true;
1054
+
1055
+ const validation = await this.modificationValidator.validate(request);
1056
+
1057
+ if (validation.rollbackRequired && this.config.constraints.autoRollback && ctx) {
1058
+ await this.autoRollback(ctx, `Critical constraint violation: ${request.type}`);
1059
+ }
1060
+
1061
+ return validation.valid;
1062
+ }
1063
+
1064
+ private canApplyModification(ctx: RunContext): boolean {
1065
+ if (!this.config.constraints.enabled) return true;
1066
+ return ctx.modificationsCount < this.config.constraints.maxModificationsPerRun;
1067
+ }
1068
+
1069
+ private recordModification(ctx: RunContext, type: string, data: unknown): void {
1070
+ ctx.modificationsCount++;
1071
+ ctx.appliedModifications.push({
1072
+ id: `mod_${nanoid(8)}`,
1073
+ type,
1074
+ appliedAt: new Date(),
1075
+ data,
1076
+ });
1077
+ }
1078
+
1079
+ private async autoRollback(ctx: RunContext, reason: string): Promise<void> {
1080
+ const now = Date.now();
1081
+ const window = this.config.constraints.rollbackWindow;
1082
+ const target = ctx.checkpoints
1083
+ .filter((c) => now - c.timestamp.getTime() <= window)
1084
+ .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())[0];
1085
+
1086
+ if (target) {
1087
+ await this.rollbackToCheckpoint(target.id, reason);
1088
+ }
705
1089
  }
706
1090
  }