@cogitator-ai/self-modifying 17.0.16 → 17.0.18
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.
- package/LICENSE +21 -0
- package/dist/architecture-evolution/capability-analyzer.d.ts.map +1 -1
- package/dist/architecture-evolution/capability-analyzer.js +6 -3
- package/dist/architecture-evolution/capability-analyzer.js.map +1 -1
- package/dist/architecture-evolution/evolution-strategy.d.ts.map +1 -1
- package/dist/architecture-evolution/evolution-strategy.js +4 -2
- package/dist/architecture-evolution/evolution-strategy.js.map +1 -1
- package/dist/architecture-evolution/parameter-optimizer.d.ts.map +1 -1
- package/dist/architecture-evolution/parameter-optimizer.js +32 -9
- package/dist/architecture-evolution/parameter-optimizer.js.map +1 -1
- package/dist/architecture-evolution/prompts.d.ts.map +1 -1
- package/dist/architecture-evolution/prompts.js +42 -4
- package/dist/architecture-evolution/prompts.js.map +1 -1
- package/dist/constraints/modification-validator.d.ts.map +1 -1
- package/dist/constraints/modification-validator.js +16 -5
- package/dist/constraints/modification-validator.js.map +1 -1
- package/dist/constraints/rollback-manager.d.ts +1 -0
- package/dist/constraints/rollback-manager.d.ts.map +1 -1
- package/dist/constraints/rollback-manager.js +25 -1
- package/dist/constraints/rollback-manager.js.map +1 -1
- package/dist/events/event-emitter.d.ts +0 -1
- package/dist/events/event-emitter.d.ts.map +1 -1
- package/dist/events/event-emitter.js +6 -10
- package/dist/events/event-emitter.js.map +1 -1
- package/dist/meta-reasoning/meta-reasoner.d.ts +1 -1
- package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -1
- package/dist/meta-reasoning/meta-reasoner.js +22 -13
- package/dist/meta-reasoning/meta-reasoner.js.map +1 -1
- package/dist/meta-reasoning/observation-collector.d.ts.map +1 -1
- package/dist/meta-reasoning/observation-collector.js +6 -2
- package/dist/meta-reasoning/observation-collector.js.map +1 -1
- package/dist/meta-reasoning/prompts.d.ts.map +1 -1
- package/dist/meta-reasoning/prompts.js +5 -38
- package/dist/meta-reasoning/prompts.js.map +1 -1
- package/dist/meta-reasoning/strategy-selector.d.ts.map +1 -1
- package/dist/meta-reasoning/strategy-selector.js +6 -0
- package/dist/meta-reasoning/strategy-selector.js.map +1 -1
- package/dist/self-modifying-agent.d.ts +8 -1
- package/dist/self-modifying-agent.d.ts.map +1 -1
- package/dist/self-modifying-agent.js +108 -14
- package/dist/self-modifying-agent.js.map +1 -1
- package/dist/tool-generation/gap-analyzer.d.ts.map +1 -1
- package/dist/tool-generation/gap-analyzer.js +3 -2
- package/dist/tool-generation/gap-analyzer.js.map +1 -1
- package/dist/tool-generation/generated-tool-store.d.ts.map +1 -1
- package/dist/tool-generation/generated-tool-store.js +90 -10
- package/dist/tool-generation/generated-tool-store.js.map +1 -1
- package/dist/tool-generation/index.d.ts +1 -1
- package/dist/tool-generation/index.d.ts.map +1 -1
- package/dist/tool-generation/index.js +1 -1
- package/dist/tool-generation/index.js.map +1 -1
- package/dist/tool-generation/prompts.d.ts +3 -3
- package/dist/tool-generation/prompts.d.ts.map +1 -1
- package/dist/tool-generation/prompts.js +65 -12
- package/dist/tool-generation/prompts.js.map +1 -1
- package/dist/tool-generation/tool-generator.d.ts +1 -1
- package/dist/tool-generation/tool-generator.d.ts.map +1 -1
- package/dist/tool-generation/tool-generator.js +55 -3
- package/dist/tool-generation/tool-generator.js.map +1 -1
- package/dist/tool-generation/tool-sandbox.d.ts +2 -6
- package/dist/tool-generation/tool-sandbox.d.ts.map +1 -1
- package/dist/tool-generation/tool-sandbox.js +220 -130
- package/dist/tool-generation/tool-sandbox.js.map +1 -1
- package/dist/tool-generation/tool-validator.d.ts +1 -0
- package/dist/tool-generation/tool-validator.d.ts.map +1 -1
- package/dist/tool-generation/tool-validator.js +48 -1
- package/dist/tool-generation/tool-validator.js.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +30 -5
- package/dist/utils/index.js.map +1 -1
- package/package.json +14 -14
- package/src/__tests__/self-modifying-agent.test.ts +42 -10
- package/src/architecture-evolution/capability-analyzer.ts +7 -4
- package/src/architecture-evolution/evolution-strategy.ts +5 -2
- package/src/architecture-evolution/parameter-optimizer.ts +39 -15
- package/src/architecture-evolution/prompts.ts +48 -4
- package/src/constraints/modification-validator.ts +19 -8
- package/src/constraints/rollback-manager.ts +20 -1
- package/src/events/event-emitter.ts +6 -15
- package/src/meta-reasoning/meta-reasoner.ts +22 -15
- package/src/meta-reasoning/observation-collector.ts +6 -2
- package/src/meta-reasoning/prompts.ts +5 -44
- package/src/meta-reasoning/strategy-selector.ts +6 -0
- package/src/self-modifying-agent.ts +123 -14
- package/src/tool-generation/gap-analyzer.ts +3 -2
- package/src/tool-generation/generated-tool-store.ts +97 -10
- package/src/tool-generation/index.ts +1 -1
- package/src/tool-generation/prompts.ts +81 -12
- package/src/tool-generation/tool-generator.ts +71 -3
- package/src/tool-generation/tool-sandbox.ts +241 -170
- package/src/tool-generation/tool-validator.ts +51 -1
- package/src/utils/index.ts +29 -5
|
@@ -106,19 +106,23 @@ export class MetaReasoner {
|
|
|
106
106
|
);
|
|
107
107
|
|
|
108
108
|
case 'confidence_drop':
|
|
109
|
+
case 'on_low_confidence':
|
|
109
110
|
return context.confidence < this.config.triggerOnConfidenceDrop;
|
|
110
111
|
|
|
111
112
|
case 'progress_stall':
|
|
113
|
+
case 'on_stagnation':
|
|
112
114
|
return context.stagnationCount >= this.config.triggerOnProgressStall;
|
|
113
115
|
|
|
114
|
-
case 'periodic':
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
case 'periodic': {
|
|
117
|
+
const elapsed = Date.now() - lastAssessment;
|
|
118
|
+
return elapsed >= this.config.metaAssessmentCooldown * this.config.triggerAfterIterations;
|
|
119
|
+
}
|
|
118
120
|
|
|
121
|
+
case 'on_failure':
|
|
119
122
|
case 'tool_call_failed':
|
|
120
123
|
return true;
|
|
121
124
|
|
|
125
|
+
case 'on_request':
|
|
122
126
|
case 'explicit_request':
|
|
123
127
|
return true;
|
|
124
128
|
|
|
@@ -293,34 +297,37 @@ export class MetaReasoner {
|
|
|
293
297
|
return adaptation;
|
|
294
298
|
}
|
|
295
299
|
|
|
296
|
-
rollback(runId: string): MetaAdaptation | null {
|
|
300
|
+
rollback(runId: string, adaptationId?: string): MetaAdaptation | null {
|
|
297
301
|
const runAdaptations = this.adaptations.get(runId) ?? [];
|
|
298
|
-
const
|
|
302
|
+
const target = adaptationId
|
|
303
|
+
? runAdaptations.find((a) => a.id === adaptationId)
|
|
304
|
+
: runAdaptations[runAdaptations.length - 1];
|
|
299
305
|
|
|
300
|
-
if (!
|
|
306
|
+
if (!target?.rollbackable) {
|
|
301
307
|
return null;
|
|
302
308
|
}
|
|
303
309
|
|
|
304
|
-
if (
|
|
310
|
+
if (target.rollbackDeadline && Date.now() > target.rollbackDeadline) {
|
|
305
311
|
return null;
|
|
306
312
|
}
|
|
307
313
|
|
|
308
314
|
const rollback: MetaAdaptation = {
|
|
309
315
|
id: `rollback_${nanoid(10)}`,
|
|
310
|
-
assessmentId:
|
|
316
|
+
assessmentId: target.assessmentId,
|
|
311
317
|
timestamp: Date.now(),
|
|
312
318
|
|
|
313
319
|
type: 'rollback',
|
|
314
|
-
before:
|
|
315
|
-
after:
|
|
320
|
+
before: target.after,
|
|
321
|
+
after: target.before,
|
|
316
322
|
|
|
317
323
|
rollbackable: false,
|
|
318
324
|
};
|
|
319
325
|
|
|
320
|
-
if (
|
|
321
|
-
this.currentMode.set(runId,
|
|
326
|
+
if (target.type === 'mode_switch' && target.before.mode) {
|
|
327
|
+
this.currentMode.set(runId, target.before.mode);
|
|
322
328
|
}
|
|
323
329
|
|
|
330
|
+
target.rollbackable = false;
|
|
324
331
|
runAdaptations.push(rollback);
|
|
325
332
|
return rollback;
|
|
326
333
|
}
|
|
@@ -337,7 +344,7 @@ export class MetaReasoner {
|
|
|
337
344
|
adaptation.outcome = outcome;
|
|
338
345
|
|
|
339
346
|
if (this.config.rollbackOnDecline && !outcome.improved && adaptation.rollbackable) {
|
|
340
|
-
this.rollback(runId);
|
|
347
|
+
this.rollback(runId, adaptationId);
|
|
341
348
|
}
|
|
342
349
|
}
|
|
343
350
|
}
|
|
@@ -352,7 +359,7 @@ export class MetaReasoner {
|
|
|
352
359
|
}
|
|
353
360
|
|
|
354
361
|
getModeConfig(mode: ReasoningMode): ReasoningModeConfig {
|
|
355
|
-
return this.config.modeProfiles[mode];
|
|
362
|
+
return this.config.modeProfiles[mode] ?? this.config.modeProfiles[this.config.defaultMode];
|
|
356
363
|
}
|
|
357
364
|
|
|
358
365
|
getRunStats(runId: string): {
|
|
@@ -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
|
-
|
|
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 ?
|
|
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,5 @@
|
|
|
1
1
|
import type { MetaObservation, ReasoningMode, ReasoningModeConfig } from '@cogitator-ai/types';
|
|
2
|
+
import { extractJson } from '../utils';
|
|
2
3
|
|
|
3
4
|
export function buildMetaAssessmentPrompt(
|
|
4
5
|
observation: MetaObservation,
|
|
@@ -62,20 +63,20 @@ Analyze the agent's reasoning process and respond with a JSON object:
|
|
|
62
63
|
"reasoning": "string",
|
|
63
64
|
"issues": [
|
|
64
65
|
{
|
|
65
|
-
"type": "stagnation" | "
|
|
66
|
-
"severity": "low" | "medium" | "high"
|
|
66
|
+
"type": "stagnation" | "low_confidence" | "high_cost" | "repetition" | "tool_failure",
|
|
67
|
+
"severity": "low" | "medium" | "high",
|
|
67
68
|
"description": "string"
|
|
68
69
|
}
|
|
69
70
|
],
|
|
70
71
|
"opportunities": [
|
|
71
72
|
{
|
|
72
|
-
"type": "
|
|
73
|
+
"type": "mode_switch" | "parameter_tune" | "context_add" | "tool_compose",
|
|
73
74
|
"description": "string",
|
|
74
75
|
"expectedImprovement": number
|
|
75
76
|
}
|
|
76
77
|
],
|
|
77
78
|
"recommendation": {
|
|
78
|
-
"action": "continue" | "switch_mode" | "adjust_parameters" | "inject_context" | "
|
|
79
|
+
"action": "continue" | "switch_mode" | "adjust_parameters" | "inject_context" | "abort",
|
|
79
80
|
"newMode": "string",
|
|
80
81
|
"parameterChanges": {},
|
|
81
82
|
"contextAddition": "string",
|
|
@@ -119,46 +120,6 @@ export function parseMetaAssessmentResponse(content: string): ParsedAssessment |
|
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
|
|
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;
|
|
149
|
-
|
|
150
|
-
if (ch === '{') depth++;
|
|
151
|
-
else if (ch === '}') {
|
|
152
|
-
depth--;
|
|
153
|
-
if (depth === 0) {
|
|
154
|
-
return text.slice(start, i + 1);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
123
|
export const META_REASONING_SYSTEM_PROMPT = `You are a meta-reasoning system analyzing an AI agent's reasoning process.
|
|
163
124
|
Your job is to assess whether the agent is on track and recommend strategic adjustments.
|
|
164
125
|
|
|
@@ -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
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
1
2
|
import type {
|
|
2
3
|
Agent,
|
|
3
4
|
AgentConfig,
|
|
@@ -9,6 +10,8 @@ import type {
|
|
|
9
10
|
MetaObservation,
|
|
10
11
|
MetaAdaptation,
|
|
11
12
|
ModificationCheckpoint,
|
|
13
|
+
AppliedModification,
|
|
14
|
+
ModificationRequest,
|
|
12
15
|
SelfModifyingEvent,
|
|
13
16
|
CapabilityGap,
|
|
14
17
|
Message,
|
|
@@ -44,6 +47,8 @@ export interface RunContext {
|
|
|
44
47
|
observations: MetaObservation[];
|
|
45
48
|
adaptations: MetaAdaptation[];
|
|
46
49
|
checkpoints: ModificationCheckpoint[];
|
|
50
|
+
modificationsCount: number;
|
|
51
|
+
appliedModifications: AppliedModification[];
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
export class SelfModifyingAgent {
|
|
@@ -63,6 +68,7 @@ export class SelfModifyingAgent {
|
|
|
63
68
|
|
|
64
69
|
private currentContext: RunContext | null = null;
|
|
65
70
|
private isInitialized = false;
|
|
71
|
+
private storedExecutableTools: Tool[] = [];
|
|
66
72
|
|
|
67
73
|
constructor(options: SelfModifyingAgentOptions) {
|
|
68
74
|
this.agent = options.agent;
|
|
@@ -145,7 +151,7 @@ export class SelfModifyingAgent {
|
|
|
145
151
|
const tools = this.getAvailableTools();
|
|
146
152
|
|
|
147
153
|
const baseConfig: ArchitectureConfig = {
|
|
148
|
-
model: 'default',
|
|
154
|
+
model: this.agent.model ?? 'default',
|
|
149
155
|
temperature: 0.7,
|
|
150
156
|
maxTokens: 4096,
|
|
151
157
|
toolStrategy: 'sequential',
|
|
@@ -162,6 +168,8 @@ export class SelfModifyingAgent {
|
|
|
162
168
|
observations: [],
|
|
163
169
|
adaptations: [],
|
|
164
170
|
checkpoints: [],
|
|
171
|
+
modificationsCount: 0,
|
|
172
|
+
appliedModifications: [],
|
|
165
173
|
};
|
|
166
174
|
|
|
167
175
|
void this.emitter.emit({
|
|
@@ -172,6 +180,10 @@ export class SelfModifyingAgent {
|
|
|
172
180
|
});
|
|
173
181
|
|
|
174
182
|
try {
|
|
183
|
+
if (this.config.constraints.enabled && this.config.constraints.autoRollback) {
|
|
184
|
+
await this.createCheckpoint();
|
|
185
|
+
}
|
|
186
|
+
|
|
175
187
|
if (this.config.architectureEvolution.enabled) {
|
|
176
188
|
await this.optimizeArchitecture(input);
|
|
177
189
|
}
|
|
@@ -215,6 +227,10 @@ export class SelfModifyingAgent {
|
|
|
215
227
|
|
|
216
228
|
return result;
|
|
217
229
|
} catch (error) {
|
|
230
|
+
if (this.config.constraints.enabled && this.config.constraints.autoRollback) {
|
|
231
|
+
await this.autoRollbackOnError();
|
|
232
|
+
}
|
|
233
|
+
|
|
218
234
|
void this.emitter.emit({
|
|
219
235
|
type: 'run_completed',
|
|
220
236
|
runId,
|
|
@@ -301,7 +317,7 @@ export class SelfModifyingAgent {
|
|
|
301
317
|
this.agent.name || 'agent',
|
|
302
318
|
agentConfig,
|
|
303
319
|
this.currentContext.tools,
|
|
304
|
-
[]
|
|
320
|
+
[...this.currentContext.appliedModifications]
|
|
305
321
|
);
|
|
306
322
|
|
|
307
323
|
this.currentContext.checkpoints.push(checkpoint);
|
|
@@ -322,6 +338,13 @@ export class SelfModifyingAgent {
|
|
|
322
338
|
|
|
323
339
|
if (this.currentContext) {
|
|
324
340
|
this.currentContext.tools = restored.tools;
|
|
341
|
+
this.currentContext.currentConfig = {
|
|
342
|
+
...this.currentContext.currentConfig,
|
|
343
|
+
model: restored.agentConfig.model ?? this.currentContext.currentConfig.model,
|
|
344
|
+
temperature:
|
|
345
|
+
restored.agentConfig.temperature ?? this.currentContext.currentConfig.temperature,
|
|
346
|
+
maxTokens: restored.agentConfig.maxTokens ?? this.currentContext.currentConfig.maxTokens,
|
|
347
|
+
};
|
|
325
348
|
}
|
|
326
349
|
|
|
327
350
|
void this.emitter.emit({
|
|
@@ -340,7 +363,8 @@ export class SelfModifyingAgent {
|
|
|
340
363
|
private async ensureInitialized(): Promise<void> {
|
|
341
364
|
if (this.isInitialized) return;
|
|
342
365
|
|
|
343
|
-
await this.toolStore.list({ status: 'active' });
|
|
366
|
+
const activeTools = await this.toolStore.list({ status: 'active' });
|
|
367
|
+
this.storedExecutableTools = activeTools.map((t) => this.toolGenerator.createExecutableTool(t));
|
|
344
368
|
|
|
345
369
|
this.isInitialized = true;
|
|
346
370
|
}
|
|
@@ -447,7 +471,7 @@ export class SelfModifyingAgent {
|
|
|
447
471
|
}
|
|
448
472
|
|
|
449
473
|
private getAvailableTools(): Tool[] {
|
|
450
|
-
return this.agent.tools ?? [];
|
|
474
|
+
return [...(this.agent.tools ?? []), ...this.storedExecutableTools];
|
|
451
475
|
}
|
|
452
476
|
|
|
453
477
|
private async optimizeArchitecture(input: string): Promise<void> {
|
|
@@ -456,22 +480,24 @@ export class SelfModifyingAgent {
|
|
|
456
480
|
try {
|
|
457
481
|
const result = await this.parameterOptimizer.optimize(input);
|
|
458
482
|
|
|
459
|
-
if (result.shouldAdopt && result.confidence > 0.6) {
|
|
460
|
-
const validation = await this.
|
|
483
|
+
if (result.shouldAdopt && result.confidence > 0.6 && this.canApplyModification()) {
|
|
484
|
+
const validation = await this.validateModification({
|
|
461
485
|
type: 'config_change',
|
|
462
486
|
target: 'architecture',
|
|
463
487
|
changes: result.recommendedConfig,
|
|
464
488
|
reason: result.reasoning,
|
|
465
489
|
});
|
|
466
490
|
|
|
467
|
-
if (validation
|
|
491
|
+
if (validation) {
|
|
468
492
|
this.currentContext.currentConfig = result.recommendedConfig;
|
|
493
|
+
this.recordModification('config_change', result.recommendedConfig);
|
|
469
494
|
|
|
470
495
|
void this.emitter.emit({
|
|
471
496
|
type: 'architecture_evolved',
|
|
472
497
|
runId: this.currentContext.runId,
|
|
473
498
|
timestamp: new Date(),
|
|
474
499
|
data: {
|
|
500
|
+
success: true,
|
|
475
501
|
candidateId: result.candidate?.id,
|
|
476
502
|
changes: result.recommendedConfig,
|
|
477
503
|
metrics: result.metrics,
|
|
@@ -484,7 +510,10 @@ export class SelfModifyingAgent {
|
|
|
484
510
|
type: 'architecture_evolved',
|
|
485
511
|
runId: this.currentContext.runId,
|
|
486
512
|
timestamp: new Date(),
|
|
487
|
-
data: {
|
|
513
|
+
data: {
|
|
514
|
+
success: false,
|
|
515
|
+
error: error instanceof Error ? error.message : String(error),
|
|
516
|
+
},
|
|
488
517
|
});
|
|
489
518
|
}
|
|
490
519
|
}
|
|
@@ -496,6 +525,12 @@ export class SelfModifyingAgent {
|
|
|
496
525
|
const analysis = await this.gapAnalyzer.analyze(input, this.currentContext.tools);
|
|
497
526
|
|
|
498
527
|
for (const gap of analysis.gaps) {
|
|
528
|
+
if (
|
|
529
|
+
this.currentContext.generatedTools.length >= this.config.toolGeneration.maxToolsPerSession
|
|
530
|
+
) {
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
|
|
499
534
|
if (gap.confidence >= this.config.toolGeneration.minConfidenceForGeneration) {
|
|
500
535
|
void this.emitter.emit({
|
|
501
536
|
type: 'tool_generation_started',
|
|
@@ -506,11 +541,41 @@ export class SelfModifyingAgent {
|
|
|
506
541
|
|
|
507
542
|
const tool = await this.generateTool(gap);
|
|
508
543
|
|
|
509
|
-
if (tool)
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
544
|
+
if (!tool) continue;
|
|
545
|
+
|
|
546
|
+
const linesOfCode = tool.implementation.split('\n').length;
|
|
547
|
+
const validated = await this.validateModification({
|
|
548
|
+
type: 'tool_generation',
|
|
549
|
+
target: tool.name,
|
|
550
|
+
changes: { name: tool.name, implementation: tool.implementation },
|
|
551
|
+
reason: `Generated tool for gap: ${gap.suggestedToolName}`,
|
|
552
|
+
payload: {
|
|
553
|
+
sandboxExecution: this.config.toolGeneration.sandboxConfig?.enabled ?? false,
|
|
554
|
+
linesOfCode,
|
|
555
|
+
complexity: linesOfCode,
|
|
556
|
+
modificationDepth: 1,
|
|
557
|
+
},
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
if (!validated || !this.canApplyModification()) {
|
|
561
|
+
void this.emitter.emit({
|
|
562
|
+
type: 'tool_generation_completed',
|
|
563
|
+
runId: this.currentContext.runId,
|
|
564
|
+
timestamp: new Date(),
|
|
565
|
+
data: {
|
|
566
|
+
toolId: tool.id,
|
|
567
|
+
name: tool.name,
|
|
568
|
+
success: false,
|
|
569
|
+
error: 'Rejected by safety constraints or modification limit',
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
continue;
|
|
513
573
|
}
|
|
574
|
+
|
|
575
|
+
this.currentContext.generatedTools.push(tool);
|
|
576
|
+
const executableTool = this.toolGenerator.createExecutableTool(tool);
|
|
577
|
+
this.currentContext.tools.push(executableTool);
|
|
578
|
+
this.recordModification('tool_generation', { toolId: tool.id, name: tool.name });
|
|
514
579
|
}
|
|
515
580
|
}
|
|
516
581
|
} catch (error) {
|
|
@@ -693,6 +758,49 @@ export class SelfModifyingAgent {
|
|
|
693
758
|
});
|
|
694
759
|
}
|
|
695
760
|
|
|
761
|
+
private async validateModification(request: ModificationRequest): Promise<boolean> {
|
|
762
|
+
if (!this.config.constraints.enabled) return true;
|
|
763
|
+
|
|
764
|
+
const validation = await this.modificationValidator.validate(request);
|
|
765
|
+
|
|
766
|
+
if (validation.rollbackRequired && this.config.constraints.autoRollback) {
|
|
767
|
+
await this.autoRollbackOnError();
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return validation.valid;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
private canApplyModification(): boolean {
|
|
774
|
+
if (!this.config.constraints.enabled) return true;
|
|
775
|
+
if (!this.currentContext) return true;
|
|
776
|
+
return this.currentContext.modificationsCount < this.config.constraints.maxModificationsPerRun;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
private recordModification(type: string, data: unknown): void {
|
|
780
|
+
if (!this.currentContext) return;
|
|
781
|
+
this.currentContext.modificationsCount++;
|
|
782
|
+
this.currentContext.appliedModifications.push({
|
|
783
|
+
id: `mod_${nanoid(8)}`,
|
|
784
|
+
type,
|
|
785
|
+
appliedAt: new Date(),
|
|
786
|
+
data,
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
private async autoRollbackOnError(): Promise<void> {
|
|
791
|
+
if (!this.currentContext) return;
|
|
792
|
+
|
|
793
|
+
const now = Date.now();
|
|
794
|
+
const window = this.config.constraints.rollbackWindow;
|
|
795
|
+
const target = this.currentContext.checkpoints
|
|
796
|
+
.filter((c) => now - c.timestamp.getTime() <= window)
|
|
797
|
+
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())[0];
|
|
798
|
+
|
|
799
|
+
if (target) {
|
|
800
|
+
await this.rollbackToCheckpoint(target.id);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
696
804
|
private estimateConfidence(output: string): number {
|
|
697
805
|
if (!output) return 0.3;
|
|
698
806
|
if (output.length < 50) return 0.4;
|
|
@@ -700,7 +808,8 @@ export class SelfModifyingAgent {
|
|
|
700
808
|
return 0.8;
|
|
701
809
|
}
|
|
702
810
|
|
|
703
|
-
private isTaskComplete(
|
|
704
|
-
return
|
|
811
|
+
private isTaskComplete(output: string): boolean {
|
|
812
|
+
if (!output.trim()) return false;
|
|
813
|
+
return this.estimateConfidence(output) >= 0.6;
|
|
705
814
|
}
|
|
706
815
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import type {
|
|
2
3
|
Tool,
|
|
3
4
|
LLMBackend,
|
|
@@ -151,7 +152,6 @@ Consider tool composition before suggesting new tools.`,
|
|
|
151
152
|
return 1.0;
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
const _intentWords = userIntent.toLowerCase().split(/\s+/).length;
|
|
155
155
|
const toolDescriptionWords = availableTools
|
|
156
156
|
.map((t) => t.description.toLowerCase().split(/\s+/))
|
|
157
157
|
.flat();
|
|
@@ -222,7 +222,8 @@ Consider tool composition before suggesting new tools.`,
|
|
|
222
222
|
.map((t) => t.name)
|
|
223
223
|
.sort()
|
|
224
224
|
.join(',');
|
|
225
|
-
|
|
225
|
+
const raw = `${userIntent}|${toolSignature}`;
|
|
226
|
+
return createHash('sha256').update(raw).digest('hex');
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
clearCache(): void {
|
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
import type { GeneratedTool, GeneratedToolStore as IGeneratedToolStore } from '@cogitator-ai/types';
|
|
2
2
|
|
|
3
|
+
const STOP_WORDS = new Set([
|
|
4
|
+
'the',
|
|
5
|
+
'and',
|
|
6
|
+
'for',
|
|
7
|
+
'not',
|
|
8
|
+
'are',
|
|
9
|
+
'was',
|
|
10
|
+
'were',
|
|
11
|
+
'been',
|
|
12
|
+
'being',
|
|
13
|
+
'have',
|
|
14
|
+
'has',
|
|
15
|
+
'had',
|
|
16
|
+
'does',
|
|
17
|
+
'did',
|
|
18
|
+
'will',
|
|
19
|
+
'would',
|
|
20
|
+
'could',
|
|
21
|
+
'should',
|
|
22
|
+
'may',
|
|
23
|
+
'might',
|
|
24
|
+
'shall',
|
|
25
|
+
'can',
|
|
26
|
+
'this',
|
|
27
|
+
'that',
|
|
28
|
+
'these',
|
|
29
|
+
'those',
|
|
30
|
+
'with',
|
|
31
|
+
'from',
|
|
32
|
+
'into',
|
|
33
|
+
'through',
|
|
34
|
+
'during',
|
|
35
|
+
'before',
|
|
36
|
+
'after',
|
|
37
|
+
'above',
|
|
38
|
+
'below',
|
|
39
|
+
'between',
|
|
40
|
+
'under',
|
|
41
|
+
'over',
|
|
42
|
+
'again',
|
|
43
|
+
'further',
|
|
44
|
+
'then',
|
|
45
|
+
'once',
|
|
46
|
+
'here',
|
|
47
|
+
'there',
|
|
48
|
+
'when',
|
|
49
|
+
'where',
|
|
50
|
+
'why',
|
|
51
|
+
'how',
|
|
52
|
+
'all',
|
|
53
|
+
'each',
|
|
54
|
+
'every',
|
|
55
|
+
'both',
|
|
56
|
+
'few',
|
|
57
|
+
'more',
|
|
58
|
+
'most',
|
|
59
|
+
'other',
|
|
60
|
+
'some',
|
|
61
|
+
'such',
|
|
62
|
+
'only',
|
|
63
|
+
'own',
|
|
64
|
+
'same',
|
|
65
|
+
'than',
|
|
66
|
+
'too',
|
|
67
|
+
'very',
|
|
68
|
+
'just',
|
|
69
|
+
'because',
|
|
70
|
+
'but',
|
|
71
|
+
'nor',
|
|
72
|
+
'yet',
|
|
73
|
+
'about',
|
|
74
|
+
]);
|
|
75
|
+
|
|
3
76
|
export interface ToolUsageRecord {
|
|
4
77
|
toolId: string;
|
|
5
78
|
timestamp: Date;
|
|
@@ -25,7 +98,7 @@ export class InMemoryGeneratedToolStore implements IGeneratedToolStore {
|
|
|
25
98
|
|
|
26
99
|
async save(tool: GeneratedTool): Promise<void> {
|
|
27
100
|
const existing = this.tools.get(tool.id);
|
|
28
|
-
const version = existing ? existing.version + 1 :
|
|
101
|
+
const version = existing ? existing.version + 1 : 1;
|
|
29
102
|
this.tools.set(tool.id, { ...tool, version, updatedAt: new Date() });
|
|
30
103
|
}
|
|
31
104
|
|
|
@@ -140,17 +213,27 @@ export class InMemoryGeneratedToolStore implements IGeneratedToolStore {
|
|
|
140
213
|
}
|
|
141
214
|
|
|
142
215
|
async findSimilar(description: string, limit: number = 5): Promise<GeneratedTool[]> {
|
|
143
|
-
const descWords = new Set(
|
|
216
|
+
const descWords = new Set(
|
|
217
|
+
description
|
|
218
|
+
.toLowerCase()
|
|
219
|
+
.split(/\s+/)
|
|
220
|
+
.filter((w) => w.length >= 3 && !STOP_WORDS.has(w))
|
|
221
|
+
);
|
|
144
222
|
const scored: Array<{ tool: GeneratedTool; score: number }> = [];
|
|
145
223
|
|
|
146
224
|
for (const tool of this.tools.values()) {
|
|
147
225
|
if (tool.status === 'deprecated') continue;
|
|
148
226
|
|
|
149
|
-
const toolWords = new Set(
|
|
227
|
+
const toolWords = new Set(
|
|
228
|
+
`${tool.name} ${tool.description}`
|
|
229
|
+
.toLowerCase()
|
|
230
|
+
.split(/\s+/)
|
|
231
|
+
.filter((w) => w.length >= 3 && !STOP_WORDS.has(w))
|
|
232
|
+
);
|
|
150
233
|
|
|
151
234
|
let matchCount = 0;
|
|
152
235
|
for (const word of descWords) {
|
|
153
|
-
if (
|
|
236
|
+
if (toolWords.has(word)) {
|
|
154
237
|
matchCount++;
|
|
155
238
|
}
|
|
156
239
|
}
|
|
@@ -204,13 +287,13 @@ export class InMemoryGeneratedToolStore implements IGeneratedToolStore {
|
|
|
204
287
|
let removed = 0;
|
|
205
288
|
const now = Date.now();
|
|
206
289
|
|
|
290
|
+
const keysToRemove: string[] = [];
|
|
291
|
+
|
|
207
292
|
for (const [id, tool] of this.tools) {
|
|
208
293
|
if (options.maxAge && tool.createdAt) {
|
|
209
294
|
const age = now - tool.createdAt.getTime();
|
|
210
295
|
if (age > options.maxAge && tool.status !== 'active') {
|
|
211
|
-
|
|
212
|
-
this.usageRecords.delete(id);
|
|
213
|
-
removed++;
|
|
296
|
+
keysToRemove.push(id);
|
|
214
297
|
continue;
|
|
215
298
|
}
|
|
216
299
|
}
|
|
@@ -218,13 +301,17 @@ export class InMemoryGeneratedToolStore implements IGeneratedToolStore {
|
|
|
218
301
|
if (options.minUsage !== undefined) {
|
|
219
302
|
const usage = tool.usageCount || 0;
|
|
220
303
|
if (usage < options.minUsage && tool.status === 'deprecated') {
|
|
221
|
-
|
|
222
|
-
this.usageRecords.delete(id);
|
|
223
|
-
removed++;
|
|
304
|
+
keysToRemove.push(id);
|
|
224
305
|
}
|
|
225
306
|
}
|
|
226
307
|
}
|
|
227
308
|
|
|
309
|
+
for (const id of keysToRemove) {
|
|
310
|
+
this.tools.delete(id);
|
|
311
|
+
this.usageRecords.delete(id);
|
|
312
|
+
removed++;
|
|
313
|
+
}
|
|
314
|
+
|
|
228
315
|
if (options.maxDeprecated !== undefined) {
|
|
229
316
|
const deprecated = Array.from(this.tools.values())
|
|
230
317
|
.filter((t) => t.status === 'deprecated')
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { GapAnalyzer, type GapAnalyzerOptions } from './gap-analyzer';
|
|
2
2
|
export { ToolGenerator, type ToolGeneratorOptions, type GenerationResult } from './tool-generator';
|
|
3
3
|
export { ToolValidator, type ToolValidatorOptions } from './tool-validator';
|
|
4
|
-
export { ToolSandbox, DEFAULT_SANDBOX_CONFIG } from './tool-sandbox';
|
|
4
|
+
export { ToolSandbox, DEFAULT_SANDBOX_CONFIG, deepEqual } from './tool-sandbox';
|
|
5
5
|
export {
|
|
6
6
|
InMemoryGeneratedToolStore,
|
|
7
7
|
type ToolUsageRecord,
|