@cogitator-ai/self-modifying 17.0.11 → 17.0.16

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 (68) hide show
  1. package/README.md +3 -3
  2. package/dist/architecture-evolution/capability-analyzer.d.ts +2 -0
  3. package/dist/architecture-evolution/capability-analyzer.d.ts.map +1 -1
  4. package/dist/architecture-evolution/capability-analyzer.js +4 -2
  5. package/dist/architecture-evolution/capability-analyzer.js.map +1 -1
  6. package/dist/architecture-evolution/index.d.ts +4 -4
  7. package/dist/architecture-evolution/index.js +4 -4
  8. package/dist/architecture-evolution/parameter-optimizer.d.ts +2 -0
  9. package/dist/architecture-evolution/parameter-optimizer.d.ts.map +1 -1
  10. package/dist/architecture-evolution/parameter-optimizer.js +7 -4
  11. package/dist/architecture-evolution/parameter-optimizer.js.map +1 -1
  12. package/dist/architecture-evolution/prompts.js +1 -1
  13. package/dist/constraints/index.d.ts +3 -3
  14. package/dist/constraints/index.js +3 -3
  15. package/dist/constraints/modification-validator.d.ts.map +1 -1
  16. package/dist/constraints/modification-validator.js +1 -1
  17. package/dist/constraints/modification-validator.js.map +1 -1
  18. package/dist/events/index.d.ts +1 -1
  19. package/dist/events/index.js +1 -1
  20. package/dist/index.d.ts +7 -7
  21. package/dist/index.js +7 -7
  22. package/dist/meta-reasoning/index.d.ts +4 -4
  23. package/dist/meta-reasoning/index.js +4 -4
  24. package/dist/meta-reasoning/meta-reasoner.d.ts +1 -1
  25. package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -1
  26. package/dist/meta-reasoning/meta-reasoner.js +4 -4
  27. package/dist/meta-reasoning/meta-reasoner.js.map +1 -1
  28. package/dist/self-modifying-agent.d.ts.map +1 -1
  29. package/dist/self-modifying-agent.js +21 -12
  30. package/dist/self-modifying-agent.js.map +1 -1
  31. package/dist/tool-generation/gap-analyzer.d.ts +2 -0
  32. package/dist/tool-generation/gap-analyzer.d.ts.map +1 -1
  33. package/dist/tool-generation/gap-analyzer.js +4 -2
  34. package/dist/tool-generation/gap-analyzer.js.map +1 -1
  35. package/dist/tool-generation/index.d.ts +6 -6
  36. package/dist/tool-generation/index.js +6 -6
  37. package/dist/tool-generation/prompts.d.ts +3 -3
  38. package/dist/tool-generation/prompts.d.ts.map +1 -1
  39. package/dist/tool-generation/prompts.js +51 -93
  40. package/dist/tool-generation/prompts.js.map +1 -1
  41. package/dist/tool-generation/tool-generator.d.ts +2 -0
  42. package/dist/tool-generation/tool-generator.d.ts.map +1 -1
  43. package/dist/tool-generation/tool-generator.js +8 -11
  44. package/dist/tool-generation/tool-generator.js.map +1 -1
  45. package/dist/tool-generation/tool-sandbox.d.ts.map +1 -1
  46. package/dist/tool-generation/tool-sandbox.js.map +1 -1
  47. package/dist/tool-generation/tool-validator.d.ts +2 -0
  48. package/dist/tool-generation/tool-validator.d.ts.map +1 -1
  49. package/dist/tool-generation/tool-validator.js +5 -3
  50. package/dist/tool-generation/tool-validator.js.map +1 -1
  51. package/dist/utils/index.d.ts +1 -1
  52. package/dist/utils/index.d.ts.map +1 -1
  53. package/dist/utils/index.js +23 -5
  54. package/dist/utils/index.js.map +1 -1
  55. package/package.json +1 -1
  56. package/src/__tests__/self-modifying-agent.test.ts +24 -20
  57. package/src/__tests__/utils.test.ts +22 -1
  58. package/src/architecture-evolution/capability-analyzer.ts +4 -1
  59. package/src/architecture-evolution/parameter-optimizer.ts +5 -1
  60. package/src/constraints/modification-validator.ts +4 -1
  61. package/src/meta-reasoning/meta-reasoner.ts +3 -1
  62. package/src/self-modifying-agent.ts +25 -16
  63. package/src/tool-generation/gap-analyzer.ts +4 -1
  64. package/src/tool-generation/prompts.ts +55 -98
  65. package/src/tool-generation/tool-generator.ts +6 -8
  66. package/src/tool-generation/tool-sandbox.ts +2 -1
  67. package/src/tool-generation/tool-validator.ts +4 -1
  68. package/src/utils/index.ts +24 -4
