@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
@@ -10,8 +10,6 @@ import type {
10
10
  ReasoningModeConfig,
11
11
  Insight,
12
12
  LLMBackend,
13
- MetaIssue,
14
- MetaOpportunity,
15
13
  } from '@cogitator-ai/types';
16
14
  import { DEFAULT_META_REASONING_CONFIG } from '@cogitator-ai/types';
17
15
  import {
@@ -28,6 +26,17 @@ import {
28
26
 
29
27
  export { DEFAULT_META_REASONING_CONFIG };
30
28
 
29
+ const TRIGGER_ALIASES: Partial<Record<MetaTrigger, MetaTrigger>> = {
30
+ confidence_drop: 'on_low_confidence',
31
+ progress_stall: 'on_stagnation',
32
+ tool_call_failed: 'on_failure',
33
+ explicit_request: 'on_request',
34
+ };
35
+
36
+ function canonicalTrigger(trigger: MetaTrigger): MetaTrigger {
37
+ return TRIGGER_ALIASES[trigger] ?? trigger;
38
+ }
39
+
31
40
  export interface MetaReasonerOptions {
32
41
  llm: LLMBackend;
33
42
  model: string;
@@ -44,6 +53,8 @@ export class MetaReasoner {
44
53
  private assessments = new Map<string, MetaAssessment[]>();
45
54
  private adaptations = new Map<string, MetaAdaptation[]>();
46
55
  private currentMode = new Map<string, ReasoningMode>();
56
+ private parameterOverrides = new Map<string, Partial<ReasoningModeConfig>>();
57
+ private overridesBefore = new Map<string, Partial<ReasoningModeConfig>>();
47
58
 
48
59
  private lastAssessmentTime = new Map<string, number>();
49
60
  private lastAdaptationTime = new Map<string, number>();
@@ -51,7 +62,14 @@ export class MetaReasoner {
51
62
  constructor(options: MetaReasonerOptions) {
52
63
  this.llm = options.llm;
53
64
  this.model = options.model;
54
- this.config = { ...DEFAULT_META_REASONING_CONFIG, ...options.config } as MetaReasoningConfig;
65
+ this.config = {
66
+ ...DEFAULT_META_REASONING_CONFIG,
67
+ ...options.config,
68
+ modeProfiles: {
69
+ ...DEFAULT_META_REASONING_CONFIG.modeProfiles,
70
+ ...options.config?.modeProfiles,
71
+ },
72
+ };
55
73
 
56
74
  this.collector = new ObservationCollector();
57
75
  this.selector = new StrategySelector({
@@ -65,10 +83,17 @@ export class MetaReasoner {
65
83
  this.assessments.set(runId, []);
66
84
  this.adaptations.set(runId, []);
67
85
  this.currentMode.set(runId, this.config.defaultMode);
86
+ this.parameterOverrides.delete(runId);
68
87
 
69
88
  return this.getModeConfig(this.config.defaultMode);
70
89
  }
71
90
 
91
+ isTriggerEnabled(trigger: MetaTrigger): boolean {
92
+ const canonical = canonicalTrigger(trigger);
93
+ if (canonical === 'on_request') return true;
94
+ return this.config.triggers.some((t) => canonicalTrigger(t) === canonical);
95
+ }
96
+
72
97
  recordAction(runId: string, action: ActionRecord): void {
73
98
  this.collector.recordAction(runId, action);
74
99
  }
@@ -88,6 +113,7 @@ export class MetaReasoner {
88
113
  }
89
114
  ): boolean {
90
115
  if (!this.config.enabled) return false;
116
+ if (!this.isTriggerEnabled(trigger)) return false;
91
117
 
92
118
  const lastAssessment = this.lastAssessmentTime.get(runId) ?? 0;
93
119
  if (Date.now() - lastAssessment < this.config.metaAssessmentCooldown) {
@@ -106,19 +132,23 @@ export class MetaReasoner {
106
132
  );
107
133
 
108
134
  case 'confidence_drop':
135
+ case 'on_low_confidence':
109
136
  return context.confidence < this.config.triggerOnConfidenceDrop;
110
137
 
111
138
  case 'progress_stall':
139
+ case 'on_stagnation':
112
140
  return context.stagnationCount >= this.config.triggerOnProgressStall;
113
141
 
114
- case 'periodic':
115
- return (
116
- context.iteration > 0 && context.iteration % this.config.triggerAfterIterations === 0
117
- );
142
+ case 'periodic': {
143
+ const elapsed = Date.now() - lastAssessment;
144
+ return elapsed >= this.config.metaAssessmentCooldown * this.config.triggerAfterIterations;
145
+ }
118
146
 
147
+ case 'on_failure':
119
148
  case 'tool_call_failed':
120
149
  return true;
121
150
 
151
+ case 'on_request':
122
152
  case 'explicit_request':
123
153
  return true;
124
154
 
@@ -151,6 +181,7 @@ export class MetaReasoner {
151
181
  });
152
182
 
153
183
  const parsed = parseMetaAssessmentResponse(response.content);
184
+ const recommendation = this.buildRecommendation(parsed, observation);
154
185
 
155
186
  const assessment: MetaAssessment = {
156
187
  id: `meta_${nanoid(10)}`,
@@ -161,18 +192,16 @@ export class MetaReasoner {
161
192
  confidence: parsed?.confidence ?? 0.5,
162
193
  reasoning: parsed?.reasoning ?? 'Assessment unavailable',
163
194
 
164
- issues: (parsed?.issues ?? []) as MetaIssue[],
195
+ issues: parsed?.issues ?? [],
165
196
  opportunities: (parsed?.opportunities ?? []).map((o) => ({
166
- type: o.type as MetaOpportunity['type'],
167
- confidence: o.expectedImprovement ?? 0.5,
197
+ type: o.type,
198
+ confidence: o.expectedImprovement,
168
199
  description: o.description,
169
- })) as MetaOpportunity[],
200
+ })),
170
201
 
171
- recommendation: this.buildRecommendation(parsed, observation),
202
+ recommendation,
172
203
 
173
- requiresAdaptation:
174
- parsed?.recommendation?.action !== undefined &&
175
- parsed?.recommendation?.action !== 'continue',
204
+ requiresAdaptation: recommendation.action !== 'continue',
176
205
 
177
206
  assessmentDuration: Date.now() - startTime,
178
207
  assessmentCost: (response.usage?.outputTokens ?? 0) * 0.00001,
@@ -207,16 +236,7 @@ export class MetaReasoner {
207
236
  };
208
237
  }
209
238
 
210
- return {
211
- action: parsed.recommendation.action as MetaRecommendation['action'],
212
- newMode: parsed.recommendation.newMode as ReasoningMode | undefined,
213
- parameterChanges: parsed.recommendation.parameterChanges as
214
- | Partial<ReasoningModeConfig>
215
- | undefined,
216
- contextAddition: parsed.recommendation.contextAddition,
217
- confidence: parsed.recommendation.confidence,
218
- reasoning: parsed.recommendation.reasoning,
219
- };
239
+ return { ...parsed.recommendation };
220
240
  }
221
241
 
222
242
  async adapt(runId: string, assessment: MetaAssessment): Promise<MetaAdaptation | null> {
@@ -235,38 +255,62 @@ export class MetaReasoner {
235
255
  return null;
236
256
  }
237
257
 
238
- const adaptationCount = this.adaptations.get(runId)?.length ?? 0;
258
+ const adaptationCount = (this.adaptations.get(runId) ?? []).filter(
259
+ (a) => a.type !== 'rollback'
260
+ ).length;
239
261
  if (adaptationCount >= this.config.maxAdaptations) {
240
262
  return null;
241
263
  }
242
264
 
243
265
  const currentMode = this.currentMode.get(runId) ?? this.config.defaultMode;
244
- const currentConfig = this.getModeConfig(currentMode);
266
+ const currentConfig = this.getCurrentConfig(runId);
245
267
 
246
- let newConfig: Partial<ReasoningModeConfig> = {};
247
- let adaptationType: MetaAdaptation['type'] = 'parameter_change';
268
+ let newConfig: Partial<ReasoningModeConfig>;
269
+ let adaptationType: MetaAdaptation['type'];
270
+ let newMode = currentMode;
271
+ const previousOverrides = this.parameterOverrides.get(runId);
248
272
 
249
273
  switch (recommendation.action) {
250
- case 'switch_mode':
251
- if (recommendation.newMode && this.config.allowedModes.includes(recommendation.newMode)) {
252
- newConfig = this.getModeConfig(recommendation.newMode);
253
- adaptationType = 'mode_switch';
254
- this.currentMode.set(runId, recommendation.newMode);
274
+ case 'switch_mode': {
275
+ const target = recommendation.newMode;
276
+ if (!target || target === currentMode || !this.config.allowedModes.includes(target)) {
277
+ return null;
255
278
  }
279
+ newConfig = this.getModeConfig(target);
280
+ adaptationType = 'mode_switch';
281
+ newMode = target;
282
+ this.currentMode.set(runId, target);
283
+ this.parameterOverrides.delete(runId);
256
284
  break;
285
+ }
257
286
 
258
- case 'adjust_parameters':
259
- if (recommendation.parameterChanges) {
260
- newConfig = { ...currentConfig, ...recommendation.parameterChanges };
261
- adaptationType = 'parameter_change';
287
+ case 'adjust_parameters': {
288
+ const changes = recommendation.parameterChanges;
289
+ if (!changes) return null;
290
+ const effective: Partial<ReasoningModeConfig> = {};
291
+ if (
292
+ changes.temperature !== undefined &&
293
+ changes.temperature !== currentConfig.temperature
294
+ ) {
295
+ effective.temperature = changes.temperature;
296
+ }
297
+ if (changes.depth !== undefined && changes.depth !== currentConfig.depth) {
298
+ effective.depth = changes.depth;
262
299
  }
300
+ if (Object.keys(effective).length === 0) return null;
301
+ newConfig = { ...currentConfig, ...effective };
302
+ adaptationType = 'parameter_change';
303
+ this.parameterOverrides.set(runId, { ...previousOverrides, ...effective });
263
304
  break;
305
+ }
264
306
 
265
307
  case 'inject_context':
308
+ if (!recommendation.contextAddition) return null;
309
+ newConfig = { ...currentConfig };
266
310
  adaptationType = 'context_injection';
267
311
  break;
268
312
 
269
- case 'abort':
313
+ default:
270
314
  return null;
271
315
  }
272
316
 
@@ -278,6 +322,9 @@ export class MetaReasoner {
278
322
  type: adaptationType,
279
323
  before: currentConfig,
280
324
  after: newConfig,
325
+ previousMode: currentMode,
326
+ newMode,
327
+ reason: recommendation.reasoning || undefined,
281
328
 
282
329
  rollbackable: this.config.enableRollback,
283
330
  rollbackDeadline: this.config.enableRollback
@@ -285,6 +332,10 @@ export class MetaReasoner {
285
332
  : undefined,
286
333
  };
287
334
 
335
+ if (previousOverrides) {
336
+ this.overridesBefore.set(adaptation.id, previousOverrides);
337
+ }
338
+
288
339
  const runAdaptations = this.adaptations.get(runId) ?? [];
289
340
  runAdaptations.push(adaptation);
290
341
  this.adaptations.set(runId, runAdaptations);
@@ -293,34 +344,51 @@ export class MetaReasoner {
293
344
  return adaptation;
294
345
  }
295
346
 
296
- rollback(runId: string): MetaAdaptation | null {
347
+ rollback(runId: string, adaptationId?: string): MetaAdaptation | null {
297
348
  const runAdaptations = this.adaptations.get(runId) ?? [];
298
- const lastAdaptation = runAdaptations[runAdaptations.length - 1];
349
+ const target = adaptationId
350
+ ? runAdaptations.find((a) => a.id === adaptationId)
351
+ : [...runAdaptations].reverse().find((a) => a.type !== 'rollback');
299
352
 
300
- if (!lastAdaptation?.rollbackable) {
353
+ if (!target?.rollbackable) {
301
354
  return null;
302
355
  }
303
356
 
304
- if (lastAdaptation.rollbackDeadline && Date.now() > lastAdaptation.rollbackDeadline) {
357
+ if (target.rollbackDeadline && Date.now() > target.rollbackDeadline) {
305
358
  return null;
306
359
  }
307
360
 
308
361
  const rollback: MetaAdaptation = {
309
362
  id: `rollback_${nanoid(10)}`,
310
- assessmentId: lastAdaptation.assessmentId,
363
+ assessmentId: target.assessmentId,
311
364
  timestamp: Date.now(),
312
365
 
313
366
  type: 'rollback',
314
- before: lastAdaptation.after,
315
- after: lastAdaptation.before,
367
+ before: target.after,
368
+ after: target.before,
369
+ previousMode: target.newMode,
370
+ newMode: target.previousMode,
371
+ reason: `Rollback of ${target.id}`,
372
+ isRollback: true,
316
373
 
317
374
  rollbackable: false,
318
375
  };
319
376
 
320
- if (lastAdaptation.type === 'mode_switch' && lastAdaptation.before.mode) {
321
- this.currentMode.set(runId, lastAdaptation.before.mode);
377
+ if (target.type === 'mode_switch' || target.type === 'parameter_change') {
378
+ const restoredMode = target.previousMode ?? target.before.mode;
379
+ if (restoredMode) {
380
+ this.currentMode.set(runId, restoredMode);
381
+ }
382
+ const restoredOverrides = this.overridesBefore.get(target.id);
383
+ if (restoredOverrides) {
384
+ this.parameterOverrides.set(runId, restoredOverrides);
385
+ } else {
386
+ this.parameterOverrides.delete(runId);
387
+ }
322
388
  }
323
389
 
390
+ target.rollbackable = false;
391
+ this.overridesBefore.delete(target.id);
324
392
  runAdaptations.push(rollback);
325
393
  return rollback;
326
394
  }
@@ -337,14 +405,14 @@ export class MetaReasoner {
337
405
  adaptation.outcome = outcome;
338
406
 
339
407
  if (this.config.rollbackOnDecline && !outcome.improved && adaptation.rollbackable) {
340
- this.rollback(runId);
408
+ this.rollback(runId, adaptationId);
341
409
  }
342
410
  }
343
411
  }
344
412
 
345
413
  getCurrentConfig(runId: string): ReasoningModeConfig {
346
414
  const mode = this.currentMode.get(runId) ?? this.config.defaultMode;
347
- return this.getModeConfig(mode);
415
+ return { ...this.getModeConfig(mode), ...this.parameterOverrides.get(runId) };
348
416
  }
349
417
 
350
418
  getCurrentMode(runId: string): ReasoningMode {
@@ -352,7 +420,7 @@ export class MetaReasoner {
352
420
  }
353
421
 
354
422
  getModeConfig(mode: ReasoningMode): ReasoningModeConfig {
355
- return this.config.modeProfiles[mode];
423
+ return this.config.modeProfiles[mode] ?? this.config.modeProfiles[this.config.defaultMode];
356
424
  }
357
425
 
358
426
  getRunStats(runId: string): {
@@ -377,9 +445,13 @@ export class MetaReasoner {
377
445
  this.collector.cleanupRun(runId);
378
446
  this.selector.cleanupRun(runId);
379
447
  this.assessments.delete(runId);
380
- this.adaptations.delete(runId);
381
448
  this.currentMode.delete(runId);
449
+ this.parameterOverrides.delete(runId);
382
450
  this.lastAssessmentTime.delete(runId);
383
451
  this.lastAdaptationTime.delete(runId);
452
+ for (const adaptation of this.adaptations.get(runId) ?? []) {
453
+ this.overridesBefore.delete(adaptation.id);
454
+ }
455
+ this.adaptations.delete(runId);
384
456
  }
385
457
  }
@@ -54,7 +54,11 @@ export class ObservationCollector {
54
54
 
55
55
  collect(context: ObservationContext, insights: Insight[]): MetaObservation {
56
56
  const { runId, iteration, goal, currentMode } = context;
57
- const prevObservations = this.observations.get(runId) ?? [];
57
+ let prevObservations = this.observations.get(runId);
58
+ if (!prevObservations) {
59
+ prevObservations = [];
60
+ this.observations.set(runId, prevObservations);
61
+ }
58
62
  const lastObs = prevObservations[prevObservations.length - 1];
59
63
  const actions = this.actionHistory.get(runId) ?? [];
60
64
  const confidenceHist = this.confidenceHistory.get(runId) ?? [];
@@ -62,7 +66,7 @@ export class ObservationCollector {
62
66
  const currentConfidence = confidenceHist[confidenceHist.length - 1] ?? 0.5;
63
67
  const progressScore = this.calculateProgress(actions);
64
68
  const progressDelta = lastObs ? progressScore - lastObs.progressScore : 0;
65
- const stagnationCount = progressDelta < 0.05 ? (lastObs?.stagnationCount ?? 0) + 1 : 0;
69
+ const stagnationCount = lastObs ? (progressDelta < 0.05 ? lastObs.stagnationCount + 1 : 0) : 0;
66
70
  const repetitionScore = this.calculateRepetition(actions);
67
71
  const toolSuccessRate = this.calculateToolSuccessRate(actions);
68
72
  const confidenceTrend = this.calculateTrend(confidenceHist);
@@ -1,4 +1,12 @@
1
- import type { MetaObservation, ReasoningMode, ReasoningModeConfig } from '@cogitator-ai/types';
1
+ import type {
2
+ MetaIssue,
3
+ MetaObservation,
4
+ MetaOpportunity,
5
+ MetaRecommendation,
6
+ ReasoningMode,
7
+ ReasoningModeConfig,
8
+ } from '@cogitator-ai/types';
9
+ import { extractJson } from '../utils';
2
10
 
3
11
  export function buildMetaAssessmentPrompt(
4
12
  observation: MetaObservation,
@@ -62,20 +70,20 @@ Analyze the agent's reasoning process and respond with a JSON object:
62
70
  "reasoning": "string",
63
71
  "issues": [
64
72
  {
65
- "type": "stagnation" | "repetition" | "resource_exhaustion" | "confidence_decline" | "strategy_mismatch" | "goal_drift",
66
- "severity": "low" | "medium" | "high" | "critical",
73
+ "type": "stagnation" | "low_confidence" | "high_cost" | "repetition" | "tool_failure",
74
+ "severity": "low" | "medium" | "high",
67
75
  "description": "string"
68
76
  }
69
77
  ],
70
78
  "opportunities": [
71
79
  {
72
- "type": "strategy_switch" | "temperature_adjust" | "tool_pivot" | "goal_refinement" | "context_injection",
80
+ "type": "mode_switch" | "parameter_tune" | "context_add" | "tool_compose",
73
81
  "description": "string",
74
82
  "expectedImprovement": number
75
83
  }
76
84
  ],
77
85
  "recommendation": {
78
- "action": "continue" | "switch_mode" | "adjust_parameters" | "inject_context" | "escalate" | "abort",
86
+ "action": "continue" | "switch_mode" | "adjust_parameters" | "inject_context" | "abort",
79
87
  "newMode": "string",
80
88
  "parameterChanges": {},
81
89
  "contextAddition": "string",
@@ -85,78 +93,145 @@ Analyze the agent's reasoning process and respond with a JSON object:
85
93
  }`;
86
94
  }
87
95
 
96
+ const REASONING_MODES: readonly ReasoningMode[] = [
97
+ 'analytical',
98
+ 'creative',
99
+ 'systematic',
100
+ 'intuitive',
101
+ 'reflective',
102
+ 'exploratory',
103
+ ];
104
+ const ISSUE_TYPES: readonly MetaIssue['type'][] = [
105
+ 'stagnation',
106
+ 'low_confidence',
107
+ 'high_cost',
108
+ 'repetition',
109
+ 'tool_failure',
110
+ ];
111
+ const SEVERITIES: readonly MetaIssue['severity'][] = ['low', 'medium', 'high'];
112
+ const OPPORTUNITY_TYPES: readonly MetaOpportunity['type'][] = [
113
+ 'mode_switch',
114
+ 'parameter_tune',
115
+ 'context_add',
116
+ 'tool_compose',
117
+ ];
118
+ const ACTIONS: readonly MetaRecommendation['action'][] = [
119
+ 'continue',
120
+ 'switch_mode',
121
+ 'adjust_parameters',
122
+ 'inject_context',
123
+ 'abort',
124
+ ];
125
+
88
126
  export interface ParsedAssessment {
89
- onTrack: boolean;
90
- confidence: number;
91
- reasoning: string;
92
- issues: Array<{
93
- type: string;
94
- severity: string;
95
- description: string;
96
- }>;
127
+ onTrack?: boolean;
128
+ confidence?: number;
129
+ reasoning?: string;
130
+ issues: MetaIssue[];
97
131
  opportunities: Array<{
98
- type: string;
132
+ type: MetaOpportunity['type'];
99
133
  description: string;
100
134
  expectedImprovement: number;
101
135
  }>;
102
- recommendation: {
103
- action: string;
104
- newMode?: string;
105
- parameterChanges?: Record<string, unknown>;
136
+ recommendation?: {
137
+ action: MetaRecommendation['action'];
138
+ newMode?: ReasoningMode;
139
+ parameterChanges?: Partial<ReasoningModeConfig>;
106
140
  contextAddition?: string;
107
141
  confidence: number;
108
142
  reasoning: string;
109
143
  };
110
144
  }
111
145
 
146
+ function isRecord(value: unknown): value is Record<string, unknown> {
147
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
148
+ }
149
+
150
+ function pick<T extends string>(value: unknown, allowed: readonly T[]): T | undefined {
151
+ return typeof value === 'string' && (allowed as readonly string[]).includes(value)
152
+ ? (value as T)
153
+ : undefined;
154
+ }
155
+
156
+ function probability(value: unknown): number | undefined {
157
+ return typeof value === 'number' && Number.isFinite(value)
158
+ ? Math.min(1, Math.max(0, value))
159
+ : undefined;
160
+ }
161
+
162
+ function parseParameterChanges(value: unknown): Partial<ReasoningModeConfig> | undefined {
163
+ if (!isRecord(value)) return undefined;
164
+ const changes: Partial<ReasoningModeConfig> = {};
165
+ if (typeof value.temperature === 'number' && Number.isFinite(value.temperature)) {
166
+ changes.temperature = Math.min(2, Math.max(0, value.temperature));
167
+ }
168
+ if (typeof value.depth === 'number' && Number.isFinite(value.depth)) {
169
+ changes.depth = Math.min(10, Math.max(1, Math.round(value.depth)));
170
+ }
171
+ return Object.keys(changes).length > 0 ? changes : undefined;
172
+ }
173
+
174
+ function parseRecommendation(value: unknown): ParsedAssessment['recommendation'] {
175
+ if (!isRecord(value)) return undefined;
176
+ const action = pick(value.action, ACTIONS);
177
+ if (!action) return undefined;
178
+
179
+ return {
180
+ action,
181
+ newMode: pick(value.newMode, REASONING_MODES),
182
+ parameterChanges: parseParameterChanges(value.parameterChanges),
183
+ contextAddition:
184
+ typeof value.contextAddition === 'string' && value.contextAddition.trim()
185
+ ? value.contextAddition.trim()
186
+ : undefined,
187
+ confidence: probability(value.confidence) ?? 0,
188
+ reasoning: typeof value.reasoning === 'string' ? value.reasoning : '',
189
+ };
190
+ }
191
+
112
192
  export function parseMetaAssessmentResponse(content: string): ParsedAssessment | null {
193
+ let parsed: unknown;
113
194
  try {
114
195
  const json = extractJson(content);
115
196
  if (!json) return null;
116
- return JSON.parse(json) as ParsedAssessment;
197
+ parsed = JSON.parse(json);
117
198
  } catch {
118
199
  return null;
119
200
  }
120
- }
121
-
122
- function extractJson(text: string): string | null {
123
- const start = text.indexOf('{');
124
- if (start === -1) return null;
125
-
126
- let depth = 0;
127
- let inString = false;
128
- let escape = false;
129
-
130
- for (let i = start; i < text.length; i++) {
131
- const ch = text[i];
132
-
133
- if (escape) {
134
- escape = false;
135
- continue;
136
- }
137
-
138
- if (ch === '\\' && inString) {
139
- escape = true;
140
- continue;
141
- }
142
-
143
- if (ch === '"') {
144
- inString = !inString;
145
- continue;
146
- }
147
-
148
- if (inString) continue;
201
+ if (!isRecord(parsed)) return null;
202
+
203
+ const issues: MetaIssue[] = [];
204
+ for (const raw of Array.isArray(parsed.issues) ? parsed.issues : []) {
205
+ if (!isRecord(raw)) continue;
206
+ const type = pick(raw.type, ISSUE_TYPES);
207
+ if (!type) continue;
208
+ issues.push({
209
+ type,
210
+ severity: pick(raw.severity, SEVERITIES) ?? 'medium',
211
+ description: typeof raw.description === 'string' ? raw.description : '',
212
+ });
213
+ }
149
214
 
150
- if (ch === '{') depth++;
151
- else if (ch === '}') {
152
- depth--;
153
- if (depth === 0) {
154
- return text.slice(start, i + 1);
155
- }
156
- }
215
+ const opportunities: ParsedAssessment['opportunities'] = [];
216
+ for (const raw of Array.isArray(parsed.opportunities) ? parsed.opportunities : []) {
217
+ if (!isRecord(raw)) continue;
218
+ const type = pick(raw.type, OPPORTUNITY_TYPES);
219
+ if (!type) continue;
220
+ opportunities.push({
221
+ type,
222
+ description: typeof raw.description === 'string' ? raw.description : '',
223
+ expectedImprovement: probability(raw.expectedImprovement) ?? 0.5,
224
+ });
157
225
  }
158
226
 
159
- return null;
227
+ return {
228
+ onTrack: typeof parsed.onTrack === 'boolean' ? parsed.onTrack : undefined,
229
+ confidence: probability(parsed.confidence),
230
+ reasoning: typeof parsed.reasoning === 'string' ? parsed.reasoning : undefined,
231
+ issues,
232
+ opportunities,
233
+ recommendation: parseRecommendation(parsed.recommendation),
234
+ };
160
235
  }
161
236
 
162
237
  export const META_REASONING_SYSTEM_PROMPT = `You are a meta-reasoning system analyzing an AI agent's reasoning process.
@@ -143,6 +143,12 @@ export class StrategySelector {
143
143
  if (currentMode === 'intuitive' && alternatives.includes('analytical')) {
144
144
  return 'analytical';
145
145
  }
146
+ if (currentMode === 'reflective' && alternatives.includes('intuitive')) {
147
+ return 'intuitive';
148
+ }
149
+ if (currentMode === 'exploratory' && alternatives.includes('analytical')) {
150
+ return 'analytical';
151
+ }
146
152
 
147
153
  return alternatives[0] ?? null;
148
154
  }