agdi 2.4.1 → 2.5.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.
Files changed (3) hide show
  1. package/README.md +19 -0
  2. package/dist/index.js +121 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -209,6 +209,25 @@ All decisions logged to `~/.agdi/audit.jsonl`:
209
209
 
210
210
  ## 🤖 Supported Models
211
211
 
212
+ ### Free Models (OpenRouter - No Credits Needed)
213
+
214
+ | Model | ID | Best For |
215
+ |-------|-----|----------|
216
+ | GPT-OSS 120B | `openai/gpt-oss-120b:free` | General coding |
217
+ | GPT-OSS 20B | `openai/gpt-oss-20b:free` | Fast responses |
218
+ | Qwen3 Coder | `qwen/qwen3-coder:free` | Code generation |
219
+ | Qwen3 Next 80B | `qwen/qwen3-next-80b-a3b-instruct:free` | Complex tasks |
220
+ | Kimi K2 | `moonshotai/kimi-k2:free` | General purpose |
221
+ | Gemma 3N E2B | `google/gemma-3n-e2b-it:free` | Lightweight |
222
+ | LFM Thinking | `liquid/lfm-2.5-1.2b-thinking:free` | Agentic tasks |
223
+ | Devstral ⚠️ | `mistralai/devstral-2512:free` | Ends Jan 27 |
224
+
225
+ ### Image Generation
226
+
227
+ | Model | ID | Description |
228
+ |-------|-----|-------------|
229
+ | Seedream 4.5 | `bytedance-seed/seedream-4.5` | Auto-generates project images |
230
+
212
231
  ### Bring Your Own Key
213
232
 
214
233
  <table>