@@ -1,27 +1,15 @@
1
1
  import type { CapabilityGap, GeneratedTool, ToolValidationResult } from '@cogitator-ai/types';
2
2
  import { extractJson } from '../utils';
3
3
 
4
- export const TOOL_GENERATION_SYSTEM_PROMPT = `You are an expert JavaScript developer specializing in creating tools for AI agents.
5
- Your task is to generate safe, efficient tool implementations.
6
-
7
- CRITICAL CONSTRAINTS:
8
- 1. Generate ONLY plain JavaScript (ES2020+) - NO TypeScript syntax, NO type annotations, NO interfaces
9
- 2. No external dependencies - only built-in globals (Math, JSON, Date, Array, Object, String, Number, Boolean, RegExp, Map, Set, Error)
10
- 3. All generated code must be self-contained
11
- 4. Never generate code that accesses file system, network, or system resources
12
- 5. Always include proper error handling with try-catch
13
- 6. The implementation MUST define an async function called "execute" that takes a params object and returns a result
14
- 7. Do NOT use: eval, Function, import, require, process, global, fetch, setTimeout, setInterval, constructor
15
-
16
- OUTPUT FORMAT:
17
- Return a JSON object with:
18
- {
19
- "name": "tool_name",
20
- "description": "Clear description of what the tool does",
21
- "implementation": "async function execute(params) { ... }",
22
- "parameters": { "type": "object", "properties": {...}, "required": [...] },
23
- "reasoning": "Why this implementation was chosen"
24
- }`;
4
+ export const TOOL_GENERATION_SYSTEM_PROMPT = `You generate JavaScript tools. Respond with ONLY a JSON object, no other text.
5
+
6
+ Rules:
7
+ - Plain JavaScript only, no TypeScript
8
+ - No require/import/eval/process/fetch
9
+ - Must have an async function called "execute"
10
+
11
+ Example response:
12
+ {"name":"add","description":"Add two numbers","implementation":"async function execute(params) { try { return params.a + params.b; } catch(e) { return 0; } }","parameters":{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}},"required":["a","b"]},"reasoning":"Simple addition"}`;
25
13
 
