@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
@@ -37,10 +37,12 @@ ${contextSection}
37
37
 
38
38
  Respond with a JSON object:
39
39
  {
40
- "complexity": "trivial" | "simple" | "moderate" | "complex" | "extreme",
40
+ "complexity": "trivial" | "simple" | "moderate" | "complex" | "expert" | "extreme",
41
41
  "domain": "general" | "coding" | "reasoning" | "creative" | "factual" | "conversational",
42
42
  "estimatedTokens": number,
43
43
  "requiresTools": boolean,
44
+ "requiresReasoning": boolean,
45
+ "requiresCreativity": boolean,
44
46
  "toolIntensity": "none" | "light" | "moderate" | "heavy",
45
47
  "reasoningDepth": "shallow" | "moderate" | "deep" | "exhaustive",
46
48
  "creativityLevel": "low" | "moderate" | "high",
@@ -58,8 +60,18 @@ export function buildCandidateGenerationPrompt(
58
60
  config: Partial<ArchitectureConfig>;
59
61
  score: number;
60
62
  metrics: Record<string, number>;
61
- }>
63
+ }>,
64
+ options: { availableModels?: string[] } = {}
62
65
  ): string {
66
+ const availableModels = options.availableModels ?? [];
67
+ const modelLine =
68
+ availableModels.length > 0
69
+ ? `\n "model": ${availableModels.map((m) => JSON.stringify(m)).join(' | ')} | null,`
70
+ : '';
71
+ const modelRule =
72
+ availableModels.length > 0
73
+ ? `Only use models from this list: ${availableModels.join(', ')}.`
74
+ : 'Do not change the model.';
63
75
  const historySection = historicalPerformance?.length
64
76
  ? `
65
77
  HISTORICAL PERFORMANCE:
@@ -83,18 +95,17 @@ ${historySection}
83
95
 
84
96
  Generate 3-5 candidate configurations that might improve performance.
85
97
  Each candidate should modify 1-3 parameters from current config.
98
+ ${modelRule}
86
99
 
87
100
  Respond with a JSON array:
88
101
  [
89
102
  {
90
103
  "id": "candidate_1",
91
- "config": {
92
- "model": "model name or null to keep current",
93
- "temperature": number or null,
104
+ "config": {${modelLine}
105
+ "temperature": number between 0 and 2 or null,
94
106
  "maxTokens": number or null,
95
- "systemPromptAdditions": "additional instructions or null",
96
107
  "toolStrategy": "sequential" | "parallel" | "adaptive" | null,
97
- "reflectionDepth": number or null
108
+ "reflectionDepth": integer between 0 and 5 or null
98
109
  },
99
110
  "reasoning": "Why this configuration might help",
100
111
  "expectedImprovement": 0.0-1.0,
@@ -140,56 +151,187 @@ Respond with:
140
151
  }`;
141
152
  }
142
153
 
