@cogitator-ai/self-modifying 0.1.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.
- package/LICENSE +21 -0
- package/README.md +714 -0
- package/dist/architecture-evolution/capability-analyzer.d.ts +32 -0
- package/dist/architecture-evolution/capability-analyzer.d.ts.map +1 -0
- package/dist/architecture-evolution/capability-analyzer.js +264 -0
- package/dist/architecture-evolution/capability-analyzer.js.map +1 -0
- package/dist/architecture-evolution/evolution-strategy.d.ts +29 -0
- package/dist/architecture-evolution/evolution-strategy.d.ts.map +1 -0
- package/dist/architecture-evolution/evolution-strategy.js +176 -0
- package/dist/architecture-evolution/evolution-strategy.js.map +1 -0
- package/dist/architecture-evolution/index.d.ts +5 -0
- package/dist/architecture-evolution/index.d.ts.map +1 -0
- package/dist/architecture-evolution/index.js +5 -0
- package/dist/architecture-evolution/index.js.map +1 -0
- package/dist/architecture-evolution/parameter-optimizer.d.ts +67 -0
- package/dist/architecture-evolution/parameter-optimizer.d.ts.map +1 -0
- package/dist/architecture-evolution/parameter-optimizer.js +341 -0
- package/dist/architecture-evolution/parameter-optimizer.js.map +1 -0
- package/dist/architecture-evolution/prompts.d.ts +33 -0
- package/dist/architecture-evolution/prompts.d.ts.map +1 -0
- package/dist/architecture-evolution/prompts.js +169 -0
- package/dist/architecture-evolution/prompts.js.map +1 -0
- package/dist/constraints/index.d.ts +4 -0
- package/dist/constraints/index.d.ts.map +1 -0
- package/dist/constraints/index.js +4 -0
- package/dist/constraints/index.js.map +1 -0
- package/dist/constraints/modification-validator.d.ts +26 -0
- package/dist/constraints/modification-validator.d.ts.map +1 -0
- package/dist/constraints/modification-validator.js +313 -0
- package/dist/constraints/modification-validator.js.map +1 -0
- package/dist/constraints/rollback-manager.d.ts +52 -0
- package/dist/constraints/rollback-manager.d.ts.map +1 -0
- package/dist/constraints/rollback-manager.js +113 -0
- package/dist/constraints/rollback-manager.js.map +1 -0
- package/dist/constraints/safety-constraints.d.ts +11 -0
- package/dist/constraints/safety-constraints.d.ts.map +1 -0
- package/dist/constraints/safety-constraints.js +78 -0
- package/dist/constraints/safety-constraints.js.map +1 -0
- package/dist/events/event-emitter.d.ts +12 -0
- package/dist/events/event-emitter.d.ts.map +1 -0
- package/dist/events/event-emitter.js +43 -0
- package/dist/events/event-emitter.js.map +1 -0
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +2 -0
- package/dist/events/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/meta-reasoning/index.d.ts +5 -0
- package/dist/meta-reasoning/index.d.ts.map +1 -0
- package/dist/meta-reasoning/index.js +5 -0
- package/dist/meta-reasoning/index.js.map +1 -0
- package/dist/meta-reasoning/meta-reasoner.d.ts +53 -0
- package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -0
- package/dist/meta-reasoning/meta-reasoner.js +261 -0
- package/dist/meta-reasoning/meta-reasoner.js.map +1 -0
- package/dist/meta-reasoning/observation-collector.d.ts +37 -0
- package/dist/meta-reasoning/observation-collector.d.ts.map +1 -0
- package/dist/meta-reasoning/observation-collector.js +123 -0
- package/dist/meta-reasoning/observation-collector.js.map +1 -0
- package/dist/meta-reasoning/prompts.d.ts +31 -0
- package/dist/meta-reasoning/prompts.d.ts.map +1 -0
- package/dist/meta-reasoning/prompts.js +96 -0
- package/dist/meta-reasoning/prompts.js.map +1 -0
- package/dist/meta-reasoning/strategy-selector.d.ts +27 -0
- package/dist/meta-reasoning/strategy-selector.d.ts.map +1 -0
- package/dist/meta-reasoning/strategy-selector.js +138 -0
- package/dist/meta-reasoning/strategy-selector.js.map +1 -0
- package/dist/self-modifying-agent.d.ts +61 -0
- package/dist/self-modifying-agent.d.ts.map +1 -0
- package/dist/self-modifying-agent.js +449 -0
- package/dist/self-modifying-agent.js.map +1 -0
- package/dist/tool-generation/gap-analyzer.d.ts +25 -0
- package/dist/tool-generation/gap-analyzer.d.ts.map +1 -0
- package/dist/tool-generation/gap-analyzer.js +153 -0
- package/dist/tool-generation/gap-analyzer.js.map +1 -0
- package/dist/tool-generation/generated-tool-store.d.ts +51 -0
- package/dist/tool-generation/generated-tool-store.d.ts.map +1 -0
- package/dist/tool-generation/generated-tool-store.js +195 -0
- package/dist/tool-generation/generated-tool-store.js.map +1 -0
- package/dist/tool-generation/index.d.ts +7 -0
- package/dist/tool-generation/index.d.ts.map +1 -0
- package/dist/tool-generation/index.js +7 -0
- package/dist/tool-generation/index.js.map +1 -0
- package/dist/tool-generation/prompts.d.ts +28 -0
- package/dist/tool-generation/prompts.d.ts.map +1 -0
- package/dist/tool-generation/prompts.js +269 -0
- package/dist/tool-generation/prompts.js.map +1 -0
- package/dist/tool-generation/tool-generator.d.ts +29 -0
- package/dist/tool-generation/tool-generator.d.ts.map +1 -0
- package/dist/tool-generation/tool-generator.js +169 -0
- package/dist/tool-generation/tool-generator.js.map +1 -0
- package/dist/tool-generation/tool-sandbox.d.ts +31 -0
- package/dist/tool-generation/tool-sandbox.d.ts.map +1 -0
- package/dist/tool-generation/tool-sandbox.js +240 -0
- package/dist/tool-generation/tool-sandbox.js.map +1 -0
- package/dist/tool-generation/tool-validator.d.ts +32 -0
- package/dist/tool-generation/tool-validator.d.ts.map +1 -0
- package/dist/tool-generation/tool-validator.js +304 -0
- package/dist/tool-generation/tool-validator.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/llm-helper.d.ts +6 -0
- package/dist/utils/llm-helper.d.ts.map +1 -0
- package/dist/utils/llm-helper.js +18 -0
- package/dist/utils/llm-helper.js.map +1 -0
- package/package.json +61 -0
- package/src/__tests__/architecture-evolution.test.ts +368 -0
- package/src/__tests__/constraints.test.ts +266 -0
- package/src/__tests__/index.test.ts +99 -0
- package/src/__tests__/meta-reasoning.test.ts +343 -0
- package/src/__tests__/tool-generation.test.ts +455 -0
- package/src/architecture-evolution/capability-analyzer.ts +337 -0
- package/src/architecture-evolution/evolution-strategy.ts +224 -0
- package/src/architecture-evolution/index.ts +26 -0
- package/src/architecture-evolution/parameter-optimizer.ts +489 -0
- package/src/architecture-evolution/prompts.ts +216 -0
- package/src/constraints/index.ts +23 -0
- package/src/constraints/modification-validator.ts +402 -0
- package/src/constraints/rollback-manager.ts +173 -0
- package/src/constraints/safety-constraints.ts +103 -0
- package/src/events/event-emitter.ts +62 -0
- package/src/events/index.ts +1 -0
- package/src/index.ts +112 -0
- package/src/meta-reasoning/index.ts +24 -0
- package/src/meta-reasoning/meta-reasoner.ts +381 -0
- package/src/meta-reasoning/observation-collector.ts +161 -0
- package/src/meta-reasoning/prompts.ts +131 -0
- package/src/meta-reasoning/strategy-selector.ts +179 -0
- package/src/self-modifying-agent.ts +585 -0
- package/src/tool-generation/gap-analyzer.ts +234 -0
- package/src/tool-generation/generated-tool-store.ts +268 -0
- package/src/tool-generation/index.ts +19 -0
- package/src/tool-generation/prompts.ts +308 -0
- package/src/tool-generation/tool-generator.ts +243 -0
- package/src/tool-generation/tool-sandbox.ts +332 -0
- package/src/tool-generation/tool-validator.ts +365 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/llm-helper.ts +24 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import type { CapabilityGap, GeneratedTool, ToolValidationResult } from '@cogitator-ai/types';
|
|
2
|
+
|
|
3
|
+
export const TOOL_GENERATION_SYSTEM_PROMPT = `You are an expert TypeScript developer specializing in creating tools for AI agents.
|
|
4
|
+
Your task is to generate safe, efficient, and well-typed tool implementations.
|
|
5
|
+
|
|
6
|
+
CRITICAL CONSTRAINTS:
|
|
7
|
+
1. Generate ONLY pure TypeScript functions - no external dependencies beyond built-in modules
|
|
8
|
+
2. All generated code must be self-contained and synchronous where possible
|
|
9
|
+
3. Never generate code that accesses file system, network, or system resources unless explicitly requested
|
|
10
|
+
4. Always include proper error handling
|
|
11
|
+
5. Use Zod for parameter validation when schemas are provided
|
|
12
|
+
6. Follow the exact Tool interface structure
|
|
13
|
+
|
|
14
|
+
OUTPUT FORMAT:
|
|
15
|
+
Return a JSON object with:
|
|
16
|
+
{
|
|
17
|
+
"name": "tool_name",
|
|
18
|
+
"description": "Clear description of what the tool does",
|
|
19
|
+
"implementation": "// TypeScript code as a string",
|
|
20
|
+
"parameters": { "type": "object", "properties": {...}, "required": [...] },
|
|
21
|
+
"reasoning": "Why this implementation was chosen"
|
|
22
|
+
}`;
|
|
23
|
+
|
|
24
|
+
export function buildGapAnalysisPrompt(
|
|
25
|
+
userIntent: string,
|
|
26
|
+
availableTools: Array<{ name: string; description: string }>,
|
|
27
|
+
failedAttempts?: string[]
|
|
28
|
+
): string {
|
|
29
|
+
const toolList = availableTools
|
|
30
|
+
.map((t) => `- ${t.name}: ${t.description}`)
|
|
31
|
+
.join('\n');
|
|
32
|
+
|
|
33
|
+
const failureContext = failedAttempts?.length
|
|
34
|
+
? `\n\nPrevious failed attempts:\n${failedAttempts.map((f) => `- ${f}`).join('\n')}`
|
|
35
|
+
: '';
|
|
36
|
+
|
|
37
|
+
return `Analyze the following user intent and determine if any capabilities are missing from the available tools.
|
|
38
|
+
|
|
39
|
+
USER INTENT:
|
|
40
|
+
${userIntent}
|
|
41
|
+
|
|
42
|
+
AVAILABLE TOOLS:
|
|
43
|
+
${toolList}
|
|
44
|
+
${failureContext}
|
|
45
|
+
|
|
46
|
+
Respond with a JSON object:
|
|
47
|
+
{
|
|
48
|
+
"hasGap": boolean,
|
|
49
|
+
"gaps": [
|
|
50
|
+
{
|
|
51
|
+
"id": "unique_gap_id",
|
|
52
|
+
"description": "What capability is missing",
|
|
53
|
+
"requiredCapability": "Specific capability needed",
|
|
54
|
+
"suggestedToolName": "proposed_tool_name",
|
|
55
|
+
"complexity": "simple" | "moderate" | "complex",
|
|
56
|
+
"confidence": 0.0-1.0,
|
|
57
|
+
"reasoning": "Why this gap exists"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"canProceed": boolean,
|
|
61
|
+
"alternativeApproach": "If gaps exist but can still proceed, explain how"
|
|
62
|
+
}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function buildToolGenerationPrompt(
|
|
66
|
+
gap: CapabilityGap,
|
|
67
|
+
existingTools: Array<{ name: string; description: string }>,
|
|
68
|
+
constraints?: {
|
|
69
|
+
maxLines?: number;
|
|
70
|
+
allowedModules?: string[];
|
|
71
|
+
securityLevel?: 'strict' | 'moderate' | 'permissive';
|
|
72
|
+
}
|
|
73
|
+
): string {
|
|
74
|
+
const securityRules = {
|
|
75
|
+
strict: `
|
|
76
|
+
- NO file system access
|
|
77
|
+
- NO network requests
|
|
78
|
+
- NO eval() or Function constructor
|
|
79
|
+
- NO dynamic imports
|
|
80
|
+
- NO process or child_process access
|
|
81
|
+
- ONLY pure computation`,
|
|
82
|
+
moderate: `
|
|
83
|
+
- File system access ONLY if explicitly requested
|
|
84
|
+
- Network requests ONLY to whitelisted domains
|
|
85
|
+
- NO eval() or Function constructor
|
|
86
|
+
- NO dynamic imports`,
|
|
87
|
+
permissive: `
|
|
88
|
+
- File system access allowed with path validation
|
|
89
|
+
- Network requests allowed
|
|
90
|
+
- NO eval() or Function constructor`,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const security = constraints?.securityLevel || 'strict';
|
|
94
|
+
const maxLines = constraints?.maxLines || 100;
|
|
95
|
+
|
|
96
|
+
return `Generate a TypeScript tool implementation for the following capability gap.
|
|
97
|
+
|
|
98
|
+
CAPABILITY GAP:
|
|
99
|
+
- Description: ${gap.description}
|
|
100
|
+
- Required: ${gap.requiredCapability}
|
|
101
|
+
- Suggested name: ${gap.suggestedToolName}
|
|
102
|
+
- Complexity: ${gap.complexity}
|
|
103
|
+
|
|
104
|
+
EXISTING TOOLS (avoid duplication):
|
|
105
|
+
${existingTools.map((t) => `- ${t.name}: ${t.description}`).join('\n')}
|
|
106
|
+
|
|
107
|
+
CONSTRAINTS:
|
|
108
|
+
- Maximum ${maxLines} lines of code
|
|
109
|
+
- Security level: ${security}
|
|
110
|
+
${securityRules[security]}
|
|
111
|
+
${constraints?.allowedModules ? `- Allowed modules: ${constraints.allowedModules.join(', ')}` : ''}
|
|
112
|
+
|
|
113
|
+
Generate a complete, self-contained tool following this exact structure:
|
|
114
|
+
{
|
|
115
|
+
"name": "${gap.suggestedToolName}",
|
|
116
|
+
"description": "Clear description",
|
|
117
|
+
"implementation": "async function execute(params: Params): Promise<Result> { ... }",
|
|
118
|
+
"parameters": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"properties": { ... },
|
|
121
|
+
"required": [ ... ]
|
|
122
|
+
},
|
|
123
|
+
"reasoning": "Implementation rationale"
|
|
124
|
+
}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function buildToolValidationPrompt(
|
|
128
|
+
tool: GeneratedTool,
|
|
129
|
+
testCases: Array<{ input: unknown; expectedBehavior: string }>
|
|
130
|
+
): string {
|
|
131
|
+
return `Validate the following generated tool for correctness, safety, and edge cases.
|
|
132
|
+
|
|
133
|
+
TOOL:
|
|
134
|
+
Name: ${tool.name}
|
|
135
|
+
Description: ${tool.description}
|
|
136
|
+
|
|
137
|
+
IMPLEMENTATION:
|
|
138
|
+
\`\`\`typescript
|
|
139
|
+
${tool.implementation}
|
|
140
|
+
\`\`\`
|
|
141
|
+
|
|
142
|
+
PARAMETERS:
|
|
143
|
+
${JSON.stringify(tool.parameters, null, 2)}
|
|
144
|
+
|
|
145
|
+
TEST CASES TO CONSIDER:
|
|
146
|
+
${testCases.map((tc, i) => `${i + 1}. Input: ${JSON.stringify(tc.input)} - Expected: ${tc.expectedBehavior}`).join('\n')}
|
|
147
|
+
|
|
148
|
+
Analyze and respond with:
|
|
149
|
+
{
|
|
150
|
+
"isValid": boolean,
|
|
151
|
+
"securityIssues": ["list of security concerns"],
|
|
152
|
+
"logicIssues": ["list of logic/correctness issues"],
|
|
153
|
+
"edgeCases": ["unhandled edge cases"],
|
|
154
|
+
"suggestions": ["improvement suggestions"],
|
|
155
|
+
"testResults": [
|
|
156
|
+
{ "testCase": 1, "wouldPass": boolean, "reason": "explanation" }
|
|
157
|
+
],
|
|
158
|
+
"overallScore": 0.0-1.0,
|
|
159
|
+
"recommendation": "approve" | "revise" | "reject"
|
|
160
|
+
}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function buildToolImprovementPrompt(
|
|
164
|
+
tool: GeneratedTool,
|
|
165
|
+
validationResult: ToolValidationResult,
|
|
166
|
+
iteration: number
|
|
167
|
+
): string {
|
|
168
|
+
const issues = [
|
|
169
|
+
...validationResult.securityIssues.map((i) => `[SECURITY] ${i}`),
|
|
170
|
+
...validationResult.logicIssues.map((i) => `[LOGIC] ${i}`),
|
|
171
|
+
...validationResult.edgeCases.map((i) => `[EDGE CASE] ${i}`),
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
return `Improve the following tool based on validation feedback.
|
|
175
|
+
|
|
176
|
+
ITERATION: ${iteration}
|
|
177
|
+
|
|
178
|
+
CURRENT TOOL:
|
|
179
|
+
Name: ${tool.name}
|
|
180
|
+
Description: ${tool.description}
|
|
181
|
+
|
|
182
|
+
CURRENT IMPLEMENTATION:
|
|
183
|
+
\`\`\`typescript
|
|
184
|
+
${tool.implementation}
|
|
185
|
+
\`\`\`
|
|
186
|
+
|
|
187
|
+
ISSUES TO FIX:
|
|
188
|
+
${issues.map((i, idx) => `${idx + 1}. ${i}`).join('\n')}
|
|
189
|
+
|
|
190
|
+
SUGGESTIONS:
|
|
191
|
+
${validationResult.suggestions.map((s, idx) => `${idx + 1}. ${s}`).join('\n')}
|
|
192
|
+
|
|
193
|
+
Generate an improved implementation that addresses ALL issues.
|
|
194
|
+
Respond with the same JSON format as before:
|
|
195
|
+
{
|
|
196
|
+
"name": "${tool.name}",
|
|
197
|
+
"description": "Updated description if needed",
|
|
198
|
+
"implementation": "// Improved TypeScript code",
|
|
199
|
+
"parameters": { ... },
|
|
200
|
+
"reasoning": "What was changed and why"
|
|
201
|
+
}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function parseGapAnalysisResponse(response: string): {
|
|
205
|
+
hasGap: boolean;
|
|
206
|
+
gaps: CapabilityGap[];
|
|
207
|
+
canProceed: boolean;
|
|
208
|
+
alternativeApproach?: string;
|
|
209
|
+
} {
|
|
210
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
211
|
+
if (!jsonMatch) {
|
|
212
|
+
return { hasGap: false, gaps: [], canProceed: true };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
217
|
+
return {
|
|
218
|
+
hasGap: Boolean(parsed.hasGap),
|
|
219
|
+
gaps: Array.isArray(parsed.gaps)
|
|
220
|
+
? parsed.gaps.map((g: Record<string, unknown>, idx: number) => ({
|
|
221
|
+
id: String(g.id || `gap_${idx}`),
|
|
222
|
+
description: String(g.description || ''),
|
|
223
|
+
requiredCapability: String(g.requiredCapability || ''),
|
|
224
|
+
suggestedToolName: String(g.suggestedToolName || `generated_tool_${idx}`),
|
|
225
|
+
complexity: (['simple', 'moderate', 'complex'].includes(String(g.complexity))
|
|
226
|
+
? g.complexity
|
|
227
|
+
: 'moderate') as 'simple' | 'moderate' | 'complex',
|
|
228
|
+
confidence: typeof g.confidence === 'number' ? g.confidence : 0.5,
|
|
229
|
+
reasoning: String(g.reasoning || ''),
|
|
230
|
+
}))
|
|
231
|
+
: [],
|
|
232
|
+
canProceed: Boolean(parsed.canProceed),
|
|
233
|
+
alternativeApproach: parsed.alternativeApproach
|
|
234
|
+
? String(parsed.alternativeApproach)
|
|
235
|
+
: undefined,
|
|
236
|
+
};
|
|
237
|
+
} catch {
|
|
238
|
+
return { hasGap: false, gaps: [], canProceed: true };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function parseToolGenerationResponse(response: string): GeneratedTool | null {
|
|
243
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
244
|
+
if (!jsonMatch) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
250
|
+
if (!parsed.name || !parsed.implementation) {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
id: `gen_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
256
|
+
name: String(parsed.name),
|
|
257
|
+
description: String(parsed.description || ''),
|
|
258
|
+
implementation: String(parsed.implementation),
|
|
259
|
+
parameters: parsed.parameters || { type: 'object', properties: {} },
|
|
260
|
+
createdAt: new Date(),
|
|
261
|
+
version: 1,
|
|
262
|
+
status: 'pending_validation',
|
|
263
|
+
metadata: {
|
|
264
|
+
reasoning: parsed.reasoning ? String(parsed.reasoning) : undefined,
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
} catch {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function parseValidationResponse(response: string): ToolValidationResult | null {
|
|
273
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
274
|
+
if (!jsonMatch) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
isValid: Boolean(parsed.isValid),
|
|
283
|
+
securityIssues: Array.isArray(parsed.securityIssues)
|
|
284
|
+
? parsed.securityIssues.map(String)
|
|
285
|
+
: [],
|
|
286
|
+
logicIssues: Array.isArray(parsed.logicIssues)
|
|
287
|
+
? parsed.logicIssues.map(String)
|
|
288
|
+
: [],
|
|
289
|
+
edgeCases: Array.isArray(parsed.edgeCases)
|
|
290
|
+
? parsed.edgeCases.map(String)
|
|
291
|
+
: [],
|
|
292
|
+
suggestions: Array.isArray(parsed.suggestions)
|
|
293
|
+
? parsed.suggestions.map(String)
|
|
294
|
+
: [],
|
|
295
|
+
testResults: Array.isArray(parsed.testResults)
|
|
296
|
+
? parsed.testResults.map((tr: Record<string, unknown>) => ({
|
|
297
|
+
input: tr.input,
|
|
298
|
+
output: tr.output,
|
|
299
|
+
passed: Boolean(tr.wouldPass ?? tr.passed),
|
|
300
|
+
error: tr.error ? String(tr.error) : undefined,
|
|
301
|
+
}))
|
|
302
|
+
: [],
|
|
303
|
+
overallScore: typeof parsed.overallScore === 'number' ? parsed.overallScore : 0,
|
|
304
|
+
};
|
|
305
|
+
} catch {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Tool,
|
|
3
|
+
LLMBackend,
|
|
4
|
+
CapabilityGap,
|
|
5
|
+
GeneratedTool,
|
|
6
|
+
ToolValidationResult,
|
|
7
|
+
ToolSelfGenerationConfig,
|
|
8
|
+
} from '@cogitator-ai/types';
|
|
9
|
+
import type { ZodType } from 'zod';
|
|
10
|
+
import { ToolValidator } from './tool-validator';
|
|
11
|
+
import {
|
|
12
|
+
TOOL_GENERATION_SYSTEM_PROMPT,
|
|
13
|
+
buildToolGenerationPrompt,
|
|
14
|
+
buildToolImprovementPrompt,
|
|
15
|
+
parseToolGenerationResponse,
|
|
16
|
+
} from './prompts';
|
|
17
|
+
|
|
18
|
+
export interface ToolGeneratorOptions {
|
|
19
|
+
llm: LLMBackend;
|
|
20
|
+
config: ToolSelfGenerationConfig;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface GenerationResult {
|
|
24
|
+
tool: GeneratedTool | null;
|
|
25
|
+
validationResult: ToolValidationResult | null;
|
|
26
|
+
iterations: number;
|
|
27
|
+
success: boolean;
|
|
28
|
+
error?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class ToolGenerator {
|
|
32
|
+
private readonly llm: LLMBackend;
|
|
33
|
+
private readonly config: ToolSelfGenerationConfig;
|
|
34
|
+
private readonly validator: ToolValidator;
|
|
35
|
+
|
|
36
|
+
constructor(options: ToolGeneratorOptions) {
|
|
37
|
+
this.llm = options.llm;
|
|
38
|
+
this.config = options.config;
|
|
39
|
+
this.validator = new ToolValidator({
|
|
40
|
+
llm: options.llm,
|
|
41
|
+
config: options.config,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async generate(
|
|
46
|
+
gap: CapabilityGap,
|
|
47
|
+
existingTools: Tool[],
|
|
48
|
+
testCases?: Array<{ input: unknown; expectedOutput?: unknown }>
|
|
49
|
+
): Promise<GenerationResult> {
|
|
50
|
+
let currentTool: GeneratedTool | null = null;
|
|
51
|
+
let validationResult: ToolValidationResult | null = null;
|
|
52
|
+
let iterations = 0;
|
|
53
|
+
|
|
54
|
+
const maxIterations = this.config.maxIterationsPerTool || 3;
|
|
55
|
+
|
|
56
|
+
while (iterations < maxIterations) {
|
|
57
|
+
iterations++;
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
if (currentTool === null) {
|
|
61
|
+
currentTool = await this.generateInitial(gap, existingTools);
|
|
62
|
+
} else if (validationResult) {
|
|
63
|
+
currentTool = await this.improve(currentTool, validationResult, iterations);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!currentTool) {
|
|
67
|
+
return {
|
|
68
|
+
tool: null,
|
|
69
|
+
validationResult: null,
|
|
70
|
+
iterations,
|
|
71
|
+
success: false,
|
|
72
|
+
error: 'Failed to generate tool implementation',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
validationResult = await this.validator.validate(currentTool, testCases);
|
|
77
|
+
|
|
78
|
+
if (validationResult.isValid) {
|
|
79
|
+
currentTool.status = 'validated';
|
|
80
|
+
currentTool.validationScore = validationResult.overallScore;
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
tool: currentTool,
|
|
84
|
+
validationResult,
|
|
85
|
+
iterations,
|
|
86
|
+
success: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (validationResult.securityIssues.length > 0 && iterations >= 2) {
|
|
91
|
+
return {
|
|
92
|
+
tool: currentTool,
|
|
93
|
+
validationResult,
|
|
94
|
+
iterations,
|
|
95
|
+
success: false,
|
|
96
|
+
error: `Security issues persist after ${iterations} iterations: ${validationResult.securityIssues.join(', ')}`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
tool: currentTool,
|
|
102
|
+
validationResult,
|
|
103
|
+
iterations,
|
|
104
|
+
success: false,
|
|
105
|
+
error: error instanceof Error ? error.message : String(error),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
tool: currentTool,
|
|
112
|
+
validationResult,
|
|
113
|
+
iterations,
|
|
114
|
+
success: false,
|
|
115
|
+
error: `Failed to generate valid tool after ${maxIterations} iterations`,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async generateQuick(
|
|
120
|
+
description: string,
|
|
121
|
+
name: string,
|
|
122
|
+
parameters: Record<string, unknown>
|
|
123
|
+
): Promise<GeneratedTool | null> {
|
|
124
|
+
const gap: CapabilityGap = {
|
|
125
|
+
id: `quick_${Date.now()}`,
|
|
126
|
+
description,
|
|
127
|
+
requiredCapability: description,
|
|
128
|
+
suggestedToolName: name,
|
|
129
|
+
complexity: 'simple',
|
|
130
|
+
confidence: 1,
|
|
131
|
+
reasoning: 'User-requested quick generation',
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const result = await this.generate(gap, []);
|
|
135
|
+
return result.tool;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private async generateInitial(
|
|
139
|
+
gap: CapabilityGap,
|
|
140
|
+
existingTools: Tool[]
|
|
141
|
+
): Promise<GeneratedTool | null> {
|
|
142
|
+
const toolSummaries = existingTools.map((t) => ({
|
|
143
|
+
name: t.name,
|
|
144
|
+
description: t.description,
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
const prompt = buildToolGenerationPrompt(gap, toolSummaries, {
|
|
148
|
+
maxLines: 100,
|
|
149
|
+
securityLevel: 'strict',
|
|
150
|
+
allowedModules: this.config.sandboxConfig?.allowedModules,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const response = await this.callLLM([
|
|
154
|
+
{ role: 'system', content: TOOL_GENERATION_SYSTEM_PROMPT },
|
|
155
|
+
{ role: 'user', content: prompt },
|
|
156
|
+
], 0.4);
|
|
157
|
+
|
|
158
|
+
const tool = parseToolGenerationResponse(response.content);
|
|
159
|
+
|
|
160
|
+
if (tool) {
|
|
161
|
+
tool.metadata = {
|
|
162
|
+
...tool.metadata,
|
|
163
|
+
gapId: gap.id,
|
|
164
|
+
complexity: gap.complexity,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return tool;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private async improve(
|
|
172
|
+
tool: GeneratedTool,
|
|
173
|
+
validationResult: ToolValidationResult,
|
|
174
|
+
iteration: number
|
|
175
|
+
): Promise<GeneratedTool | null> {
|
|
176
|
+
const prompt = buildToolImprovementPrompt(tool, validationResult, iteration);
|
|
177
|
+
|
|
178
|
+
const response = await this.callLLM([
|
|
179
|
+
{ role: 'system', content: TOOL_GENERATION_SYSTEM_PROMPT },
|
|
180
|
+
{ role: 'user', content: prompt },
|
|
181
|
+
], 0.3);
|
|
182
|
+
|
|
183
|
+
const improved = parseToolGenerationResponse(response.content);
|
|
184
|
+
|
|
185
|
+
if (improved) {
|
|
186
|
+
improved.id = tool.id;
|
|
187
|
+
improved.version = tool.version + 1;
|
|
188
|
+
improved.metadata = {
|
|
189
|
+
...tool.metadata,
|
|
190
|
+
...improved.metadata,
|
|
191
|
+
previousVersion: tool.version,
|
|
192
|
+
improvementIteration: iteration,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return improved;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
createExecutableTool(generated: GeneratedTool): Tool {
|
|
200
|
+
const execute = this.compileImplementation(generated.implementation);
|
|
201
|
+
const { z } = require('zod');
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
name: generated.name,
|
|
205
|
+
description: generated.description,
|
|
206
|
+
parameters: z.record(z.unknown()) as ZodType<unknown>,
|
|
207
|
+
execute,
|
|
208
|
+
toJSON: () => ({
|
|
209
|
+
name: generated.name,
|
|
210
|
+
description: generated.description,
|
|
211
|
+
parameters: {
|
|
212
|
+
type: 'object' as const,
|
|
213
|
+
properties: generated.parameters as Record<string, unknown>,
|
|
214
|
+
},
|
|
215
|
+
}),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private compileImplementation(
|
|
220
|
+
implementation: string
|
|
221
|
+
): (params: unknown) => Promise<unknown> {
|
|
222
|
+
return async (params: unknown): Promise<unknown> => {
|
|
223
|
+
const factory = new Function(`
|
|
224
|
+
"use strict";
|
|
225
|
+
${implementation}
|
|
226
|
+
return execute;
|
|
227
|
+
`);
|
|
228
|
+
|
|
229
|
+
const execute = factory();
|
|
230
|
+
return execute(params);
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private async callLLM(
|
|
235
|
+
messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,
|
|
236
|
+
temperature: number
|
|
237
|
+
) {
|
|
238
|
+
if (this.llm.complete) {
|
|
239
|
+
return this.llm.complete({ messages, temperature });
|
|
240
|
+
}
|
|
241
|
+
return this.llm.chat({ model: 'default', messages, temperature });
|
|
242
|
+
}
|
|
243
|
+
}
|