ai-codegen-cli-vrk 2.0.5 → 2.0.7

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 CHANGED
@@ -1,2 +1,2 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  import "../src/runner.js";
package/package.json CHANGED
@@ -1,20 +1,18 @@
1
- {
2
- "name": "ai-codegen-cli-vrk",
3
- "version": "2.0.5",
4
- "description": "Minimalist 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
- "readline-sync": "^1.4.10"
16
- },
17
- "engines": {
18
- "node": ">=18.0.0"
19
- }
1
+ {
2
+ "name": "ai-codegen-cli-vrk",
3
+ "version": "2.0.7",
4
+ "description": "Minimalist 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
+ "@google/generative-ai": "^0.21.0",
15
+ "fs-extra": "^11.2.0",
16
+ "readline-sync": "^1.4.10"
17
+ }
20
18
  }
package/src/aiClient.js CHANGED
@@ -1,34 +1,41 @@
1
- let API_KEY = null;
2
- let SELECTED_MODEL_PATH = null;
1
+ import { GoogleGenerativeAI } from "@google/generative-ai";
2
+
3
+ let genAI = null;
4
+ let activeModel = null;
3
5
 
4
6
  export function setApiKey(apiKey) {
5
- API_KEY = apiKey;
7
+ // Auto-trim to remove any accidental spaces from copy-pasting
8
+ const cleanKey = apiKey.trim();
9
+ genAI = new GoogleGenerativeAI(cleanKey);
6
10
  }
7
11
 
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;
12
+ async function getWorkingModel() {
13
+ if (activeModel) return activeModel;
14
+
15
+ const candidates = ["gemini-1.5-flash", "gemini-1.5-flash-latest", "gemini-pro"];
16
+
17
+ for (const name of candidates) {
18
+ try {
19
+ // Force the stable 'v1' API version to avoid Beta key issues
20
+ const m = genAI.getGenerativeModel({ model: name }, { apiVersion: "v1" });
21
+
22
+ // Verification call
23
+ await m.generateContent({ contents: [{ role: "user", parts: [{ text: "hi" }] }], generationConfig: { maxOutputTokens: 1 } });
24
+ activeModel = m;
25
+ return m;
26
+ } catch (err) {
27
+ if (err.message.includes("404") || err.message.includes("not found")) continue;
28
+ throw err;
29
+ }
24
30
  }
31
+ throw new Error("No compatible Gemini models found.");
25
32
  }
26
33
 
27
34
  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 = `
35
+ try {
36
+ const model = await getWorkingModel();
37
+
38
+ const prompt = `
32
39
  Generate the ENTIRE project in a SINGLE response.
33
40
  Strictly pass all test cases.
34
41
 
@@ -45,28 +52,27 @@ TESTS:
45
52
  ${tests}
46
53
 
47
54
  ### RULES:
48
- - Minimalist logic only.
55
+ - Minimalist logic.
49
56
  - Bare minimum code to pass.
50
57
  - No talk or explanations.
51
58
  `;
52
59
 
53
- const response = await fetch(url, {
54
- method: "POST",
55
- headers: { "Content-Type": "application/json" },
56
- body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }] })
57
- });
60
+ const result = await model.generateContent(prompt);
61
+ const response = await result.response;
62
+ const text = response.text();
63
+ return text.replace(/```[a-z]*\n([\s\S]*?)\n```/gi, "$1").trim();
58
64
 
59
- const data = await response.json();
65
+ } catch (error) {
66
+ // If key is truly invalid, give a clear message
67
+ if (error.message.includes("API key not valid")) {
68
+ throw new Error("The API key you entered is invalid. Please double-check it at aistudio.google.com");
69
+ }
60
70
 
61
- // If overloaded (503) or rate limited (429), wait 10 seconds and retry
62
- if ((response.status === 503 || response.status === 429) && retryCount < 5) {
63
- console.log(`..... (Server busy, waiting 10s to retry ${retryCount + 1}/5)`);
64
- await new Promise(r => setTimeout(r, 10000));
65
- return generateFullProject(task, tests, retryCount + 1);
71
+ if ((error.message.includes("503") || error.message.includes("429")) && retryCount < 5) {
72
+ console.log(`..... (Server busy, retrying ${retryCount + 1}/5)`);
73
+ await new Promise(r => setTimeout(r, 10000));
74
+ return generateFullProject(task, tests, retryCount + 1);
75
+ }
76
+ throw error;
66
77
  }
67
-
68
- if (!response.ok) throw new Error(data.error?.message || "Generation failed");
69
-
70
- const text = data.candidates?.[0]?.content?.parts?.[0]?.text || "";
71
- return text.replace(/```[a-z]*\n([\s\S]*?)\n```/gi, "$1").trim();
72
78
  }
package/src/runner.js CHANGED
@@ -4,16 +4,15 @@ import { setApiKey, generateFullProject } from "./aiClient.js";
4
4
  import { writeSingleFile } from "./fileWriter.js";
5
5
 
6
6
  async function main() {
7
- // Input API Key - set to visible
8
- const apiKey = readlineSync.question("--- ", { hideEchoBack: false });
9
- if (!apiKey || apiKey.trim().length === 0) process.exit(1);
10
- setApiKey(apiKey.trim());
7
+ const apiKeyInput = readlineSync.question("--- ", { hideEchoBack: false });
8
+ if (!apiKeyInput || apiKeyInput.trim().length === 0) process.exit(1);
9
+
10
+ // Trimming again here just to be safe
11
+ setApiKey(apiKeyInput.trim());
11
12
 
12
- // Input Task
13
13
  const task = readlineSync.question("- ");
14
14
  if (!task || task.trim().length === 0) process.exit(1);
15
15
 
16
- // Input Tests
17
16
  const testsInput = readlineSync.question("-- ");
18
17
  let tests = "";
19
18
  try {