154
+ const COMPLEXITIES: readonly TaskProfile['complexity'][] = [
155
+ 'trivial',
156
+ 'simple',
157
+ 'moderate',
158
+ 'complex',
159
+ 'expert',
160
+ 'extreme',
161
+ ];
162
+ const DOMAINS: readonly TaskProfile['domain'][] = [
163
+ 'general',
164
+ 'coding',
165
+ 'reasoning',
166
+ 'creative',
167
+ 'factual',
168
+ 'conversational',
169
+ ];
170
+ const TOOL_INTENSITIES: readonly TaskProfile['toolIntensity'][] = [
171
+ 'none',
172
+ 'light',
173
+ 'moderate',
174
+ 'heavy',
175
+ ];
176
+ const REASONING_DEPTHS: readonly TaskProfile['reasoningDepth'][] = [
177
+ 'shallow',
178
+ 'moderate',
179
+ 'deep',
180
+ 'exhaustive',
181
+ ];
182
+ const CREATIVITY_LEVELS: readonly TaskProfile['creativityLevel'][] = ['low', 'moderate', 'high'];
183
+ const ACCURACY_LEVELS: readonly TaskProfile['accuracyRequirement'][] = [
184
+ 'approximate',
185
+ 'moderate',
186
+ 'high',
187
+ 'critical',
188
+ ];
189
+ const TIME_CONSTRAINTS: readonly TaskProfile['timeConstraint'][] = [
190
+ 'none',
191
+ 'relaxed',
192
+ 'moderate',
193
+ 'strict',
194
+ ];
195
+ const TOOL_STRATEGIES: readonly ArchitectureConfig['toolStrategy'][] = [
196
+ 'sequential',
197
+ 'parallel',
198
+ 'adaptive',
199
+ ];
200
+ const RISKS: readonly EvolutionCandidate['risk'][] = ['low', 'medium', 'high'];
201
+
202
+ export const MAX_TOKENS_RANGE = { min: 100, max: 32000 } as const;
203
+ export const REFLECTION_DEPTH_RANGE = { min: 0, max: 5 } as const;
204
+ export const TEMPERATURE_RANGE = { min: 0, max: 2 } as const;
205
+
206
+ function pickEnum<T extends string>(value: unknown, allowed: readonly T[], fallback: T): T {
207
+ return typeof value === 'string' && (allowed as readonly string[]).includes(value)
208
+ ? (value as T)
209
+ : fallback;
210
+ }
211
+
212
+ function finiteNumber(value: unknown): number | undefined {
213
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
214
+ }
215
+
216
+ function clamp(value: number, range: { min: number; max: number }): number {
217
+ return Math.min(range.max, Math.max(range.min, value));
218
+ }
219
+
220
+ function isRecord(value: unknown): value is Record<string, unknown> {
221
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
222
+ }
223
+
143
224
  export function parseTaskProfileResponse(response: string): TaskProfile | null {
144
225
  const json = extractJson(response);
145
226
  if (!json) return null;
146
227
 
228
+ let parsed: unknown;
147
229
  try {
148
- const parsed = JSON.parse(json);
149
-
150
- return {
151
- complexity: parsed.complexity || 'moderate',
152
- domain: parsed.domain || 'general',
153
- estimatedTokens: parsed.estimatedTokens || 1000,
154
- requiresTools: Boolean(parsed.requiresTools),
155
- toolIntensity: parsed.toolIntensity || 'none',
156
- reasoningDepth: parsed.reasoningDepth || 'moderate',
157
- creativityLevel: parsed.creativityLevel || 'moderate',
158
- accuracyRequirement: parsed.accuracyRequirement || 'moderate',
159
- timeConstraint: parsed.timeConstraint || 'none',
160
- };
230
+ parsed = JSON.parse(json);
161
231
  } catch {
162
232
  return null;
163
233
  }
234
+ if (!isRecord(parsed)) return null;
235
+
236
+ const estimatedTokens = finiteNumber(parsed.estimatedTokens);
237
+
238
+ return {
239
+ complexity: pickEnum(parsed.complexity, COMPLEXITIES, 'moderate'),
240
+ domain: pickEnum(parsed.domain, DOMAINS, 'general'),
241
+ estimatedTokens:
242
+ estimatedTokens !== undefined && estimatedTokens > 0 ? Math.round(estimatedTokens) : 1000,
243
+ requiresTools: Boolean(parsed.requiresTools),
244
+ requiresReasoning: Boolean(parsed.requiresReasoning),
245
+ requiresCreativity: Boolean(parsed.requiresCreativity),
246
+ toolIntensity: pickEnum(parsed.toolIntensity, TOOL_INTENSITIES, 'none'),
247
+ reasoningDepth: pickEnum(parsed.reasoningDepth, REASONING_DEPTHS, 'moderate'),
248
+ creativityLevel: pickEnum(parsed.creativityLevel, CREATIVITY_LEVELS, 'moderate'),
249
+ accuracyRequirement: pickEnum(parsed.accuracyRequirement, ACCURACY_LEVELS, 'moderate'),
250
+ timeConstraint: pickEnum(parsed.timeConstraint, TIME_CONSTRAINTS, 'none'),
251
+ };
164
252
  }
165
253
 
