@stackmemoryai/stackmemory 0.5.23 → 0.5.24
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/dist/cli/claude-sm.js +2 -0
- package/dist/cli/claude-sm.js.map +2 -2
- package/dist/cli/commands/discovery.js +279 -0
- package/dist/cli/commands/discovery.js.map +7 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +2 -2
- package/dist/core/retrieval/llm-context-retrieval.js +1 -3
- package/dist/core/retrieval/llm-context-retrieval.js.map +3 -3
- package/dist/integrations/mcp/handlers/discovery-handlers.js +497 -0
- package/dist/integrations/mcp/handlers/discovery-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/index.js +40 -12
- package/dist/integrations/mcp/handlers/index.js.map +2 -2
- package/dist/integrations/mcp/server.js +270 -0
- package/dist/integrations/mcp/server.js.map +2 -2
- package/dist/integrations/mcp/tool-definitions.js +141 -5
- package/dist/integrations/mcp/tool-definitions.js.map +2 -2
- package/package.json +1 -1
- package/dist/cli/commands/agent.js +0 -286
- package/dist/cli/commands/agent.js.map +0 -7
- package/dist/cli/commands/chromadb.js +0 -482
- package/dist/cli/commands/chromadb.js.map +0 -7
- package/dist/cli/commands/gc.js +0 -251
- package/dist/cli/commands/gc.js.map +0 -7
- package/dist/cli/commands/infinite-storage.js +0 -292
- package/dist/cli/commands/infinite-storage.js.map +0 -7
- package/dist/cli/commands/linear-create.js +0 -171
- package/dist/cli/commands/linear-create.js.map +0 -7
- package/dist/cli/commands/linear-list.js +0 -103
- package/dist/cli/commands/linear-list.js.map +0 -7
- package/dist/cli/commands/linear-migrate.js +0 -64
- package/dist/cli/commands/linear-migrate.js.map +0 -7
- package/dist/cli/commands/linear-test.js +0 -134
- package/dist/cli/commands/linear-test.js.map +0 -7
- package/dist/cli/commands/tui.js +0 -77
- package/dist/cli/commands/tui.js.map +0 -7
- package/dist/cli/commands/webhook.js +0 -181
- package/dist/cli/commands/webhook.js.map +0 -7
- package/dist/cli/streamlined-cli.js +0 -144
- package/dist/cli/streamlined-cli.js.map +0 -7
- package/dist/core/events/event-bus.js +0 -110
- package/dist/core/events/event-bus.js.map +0 -7
- package/dist/core/frame/workflow-templates-stub.js +0 -42
- package/dist/core/frame/workflow-templates-stub.js.map +0 -7
- package/dist/core/plugins/plugin-interface.js +0 -87
- package/dist/core/plugins/plugin-interface.js.map +0 -7
- package/dist/core/session/clear-survival-stub.js +0 -53
- package/dist/core/session/clear-survival-stub.js.map +0 -7
- package/dist/core/storage/chromadb-simple.js +0 -172
- package/dist/core/storage/chromadb-simple.js.map +0 -7
- package/dist/core/storage/simplified-storage.js +0 -328
- package/dist/core/storage/simplified-storage.js.map +0 -7
- package/dist/features/tasks/pebbles-task-store.js +0 -647
- package/dist/features/tasks/pebbles-task-store.js.map +0 -7
- package/dist/integrations/linear/sync-enhanced.js +0 -202
- package/dist/integrations/linear/sync-enhanced.js.map +0 -7
- package/dist/plugins/linear/index.js +0 -166
- package/dist/plugins/linear/index.js.map +0 -7
- package/dist/plugins/loader.js +0 -57
- package/dist/plugins/loader.js.map +0 -7
- package/dist/plugins/plugin-interface.js +0 -67
- package/dist/plugins/plugin-interface.js.map +0 -7
- package/dist/plugins/ralph/simple-ralph-plugin.js +0 -305
- package/dist/plugins/ralph/simple-ralph-plugin.js.map +0 -7
- package/dist/plugins/ralph/use-cases/code-generator.js +0 -151
- package/dist/plugins/ralph/use-cases/code-generator.js.map +0 -7
- package/dist/plugins/ralph/use-cases/test-generator.js +0 -201
- package/dist/plugins/ralph/use-cases/test-generator.js.map +0 -7
- package/dist/utils/logger.js +0 -52
- package/dist/utils/logger.js.map +0 -7
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/plugins/plugin-interface.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin Interface for StackMemory\n * Allows optional features to be added without core dependencies\n */\n\nexport interface StackMemoryPlugin {\n name: string;\n version: string;\n description: string;\n\n // Lifecycle hooks\n initialize?(): Promise<void>;\n shutdown?(): Promise<void>;\n\n // Register CLI commands\n registerCommands?(): PluginCommand[];\n\n // Register MCP tools\n registerTools?(): PluginTool[];\n\n // Event handlers\n onFrameCreated?(frame: any): void;\n onFrameUpdated?(frame: any): void;\n onContextSaved?(context: any): void;\n onContextLoaded?(context: any): void;\n}\n\nexport interface PluginCommand {\n name: string;\n description: string;\n action: (options: any) => Promise<void>;\n options?: CommandOption[];\n}\n\nexport interface CommandOption {\n flag: string;\n description: string;\n defaultValue?: any;\n}\n\nexport interface PluginTool {\n name: string;\n description: string;\n inputSchema: any;\n handler: (input: any) => Promise<any>;\n}\n\nexport class PluginManager {\n private plugins: Map<string, StackMemoryPlugin> = new Map();\n\n async register(plugin: StackMemoryPlugin): Promise<void> {\n if (this.plugins.has(plugin.name)) {\n throw new Error(`Plugin ${plugin.name} already registered`);\n }\n\n this.plugins.set(plugin.name, plugin);\n\n if (plugin.initialize) {\n await plugin.initialize();\n }\n }\n\n async unregister(name: string): Promise<void> {\n const plugin = this.plugins.get(name);\n if (!plugin) return;\n\n if (plugin.shutdown) {\n await plugin.shutdown();\n }\n\n this.plugins.delete(name);\n }\n\n getPlugin(name: string): StackMemoryPlugin | undefined {\n return this.plugins.get(name);\n }\n\n getAllPlugins(): StackMemoryPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n // Get all commands from all plugins\n getAllCommands(): PluginCommand[] {\n const commands: PluginCommand[] = [];\n for (const plugin of this.plugins.values()) {\n if (plugin.registerCommands) {\n commands.push(...plugin.registerCommands());\n }\n }\n return commands;\n }\n\n // Get all tools from all plugins\n getAllTools(): PluginTool[] {\n const tools: PluginTool[] = [];\n for (const plugin of this.plugins.values()) {\n if (plugin.registerTools) {\n tools.push(...plugin.registerTools());\n }\n }\n return tools;\n }\n\n // Emit events to all plugins\n async emitFrameCreated(frame: any): Promise<void> {\n for (const plugin of this.plugins.values()) {\n if (plugin.onFrameCreated) {\n plugin.onFrameCreated(frame);\n }\n }\n }\n\n async emitContextSaved(context: any): Promise<void> {\n for (const plugin of this.plugins.values()) {\n if (plugin.onContextSaved) {\n plugin.onContextSaved(context);\n }\n }\n }\n}\n\n// Singleton instance\nexport const pluginManager = new PluginManager();\n"],
|
|
5
|
-
"mappings": "AA+CO,MAAM,cAAc;AAAA,EACjB,UAA0C,oBAAI,IAAI;AAAA,EAE1D,MAAM,SAAS,QAA0C;AACvD,QAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,GAAG;AACjC,YAAM,IAAI,MAAM,UAAU,OAAO,IAAI,qBAAqB;AAAA,IAC5D;AAEA,SAAK,QAAQ,IAAI,OAAO,MAAM,MAAM;AAEpC,QAAI,OAAO,YAAY;AACrB,YAAM,OAAO,WAAW;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,MAA6B;AAC5C,UAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;AACpC,QAAI,CAAC,OAAQ;AAEb,QAAI,OAAO,UAAU;AACnB,YAAM,OAAO,SAAS;AAAA,IACxB;AAEA,SAAK,QAAQ,OAAO,IAAI;AAAA,EAC1B;AAAA,EAEA,UAAU,MAA6C;AACrD,WAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC9B;AAAA,EAEA,gBAAqC;AACnC,WAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,EACzC;AAAA;AAAA,EAGA,iBAAkC;AAChC,UAAM,WAA4B,CAAC;AACnC,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,kBAAkB;AAC3B,iBAAS,KAAK,GAAG,OAAO,iBAAiB,CAAC;AAAA,MAC5C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAA4B;AAC1B,UAAM,QAAsB,CAAC;AAC7B,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,eAAe;AACxB,cAAM,KAAK,GAAG,OAAO,cAAc,CAAC;AAAA,MACtC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,iBAAiB,OAA2B;AAChD,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,gBAAgB;AACzB,eAAO,eAAe,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,SAA6B;AAClD,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,gBAAgB;AACzB,eAAO,eAAe,OAAO;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAGO,MAAM,gBAAgB,IAAI,cAAc;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
import { BasePlugin } from "../../core/plugins/plugin-interface.js";
|
|
2
|
-
import { EventTypes } from "../../core/events/event-bus.js";
|
|
3
|
-
import { execSync } from "child_process";
|
|
4
|
-
import * as fs from "fs/promises";
|
|
5
|
-
import * as path from "path";
|
|
6
|
-
class SimpleRalphPlugin extends BasePlugin {
|
|
7
|
-
name = "simple-ralph";
|
|
8
|
-
version = "2.0.0";
|
|
9
|
-
description = "Simplified Ralph loop for focused iterative development";
|
|
10
|
-
activeTasks = /* @__PURE__ */ new Map();
|
|
11
|
-
taskResults = /* @__PURE__ */ new Map();
|
|
12
|
-
async onInitialize() {
|
|
13
|
-
this.on(EventTypes.CONTEXT_LOADED, this.handleContextLoaded.bind(this));
|
|
14
|
-
}
|
|
15
|
-
async onStart() {
|
|
16
|
-
console.log("Simple Ralph plugin started");
|
|
17
|
-
}
|
|
18
|
-
async onStop() {
|
|
19
|
-
for (const taskId of this.activeTasks.keys()) {
|
|
20
|
-
await this.cancelTask(taskId);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
async onShutdown() {
|
|
24
|
-
this.activeTasks.clear();
|
|
25
|
-
this.taskResults.clear();
|
|
26
|
-
}
|
|
27
|
-
onValidateConfig(config) {
|
|
28
|
-
const errors = [];
|
|
29
|
-
const warnings = [];
|
|
30
|
-
if (config.options?.maxIterations && config.options.maxIterations > 100) {
|
|
31
|
-
warnings.push("Max iterations > 100 may take a long time");
|
|
32
|
-
}
|
|
33
|
-
return { valid: true, errors, warnings };
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Run a simple iterative task
|
|
37
|
-
*/
|
|
38
|
-
async runTask(task) {
|
|
39
|
-
const taskId = task.id || this.generateTaskId();
|
|
40
|
-
this.activeTasks.set(taskId, task);
|
|
41
|
-
const result = {
|
|
42
|
-
taskId,
|
|
43
|
-
success: false,
|
|
44
|
-
iterations: 0,
|
|
45
|
-
totalDuration: 0,
|
|
46
|
-
finalState: "initialized",
|
|
47
|
-
results: []
|
|
48
|
-
};
|
|
49
|
-
const startTime = Date.now();
|
|
50
|
-
const maxIterations = task.maxIterations || 10;
|
|
51
|
-
try {
|
|
52
|
-
this.emit(EventTypes.RALPH_ITERATION_START, {
|
|
53
|
-
taskId,
|
|
54
|
-
task: task.description,
|
|
55
|
-
maxIterations
|
|
56
|
-
});
|
|
57
|
-
for (let i = 1; i <= maxIterations; i++) {
|
|
58
|
-
const iterationResult = await this.runIteration(task, i);
|
|
59
|
-
result.results.push(iterationResult);
|
|
60
|
-
result.iterations = i;
|
|
61
|
-
if (iterationResult.success) {
|
|
62
|
-
result.success = true;
|
|
63
|
-
result.finalState = "completed";
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
if (i < maxIterations && !this.shouldContinue(iterationResult)) {
|
|
67
|
-
result.finalState = "stopped";
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
result.totalDuration = Date.now() - startTime;
|
|
72
|
-
this.emit(EventTypes.RALPH_LOOP_COMPLETE, {
|
|
73
|
-
taskId,
|
|
74
|
-
success: result.success,
|
|
75
|
-
iterations: result.iterations,
|
|
76
|
-
duration: result.totalDuration
|
|
77
|
-
});
|
|
78
|
-
this.taskResults.set(taskId, result);
|
|
79
|
-
return result;
|
|
80
|
-
} catch (error) {
|
|
81
|
-
result.finalState = "failed";
|
|
82
|
-
result.totalDuration = Date.now() - startTime;
|
|
83
|
-
this.emit(EventTypes.RALPH_ITERATION_FAILED, {
|
|
84
|
-
taskId,
|
|
85
|
-
error: error instanceof Error ? error.message : String(error)
|
|
86
|
-
});
|
|
87
|
-
throw error;
|
|
88
|
-
} finally {
|
|
89
|
-
this.activeTasks.delete(taskId);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Run a single iteration
|
|
94
|
-
*/
|
|
95
|
-
async runIteration(task, iteration) {
|
|
96
|
-
const startTime = Date.now();
|
|
97
|
-
const result = {
|
|
98
|
-
iteration,
|
|
99
|
-
success: false,
|
|
100
|
-
changes: [],
|
|
101
|
-
testsPassed: false,
|
|
102
|
-
metrics: {
|
|
103
|
-
duration: 0,
|
|
104
|
-
filesChanged: 0,
|
|
105
|
-
testsRun: 0
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
try {
|
|
109
|
-
const analysis = await this.analyzeCurrentState();
|
|
110
|
-
const plan = await this.planChanges(task, analysis);
|
|
111
|
-
const changes = await this.applyChanges(plan);
|
|
112
|
-
result.changes = changes;
|
|
113
|
-
result.metrics.filesChanged = changes.length;
|
|
114
|
-
const testResult = await this.runTests();
|
|
115
|
-
result.testsPassed = testResult.passed;
|
|
116
|
-
result.metrics.testsRun = testResult.total;
|
|
117
|
-
result.success = await this.checkAcceptanceCriteria(task, testResult);
|
|
118
|
-
this.emit(EventTypes.RALPH_ITERATION_COMPLETE, {
|
|
119
|
-
taskId: task.id,
|
|
120
|
-
iteration,
|
|
121
|
-
success: result.success,
|
|
122
|
-
changes: changes.length
|
|
123
|
-
});
|
|
124
|
-
} catch (error) {
|
|
125
|
-
result.errors = [error instanceof Error ? error.message : String(error)];
|
|
126
|
-
this.emit(EventTypes.RALPH_ITERATION_FAILED, {
|
|
127
|
-
taskId: task.id,
|
|
128
|
-
iteration,
|
|
129
|
-
error: result.errors[0]
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
result.metrics.duration = Date.now() - startTime;
|
|
133
|
-
return result;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Analyze current project state
|
|
137
|
-
*/
|
|
138
|
-
async analyzeCurrentState() {
|
|
139
|
-
const analysis = {
|
|
140
|
-
hasTests: false,
|
|
141
|
-
hasPackageJson: false,
|
|
142
|
-
gitStatus: "clean",
|
|
143
|
-
lastCommit: ""
|
|
144
|
-
};
|
|
145
|
-
try {
|
|
146
|
-
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
147
|
-
try {
|
|
148
|
-
await fs.access(packageJsonPath);
|
|
149
|
-
analysis.hasPackageJson = true;
|
|
150
|
-
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
|
|
151
|
-
analysis.hasTests = !!packageJson.scripts?.test;
|
|
152
|
-
} catch {
|
|
153
|
-
}
|
|
154
|
-
try {
|
|
155
|
-
analysis.gitStatus = execSync("git status --porcelain", { encoding: "utf-8" }).trim() || "clean";
|
|
156
|
-
analysis.lastCommit = execSync("git log -1 --oneline", { encoding: "utf-8" }).trim();
|
|
157
|
-
} catch {
|
|
158
|
-
}
|
|
159
|
-
} catch (error) {
|
|
160
|
-
console.error("Error analyzing state:", error);
|
|
161
|
-
}
|
|
162
|
-
return analysis;
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Plan changes based on task and current state
|
|
166
|
-
*/
|
|
167
|
-
async planChanges(task, analysis) {
|
|
168
|
-
const changes = [];
|
|
169
|
-
if (!analysis.hasTests && task.acceptanceCriteria.some((c) => c.includes("test"))) {
|
|
170
|
-
changes.push("add-tests");
|
|
171
|
-
}
|
|
172
|
-
if (task.description.includes("refactor")) {
|
|
173
|
-
changes.push("refactor-code");
|
|
174
|
-
}
|
|
175
|
-
if (task.description.includes("document")) {
|
|
176
|
-
changes.push("add-documentation");
|
|
177
|
-
}
|
|
178
|
-
if (task.description.includes("optimize")) {
|
|
179
|
-
changes.push("optimize-performance");
|
|
180
|
-
}
|
|
181
|
-
if (changes.length === 0) {
|
|
182
|
-
changes.push("incremental-improvement");
|
|
183
|
-
}
|
|
184
|
-
return changes;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Apply planned changes
|
|
188
|
-
*/
|
|
189
|
-
async applyChanges(plan) {
|
|
190
|
-
const appliedChanges = [];
|
|
191
|
-
for (const change of plan) {
|
|
192
|
-
try {
|
|
193
|
-
switch (change) {
|
|
194
|
-
case "add-tests":
|
|
195
|
-
appliedChanges.push("Added test suite");
|
|
196
|
-
break;
|
|
197
|
-
case "refactor-code":
|
|
198
|
-
appliedChanges.push("Refactored code structure");
|
|
199
|
-
break;
|
|
200
|
-
case "add-documentation":
|
|
201
|
-
appliedChanges.push("Added documentation");
|
|
202
|
-
break;
|
|
203
|
-
case "optimize-performance":
|
|
204
|
-
appliedChanges.push("Optimized performance");
|
|
205
|
-
break;
|
|
206
|
-
default:
|
|
207
|
-
appliedChanges.push("Made incremental improvements");
|
|
208
|
-
}
|
|
209
|
-
} catch (error) {
|
|
210
|
-
console.error(`Failed to apply change ${change}:`, error);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return appliedChanges;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Run project tests
|
|
217
|
-
*/
|
|
218
|
-
async runTests() {
|
|
219
|
-
try {
|
|
220
|
-
const output = execSync("npm test", { encoding: "utf-8", stdio: "pipe" });
|
|
221
|
-
const passed = !output.includes("failed") && !output.includes("error");
|
|
222
|
-
const total = output.match(/\d+ (tests?|specs?)/i)?.[0]?.match(/\d+/)?.[0] || 0;
|
|
223
|
-
return {
|
|
224
|
-
passed,
|
|
225
|
-
total: parseInt(String(total)) || 1,
|
|
226
|
-
failed: passed ? 0 : 1
|
|
227
|
-
};
|
|
228
|
-
} catch (error) {
|
|
229
|
-
return { passed: false, total: 0, failed: 1 };
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Check if acceptance criteria are met
|
|
234
|
-
*/
|
|
235
|
-
async checkAcceptanceCriteria(task, testResult) {
|
|
236
|
-
for (const criterion of task.acceptanceCriteria) {
|
|
237
|
-
const lower = criterion.toLowerCase();
|
|
238
|
-
if (lower.includes("test") && !testResult.passed) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
if (lower.includes("lint")) {
|
|
242
|
-
try {
|
|
243
|
-
execSync("npm run lint", { stdio: "pipe" });
|
|
244
|
-
} catch {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (lower.includes("build")) {
|
|
249
|
-
try {
|
|
250
|
-
execSync("npm run build", { stdio: "pipe" });
|
|
251
|
-
} catch {
|
|
252
|
-
return false;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Determine if we should continue iterating
|
|
260
|
-
*/
|
|
261
|
-
shouldContinue(result) {
|
|
262
|
-
if (result.changes.length === 0) {
|
|
263
|
-
return false;
|
|
264
|
-
}
|
|
265
|
-
if (result.errors && result.errors.length > 3) {
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
return true;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Cancel an active task
|
|
272
|
-
*/
|
|
273
|
-
async cancelTask(taskId) {
|
|
274
|
-
if (this.activeTasks.has(taskId)) {
|
|
275
|
-
this.activeTasks.delete(taskId);
|
|
276
|
-
this.emit("ralph.task.cancelled", { taskId });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Get task results
|
|
281
|
-
*/
|
|
282
|
-
getTaskResult(taskId) {
|
|
283
|
-
return this.taskResults.get(taskId);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Get all active tasks
|
|
287
|
-
*/
|
|
288
|
-
getActiveTasks() {
|
|
289
|
-
return Array.from(this.activeTasks.values());
|
|
290
|
-
}
|
|
291
|
-
handleContextLoaded(event) {
|
|
292
|
-
console.log("Context loaded, can use for enhanced planning");
|
|
293
|
-
}
|
|
294
|
-
generateTaskId() {
|
|
295
|
-
return `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
function createSimpleRalphPlugin(config) {
|
|
299
|
-
return new SimpleRalphPlugin();
|
|
300
|
-
}
|
|
301
|
-
export {
|
|
302
|
-
SimpleRalphPlugin,
|
|
303
|
-
createSimpleRalphPlugin
|
|
304
|
-
};
|
|
305
|
-
//# sourceMappingURL=simple-ralph-plugin.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/plugins/ralph/simple-ralph-plugin.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Simple Ralph Plugin - Focused iteration loop for practical dev tasks\n * No complex orchestration, just iterative improvement\n */\n\nimport { BasePlugin, PluginConfig, ValidationResult } from '../../core/plugins/plugin-interface.js';\nimport { EventTypes } from '../../core/events/event-bus.js';\nimport { execSync } from 'child_process';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nexport interface SimpleTask {\n id: string;\n description: string;\n acceptanceCriteria: string[];\n maxIterations?: number;\n timeoutMs?: number;\n}\n\nexport interface IterationResult {\n iteration: number;\n success: boolean;\n changes: string[];\n testsPassed: boolean;\n errors?: string[];\n metrics?: {\n duration: number;\n filesChanged: number;\n testsRun: number;\n };\n}\n\nexport interface TaskResult {\n taskId: string;\n success: boolean;\n iterations: number;\n totalDuration: number;\n finalState: string;\n results: IterationResult[];\n}\n\nexport class SimpleRalphPlugin extends BasePlugin {\n readonly name = 'simple-ralph';\n readonly version = '2.0.0';\n readonly description = 'Simplified Ralph loop for focused iterative development';\n \n private activeTasks = new Map<string, SimpleTask>();\n private taskResults = new Map<string, TaskResult>();\n\n protected async onInitialize(): Promise<void> {\n // Subscribe to relevant events\n this.on(EventTypes.CONTEXT_LOADED, this.handleContextLoaded.bind(this));\n }\n\n protected async onStart(): Promise<void> {\n console.log('Simple Ralph plugin started');\n }\n\n protected async onStop(): Promise<void> {\n // Cancel any active tasks\n for (const taskId of this.activeTasks.keys()) {\n await this.cancelTask(taskId);\n }\n }\n\n protected async onShutdown(): Promise<void> {\n this.activeTasks.clear();\n this.taskResults.clear();\n }\n\n protected onValidateConfig(config: PluginConfig): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (config.options?.maxIterations && config.options.maxIterations > 100) {\n warnings.push('Max iterations > 100 may take a long time');\n }\n\n return { valid: true, errors, warnings };\n }\n\n /**\n * Run a simple iterative task\n */\n async runTask(task: SimpleTask): Promise<TaskResult> {\n const taskId = task.id || this.generateTaskId();\n this.activeTasks.set(taskId, task);\n\n const result: TaskResult = {\n taskId,\n success: false,\n iterations: 0,\n totalDuration: 0,\n finalState: 'initialized',\n results: []\n };\n\n const startTime = Date.now();\n const maxIterations = task.maxIterations || 10;\n\n try {\n // Emit task start event\n this.emit(EventTypes.RALPH_ITERATION_START, {\n taskId,\n task: task.description,\n maxIterations\n });\n\n // Run iterations\n for (let i = 1; i <= maxIterations; i++) {\n const iterationResult = await this.runIteration(task, i);\n result.results.push(iterationResult);\n result.iterations = i;\n\n if (iterationResult.success) {\n result.success = true;\n result.finalState = 'completed';\n break;\n }\n\n // Check if we should continue\n if (i < maxIterations && !this.shouldContinue(iterationResult)) {\n result.finalState = 'stopped';\n break;\n }\n }\n\n result.totalDuration = Date.now() - startTime;\n\n // Emit completion event\n this.emit(EventTypes.RALPH_LOOP_COMPLETE, {\n taskId,\n success: result.success,\n iterations: result.iterations,\n duration: result.totalDuration\n });\n\n this.taskResults.set(taskId, result);\n return result;\n\n } catch (error) {\n result.finalState = 'failed';\n result.totalDuration = Date.now() - startTime;\n \n this.emit(EventTypes.RALPH_ITERATION_FAILED, {\n taskId,\n error: error instanceof Error ? error.message : String(error)\n });\n\n throw error;\n } finally {\n this.activeTasks.delete(taskId);\n }\n }\n\n /**\n * Run a single iteration\n */\n private async runIteration(task: SimpleTask, iteration: number): Promise<IterationResult> {\n const startTime = Date.now();\n const result: IterationResult = {\n iteration,\n success: false,\n changes: [],\n testsPassed: false,\n metrics: {\n duration: 0,\n filesChanged: 0,\n testsRun: 0\n }\n };\n\n try {\n // 1. Analyze current state\n const analysis = await this.analyzeCurrentState();\n\n // 2. Plan changes based on task and criteria\n const plan = await this.planChanges(task, analysis);\n\n // 3. Apply changes\n const changes = await this.applyChanges(plan);\n result.changes = changes;\n result.metrics!.filesChanged = changes.length;\n\n // 4. Run tests\n const testResult = await this.runTests();\n result.testsPassed = testResult.passed;\n result.metrics!.testsRun = testResult.total;\n\n // 5. Check acceptance criteria\n result.success = await this.checkAcceptanceCriteria(task, testResult);\n\n // Emit iteration complete\n this.emit(EventTypes.RALPH_ITERATION_COMPLETE, {\n taskId: task.id,\n iteration,\n success: result.success,\n changes: changes.length\n });\n\n } catch (error) {\n result.errors = [error instanceof Error ? error.message : String(error)];\n \n this.emit(EventTypes.RALPH_ITERATION_FAILED, {\n taskId: task.id,\n iteration,\n error: result.errors[0]\n });\n }\n\n result.metrics!.duration = Date.now() - startTime;\n return result;\n }\n\n /**\n * Analyze current project state\n */\n private async analyzeCurrentState(): Promise<any> {\n const analysis: any = {\n hasTests: false,\n hasPackageJson: false,\n gitStatus: 'clean',\n lastCommit: ''\n };\n\n try {\n // Check for package.json\n const packageJsonPath = path.join(process.cwd(), 'package.json');\n try {\n await fs.access(packageJsonPath);\n analysis.hasPackageJson = true;\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));\n analysis.hasTests = !!packageJson.scripts?.test;\n } catch {}\n\n // Check git status\n try {\n analysis.gitStatus = execSync('git status --porcelain', { encoding: 'utf-8' }).trim() || 'clean';\n analysis.lastCommit = execSync('git log -1 --oneline', { encoding: 'utf-8' }).trim();\n } catch {}\n } catch (error) {\n console.error('Error analyzing state:', error);\n }\n\n return analysis;\n }\n\n /**\n * Plan changes based on task and current state\n */\n private async planChanges(task: SimpleTask, analysis: any): Promise<string[]> {\n const changes: string[] = [];\n\n // Simple heuristic-based planning\n if (!analysis.hasTests && task.acceptanceCriteria.some(c => c.includes('test'))) {\n changes.push('add-tests');\n }\n\n if (task.description.includes('refactor')) {\n changes.push('refactor-code');\n }\n\n if (task.description.includes('document')) {\n changes.push('add-documentation');\n }\n\n if (task.description.includes('optimize')) {\n changes.push('optimize-performance');\n }\n\n // Default: try to make incremental improvement\n if (changes.length === 0) {\n changes.push('incremental-improvement');\n }\n\n return changes;\n }\n\n /**\n * Apply planned changes\n */\n private async applyChanges(plan: string[]): Promise<string[]> {\n const appliedChanges: string[] = [];\n\n for (const change of plan) {\n try {\n switch (change) {\n case 'add-tests':\n // Would implement test generation here\n appliedChanges.push('Added test suite');\n break;\n \n case 'refactor-code':\n // Would implement refactoring here\n appliedChanges.push('Refactored code structure');\n break;\n \n case 'add-documentation':\n // Would implement doc generation here\n appliedChanges.push('Added documentation');\n break;\n \n case 'optimize-performance':\n // Would implement optimization here\n appliedChanges.push('Optimized performance');\n break;\n \n default:\n // Generic improvement\n appliedChanges.push('Made incremental improvements');\n }\n } catch (error) {\n console.error(`Failed to apply change ${change}:`, error);\n }\n }\n\n return appliedChanges;\n }\n\n /**\n * Run project tests\n */\n private async runTests(): Promise<{ passed: boolean; total: number; failed: number }> {\n try {\n // Try npm test\n const output = execSync('npm test', { encoding: 'utf-8', stdio: 'pipe' });\n \n // Parse test results (simplified)\n const passed = !output.includes('failed') && !output.includes('error');\n const total = (output.match(/\\d+ (tests?|specs?)/i)?.[0]?.match(/\\d+/)?.[0]) || 0;\n \n return {\n passed,\n total: parseInt(String(total)) || 1,\n failed: passed ? 0 : 1\n };\n } catch (error) {\n // Tests failed or no tests\n return { passed: false, total: 0, failed: 1 };\n }\n }\n\n /**\n * Check if acceptance criteria are met\n */\n private async checkAcceptanceCriteria(task: SimpleTask, testResult: any): Promise<boolean> {\n for (const criterion of task.acceptanceCriteria) {\n const lower = criterion.toLowerCase();\n \n if (lower.includes('test') && !testResult.passed) {\n return false;\n }\n \n if (lower.includes('lint')) {\n try {\n execSync('npm run lint', { stdio: 'pipe' });\n } catch {\n return false;\n }\n }\n \n if (lower.includes('build')) {\n try {\n execSync('npm run build', { stdio: 'pipe' });\n } catch {\n return false;\n }\n }\n }\n \n return true;\n }\n\n /**\n * Determine if we should continue iterating\n */\n private shouldContinue(result: IterationResult): boolean {\n // Stop if we're making no progress\n if (result.changes.length === 0) {\n return false;\n }\n\n // Stop if we're hitting too many errors\n if (result.errors && result.errors.length > 3) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Cancel an active task\n */\n async cancelTask(taskId: string): Promise<void> {\n if (this.activeTasks.has(taskId)) {\n this.activeTasks.delete(taskId);\n this.emit('ralph.task.cancelled', { taskId });\n }\n }\n\n /**\n * Get task results\n */\n getTaskResult(taskId: string): TaskResult | undefined {\n return this.taskResults.get(taskId);\n }\n\n /**\n * Get all active tasks\n */\n getActiveTasks(): SimpleTask[] {\n return Array.from(this.activeTasks.values());\n }\n\n private handleContextLoaded(event: any): void {\n // Use loaded context to enhance iteration planning\n console.log('Context loaded, can use for enhanced planning');\n }\n\n private generateTaskId(): string {\n return `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n\n// Export convenient factory function\nexport function createSimpleRalphPlugin(config?: Partial<PluginConfig>): SimpleRalphPlugin {\n return new SimpleRalphPlugin();\n}"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { SimpleRalphPlugin } from "../simple-ralph-plugin.js";
|
|
2
|
-
import * as fs from "fs/promises";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
class CodeGenerator {
|
|
5
|
-
ralphPlugin;
|
|
6
|
-
constructor(ralphPlugin) {
|
|
7
|
-
this.ralphPlugin = ralphPlugin;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Generate code iteratively until it works
|
|
11
|
-
*/
|
|
12
|
-
async generateCode(request) {
|
|
13
|
-
const task = {
|
|
14
|
-
id: `codegen-${Date.now()}`,
|
|
15
|
-
description: `Generate ${request.language} code: ${request.description}`,
|
|
16
|
-
acceptanceCriteria: this.buildCriteria(request),
|
|
17
|
-
maxIterations: 5
|
|
18
|
-
};
|
|
19
|
-
await this.prepareOutputDirectory(request.outputPath);
|
|
20
|
-
const result = await this.ralphPlugin.runTask(task);
|
|
21
|
-
return {
|
|
22
|
-
mainFile: path.join(request.outputPath, this.getMainFileName(request)),
|
|
23
|
-
testFile: request.includeTests ? path.join(request.outputPath, this.getTestFileName(request)) : void 0,
|
|
24
|
-
dependencies: await this.extractDependencies(request.outputPath),
|
|
25
|
-
success: result.success,
|
|
26
|
-
iterations: result.iterations
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Build acceptance criteria based on request
|
|
31
|
-
*/
|
|
32
|
-
buildCriteria(request) {
|
|
33
|
-
const criteria = [];
|
|
34
|
-
criteria.push("Code compiles/runs without errors");
|
|
35
|
-
criteria.push("Code implements requested functionality");
|
|
36
|
-
switch (request.language) {
|
|
37
|
-
case "typescript":
|
|
38
|
-
criteria.push("TypeScript compiles without errors");
|
|
39
|
-
criteria.push("No any types unless necessary");
|
|
40
|
-
break;
|
|
41
|
-
case "javascript":
|
|
42
|
-
criteria.push("Passes ESLint checks");
|
|
43
|
-
break;
|
|
44
|
-
case "python":
|
|
45
|
-
criteria.push("Passes flake8 checks");
|
|
46
|
-
criteria.push("Type hints included");
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
if (request.includeTests) {
|
|
50
|
-
criteria.push("Tests pass");
|
|
51
|
-
criteria.push("Test coverage > 80%");
|
|
52
|
-
}
|
|
53
|
-
if (request.requirements) {
|
|
54
|
-
criteria.push(...request.requirements);
|
|
55
|
-
}
|
|
56
|
-
return criteria;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Prepare output directory
|
|
60
|
-
*/
|
|
61
|
-
async prepareOutputDirectory(outputPath) {
|
|
62
|
-
await fs.mkdir(outputPath, { recursive: true });
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Get main file name based on language
|
|
66
|
-
*/
|
|
67
|
-
getMainFileName(request) {
|
|
68
|
-
const baseName = "index";
|
|
69
|
-
switch (request.language) {
|
|
70
|
-
case "typescript":
|
|
71
|
-
return `${baseName}.ts`;
|
|
72
|
-
case "javascript":
|
|
73
|
-
return `${baseName}.js`;
|
|
74
|
-
case "python":
|
|
75
|
-
return `${baseName}.py`;
|
|
76
|
-
default:
|
|
77
|
-
return baseName;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get test file name based on language
|
|
82
|
-
*/
|
|
83
|
-
getTestFileName(request) {
|
|
84
|
-
const baseName = "index";
|
|
85
|
-
switch (request.language) {
|
|
86
|
-
case "typescript":
|
|
87
|
-
return `${baseName}.test.ts`;
|
|
88
|
-
case "javascript":
|
|
89
|
-
return `${baseName}.test.js`;
|
|
90
|
-
case "python":
|
|
91
|
-
return `test_${baseName}.py`;
|
|
92
|
-
default:
|
|
93
|
-
return `${baseName}.test`;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Extract dependencies from generated code
|
|
98
|
-
*/
|
|
99
|
-
async extractDependencies(outputPath) {
|
|
100
|
-
const dependencies = [];
|
|
101
|
-
try {
|
|
102
|
-
const packageJsonPath = path.join(outputPath, "package.json");
|
|
103
|
-
try {
|
|
104
|
-
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
|
|
105
|
-
dependencies.push(...Object.keys(packageJson.dependencies || {}));
|
|
106
|
-
dependencies.push(...Object.keys(packageJson.devDependencies || {}));
|
|
107
|
-
} catch {
|
|
108
|
-
}
|
|
109
|
-
const requirementsPath = path.join(outputPath, "requirements.txt");
|
|
110
|
-
try {
|
|
111
|
-
const requirements = await fs.readFile(requirementsPath, "utf-8");
|
|
112
|
-
dependencies.push(...requirements.split("\n").filter((l) => l.trim()));
|
|
113
|
-
} catch {
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
console.error("Error extracting dependencies:", error);
|
|
117
|
-
}
|
|
118
|
-
return [...new Set(dependencies)];
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
async function generateAPIEndpoint() {
|
|
122
|
-
const ralphPlugin = new SimpleRalphPlugin();
|
|
123
|
-
await ralphPlugin.initialize({
|
|
124
|
-
eventBus: {},
|
|
125
|
-
config: { name: "simple-ralph", version: "2.0.0", enabled: true },
|
|
126
|
-
dataDir: ".ralph",
|
|
127
|
-
getRepository: () => null,
|
|
128
|
-
registerRepository: () => {
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
const generator = new CodeGenerator(ralphPlugin);
|
|
132
|
-
const result = await generator.generateCode({
|
|
133
|
-
description: "REST API endpoint for user management with CRUD operations",
|
|
134
|
-
language: "typescript",
|
|
135
|
-
outputPath: "./generated/api",
|
|
136
|
-
includeTests: true,
|
|
137
|
-
testFramework: "jest",
|
|
138
|
-
requirements: [
|
|
139
|
-
"Use Express.js",
|
|
140
|
-
"Include validation",
|
|
141
|
-
"Add error handling",
|
|
142
|
-
"Support pagination"
|
|
143
|
-
]
|
|
144
|
-
});
|
|
145
|
-
console.log("Code generation result:", result);
|
|
146
|
-
}
|
|
147
|
-
export {
|
|
148
|
-
CodeGenerator,
|
|
149
|
-
generateAPIEndpoint
|
|
150
|
-
};
|
|
151
|
-
//# sourceMappingURL=code-generator.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/plugins/ralph/use-cases/code-generator.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Code Generator - Practical use case for iterative code generation\n * Focused on generating working code with tests\n */\n\nimport { SimpleRalphPlugin, SimpleTask } from '../simple-ralph-plugin.js';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { execSync } from 'child_process';\n\nexport interface CodeGenRequest {\n description: string;\n language: 'typescript' | 'javascript' | 'python';\n outputPath: string;\n includeTests?: boolean;\n testFramework?: string;\n requirements?: string[];\n}\n\nexport interface GeneratedCode {\n mainFile: string;\n testFile?: string;\n dependencies?: string[];\n success: boolean;\n iterations: number;\n}\n\nexport class CodeGenerator {\n private ralphPlugin: SimpleRalphPlugin;\n\n constructor(ralphPlugin: SimpleRalphPlugin) {\n this.ralphPlugin = ralphPlugin;\n }\n\n /**\n * Generate code iteratively until it works\n */\n async generateCode(request: CodeGenRequest): Promise<GeneratedCode> {\n // Create task for code generation\n const task: SimpleTask = {\n id: `codegen-${Date.now()}`,\n description: `Generate ${request.language} code: ${request.description}`,\n acceptanceCriteria: this.buildCriteria(request),\n maxIterations: 5\n };\n\n // Prepare output directory\n await this.prepareOutputDirectory(request.outputPath);\n\n // Run iterative generation\n const result = await this.ralphPlugin.runTask(task);\n\n // Parse results\n return {\n mainFile: path.join(request.outputPath, this.getMainFileName(request)),\n testFile: request.includeTests \n ? path.join(request.outputPath, this.getTestFileName(request))\n : undefined,\n dependencies: await this.extractDependencies(request.outputPath),\n success: result.success,\n iterations: result.iterations\n };\n }\n\n /**\n * Build acceptance criteria based on request\n */\n private buildCriteria(request: CodeGenRequest): string[] {\n const criteria: string[] = [];\n\n // Basic criteria\n criteria.push('Code compiles/runs without errors');\n criteria.push('Code implements requested functionality');\n\n // Language-specific criteria\n switch (request.language) {\n case 'typescript':\n criteria.push('TypeScript compiles without errors');\n criteria.push('No any types unless necessary');\n break;\n case 'javascript':\n criteria.push('Passes ESLint checks');\n break;\n case 'python':\n criteria.push('Passes flake8 checks');\n criteria.push('Type hints included');\n break;\n }\n\n // Test criteria\n if (request.includeTests) {\n criteria.push('Tests pass');\n criteria.push('Test coverage > 80%');\n }\n\n // Custom requirements\n if (request.requirements) {\n criteria.push(...request.requirements);\n }\n\n return criteria;\n }\n\n /**\n * Prepare output directory\n */\n private async prepareOutputDirectory(outputPath: string): Promise<void> {\n await fs.mkdir(outputPath, { recursive: true });\n }\n\n /**\n * Get main file name based on language\n */\n private getMainFileName(request: CodeGenRequest): string {\n const baseName = 'index';\n switch (request.language) {\n case 'typescript': return `${baseName}.ts`;\n case 'javascript': return `${baseName}.js`;\n case 'python': return `${baseName}.py`;\n default: return baseName;\n }\n }\n\n /**\n * Get test file name based on language\n */\n private getTestFileName(request: CodeGenRequest): string {\n const baseName = 'index';\n switch (request.language) {\n case 'typescript': return `${baseName}.test.ts`;\n case 'javascript': return `${baseName}.test.js`;\n case 'python': return `test_${baseName}.py`;\n default: return `${baseName}.test`;\n }\n }\n\n /**\n * Extract dependencies from generated code\n */\n private async extractDependencies(outputPath: string): Promise<string[]> {\n const dependencies: string[] = [];\n\n try {\n // Check for package.json\n const packageJsonPath = path.join(outputPath, 'package.json');\n try {\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));\n dependencies.push(...Object.keys(packageJson.dependencies || {}));\n dependencies.push(...Object.keys(packageJson.devDependencies || {}));\n } catch {}\n\n // Check for requirements.txt (Python)\n const requirementsPath = path.join(outputPath, 'requirements.txt');\n try {\n const requirements = await fs.readFile(requirementsPath, 'utf-8');\n dependencies.push(...requirements.split('\\n').filter(l => l.trim()));\n } catch {}\n } catch (error) {\n console.error('Error extracting dependencies:', error);\n }\n\n return [...new Set(dependencies)]; // Remove duplicates\n }\n}\n\n// Example usage function\nexport async function generateAPIEndpoint(): Promise<void> {\n const ralphPlugin = new SimpleRalphPlugin();\n await ralphPlugin.initialize({\n eventBus: {} as any,\n config: { name: 'simple-ralph', version: '2.0.0', enabled: true },\n dataDir: '.ralph',\n getRepository: () => null as any,\n registerRepository: () => {}\n });\n\n const generator = new CodeGenerator(ralphPlugin);\n \n const result = await generator.generateCode({\n description: 'REST API endpoint for user management with CRUD operations',\n language: 'typescript',\n outputPath: './generated/api',\n includeTests: true,\n testFramework: 'jest',\n requirements: [\n 'Use Express.js',\n 'Include validation',\n 'Add error handling',\n 'Support pagination'\n ]\n });\n\n console.log('Code generation result:', result);\n}"],
|
|
5
|
-
"mappings": "AAKA,SAAS,yBAAqC;AAC9C,YAAY,QAAQ;AACpB,YAAY,UAAU;AAoBf,MAAM,cAAc;AAAA,EACjB;AAAA,EAER,YAAY,aAAgC;AAC1C,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,SAAiD;AAElE,UAAM,OAAmB;AAAA,MACvB,IAAI,WAAW,KAAK,IAAI,CAAC;AAAA,MACzB,aAAa,YAAY,QAAQ,QAAQ,UAAU,QAAQ,WAAW;AAAA,MACtE,oBAAoB,KAAK,cAAc,OAAO;AAAA,MAC9C,eAAe;AAAA,IACjB;AAGA,UAAM,KAAK,uBAAuB,QAAQ,UAAU;AAGpD,UAAM,SAAS,MAAM,KAAK,YAAY,QAAQ,IAAI;AAGlD,WAAO;AAAA,MACL,UAAU,KAAK,KAAK,QAAQ,YAAY,KAAK,gBAAgB,OAAO,CAAC;AAAA,MACrE,UAAU,QAAQ,eACd,KAAK,KAAK,QAAQ,YAAY,KAAK,gBAAgB,OAAO,CAAC,IAC3D;AAAA,MACJ,cAAc,MAAM,KAAK,oBAAoB,QAAQ,UAAU;AAAA,MAC/D,SAAS,OAAO;AAAA,MAChB,YAAY,OAAO;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,SAAmC;AACvD,UAAM,WAAqB,CAAC;AAG5B,aAAS,KAAK,mCAAmC;AACjD,aAAS,KAAK,yCAAyC;AAGvD,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AACH,iBAAS,KAAK,oCAAoC;AAClD,iBAAS,KAAK,+BAA+B;AAC7C;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,sBAAsB;AACpC;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,sBAAsB;AACpC,iBAAS,KAAK,qBAAqB;AACnC;AAAA,IACJ;AAGA,QAAI,QAAQ,cAAc;AACxB,eAAS,KAAK,YAAY;AAC1B,eAAS,KAAK,qBAAqB;AAAA,IACrC;AAGA,QAAI,QAAQ,cAAc;AACxB,eAAS,KAAK,GAAG,QAAQ,YAAY;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAuB,YAAmC;AACtE,UAAM,GAAG,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,SAAiC;AACvD,UAAM,WAAW;AACjB,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AAAc,eAAO,GAAG,QAAQ;AAAA,MACrC,KAAK;AAAc,eAAO,GAAG,QAAQ;AAAA,MACrC,KAAK;AAAU,eAAO,GAAG,QAAQ;AAAA,MACjC;AAAS,eAAO;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,SAAiC;AACvD,UAAM,WAAW;AACjB,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AAAc,eAAO,GAAG,QAAQ;AAAA,MACrC,KAAK;AAAc,eAAO,GAAG,QAAQ;AAAA,MACrC,KAAK;AAAU,eAAO,QAAQ,QAAQ;AAAA,MACtC;AAAS,eAAO,GAAG,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAoB,YAAuC;AACvE,UAAM,eAAyB,CAAC;AAEhC,QAAI;AAEF,YAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAC5D,UAAI;AACF,cAAM,cAAc,KAAK,MAAM,MAAM,GAAG,SAAS,iBAAiB,OAAO,CAAC;AAC1E,qBAAa,KAAK,GAAG,OAAO,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC;AAChE,qBAAa,KAAK,GAAG,OAAO,KAAK,YAAY,mBAAmB,CAAC,CAAC,CAAC;AAAA,MACrE,QAAQ;AAAA,MAAC;AAGT,YAAM,mBAAmB,KAAK,KAAK,YAAY,kBAAkB;AACjE,UAAI;AACF,cAAM,eAAe,MAAM,GAAG,SAAS,kBAAkB,OAAO;AAChE,qBAAa,KAAK,GAAG,aAAa,MAAM,IAAI,EAAE,OAAO,OAAK,EAAE,KAAK,CAAC,CAAC;AAAA,MACrE,QAAQ;AAAA,MAAC;AAAA,IACX,SAAS,OAAO;AACd,cAAQ,MAAM,kCAAkC,KAAK;AAAA,IACvD;AAEA,WAAO,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC;AAAA,EAClC;AACF;AAGA,eAAsB,sBAAqC;AACzD,QAAM,cAAc,IAAI,kBAAkB;AAC1C,QAAM,YAAY,WAAW;AAAA,IAC3B,UAAU,CAAC;AAAA,IACX,QAAQ,EAAE,MAAM,gBAAgB,SAAS,SAAS,SAAS,KAAK;AAAA,IAChE,SAAS;AAAA,IACT,eAAe,MAAM;AAAA,IACrB,oBAAoB,MAAM;AAAA,IAAC;AAAA,EAC7B,CAAC;AAED,QAAM,YAAY,IAAI,cAAc,WAAW;AAE/C,QAAM,SAAS,MAAM,UAAU,aAAa;AAAA,IAC1C,aAAa;AAAA,IACb,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,eAAe;AAAA,IACf,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,IAAI,2BAA2B,MAAM;AAC/C;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|