ai-codegen-cli-vrk 1.0.1 → 2.0.1
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 +1 -1
- package/package.json +7 -4
- package/src/aiClient.js +51 -105
- package/src/fileWriter.js +4 -7
- package/src/runner.js +30 -49
- package/src/promptTemplate.js +0 -34
package/bin/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "../src/runner.js";
|
|
2
|
+
import "../src/runner.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-codegen-cli-vrk",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Terminal-based AI code generator",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Minimalist Terminal-based AI code generator",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"ai-codegen": "bin/index.js"
|
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
"src"
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"@google/generative-ai": "^0.21.0",
|
|
14
15
|
"fs-extra": "^11.2.0",
|
|
15
|
-
"groq-sdk": "^0.7.0",
|
|
16
16
|
"readline-sync": "^1.4.10"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18.0.0"
|
|
17
20
|
}
|
|
18
|
-
}
|
|
21
|
+
}
|
package/src/aiClient.js
CHANGED
|
@@ -1,110 +1,56 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
2
2
|
|
|
3
|
-
let
|
|
3
|
+
let genAI = null;
|
|
4
|
+
let model = null;
|
|
4
5
|
|
|
5
6
|
export function setApiKey(apiKey) {
|
|
6
|
-
|
|
7
|
+
genAI = new GoogleGenerativeAI(apiKey);
|
|
8
|
+
// Using 1.5-flash for speed and large context window
|
|
9
|
+
model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
|
|
7
10
|
}
|
|
8
11
|
|
|
9
|
-
async function
|
|
10
|
-
if (!
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/* ========= PHASE 2: FILE CONTENT ========= */
|
|
55
|
-
export async function generateFileContent(filePath, task, tests) {
|
|
56
|
-
try {
|
|
57
|
-
const res = await call([
|
|
58
|
-
{
|
|
59
|
-
role: "system",
|
|
60
|
-
content: `
|
|
61
|
-
Generate ONLY the source code for this file:
|
|
62
|
-
|
|
63
|
-
${filePath}
|
|
64
|
-
|
|
65
|
-
No explanations.
|
|
66
|
-
No markdown.
|
|
67
|
-
Return RAW CODE ONLY.
|
|
68
|
-
`
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
role: "user",
|
|
72
|
-
content: `TASK:\n${task}\n\nTESTS:\n${tests}`
|
|
73
|
-
}
|
|
74
|
-
]);
|
|
75
|
-
|
|
76
|
-
const content = res.choices[0].message.content?.trim();
|
|
77
|
-
|
|
78
|
-
if (content && content.length > 0) {
|
|
79
|
-
return { path: filePath, content };
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
/* fall through */
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/* ========= GENERIC FALLBACK ========= */
|
|
86
|
-
|
|
87
|
-
if (filePath.endsWith(".py")) {
|
|
88
|
-
return {
|
|
89
|
-
path: filePath,
|
|
90
|
-
content: `def main():
|
|
91
|
-
pass
|
|
92
|
-
|
|
93
|
-
if __name__ == "__main__":
|
|
94
|
-
main()
|
|
95
|
-
`
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (filePath.endsWith(".js")) {
|
|
100
|
-
return {
|
|
101
|
-
path: filePath,
|
|
102
|
-
content: `module.exports = {};`
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
path: filePath,
|
|
108
|
-
content: ""
|
|
109
|
-
};
|
|
110
|
-
}
|
|
12
|
+
export async function generateFullProject(task, tests) {
|
|
13
|
+
if (!genAI) throw new Error("API Key not set");
|
|
14
|
+
|
|
15
|
+
const prompt = `
|
|
16
|
+
You are an expert automated coding exam solver.
|
|
17
|
+
Generate the ENTIRE project in a SINGLE continuous text response.
|
|
18
|
+
|
|
19
|
+
### RULES:
|
|
20
|
+
1. ABSOLUTE PRIORITY: Test cases are the ONLY specification.
|
|
21
|
+
2. MINIMALIST: Generate the bare minimum code to pass. No extra logic.
|
|
22
|
+
3. FLAT STRUCTURE: Use simple, standard patterns.
|
|
23
|
+
4. DEPENDENCIES: Only use 'express', 'mongoose', 'jsonwebtoken', and 'cookie-parser' if needed.
|
|
24
|
+
|
|
25
|
+
### FORMATTING (STRICT):
|
|
26
|
+
Every file MUST start with this EXACT header style:
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* ==========================================
|
|
30
|
+
* FILE: package.json (Reference)
|
|
31
|
+
* ==========================================
|
|
32
|
+
* [List Dependencies here]
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// ==========================================
|
|
36
|
+
// FILE: path/to/filename.js
|
|
37
|
+
// ==========================================
|
|
38
|
+
[CODE HERE]
|
|
39
|
+
|
|
40
|
+
### TASK:
|
|
41
|
+
${task}
|
|
42
|
+
|
|
43
|
+
### TESTS:
|
|
44
|
+
${tests}
|
|
45
|
+
|
|
46
|
+
### OUTPUT:
|
|
47
|
+
Return ONLY the code sections. No talk. No markdown backticks.
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
const result = await model.generateContent(prompt);
|
|
51
|
+
const response = await result.response;
|
|
52
|
+
const text = response.text();
|
|
53
|
+
|
|
54
|
+
// Strip markdown backticks in case AI adds them
|
|
55
|
+
return text.replace(/```[a-z]*\n([\s\S]*?)\n```/gi, "$1").trim();
|
|
56
|
+
}
|
package/src/fileWriter.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import fs from "fs-extra";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
export async function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
await fs.writeFile(fullPath, file.content, "utf8");
|
|
9
|
-
}
|
|
10
|
-
}
|
|
4
|
+
export async function writeSingleFile(baseDir, content) {
|
|
5
|
+
const outputPath = path.join(baseDir, "generated_project.txt");
|
|
6
|
+
await fs.writeFile(outputPath, content, "utf8");
|
|
7
|
+
}
|
package/src/runner.js
CHANGED
|
@@ -1,63 +1,44 @@
|
|
|
1
1
|
import readlineSync from "readline-sync";
|
|
2
2
|
import fs from "fs";
|
|
3
|
+
import { setApiKey, generateFullProject } from "./aiClient.js";
|
|
4
|
+
import { writeSingleFile } from "./fileWriter.js";
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
async function main() {
|
|
7
|
+
// Visible prompt for API key
|
|
8
|
+
const apiKey = readlineSync.question("--- ");
|
|
9
|
+
if (!apiKey || apiKey.trim().length === 0) process.exit(1);
|
|
10
|
+
setApiKey(apiKey.trim());
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
hideEchoBack: true
|
|
10
|
-
});
|
|
12
|
+
const task = readlineSync.question("- ");
|
|
13
|
+
if (!task || task.trim().length === 0) process.exit(1);
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (!task || task.trim().length === 0) {
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/* -------- TESTS (--) OPTIONAL -------- */
|
|
26
|
-
const testsInput = readlineSync.question("-- ");
|
|
27
|
-
let tests = "";
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
if (
|
|
31
|
-
testsInput &&
|
|
32
|
-
(testsInput.endsWith(".js") || testsInput.endsWith(".test.js")) &&
|
|
33
|
-
fs.existsSync(testsInput)
|
|
34
|
-
) {
|
|
35
|
-
tests = fs.readFileSync(testsInput, "utf8");
|
|
36
|
-
} else {
|
|
15
|
+
const testsInput = readlineSync.question("-- ");
|
|
16
|
+
let tests = "";
|
|
17
|
+
try {
|
|
18
|
+
if (testsInput && fs.existsSync(testsInput)) {
|
|
19
|
+
tests = fs.readFileSync(testsInput, "utf8");
|
|
20
|
+
} else {
|
|
21
|
+
tests = testsInput || "Implement correctly.";
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
37
24
|
tests = testsInput;
|
|
38
25
|
}
|
|
39
|
-
} catch {
|
|
40
|
-
tests = testsInput;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/* ---- SILENT FALLBACK ---- */
|
|
44
|
-
if (!tests || tests.trim().length === 0) {
|
|
45
|
-
tests = "No tests provided. Generate a simple correct implementation.";
|
|
46
|
-
}
|
|
47
26
|
|
|
48
|
-
(async () => {
|
|
49
27
|
try {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
files.push(file);
|
|
28
|
+
console.log(".....");
|
|
29
|
+
const projectContent = await generateFullProject(task, tests);
|
|
30
|
+
|
|
31
|
+
if (!projectContent || projectContent.length < 20) {
|
|
32
|
+
throw new Error("AI returned no project content. Check your prompt.");
|
|
56
33
|
}
|
|
57
34
|
|
|
58
|
-
await
|
|
35
|
+
await writeSingleFile(process.cwd(), projectContent);
|
|
59
36
|
process.exit(0);
|
|
60
|
-
} catch {
|
|
37
|
+
} catch (error) {
|
|
38
|
+
// Report errors explicitly instead of exiting silently
|
|
39
|
+
console.error("\n❌ Error:", error.message);
|
|
61
40
|
process.exit(1);
|
|
62
41
|
}
|
|
63
|
-
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
main();
|
package/src/promptTemplate.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
RULES:
|
|
8
|
-
- Generate the MINIMUM code needed
|
|
9
|
-
- No extra logic
|
|
10
|
-
- No comments
|
|
11
|
-
- No console logs
|
|
12
|
-
- No refactoring
|
|
13
|
-
- No optimization
|
|
14
|
-
|
|
15
|
-
ARCHITECTURE:
|
|
16
|
-
- Create ONLY required files
|
|
17
|
-
- Names must match tests EXACTLY
|
|
18
|
-
- Error messages must match EXACTLY
|
|
19
|
-
|
|
20
|
-
OUTPUT:
|
|
21
|
-
- ONLY valid JSON
|
|
22
|
-
- No markdown
|
|
23
|
-
- No explanations
|
|
24
|
-
|
|
25
|
-
FORMAT:
|
|
26
|
-
{
|
|
27
|
-
"files": [
|
|
28
|
-
{
|
|
29
|
-
"path": "relative/path/file.js",
|
|
30
|
-
"content": "exact code"
|
|
31
|
-
}
|
|
32
|
-
]
|
|
33
|
-
}
|
|
34
|
-
`;
|