166
- export function parseCandidateGenerationResponse(response: string): EvolutionCandidate[] {
167
- const jsonMatch = /\[[\s\S]*\]/.exec(response);
168
- if (!jsonMatch) return [];
254
+ export function sanitizeCandidateConfig(
255
+ raw: unknown,
256
+ options: { availableModels?: string[] } = {}
257
+ ): Partial<ArchitectureConfig> {
258
+ if (!isRecord(raw)) return {};
259
+ const config: Partial<ArchitectureConfig> = {};
260
+
261
+ if (typeof raw.model === 'string' && options.availableModels?.includes(raw.model)) {
262
+ config.model = raw.model;
263
+ }
264
+
265
+ const temperature = finiteNumber(raw.temperature);
266
+ if (temperature !== undefined) {
267
+ config.temperature = clamp(temperature, TEMPERATURE_RANGE);
268
+ }
169
269
 
270
+ const maxTokens = finiteNumber(raw.maxTokens);
271
+ if (maxTokens !== undefined) {
272
+ config.maxTokens = clamp(Math.round(maxTokens), MAX_TOKENS_RANGE);
273
+ }
274
+
275
+ if (
276
+ typeof raw.toolStrategy === 'string' &&
277
+ (TOOL_STRATEGIES as readonly string[]).includes(raw.toolStrategy)
278
+ ) {
279
+ config.toolStrategy = raw.toolStrategy as ArchitectureConfig['toolStrategy'];
280
+ }
281
+
282
+ const reflectionDepth = finiteNumber(raw.reflectionDepth);
283
+ if (reflectionDepth !== undefined) {
284
+ config.reflectionDepth = clamp(Math.round(reflectionDepth), REFLECTION_DEPTH_RANGE);
285
+ }
286
+
287
+ return config;
288
+ }
289
+
290
+ export function parseCandidateGenerationResponse(
291
+ response: string,
292
+ options: { availableModels?: string[] } = {}
293
+ ): EvolutionCandidate[] {
294
+ const json = extractJsonArray(response);
295
+ if (!json) return [];
296
+
297
+ let parsed: unknown;
170
298
  try {
171
- const parsed = JSON.parse(jsonMatch[0]);
172
- if (!Array.isArray(parsed)) return [];
173
-
174
- return parsed
175
- .filter((c: Record<string, unknown>) => c && typeof c === 'object' && c.config)
176
- .map((c: Record<string, unknown>, idx: number) => ({
177
- id: String(c.id || `candidate_${idx}`),
178
- config: c.config as Partial<ArchitectureConfig>,
179
- reasoning: String(c.reasoning || ''),
180
- expectedImprovement:
181
- typeof c.expectedImprovement === 'number' ? c.expectedImprovement : 0.5,
182
- risk: (['low', 'medium', 'high'].includes(String(c.risk)) ? c.risk : 'medium') as
183
- | 'low'
184
- | 'medium'
185
- | 'high',
186
- generation: 0,
187
- score: 0,
188
- evaluationCount: 0,
189
- }));
299
+ parsed = JSON.parse(json);
190
300
  } catch {
191
301
  return [];
192
302
  }
303
+ if (!Array.isArray(parsed)) return [];
304
+
305
+ const usedIds = new Set<string>(['baseline']);
306
+ const candidates: EvolutionCandidate[] = [];
307
+
308
+ parsed.forEach((raw: unknown, idx: number) => {
309
+ if (!isRecord(raw)) return;
310
+ const config = sanitizeCandidateConfig(raw.config, options);
311
+ if (Object.keys(config).length === 0) return;
312
+
313
+ let id = typeof raw.id === 'string' && raw.id.trim() ? raw.id.trim() : `candidate_${idx}`;
314
+ while (usedIds.has(id)) {
315
+ id = `${id}_${idx}`;
316
+ }
317
+ usedIds.add(id);
318
+
319
+ const expectedImprovement = finiteNumber(raw.expectedImprovement);
320
+
321
+ candidates.push({
322
+ id,
323
+ config,
324
+ reasoning: typeof raw.reasoning === 'string' ? raw.reasoning : '',
325
+ expectedImprovement:
326
+ expectedImprovement !== undefined ? clamp(expectedImprovement, { min: 0, max: 1 }) : 0.5,
327
+ risk: pickEnum(raw.risk, RISKS, 'medium'),
328
+ generation: 0,
329
+ score: 0,
330
+ evaluationCount: 0,
331
+ });
332
+ });
333
+
334
+ return candidates;
193
335
  }
194
336
 
195
337
  export function parsePerformanceAnalysisResponse(response: string): {
@@ -214,3 +356,43 @@ export function parsePerformanceAnalysisResponse(response: string): {
214
356
  return null;
215
357
  }
216
358
  }
359
+
360
+ function extractJsonArray(text: string): string | null {
361
+ const start = text.indexOf('[');
362
+ if (start === -1) return null;
363
+
364
+ let depth = 0;
365
+ let inString = false;
366
+ let escape = false;
367
+
368
+ for (let i = start; i < text.length; i++) {
369
+ const ch = text[i];
370
+
371
+ if (escape) {
372
+ escape = false;
373
+ continue;
374
+ }
375
+
376
+ if (ch === '\\' && inString) {
377
+ escape = true;
378
+ continue;
379
+ }
380
+
381
+ if (ch === '"') {
382
+ inString = !inString;
383
+ continue;
384
+ }
385
+
386
+ if (inString) continue;
387
+
388
+ if (ch === '[' || ch === '{') depth++;
389
+ else if (ch === ']' || ch === '}') {
390
+ depth--;
391
+ if (depth === 0) {
392
+ return text.slice(start, i + 1);
393
+ }
394
+ }
395
+ }
396
+
397
+ return null;
398
+ }
@@ -74,6 +74,9 @@ export class ModificationValidator {
74
74
  const results: ConstraintCheckResult[] = [];
75
75
 
76
76
  for (const constraint of this.constraints.safety) {
77
+ if (constraint.appliesTo && !constraint.appliesTo.includes(request.type)) {
78
+ continue;
79
+ }
77
80
  const satisfied = this.evaluateSafetyRule(constraint.rule, request);
78
81
  results.push({
79
82
  constraintId: constraint.id,
@@ -88,14 +91,26 @@ export class ModificationValidator {
88
91
  }
89
92
 
90
93
  private evaluateSafetyRule(rule: ConstraintRule, request: ModificationRequest): boolean {
94
+ const context = this.payloadOf(request);
95
+
91
96
  if (typeof rule === 'string') {
92
- return this.evaluateExpression(rule, request.payload as Record<string, unknown>);
97
+ return this.evaluateExpression(rule, context);
98
+ }
99
+
100
+ const checks: boolean[] = [];
101
+
102
+ if (rule.expression) {
103
+ checks.push(this.evaluateExpression(rule.expression, context));
93
104
  }
94
105
 
95
- return this.evaluateExpression(
96
- rule.expression ?? '',
97
- request.payload as Record<string, unknown>
98
- );
106
+ if (rule.pattern) {
107
+ const subject = JSON.stringify(request.changes ?? request.payload ?? '');
108
+ checks.push(rule.pattern.test(subject));
109
+ }
110
+
111
+ if (checks.length === 0) return false;
112
+
113
+ return checks.every(Boolean);
99
114
  }
100
115
 
101
116
  private evaluateExpression(expression: string, context: Record<string, unknown>): boolean {
@@ -159,10 +174,20 @@ export class ModificationValidator {
159
174
  return Boolean(value);
160
175
  }
161
176
 
177
+ private payloadOf(request: ModificationRequest): Record<string, unknown> {
178
+ const payload = request.payload;
179
+ return payload && typeof payload === 'object' && !Array.isArray(payload)
180
+ ? (payload as Record<string, unknown>)
181
+ : {};
182
+ }
183
+
162
184
  private resolveValue(expr: string, context: Record<string, unknown>): unknown {
163
185
  if (expr === 'true') return true;
164
186
  if (expr === 'false') return false;
165
- if (/^\d+(\.\d+)?$/.test(expr)) return parseFloat(expr);
187
+ if (expr === 'null') return null;
188
+ if (/^-?\d+(\.\d+)?$/.test(expr)) return parseFloat(expr);
189
+ const quoted = /^(['"])(.*)\1$/.exec(expr);
190
+ if (quoted) return quoted[2];
166
191
 
167
192
  const keys = expr.split('.');
168
193
  let current: unknown = context;
@@ -181,34 +206,36 @@ export class ModificationValidator {
181
206
  ): Promise<ConstraintCheckResult[]> {
182
207
  const results: ConstraintCheckResult[] = [];
183
208
 
184
- if (request.type !== 'tool_generation') {
209
+ if (request.type !== 'tool_generation' && request.type !== 'tool_creation') {
185
210
  return results;
186
211
  }
187
212
 
188
- const payload = request.payload as { category?: string; complexity?: number };
213
+ const payload = this.payloadOf(request) as { category?: unknown; complexity?: unknown };
214
+ const category = typeof payload.category === 'string' ? payload.category : undefined;
215
+ const complexity = typeof payload.complexity === 'number' ? payload.complexity : undefined;
189
216
 
190
217
  for (const constraint of this.constraints.capability) {
191
218
  let satisfied = true;
192
219
  let message: string | undefined;
193
220
 
194
- if (payload.category) {
195
- if (constraint.forbidden?.includes(payload.category)) {
221
+ if (category) {
222
+ if (constraint.forbidden?.includes(category)) {
196
223
  satisfied = false;
197
- message = `Category '${payload.category}' is forbidden`;
198
- } else if (constraint.allowed?.length && !constraint.allowed.includes(payload.category)) {
224
+ message = `Category '${category}' is forbidden`;
225
+ } else if (constraint.allowed?.length && !constraint.allowed.includes(category)) {
199
226
  satisfied = false;
200
- message = `Category '${payload.category}' is not in allowed list`;
227
+ message = `Category '${category}' is not in allowed list`;
201
228
  }
202
229
  }
203
230
 
204
231
  if (
205
232
  satisfied &&
206
- constraint.maxComplexity &&
207
- payload.complexity &&
208
- payload.complexity > constraint.maxComplexity
233
+ constraint.maxComplexity !== undefined &&
234
+ complexity !== undefined &&
235
+ complexity > constraint.maxComplexity
209
236
  ) {
210
237
  satisfied = false;
211
- message = `Complexity ${payload.complexity} exceeds max ${constraint.maxComplexity}`;
238
+ message = `Complexity ${complexity} exceeds max ${constraint.maxComplexity}`;
212
239
  }
213
240
 
214
241
  results.push({
@@ -227,7 +254,7 @@ export class ModificationValidator {
227
254
  request: ModificationRequest
228
255
  ): Promise<ConstraintCheckResult[]> {
229
256
  const results: ConstraintCheckResult[] = [];
230
- const payload = (request.payload ?? {}) as {
257
+ const payload = this.payloadOf(request) as {
231
258
  tokensUsed?: number;
232
259
  cost?: number;
233
260
  activeTools?: number;
@@ -239,7 +266,7 @@ export class ModificationValidator {
239
266
 
240
267
  if (
241
268
  constraint.maxTokensPerRun &&
242
- payload.tokensUsed &&
269
+ payload.tokensUsed != null &&
243
270
  payload.tokensUsed > constraint.maxTokensPerRun
244
271
  ) {
245
272
  satisfied = false;
@@ -249,7 +276,7 @@ export class ModificationValidator {
249
276
  if (
250
277
  satisfied &&
251
278
  constraint.maxCostPerRun &&
252
- payload.cost &&
279
+ payload.cost != null &&
253
280
  payload.cost > constraint.maxCostPerRun
254
281
  ) {
255
282
  satisfied = false;
@@ -259,7 +286,7 @@ export class ModificationValidator {
259
286
  if (
260
287
  satisfied &&
261
288
  constraint.maxToolsActive &&
262
- payload.activeTools &&
289
+ payload.activeTools != null &&
263
290
  payload.activeTools > constraint.maxToolsActive
264
291
  ) {
265
292
  satisfied = false;
@@ -119,11 +119,30 @@ export class RollbackManager {
119
119
  if (!checkpoint) return null;
120
120
 
121
121
  return {
122
- agentConfig: checkpoint.agentConfig as unknown as AgentConfig,
122
+ agentConfig: this.toAgentConfig(checkpoint.agentConfig),
123
123
  tools: checkpoint.tools.map((t) => ({ ...t })),
124
124
  };
125
125
  }
126
126
 
127
+ private toAgentConfig(record: Record<string, unknown>): AgentConfig {
128
+ const config: AgentConfig = {
129
+ name: typeof record.name === 'string' ? record.name : 'agent',
130
+ model: typeof record.model === 'string' ? record.model : 'default',
131
+ instructions: typeof record.instructions === 'string' ? record.instructions : '',
132
+ };
133
+
134
+ if (typeof record.id === 'string') config.id = record.id;
135
+ if (typeof record.description === 'string') config.description = record.description;
136
+ if (typeof record.provider === 'string') config.provider = record.provider;
137
+ if (typeof record.temperature === 'number') config.temperature = record.temperature;
138
+ if (typeof record.topP === 'number') config.topP = record.topP;
139
+ if (typeof record.maxTokens === 'number') config.maxTokens = record.maxTokens;
140
+ if (typeof record.maxIterations === 'number') config.maxIterations = record.maxIterations;
141
+ if (typeof record.timeout === 'number') config.timeout = record.timeout;
142
+
143
+ return config;
144
+ }
145
+
127
146
  async rollbackToLatest(
128
147
  agentId: string
129
148
  ): Promise<{ agentConfig: AgentConfig; tools: Tool[] } | null> {
@@ -30,7 +30,7 @@ export class SelfModifyingEventEmitter {
30
30
  ...(wildcardHandlers ? [...wildcardHandlers] : []),
31
31
  ];
32
32
 
33
- await Promise.allSettled(
33
+ const results = await Promise.allSettled(
34
34
  allHandlers.map((h) => {
35
35
  try {
36
36
  return Promise.resolve(h(event));
@@ -39,21 +39,12 @@ export class SelfModifyingEventEmitter {
39
39
  }
40
40
  })
41
41
  );
42
- }
43
42
 
44
- createEvent(
45
- type: SelfModifyingEventType,
46
- runId: string,
47
- agentId: string,
48
- data: unknown
49
- ): SelfModifyingEvent {
50
- return {
51
- type,
52
- runId,
53
- agentId,
54
- timestamp: new Date(),
55
- data,
56
- };
43
+ for (const result of results) {
44
+ if (result.status === 'rejected') {
45
+ console.error(`[self-modifying] event handler for "${event.type}" failed:`, result.reason);
46
+ }
47
+ }
57
48
  }
58
49
 
59
50
  removeAllListeners(event?: SelfModifyingEventType | '*'): void {
package/src/index.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  export {
2
2
  SelfModifyingAgent,
3
3
  type SelfModifyingAgentOptions,
4
+ type SelfModifyingAgentConfig,
5
+ type SelfModifyingEventDataMap,
6
+ type TypedSelfModifyingEvent,
4
7
  type RunContext,
5
8
  } from './self-modifying-agent';
6
9
 
@@ -15,11 +18,16 @@ export {
15
18
  buildGapAnalysisPrompt,
16
19
  buildToolGenerationPrompt,
17
20
  buildToolValidationPrompt,
21
+ buildToolImprovementPrompt,
18
22
  parseGapAnalysisResponse,
19
23
  parseToolGenerationResponse,
24
+ parseValidationResponse,
20
25
  type GapAnalyzerOptions,
21
26
  type ToolGeneratorOptions,
22
27
  type ToolValidatorOptions,
28
+ type ValidationRule,
29
+ type SandboxTestCase,
30
+ type GenerateOptions,
23
31
  type GenerationResult,
24
32
  type ToolUsageRecord,
25
33
  type ToolMetrics,
@@ -48,13 +56,17 @@ export {
48
56
  ARCHITECTURE_ANALYSIS_SYSTEM_PROMPT,
49
57
  buildTaskProfilePrompt,
50
58
  buildCandidateGenerationPrompt,
59
+ buildPerformanceAnalysisPrompt,
51
60
  parseTaskProfileResponse,
52
61
  parseCandidateGenerationResponse,
62
+ parsePerformanceAnalysisResponse,
63
+ sanitizeCandidateConfig,
53
64
  type CapabilityAnalyzerOptions,
54
65
  type EvolutionStrategyOptions,
55
66
  type ParameterOptimizerOptions,
56
67
  type SelectionResult,
57
68
  type OptimizationResult,
69
+ type HistoricalRecord,
58
70
  } from './architecture-evolution';
59
71
 
60
72
  export {
@@ -64,6 +76,8 @@ export {
64
76
  DEFAULT_SAFETY_CONSTRAINTS,
65
77
  DEFAULT_CAPABILITY_CONSTRAINTS,
66
78
  DEFAULT_RESOURCE_CONSTRAINTS,
79
+ createDefaultConstraints,
80
+ mergeConstraints,
67
81
  mergeSafetyConstraints,
68
82
  mergeCapabilityConstraints,
69
83
  mergeResourceConstraints,