package/dist/index.js CHANGED
@@ -143,7 +143,7 @@ var OpenRouterProvider = class {
143
143
  headers: {
144
144
  "Content-Type": "application/json",
145
145
  "Authorization": `Bearer ${this.config.apiKey}`,
146
- "HTTP-Referer": "https://agdi.dev",
146
+ "HTTP-Referer": "https://agdi-dev.vercel.app",
147
147
  "X-Title": "Agdi CLI"
148
148
  },
149
149
  body: JSON.stringify({
@@ -173,7 +173,7 @@ var OpenRouterProvider = class {
173
173
  headers: {
174
174
  "Content-Type": "application/json",
175
175
  "Authorization": `Bearer ${this.config.apiKey}`,
176
- "HTTP-Referer": "https://agdi.dev",
176
+ "HTTP-Referer": "https://agdi-dev.vercel.app",
177
177
  "X-Title": "Agdi CLI"
178
178
  },
179
179
  body: JSON.stringify({
@@ -1216,6 +1216,17 @@ var PROVIDER_MODELS = {
1216
1216
  { name: "\u{1F48E} Gemini 2.0 Flash", value: "gemini-2.0-flash" }
1217
1217
  ],
1218
1218
  openrouter: [
1219
+ // FREE MODELS (no API credits needed)
1220
+ { name: "\u{1F193} GPT-OSS 120B (Free)", value: "openai/gpt-oss-120b:free" },
1221
+ { name: "\u{1F193} GPT-OSS 20B (Free)", value: "openai/gpt-oss-20b:free" },
1222
+ { name: "\u{1F193} Qwen3 Coder (Free)", value: "qwen/qwen3-coder:free" },
1223
+ { name: "\u{1F193} Qwen3 Next 80B (Free)", value: "qwen/qwen3-next-80b-a3b-instruct:free" },
1224
+ { name: "\u{1F193} Kimi K2 (Free)", value: "moonshotai/kimi-k2:free" },
1225
+ { name: "\u{1F193} Gemma 3N E2B (Free)", value: "google/gemma-3n-e2b-it:free" },
1226
+ { name: "\u{1F193} Qwen 2.5 VL 7B (Free)", value: "qwen/qwen-2.5-vl-7b-instruct:free" },
1227
+ { name: "\u{1F193} LFM Thinking 1.2B (Free, Agentic)", value: "liquid/lfm-2.5-1.2b-thinking:free" },
1228
+ { name: "\u26A0\uFE0F Devstral (Free, ends Jan 27)", value: "mistralai/devstral-2512:free" },
1229
+ // PAID MODELS
1219
1230
  { name: "\u{1F9E0} Claude 3.5 Sonnet", value: "anthropic/claude-3.5-sonnet" },
1220
1231
  { name: "\u{1F48E} GPT-4o", value: "openai/gpt-4o" },
1221
1232
  { name: "\u26A1 GPT-4o Mini", value: "openai/gpt-4o-mini" },
@@ -1506,6 +1517,14 @@ function validateAction(action) {
1506
1517
  cwd: typeof obj.cwd === "string" ? obj.cwd : void 0
1507
1518
  };
1508
1519
  }
1520
+ if (type === "generateImage") {
1521
+ if (typeof obj.prompt !== "string" || !obj.prompt) return null;
1522
+ if (typeof obj.savePath !== "string" || !obj.savePath) return null;
1523
+ if (obj.savePath.includes("..") || obj.savePath.startsWith("/") || /^[A-Z]:/i.test(obj.savePath)) return null;
1524
+ const validStyles = ["realistic", "artistic", "minimal", "tech"];
1525
+ const style = typeof obj.style === "string" && validStyles.includes(obj.style) ? obj.style : void 0;
1526
+ return { type: "generateImage", prompt: obj.prompt, savePath: obj.savePath, style };
1527
+ }
1509
1528
  return null;
1510
1529
  }
1511
1530
  function parseActionPlan(response) {
@@ -2783,6 +2802,58 @@ async function ensureTrusted(workspacePath) {
2783
2802
  return result !== null;
2784
2803
  }
2785
2804
 
2805
+ // src/core/image-generator.ts
2806
+ async function generateImage(prompt, apiKey, options = {}) {
2807
+ const { width = 1024, height = 1024, style } = options;
2808
+ let enhancedPrompt = prompt;
2809
+ if (style === "tech") {
2810
+ enhancedPrompt = `Modern tech startup style, clean minimal design, professional: ${prompt}`;
2811
+ } else if (style === "realistic") {
2812
+ enhancedPrompt = `Photorealistic, high quality, professional photography: ${prompt}`;
2813
+ } else if (style === "artistic") {
2814
+ enhancedPrompt = `Artistic, creative, vibrant colors: ${prompt}`;
2815
+ } else if (style === "minimal") {
2816
+ enhancedPrompt = `Minimalist, clean, simple, modern: ${prompt}`;
2817
+ }
2818
+ const response = await fetch("https://openrouter.ai/api/v1/images/generations", {
2819
+ method: "POST",
2820
+ headers: {
2821
+ "Content-Type": "application/json",
2822
+ "Authorization": `Bearer ${apiKey}`,
2823
+ "HTTP-Referer": "https://agdi-dev.vercel.app",
2824
+ "X-Title": "Agdi CLI"
2825
+ },
2826
+ body: JSON.stringify({
2827
+ model: "bytedance-seed/seedream-4.5",
2828
+ prompt: enhancedPrompt,
2829
+ n: 1,
2830
+ size: `${width}x${height}`
2831
+ })
2832
+ });
2833
+ if (!response.ok) {
2834
+ const error = await response.text();
2835
+ throw new Error(`Image generation failed: ${response.status} - ${error}`);
2836
+ }
2837
+ const data = await response.json();
2838
+ const imageData = data.data?.[0];
2839
+ if (!imageData) {
2840
+ throw new Error("No image data returned from API");
2841
+ }
2842
+ return {
2843
+ url: imageData.url,
2844
+ base64: imageData.b64_json,
2845
+ revisedPrompt: imageData.revised_prompt
2846
+ };
2847
+ }
2848
+ async function downloadImageAsBase64(url) {
2849
+ const response = await fetch(url);
2850
+ if (!response.ok) {
2851
+ throw new Error(`Failed to download image: ${response.status}`);
2852
+ }
2853
+ const buffer = await response.arrayBuffer();
2854
+ return Buffer.from(buffer).toString("base64");
2855
+ }
2856
+
2786
2857
  // src/actions/plan-executor.ts
2787
2858
  function displayPlanSummary(plan) {
2788
2859
  const summary = summarizePlan(plan);
@@ -2831,6 +2902,9 @@ function displayActionProgress(action, index, total) {
2831
2902
  case "exec":
2832
2903
  console.log(chalk10.blue(`${num} Running: ${action.argv.join(" ")}`));
2833
2904
  break;
2905
+ case "generateImage":
2906
+ console.log(chalk10.magenta(`${num} \u{1F3A8} Generating image: ${action.savePath}`));
2907
+ break;
2834
2908
  }
2835
2909
  }
2836
2910
  async function dryRunActions(plan) {
@@ -2929,6 +3003,41 @@ async function executeAction(action) {
2929
3003
  });
2930
3004
  });
2931
3005
  }
3006
+ case "generateImage": {
3007
+ const config = loadConfig();
3008
+ const apiKey = config.openrouterApiKey;
3009
+ if (!apiKey) {
3010
+ return {
3011
+ action,
3012
+ success: false,
3013
+ error: "OpenRouter API key required for image generation. Run: agdi auth"
3014
+ };
3015
+ }
3016
+ try {
3017
+ console.log(chalk10.gray(` Prompt: "${action.prompt.slice(0, 50)}..."`));
3018
+ const result = await generateImage(action.prompt, apiKey, { style: action.style });
3019
+ if (result.url) {
3020
+ const base64Data = await downloadImageAsBase64(result.url);
3021
+ const imageBuffer = Buffer.from(base64Data, "base64");
3022
+ await writeFileTool(action.savePath, imageBuffer.toString("base64"));
3023
+ console.log(chalk10.green(` \u2713 Saved to ${action.savePath}`));
3024
+ } else if (result.base64) {
3025
+ await writeFileTool(action.savePath, result.base64);
3026
+ console.log(chalk10.green(` \u2713 Saved to ${action.savePath}`));
3027
+ }
3028
+ return {
3029
+ action,
3030
+ success: true,
3031
+ output: `Image generated: ${action.savePath}`
3032
+ };
3033
+ } catch (err) {
3034
+ return {
3035
+ action,
3036
+ success: false,
3037
+ error: err instanceof Error ? err.message : "Image generation failed"
3038
+ };
3039
+ }
3040
+ }
2932
3041
  }
2933
3042
  }
2934
3043
  async function executePlan(plan) {
@@ -3862,6 +3971,14 @@ Instead, output a single JSON object with this exact structure:
3862
3971
  - writeFile: { type: "writeFile", path: "relative/path/file.ts", content: "file contents" }
3863
3972
  - deleteFile: { type: "deleteFile", path: "relative/path/file.ts" }
3864
3973
  - exec: { type: "exec", argv: ["command", "arg1", "arg2"], cwd: "." }
3974
+ - generateImage: { type: "generateImage", prompt: "description of image", savePath: "public/hero.png", style: "tech" }
3975
+
3976
+ ## Image Generation
3977
+ For landing pages, portfolios, or apps that need visuals, use generateImage actions:
3978
+ - style options: "realistic", "artistic", "minimal", "tech"
3979
+ - Save to public/ folder (e.g., public/hero.png, public/logo.png)
3980
+ - Use descriptive prompts based on the project type
3981
+ - Example: { type: "generateImage", prompt: "Modern tech startup hero image, abstract blue gradient", savePath: "public/hero.png", style: "tech" }
3865
3982
 
3866
3983
  ## Rules
3867
3984
  1. All paths MUST be relative to workspace root (no leading /)
@@ -3871,7 +3988,8 @@ Instead, output a single JSON object with this exact structure:
3871
3988
  5. Create complete, production-ready code
3872
3989
  6. Use TypeScript by default
3873
3990
  7. Include proper error handling
3874
- 8. Output ONLY the JSON object, no extra text`;
3991
+ 8. For visual projects, include 1-2 generateImage actions for hero/logo
3992
+ 9. Output ONLY the JSON object, no extra text`;
3875
3993
  async function startCodingMode() {
3876
3994
  const activeConfig = getActiveProvider();
3877
3995
  if (!activeConfig) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdi",
3
- "version": "2.4.1",
3
+ "version": "2.5.1",
4
4
  "description": "AI-powered app generator - build full-stack apps from natural language in your terminal",
5
5
  "type": "module",
6
6
  "bin": {