26
14
  export function buildGapAnalysisPrompt(
27
15
  userIntent: string,
@@ -64,66 +52,19 @@ Respond with a JSON object:
64
52
 
65
53
  export function buildToolGenerationPrompt(
66
54
  gap: CapabilityGap,
67
- existingTools: Array<{ name: string; description: string }>,
68
- constraints?: {
55
+ _existingTools: Array<{ name: string; description: string }>,
56
+ _constraints?: {
69
57
  maxLines?: number;
70
58
  allowedModules?: string[];
71
59
  securityLevel?: 'strict' | 'moderate' | 'permissive';
72
60
  }
73
61
  ): 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;
62
+ return `Create a tool named "${gap.suggestedToolName}".
63
+ Task: ${gap.description}
64
+ Formula/Logic: ${gap.requiredCapability}
95
65
 
96
- return `Generate a plain JavaScript 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
- - MUST use plain JavaScript (ES2020+), NO TypeScript syntax, NO type annotations, NO interfaces
111
- - The "implementation" field must define an async function called "execute" that takes a plain object "params"
112
- ${securityRules[security]}
113
- ${constraints?.allowedModules ? `- Allowed modules: ${constraints.allowedModules.join(', ')}` : ''}
114
-
115
- Generate a complete, self-contained tool following this exact structure:
116
- {
117
- "name": "${gap.suggestedToolName}",
118
- "description": "Clear description",
119
- "implementation": "async function execute(params) { ... }",
120
- "parameters": {
121
- "type": "object",
122
- "properties": { ... },
123
- "required": [ ... ]
124
- },
125
- "reasoning": "Implementation rationale"
126
- }`;
66
+ Respond with ONLY this JSON (no other text):
67
+ {"name":"${gap.suggestedToolName}","description":"${gap.description}","implementation":"async function execute(params) { try { /* YOUR CODE HERE */ } catch(e) { throw e; } }","parameters":{"type":"object","properties":{/* DEFINE PARAMS */},"required":[/* REQUIRED PARAMS */]},"reasoning":"explanation"}`;
127
68
  }
128
69
 
129
70
  export function buildToolValidationPrompt(
@@ -244,32 +185,48 @@ export function parseGapAnalysisResponse(response: string): {
244
185
 
245
186
  export function parseToolGenerationResponse(response: string): GeneratedTool | null {
246
187
  const json = extractJson(response);
247
- if (!json) {
248
- return null;
188
+ if (json) {
189
+ try {
190
+ const parsed = JSON.parse(json);
191
+ if (parsed.name && parsed.implementation) {
192
+ return buildToolFromParsed(parsed);
193
+ }
194
+ } catch {}
249
195
  }
250
196
 
251
- try {
252
- const parsed = JSON.parse(json);
253
- if (!parsed.name || !parsed.implementation) {
254
- return null;
255
- }
256
-
257
- return {
258
- id: `gen_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
259
- name: String(parsed.name),
260
- description: String(parsed.description || ''),
261
- implementation: String(parsed.implementation),
262
- parameters: parsed.parameters || { type: 'object', properties: {} },
263
- createdAt: new Date(),
264
- version: 1,
265
- status: 'pending_validation',
266
- metadata: {
267
- reasoning: parsed.reasoning ? String(parsed.reasoning) : undefined,
268
- },
269
- };
270
- } catch {
271
- return null;
197
+ const fnRegex = /(?:async\s+)?function\s+execute\s*\([^)]*\)\s*\{[\s\S]*?\n\}/;
198
+ const fnMatch = fnRegex.exec(response);
199
+ if (fnMatch) {
200
+ const nameRegex = /["']?name["']?\s*[:=]\s*["']([^"']+)["']/;
201
+ const nameMatch = nameRegex.exec(response);
202
+ return buildToolFromParsed({
203
+ name: nameMatch?.[1] ?? 'generated_tool',
204
+ description: '',
205
+ implementation: fnMatch[0],
206
+ parameters: { type: 'object', properties: {} },
207
+ });
272
208
  }
209
+
210
+ return null;
211
+ }
212
+
213
+ function buildToolFromParsed(parsed: Record<string, unknown>): GeneratedTool {
214
+ return {
215
+ id: `gen_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
216
+ name: String(parsed.name),
217
+ description: String(parsed.description || ''),
218
+ implementation: String(parsed.implementation),
219
+ parameters: (parsed.parameters as GeneratedTool['parameters']) || {
220
+ type: 'object',
221
+ properties: {},
222
+ },
223
+ createdAt: new Date(),
224
+ version: 1,
225
+ status: 'pending_validation',
226
+ metadata: {
227
+ reasoning: parsed.reasoning ? String(parsed.reasoning) : undefined,
228
+ },
229
+ };
273
230
  }
274
231
 
275
232
  export function parseValidationResponse(response: string): ToolValidationResult | null {
@@ -19,6 +19,7 @@ import {
19
19
  export interface ToolGeneratorOptions {
20
20
  llm: LLMBackend;
21
21
  config: ToolSelfGenerationConfig;
22
+ model?: string;
22
23
  }
23
24
 
24
25
  export interface GenerationResult {
@@ -32,15 +33,18 @@ export interface GenerationResult {
32
33
  export class ToolGenerator {
33
34
  private readonly llm: LLMBackend;
34
35
  private readonly config: ToolSelfGenerationConfig;
36
+ private readonly model: string;
35
37
  private readonly validator: ToolValidator;
36
38
  private readonly sandbox: ToolSandbox;
37
39
 
38
40
  constructor(options: ToolGeneratorOptions) {
39
41
  this.llm = options.llm;
40
42
  this.config = options.config;
43
+ this.model = options.model ?? 'default';
41
44
  this.validator = new ToolValidator({
42
45
  llm: options.llm,
43
46
  config: options.config,
47
+ model: options.model,
44
48
  });
45
49
  this.sandbox = new ToolSandbox(options.config.sandboxConfig);
46
50
  }
@@ -67,13 +71,7 @@ export class ToolGenerator {
67
71
  }
68
72
 
69
73
  if (!currentTool) {
70
- return {
71
- tool: null,
72
- validationResult: null,
73
- iterations,
74
- success: false,
75
- error: 'Failed to generate tool implementation',
76
- };
74
+ continue;
77
75
  }
78
76
 
79
77
  validationResult = await this.validator.validate(currentTool, testCases);
@@ -240,6 +238,6 @@ export class ToolGenerator {
240
238
  if (this.llm.complete) {
241
239
  return this.llm.complete({ messages, temperature });
242
240
  }
243
- return this.llm.chat({ model: 'default', messages, temperature });
241
+ return this.llm.chat({ model: this.model, messages, temperature });
244
242
  }
245
243
  }
@@ -273,7 +273,8 @@ export class ToolSandbox {
273
273
  execute(params),
274
274
  new Promise((_, reject) =>
275
275
  setTimeout(
276
- () => reject(new Error(`Execution timeout: exceeded ${this.config.maxExecutionTime}ms`)),
276
+ () =>
277
+ reject(new Error(`Execution timeout: exceeded ${this.config.maxExecutionTime}ms`)),
277
278
  this.config.maxExecutionTime
278
279
  )
279
280
  ),
@@ -10,6 +10,7 @@ import { buildToolValidationPrompt, parseValidationResponse } from './prompts';
10
10
  export interface ToolValidatorOptions {
11
11
  llm?: LLMBackend;
12
12
  config: ToolSelfGenerationConfig;
13
+ model?: string;
13
14
  }
14
15
 
15
16
  interface ValidationRule {
@@ -141,12 +142,14 @@ const STATIC_VALIDATION_RULES: ValidationRule[] = [
141
142
  export class ToolValidator {
142
143
  private readonly llm?: LLMBackend;
143
144
  private readonly config: ToolSelfGenerationConfig;
145
+ private readonly model: string;
144
146
  private readonly sandbox: ToolSandbox;
145
147
  private readonly customRules: ValidationRule[] = [];
146
148
 
147
149
  constructor(options: ToolValidatorOptions) {
148
150
  this.llm = options.llm;
149
151
  this.config = options.config;
152
+ this.model = options.model ?? 'default';
150
153
  this.sandbox = new ToolSandbox(options.config.sandboxConfig);
151
154
  }
152
155
 
@@ -359,6 +362,6 @@ Be thorough but practical - focus on real issues.`,
359
362
  if (this.llm.complete) {
360
363
  return this.llm.complete({ messages, temperature });
361
364
  }
362
- return this.llm.chat({ model: 'default', messages, temperature });
365
+ return this.llm.chat({ model: this.model, messages, temperature });
363
366
  }
364
367
  }
@@ -1,15 +1,23 @@
1
1
  export { llmChat } from './llm-helper';
2
2
 
3
3
  export function extractJson(text: string): string | null {
4
- const start = text.indexOf('{');
4
+ let cleaned = text;
5
+
6
+ const codeBlockRegex = /```(?:json)?\s*\n?([\s\S]*?)```/;
7
+ const codeBlockMatch = codeBlockRegex.exec(cleaned);
8
+ if (codeBlockMatch) {
9
+ cleaned = codeBlockMatch[1].trim();
10
+ }
11
+
12
+ const start = cleaned.indexOf('{');
5
13
  if (start === -1) return null;
6
14
 
7
15
  let depth = 0;
8
16
  let inString = false;
9
17
  let escape = false;
10
18
 
11
- for (let i = start; i < text.length; i++) {
12
- const ch = text[i];
19
+ for (let i = start; i < cleaned.length; i++) {
20
+ const ch = cleaned[i];
13
21
 
14
22
  if (escape) {
15
23
  escape = false;
@@ -32,10 +40,22 @@ export function extractJson(text: string): string | null {
32
40
  else if (ch === '}') {
33
41
  depth--;
34
42
  if (depth === 0) {
35
- return text.slice(start, i + 1);
43
+ return cleaned.slice(start, i + 1);
36
44
  }
37
45
  }
38
46
  }
39
47
 
48
+ if (depth > 0) {
49
+ let repaired = cleaned.slice(start);
50
+ repaired = repaired.replace(/,\s*$/, '');
51
+ repaired += '}'.repeat(depth);
52
+ try {
53
+ JSON.parse(repaired);
54
+ return repaired;
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+
40
60
  return null;
41
61
  }