ai-codegen-cli-vrk 1.0.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/bin/index.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../src/runner.js";
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "ai-codegen-cli-vrk",
3
+ "version": "1.0.0",
4
+ "description": "Terminal-based AI code generator",
5
+ "type": "module",
6
+ "bin": {
7
+ "ai-codegen": "bin/index.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src"
12
+ ],
13
+ "dependencies": {
14
+ "fs-extra": "^11.2.0",
15
+ "groq-sdk": "^0.7.0",
16
+ "readline-sync": "^1.4.10"
17
+ }
18
+ }
@@ -0,0 +1,132 @@
1
+ import Groq from "groq-sdk";
2
+
3
+ let groqClient = null;
4
+
5
+ /**
6
+ * Called once per run from runner.js
7
+ */
8
+ export function setApiKey(apiKey) {
9
+ groqClient = new Groq({ apiKey });
10
+ }
11
+
12
+ /**
13
+ * Internal helper to call Groq
14
+ */
15
+ async function call(messages) {
16
+ if (!groqClient) {
17
+ throw new Error("API key not initialized");
18
+ }
19
+
20
+ return groqClient.chat.completions.create({
21
+ model: "llama-3.1-8b-instant",
22
+ temperature: 0,
23
+ response_format: { type: "json_object" },
24
+ messages
25
+ });
26
+ }
27
+
28
+ /* ================= PHASE 1: FILE PLAN ================= */
29
+ export async function generateFilePlan(task, tests) {
30
+ const res = await call([
31
+ {
32
+ role: "system",
33
+ content: `
34
+ Return ONLY JSON.
35
+
36
+ Generate ONLY file paths required to pass the tests.
37
+
38
+ FORMAT:
39
+ {
40
+ "files": [
41
+ { "path": "models/AnyModel.js" },
42
+ { "path": "controllers/anyController.js" },
43
+ { "path": "routes/anyRoutes.js" },
44
+ { "path": "index.js" }
45
+ ]
46
+ }
47
+
48
+ No explanations.
49
+ `
50
+ },
51
+ {
52
+ role: "user",
53
+ content: `TASK:\n${task}\n\nTEST CASES:\n${tests}`
54
+ }
55
+ ]);
56
+
57
+ const parsed = JSON.parse(res.choices[0].message.content);
58
+
59
+ if (!parsed.files || !Array.isArray(parsed.files)) {
60
+ throw new Error("Invalid file plan");
61
+ }
62
+
63
+ return parsed.files.map(f => f.path);
64
+ }
65
+
66
+ /* ================= PHASE 2: FILE CONTENT ================= */
67
+ export async function generateFileContent(filePath, task, tests) {
68
+ let file = null;
69
+
70
+ try {
71
+ const res = await call([
72
+ {
73
+ role: "system",
74
+ content: `
75
+ You are generating ONLY this file:
76
+
77
+ ${filePath}
78
+
79
+ RULES:
80
+ - Tests are the ONLY specification
81
+ - Minimal code only
82
+ - No comments
83
+ - No console logs
84
+ - Use CommonJS (require/module.exports)
85
+
86
+ FORMAT:
87
+ {
88
+ "path": "${filePath}",
89
+ "content": "exact source code"
90
+ }
91
+ `
92
+ },
93
+ {
94
+ role: "user",
95
+ content: `TASK:\n${task}\n\nTEST CASES:\n${tests}`
96
+ }
97
+ ]);
98
+
99
+ file = JSON.parse(res.choices[0].message.content);
100
+ } catch {
101
+ file = null;
102
+ }
103
+
104
+ /* ===== MINIMUM GENERIC FALLBACK (MODEL ONLY) ===== */
105
+ if (
106
+ !file ||
107
+ typeof file.path !== "string" ||
108
+ typeof file.content !== "string" ||
109
+ file.content.trim().length === 0
110
+ ) {
111
+ if (filePath.startsWith("models/")) {
112
+ const modelName = filePath
113
+ .replace("models/", "")
114
+ .replace(".js", "");
115
+
116
+ return {
117
+ path: filePath,
118
+ content:
119
+ `const mongoose = require('mongoose');
120
+
121
+ const schema = new mongoose.Schema({}, { strict: false });
122
+
123
+ module.exports = mongoose.model('${modelName}', schema);
124
+ `
125
+ };
126
+ }
127
+
128
+ throw new Error(`Invalid or empty content for ${filePath}`);
129
+ }
130
+
131
+ return file;
132
+ }
@@ -0,0 +1,10 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+
4
+ export async function writeFiles(baseDir, files) {
5
+ for (const file of files) {
6
+ const fullPath = path.join(baseDir, file.path);
7
+ await fs.ensureDir(path.dirname(fullPath));
8
+ await fs.writeFile(fullPath, file.content, "utf8");
9
+ }
10
+ }
@@ -0,0 +1,43 @@
1
+ export const systemPrompt = `
2
+ You are solving an automated coding exam.
3
+
4
+ ABSOLUTE PRIORITY:
5
+ The given test cases are the ONLY specification.
6
+ Ignore best practices unless tests require them.
7
+
8
+ RULES (STRICT):
9
+ - Generate the MINIMUM code needed to pass tests
10
+ - Do NOT add extra logic
11
+ - Do NOT add extra validation
12
+ - Do NOT add console logs
13
+ - Do NOT add comments unless required
14
+ - Do NOT refactor
15
+ - Do NOT optimize
16
+ - Do NOT generalize
17
+
18
+ ARCHITECTURE RULE:
19
+ - Create ONLY the files required by tests
20
+ - File names, exports, function names MUST match tests EXACTLY
21
+ - Error messages MUST match character-by-character
22
+ - Status codes MUST match exactly
23
+
24
+ OUTPUT RULES:
25
+ - Output ONLY valid JSON
26
+ - No markdown
27
+ - No explanations
28
+ - No extra text
29
+
30
+ JSON FORMAT:
31
+ {
32
+ "files": [
33
+ {
34
+ "path": "relative/path/file.js",
35
+ "content": "exact code"
36
+ }
37
+ ]
38
+ }
39
+
40
+ IMPORTANT:
41
+ Passing tests is MORE IMPORTANT than clean code.
42
+ If a simpler solution passes tests, choose it.
43
+ `;
package/src/runner.js ADDED
@@ -0,0 +1,56 @@
1
+ import readlineSync from "readline-sync";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ import { setApiKey, generateFilePlan, generateFileContent } from "./aiClient.js";
6
+ import { writeFiles } from "./fileWriter.js";
7
+
8
+ /* ----------- API KEY (---) ----------- */
9
+ const apiKey = readlineSync.question("--- ", {
10
+ hideEchoBack: true
11
+ });
12
+
13
+ if (!apiKey || apiKey.trim().length === 0) {
14
+ console.log("API key is required");
15
+ process.exit(1);
16
+ }
17
+
18
+ setApiKey(apiKey);
19
+
20
+ /* ----------- TASK (-) ----------- */
21
+ const task = readlineSync.question("- ");
22
+
23
+ /* ----------- TESTS (-- text OR file path) ----------- */
24
+ let testsInput = readlineSync.question("-- ");
25
+ let tests;
26
+
27
+ try {
28
+ if (
29
+ (testsInput.endsWith(".js") || testsInput.endsWith(".test.js")) &&
30
+ fs.existsSync(testsInput)
31
+ ) {
32
+ tests = fs.readFileSync(testsInput, "utf8");
33
+ } else {
34
+ tests = testsInput;
35
+ }
36
+ } catch {
37
+ tests = testsInput;
38
+ }
39
+
40
+ (async () => {
41
+ try {
42
+ const paths = await generateFilePlan(task, tests);
43
+
44
+ const files = [];
45
+ for (const p of paths) {
46
+ const file = await generateFileContent(p, task, tests);
47
+ files.push(file);
48
+ }
49
+
50
+ await writeFiles(process.cwd(), files);
51
+ fs.writeFileSync(".ai_codegen_success", "");
52
+ } catch (e) {
53
+ fs.writeFileSync(".ai_codegen_error", e.message || "error");
54
+ process.exit(1);
55
+ }
56
+ })();