@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.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/dist/architecture-evolution/capability-analyzer.d.ts.map +1 -1
  3. package/dist/architecture-evolution/capability-analyzer.js +6 -3
  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/parameter-optimizer.d.ts.map +1 -1
  9. package/dist/architecture-evolution/parameter-optimizer.js +32 -9
  10. package/dist/architecture-evolution/parameter-optimizer.js.map +1 -1
  11. package/dist/architecture-evolution/prompts.d.ts.map +1 -1
  12. package/dist/architecture-evolution/prompts.js +42 -4
  13. package/dist/architecture-evolution/prompts.js.map +1 -1
  14. package/dist/constraints/modification-validator.d.ts.map +1 -1
  15. package/dist/constraints/modification-validator.js +16 -5
  16. package/dist/constraints/modification-validator.js.map +1 -1
  17. package/dist/constraints/rollback-manager.d.ts +1 -0
  18. package/dist/constraints/rollback-manager.d.ts.map +1 -1
  19. package/dist/constraints/rollback-manager.js +25 -1
  20. package/dist/constraints/rollback-manager.js.map +1 -1
  21. package/dist/events/event-emitter.d.ts +0 -1
  22. package/dist/events/event-emitter.d.ts.map +1 -1
  23. package/dist/events/event-emitter.js +6 -10
  24. package/dist/events/event-emitter.js.map +1 -1
  25. package/dist/meta-reasoning/meta-reasoner.d.ts +1 -1
  26. package/dist/meta-reasoning/meta-reasoner.d.ts.map +1 -1
  27. package/dist/meta-reasoning/meta-reasoner.js +22 -13
  28. package/dist/meta-reasoning/meta-reasoner.js.map +1 -1
  29. package/dist/meta-reasoning/observation-collector.d.ts.map +1 -1
  30. package/dist/meta-reasoning/observation-collector.js +6 -2
  31. package/dist/meta-reasoning/observation-collector.js.map +1 -1
  32. package/dist/meta-reasoning/prompts.d.ts.map +1 -1
  33. package/dist/meta-reasoning/prompts.js +5 -38
  34. package/dist/meta-reasoning/prompts.js.map +1 -1
  35. package/dist/meta-reasoning/strategy-selector.d.ts.map +1 -1
  36. package/dist/meta-reasoning/strategy-selector.js +6 -0
  37. package/dist/meta-reasoning/strategy-selector.js.map +1 -1
  38. package/dist/self-modifying-agent.d.ts +8 -1
  39. package/dist/self-modifying-agent.d.ts.map +1 -1
  40. package/dist/self-modifying-agent.js +108 -14
  41. package/dist/self-modifying-agent.js.map +1 -1
  42. package/dist/tool-generation/gap-analyzer.d.ts.map +1 -1
  43. package/dist/tool-generation/gap-analyzer.js +3 -2
  44. package/dist/tool-generation/gap-analyzer.js.map +1 -1
  45. package/dist/tool-generation/generated-tool-store.d.ts.map +1 -1
  46. package/dist/tool-generation/generated-tool-store.js +90 -10
  47. package/dist/tool-generation/generated-tool-store.js.map +1 -1
  48. package/dist/tool-generation/index.d.ts +1 -1
  49. package/dist/tool-generation/index.d.ts.map +1 -1
  50. package/dist/tool-generation/index.js +1 -1
  51. package/dist/tool-generation/index.js.map +1 -1
  52. package/dist/tool-generation/prompts.d.ts +3 -3
  53. package/dist/tool-generation/prompts.d.ts.map +1 -1
  54. package/dist/tool-generation/prompts.js +65 -12
  55. package/dist/tool-generation/prompts.js.map +1 -1
  56. package/dist/tool-generation/tool-generator.d.ts +1 -1
  57. package/dist/tool-generation/tool-generator.d.ts.map +1 -1
  58. package/dist/tool-generation/tool-generator.js +55 -3
  59. package/dist/tool-generation/tool-generator.js.map +1 -1
  60. package/dist/tool-generation/tool-sandbox.d.ts +2 -6
  61. package/dist/tool-generation/tool-sandbox.d.ts.map +1 -1
  62. package/dist/tool-generation/tool-sandbox.js +220 -130
  63. package/dist/tool-generation/tool-sandbox.js.map +1 -1
  64. package/dist/tool-generation/tool-validator.d.ts +1 -0
  65. package/dist/tool-generation/tool-validator.d.ts.map +1 -1
  66. package/dist/tool-generation/tool-validator.js +48 -1
  67. package/dist/tool-generation/tool-validator.js.map +1 -1
  68. package/dist/utils/index.d.ts.map +1 -1
  69. package/dist/utils/index.js +30 -5
  70. package/dist/utils/index.js.map +1 -1
  71. package/package.json +14 -14
  72. package/src/__tests__/self-modifying-agent.test.ts +42 -10
  73. package/src/architecture-evolution/capability-analyzer.ts +7 -4
  74. package/src/architecture-evolution/evolution-strategy.ts +5 -2
  75. package/src/architecture-evolution/parameter-optimizer.ts +39 -15
  76. package/src/architecture-evolution/prompts.ts +48 -4
  77. package/src/constraints/modification-validator.ts +19 -8
  78. package/src/constraints/rollback-manager.ts +20 -1
  79. package/src/events/event-emitter.ts +6 -15
  80. package/src/meta-reasoning/meta-reasoner.ts +22 -15
  81. package/src/meta-reasoning/observation-collector.ts +6 -2
  82. package/src/meta-reasoning/prompts.ts +5 -44
  83. package/src/meta-reasoning/strategy-selector.ts +6 -0
  84. package/src/self-modifying-agent.ts +123 -14
  85. package/src/tool-generation/gap-analyzer.ts +3 -2
  86. package/src/tool-generation/generated-tool-store.ts +97 -10
  87. package/src/tool-generation/index.ts +1 -1
  88. package/src/tool-generation/prompts.ts +81 -12
  89. package/src/tool-generation/tool-generator.ts +71 -3
  90. package/src/tool-generation/tool-sandbox.ts +241 -170
  91. package/src/tool-generation/tool-validator.ts +51 -1
  92. package/src/utils/index.ts +29 -5
