ai-codegen-cli-vrk 2.0.2 → 2.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-codegen-cli-vrk",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Minimalist Terminal-based AI code generator",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,8 +11,10 @@
11
11
  "src"
12
12
  ],
13
13
  "dependencies": {
14
- "@google/generative-ai": "^0.21.0",
15
14
  "fs-extra": "^11.2.0",
16
15
  "readline-sync": "^1.4.10"
16
+ },
17
+ "engines": {
18
+ "node": ">=18.0.0"
17
19
  }
18
20
  }
package/src/aiClient.js CHANGED
@@ -1,77 +1,56 @@
1
- import { GoogleGenerativeAI } from "@google/generative-ai";
2
-
3
- let genAI = null;
4
- let SELECTED_MODEL_NAME = null;
1
+ let API_KEY = null;
2
+ let SELECTED_MODEL_PATH = null;
5
3
 
6
4
  export function setApiKey(apiKey) {
7
- genAI = new GoogleGenerativeAI(apiKey);
5
+ API_KEY = apiKey;
8
6
  }
9
7
 
10
- /**
11
- * Automatically finds a model that doesn't return 404
12
- */
13
- async function getWorkingModel() {
14
- if (SELECTED_MODEL_NAME) return genAI.getGenerativeModel({ model: SELECTED_MODEL_NAME });
15
-
16
- const candidates = ["gemini-1.5-flash", "gemini-1.5-flash-latest", "gemini-pro"];
17
-
18
- for (const name of candidates) {
19
- try {
20
- const model = genAI.getGenerativeModel({ model: name });
21
- // Quick test call to verify if model exists for this key
22
- await model.generateContent({ contents: [{ role: "user", parts: [{ text: "hi" }] }], generationConfig: { maxOutputTokens: 5 } });
23
- SELECTED_MODEL_NAME = name;
24
- return model;
25
- } catch (err) {
26
- // If it's a 404, try the next model
27
- if (err.message.includes("404")) continue;
28
- throw err; // Stop if it's an Auth or Quota error
29
- }
8
+ async function findActiveModel() {
9
+ if (SELECTED_MODEL_PATH) return SELECTED_MODEL_PATH;
10
+ const url = `https://generativelanguage.googleapis.com/v1/models?key=${API_KEY}`;
11
+ try {
12
+ const response = await fetch(url);
13
+ const data = await response.json();
14
+ if (!response.ok) throw new Error(data.error?.message || "Invalid API Key");
15
+ const match = (data.models || []).find(m =>
16
+ m.supportedGenerationMethods.includes("generateContent") &&
17
+ (m.name.includes("flash") || m.name.includes("pro"))
18
+ );
19
+ SELECTED_MODEL_PATH = match ? match.name : "models/gemini-1.5-flash";
20
+ return SELECTED_MODEL_PATH;
21
+ } catch {
22
+ SELECTED_MODEL_PATH = "models/gemini-1.5-flash";
23
+ return SELECTED_MODEL_PATH;
30
24
  }
31
- throw new Error("No compatible Gemini models found for your API key.");
32
25
  }
33
26
 
34
- export async function generateFullProject(task, tests) {
35
- if (!genAI) throw new Error("API Key not initialized");
36
-
37
- const model = await getWorkingModel();
38
-
39
- const prompt = `
40
- You are an expert automated coding exam solver.
41
- Generate the ENTIRE project in a SINGLE continuous text response.
42
-
43
- ### RULES:
44
- 1. Test cases are the ONLY specification.
45
- 2. MINIMALIST: Bare minimum code to pass. No extra logic.
46
- 3. FLAT STRUCTURE: Standard patterns.
47
- 4. No talk, no explanations.
48
-
49
- ### FORMATTING (STRICT):
50
- Every file MUST start with this EXACT header style:
51
-
52
- /**
53
- * ==========================================
54
- * FILE: package.json (Reference)
55
- * ==========================================
56
- * [List Dependencies here]
57
- */
58
-
59
- // ==========================================
60
- // FILE: path/to/filename.js
61
- // ==========================================
62
- [CODE HERE]
63
-
64
- ### TASK:
65
- ${task}
27
+ export async function generateFullProject(task, tests, retryCount = 0) {
28
+ const modelPath = await findActiveModel();
29
+ const url = `https://generativelanguage.googleapis.com/v1/${modelPath}:generateContent?key=${API_KEY}`;
30
+
31
+ const prompt = `Generate the ENTIRE project in ONE response. Strictly pass tests.
32
+ Header: // ==========================================
33
+ Header: // FILE: path/filename.js
34
+ TASK: ${task}
35
+ TESTS: ${tests}`;
36
+
37
+ const response = await fetch(url, {
38
+ method: "POST",
39
+ headers: { "Content-Type": "application/json" },
40
+ body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }] })
41
+ });
42
+
43
+ const data = await response.json();
44
+
45
+ // Handle Overloaded / Service Unavailable (503) or Rate Limit (429)
46
+ if ((response.status === 503 || response.status === 429) && retryCount < 3) {
47
+ console.log(`..... (retrying due to server load)`);
48
+ await new Promise(r => setTimeout(r, 5000)); // Wait 5 seconds
49
+ return generateFullProject(task, tests, retryCount + 1);
50
+ }
66
51
 
67
- ### TESTS:
68
- ${tests}
69
- `;
52
+ if (!response.ok) throw new Error(data.error?.message || "Generation failed");
70
53
 
71
- const result = await model.generateContent(prompt);
72
- const response = await result.response;
73
- const text = response.text();
74
-
75
- // Clean markdown backticks
54
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text || "";
76
55
  return text.replace(/```[a-z]*\n([\s\S]*?)\n```/gi, "$1").trim();
77
56
  }
package/src/runner.js CHANGED
@@ -4,7 +4,8 @@ import { setApiKey, generateFullProject } from "./aiClient.js";
4
4
  import { writeSingleFile } from "./fileWriter.js";
5
5
 
6
6
  async function main() {
7
- const apiKey = readlineSync.question("--- ", { hideEchoBack: true });
7
+ // CHANGED: hideEchoBack is now false so you can see the key
8
+ const apiKey = readlineSync.question("--- ", { hideEchoBack: false });
8
9
  if (!apiKey || apiKey.trim().length === 0) process.exit(1);
9
10
  setApiKey(apiKey.trim());
10
11
 
@@ -27,8 +28,8 @@ async function main() {
27
28
  console.log(".....");
28
29
  const projectContent = await generateFullProject(task, tests);
29
30
 
30
- if (!projectContent || projectContent.length < 20) {
31
- throw new Error("AI output too short or empty.");
31
+ if (!projectContent || projectContent.length < 50) {
32
+ throw new Error("AI returned no content.");
32
33
  }
33
34
 
34
35
  await writeSingleFile(process.cwd(), projectContent);