agdi 2.4.1 → 2.5.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/README.md +19 -0
- package/dist/index.js +121 -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.
|
|
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.
|
|
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.
|
|
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) {
|