@@ -7,9 +7,30 @@ Rules:
7
7
  - Plain JavaScript only, no TypeScript
8
8
  - No require/import/eval/process/fetch
9
9
  - Must have an async function called "execute"
10
+ - Always propagate errors with throw, never silently swallow them
10
11
 
11
12
  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"}`;
13
+ {"name":"add","description":"Add two numbers","implementation":"async function execute(params) { if (typeof params.a !== 'number' || typeof params.b !== 'number') { throw new Error('Parameters a and b must be numbers'); } return params.a + params.b; }","parameters":{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}},"required":["a","b"]},"reasoning":"Simple addition"}`;
14
+
15
+ const TOOL_NAME_REGEX = /^[a-z_][a-z0-9_]*$/;
16
+
17
+ function sanitizeForPrompt(value: string): string {
18
+ return value
19
+ .replace(/\\/g, '\\\\')
20
+ .replace(/"/g, '\\"')
21
+ .replace(/\n/g, '\\n')
22
+ .replace(/\r/g, '\\r')
23
+ .replace(/\t/g, '\\t');
24
+ }
25
+
26
+ function sanitizeToolName(name: string): string {
27
+ const cleaned = name
28
+ .toLowerCase()
29
+ .replace(/[^a-z0-9_]/g, '_')
30
+ .replace(/^[0-9]/, '_$&')
31
+ .slice(0, 64);
32
+ return TOOL_NAME_REGEX.test(cleaned) ? cleaned : `generated_tool_${Date.now()}`;
33
+ }
13
34
 
14
35
  export function buildGapAnalysisPrompt(
15
36
  userIntent: string,
@@ -52,19 +73,51 @@ Respond with a JSON object:
52
73
 
53
74
  export function buildToolGenerationPrompt(
54
75
  gap: CapabilityGap,
55
- _existingTools: Array<{ name: string; description: string }>,
56
- _constraints?: {
76
+ existingTools: Array<{ name: string; description: string }>,
77
+ constraints?: {
57
78
  maxLines?: number;
58
79
  allowedModules?: string[];
59
80
  securityLevel?: 'strict' | 'moderate' | 'permissive';
60
81
  }
61
82
  ): string {
62
- return `Create a tool named "${gap.suggestedToolName}".
63
- Task: ${gap.description}
64
- Formula/Logic: ${gap.requiredCapability}
83
+ const toolName = sanitizeToolName(gap.suggestedToolName);
84
+ const description = sanitizeForPrompt(gap.description);
85
+ const capability = sanitizeForPrompt(gap.requiredCapability);
86
+
87
+ const existingToolsSection =
88
+ existingTools.length > 0
89
+ ? `\nEXISTING TOOLS (avoid duplication, consider composing with these):\n${existingTools.map((t) => `- ${t.name}: ${t.description}`).join('\n')}\n`
90
+ : '';
91
+
92
+ const constraintsSection: string[] = [];
93
+ if (constraints?.maxLines) {
94
+ constraintsSection.push(`- Maximum ${constraints.maxLines} lines of code`);
95
+ }
96
+ if (constraints?.securityLevel) {
97
+ constraintsSection.push(`- Security level: ${constraints.securityLevel}`);
98
+ }
99
+ if (constraints?.allowedModules && constraints.allowedModules.length > 0) {
100
+ constraintsSection.push(
101
+ `- Only these modules may be referenced: ${constraints.allowedModules.join(', ')}`
102
+ );
103
+ }
104
+ if (constraints?.securityLevel === 'strict') {
105
+ constraintsSection.push(
106
+ '- No eval, Function constructor, process, global, globalThis, fetch, setTimeout, setInterval',
107
+ '- No bracket notation access to global objects',
108
+ '- No prototype chain manipulation'
109
+ );
110
+ }
111
+
112
+ const constraintsText =
113
+ constraintsSection.length > 0 ? `\nCONSTRAINTS:\n${constraintsSection.join('\n')}\n` : '';
65
114
 
115
+ return `Create a tool named "${toolName}".
116
+ Task: ${description}
117
+ Formula/Logic: ${capability}
118
+ ${existingToolsSection}${constraintsText}
66
119
  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"}`;
120
+ {"name":"${toolName}","description":"${description}","implementation":"async function execute(params) { /* YOUR CODE HERE — throw on invalid input */ }","parameters":{"type":"object","properties":{/* DEFINE PARAMS */},"required":[/* REQUIRED PARAMS */]},"reasoning":"explanation"}`;
68
121
  }
69
122
 
70
123
  export function buildToolValidationPrompt(
@@ -78,7 +131,7 @@ Name: ${tool.name}
78
131
  Description: ${tool.description}
79
132
 
80
133
  IMPLEMENTATION:
81
- \`\`\`typescript
134
+ \`\`\`javascript
82
135
  ${tool.implementation}
83
136
  \`\`\`
84
137
 
@@ -123,7 +176,7 @@ Name: ${tool.name}
123
176
  Description: ${tool.description}
124
177
 
125
178
  CURRENT IMPLEMENTATION:
126
- \`\`\`typescript
179
+ \`\`\`javascript
127
180
  ${tool.implementation}
128
181
  \`\`\`
129
182
 
@@ -165,7 +218,9 @@ export function parseGapAnalysisResponse(response: string): {
165
218
  id: String(g.id || `gap_${idx}`),
166
219
  description: String(g.description || ''),
167
220
  requiredCapability: String(g.requiredCapability || ''),
168
- suggestedToolName: String(g.suggestedToolName || `generated_tool_${idx}`),
221
+ suggestedToolName: sanitizeToolName(
222
+ String(g.suggestedToolName || `generated_tool_${idx}`)
223
+ ),
169
224
  complexity: (['simple', 'moderate', 'complex'].includes(String(g.complexity))
170
225
  ? g.complexity
171
226
  : 'moderate') as 'simple' | 'moderate' | 'complex',
@@ -194,15 +249,29 @@ export function parseToolGenerationResponse(response: string): GeneratedTool | n
194
249
  } catch {}
195
250
  }
196
251
 
197
- const fnRegex = /(?:async\s+)?function\s+execute\s*\([^)]*\)\s*\{[\s\S]*?\n\}/;
252
+ const fnRegex = /(?:async\s+)?function\s+execute\s*\([^)]*\)\s*\{[\s\S]*\}/;
198
253
  const fnMatch = fnRegex.exec(response);
199
254
  if (fnMatch) {
255
+ let impl = fnMatch[0];
256
+ let braceDepth = 0;
257
+ let endIdx = impl.length;
258
+ const firstBrace = impl.indexOf('{');
259
+ for (let i = firstBrace; i < impl.length; i++) {
260
+ if (impl[i] === '{') braceDepth++;
261
+ if (impl[i] === '}') braceDepth--;
262
+ if (braceDepth === 0) {
263
+ endIdx = i + 1;
264
+ break;
265
+ }
266
+ }
267
+ impl = impl.slice(0, endIdx);
268
+
200
269
  const nameRegex = /["']?name["']?\s*[:=]\s*["']([^"']+)["']/;
201
270
  const nameMatch = nameRegex.exec(response);
202
271
  return buildToolFromParsed({
203
272
  name: nameMatch?.[1] ?? 'generated_tool',
204
273
  description: '',
205
- implementation: fnMatch[0],
274
+ implementation: impl,
206
275
  parameters: { type: 'object', properties: {} },
207
276
  });
208
277
  }
@@ -120,7 +120,7 @@ export class ToolGenerator {
120
120
  async generateQuick(
121
121
  description: string,
122
122
  name: string,
123
- _parameters: Record<string, unknown>
123
+ parameters: Record<string, unknown>
124
124
  ): Promise<GeneratedTool | null> {
125
125
  const gap: CapabilityGap = {
126
126
  id: `quick_${Date.now()}`,
@@ -133,6 +133,14 @@ export class ToolGenerator {
133
133
  };
134
134
 
135
135
  const result = await this.generate(gap, []);
136
+
137
+ if (result.tool && Object.keys(parameters).length > 0) {
138
+ result.tool.parameters = {
139
+ type: 'object',
140
+ properties: parameters,
141
+ };
142
+ }
143
+
136
144
  return result.tool;
137
145
  }
138
146
 
@@ -206,9 +214,17 @@ export class ToolGenerator {
206
214
  createExecutableTool(generated: GeneratedTool): Tool {
207
215
  const sandbox = this.sandbox;
208
216
  const tool = generated;
217
+ const paramSchema = buildZodSchema(generated.parameters);
209
218
 
210
219
  const execute = async (params: unknown): Promise<unknown> => {
211
- const result = await sandbox.execute(tool, params);
220
+ const parsed = paramSchema.safeParse(params);
221
+ if (!parsed.success) {
222
+ throw new Error(
223
+ `Invalid parameters: ${parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`
224
+ );
225
+ }
226
+
227
+ const result = await sandbox.execute(tool, parsed.data);
212
228
  if (!result.success) {
213
229
  throw new Error(result.error ?? 'Tool execution failed');
214
230
  }
@@ -218,7 +234,7 @@ export class ToolGenerator {
218
234
  return {
219
235
  name: generated.name,
220
236
  description: generated.description,
221
- parameters: z.record(z.string(), z.unknown()) as ZodType<unknown>,
237
+ parameters: paramSchema as ZodType<unknown>,
222
238
  execute,
223
239
  toJSON: () => ({
224
240
  name: generated.name,
@@ -241,3 +257,55 @@ export class ToolGenerator {
241
257
  return this.llm.chat({ model: this.model, messages, temperature });
242
258
  }
243
259
  }
260
+
261
+ function buildZodSchema(parameters: Record<string, unknown>): ZodType<unknown> {
262
+ if (
263
+ parameters.type !== 'object' ||
264
+ !parameters.properties ||
265
+ typeof parameters.properties !== 'object'
266
+ ) {
267
+ return z.record(z.string(), z.unknown());
268
+ }
269
+
270
+ const properties = parameters.properties as Record<string, Record<string, unknown>>;
271
+ const required = Array.isArray(parameters.required)
272
+ ? new Set(parameters.required as string[])
273
+ : new Set<string>();
274
+
275
+ const shape: Record<string, ZodType<unknown>> = {};
276
+
277
+ for (const [key, propSchema] of Object.entries(properties)) {
278
+ let fieldSchema: ZodType<unknown> = jsonTypeToZod(propSchema.type as string | undefined);
279
+
280
+ if (!required.has(key)) {
281
+ fieldSchema = fieldSchema.optional() as ZodType<unknown>;
282
+ }
283
+
284
+ shape[key] = fieldSchema;
285
+ }
286
+
287
+ if (Object.keys(shape).length === 0) {
288
+ return z.record(z.string(), z.unknown());
289
+ }
290
+
291
+ return z.object(shape).passthrough() as ZodType<unknown>;
292
+ }
293
+
294
+ function jsonTypeToZod(type?: string): ZodType<unknown> {
295
+ switch (type) {
296
+ case 'string':
297
+ return z.string();
298
+ case 'number':
299
+ return z.number();
300
+ case 'integer':
301
+ return z.number().int();
302
+ case 'boolean':
303
+ return z.boolean();
304
+ case 'array':
305
+ return z.array(z.unknown());
306
+ case 'object':
307
+ return z.record(z.string(), z.unknown());
308
+ default:
309
+ return z.unknown();
310
+ }
311
+ }