@heylemon/lemonade 0.2.1 → 0.2.2
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/dist/agents/system-prompt.js +9 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/package.json +1 -1
- package/skills/image-generation/SKILL.md +23 -84
- package/skills/openai-image-gen/SKILL.md +1 -1
- package/skills/openai-image-gen/scripts/gen.py +18 -3
|
@@ -429,6 +429,15 @@ export function buildAgentSystemPrompt(params) {
|
|
|
429
429
|
"- If files must be written, use `mktemp -d` and clean up after (`rm -rf $TMPDIR`).",
|
|
430
430
|
"- Skill-provided scripts (docx, xlsx, etc.) are fine to use as-is.",
|
|
431
431
|
"",
|
|
432
|
+
"## User-Facing Communication",
|
|
433
|
+
"NEVER reveal internal implementation details to the user. This includes:",
|
|
434
|
+
"- File paths like `~/.lemonade/`, `lemonade.json`, `.env`, `auth-profiles.json`",
|
|
435
|
+
"- API key names like `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`",
|
|
436
|
+
"- Environment variable names, config file locations, or setup instructions",
|
|
437
|
+
"- References to the gateway, proxy, providers, or model routing internals",
|
|
438
|
+
"- Skill names, skill directories, or SKILL.md files",
|
|
439
|
+
'If a capability is unavailable, say something like "I can\'t do that right now" or suggest an alternative. Never ask the user to configure keys, edit config files, or troubleshoot infrastructure.',
|
|
440
|
+
"",
|
|
432
441
|
"## Cron / Reminders",
|
|
433
442
|
"ALWAYS use the `cron` tool (action: add/update/remove/list/run/status) for managing cron jobs and reminders.",
|
|
434
443
|
"NEVER use `exec` or shell commands to read/write cron files (e.g. ~/.lemonade/cron/jobs.json) directly — the gateway cron service will not detect the change.",
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b91bfc9de067fe8db99816d14e4bf59e599bae482cd3f3511d73b463997f3112
|
package/package.json
CHANGED
|
@@ -1,60 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: image-generation
|
|
3
|
-
description: Generate images using DALL-E 3. Create artwork, illustrations, photos, designs. Triggers on: generate image, create picture, make art, draw, illustration, design image
|
|
3
|
+
description: Generate images using DALL-E 3 or GPT Image models. Create artwork, illustrations, photos, designs. Triggers on: generate image, create picture, make art, draw, illustration, design image
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Image Generation Skill
|
|
7
7
|
|
|
8
|
-
Generate images using OpenAI's
|
|
8
|
+
Generate images using OpenAI's image generation API, routed through the backend proxy.
|
|
9
9
|
|
|
10
10
|
## CRITICAL: How to Generate Images
|
|
11
11
|
|
|
12
|
-
Use the `exec` tool to run a Python script
|
|
12
|
+
Use the `exec` tool to run a Python script. The script routes through the Lemonade backend proxy — no local API key needed.
|
|
13
13
|
|
|
14
14
|
```python
|
|
15
15
|
import openai
|
|
16
16
|
import os
|
|
17
|
-
import
|
|
17
|
+
import urllib.request
|
|
18
18
|
from datetime import datetime
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
backend_url = os.environ.get("LEMON_BACKEND_URL", "")
|
|
21
|
+
gateway_token = os.environ.get("GATEWAY_TOKEN", "")
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
prompt="YOUR PROMPT HERE",
|
|
27
|
-
size="1024x1024", # or 1792x1024, 1024x1792
|
|
28
|
-
quality="standard", # or "hd" for high quality
|
|
29
|
-
n=1
|
|
23
|
+
client = openai.OpenAI(
|
|
24
|
+
api_key=gateway_token,
|
|
25
|
+
base_url=f"{backend_url}/api/lemonade/proxy/v1",
|
|
30
26
|
)
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
image_url = response.data[0].url
|
|
34
|
-
print(f"Image generated: {image_url}")
|
|
35
|
-
|
|
36
|
-
# Optionally save to desktop
|
|
37
|
-
import urllib.request
|
|
38
|
-
desktop = os.path.expanduser("~/Desktop")
|
|
39
|
-
filename = f"generated_image_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
|
|
40
|
-
filepath = os.path.join(desktop, filename)
|
|
41
|
-
urllib.request.urlretrieve(image_url, filepath)
|
|
42
|
-
print(f"Saved to: {filepath}")
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Quick Template
|
|
46
|
-
|
|
47
|
-
For image generation requests:
|
|
48
|
-
|
|
49
|
-
```python
|
|
50
|
-
import openai
|
|
51
|
-
import os
|
|
52
|
-
import urllib.request
|
|
53
|
-
from datetime import datetime
|
|
54
|
-
|
|
55
|
-
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
|
|
56
|
-
|
|
57
|
-
prompt = """DETAILED PROMPT HERE"""
|
|
28
|
+
prompt = """YOUR PROMPT HERE"""
|
|
58
29
|
|
|
59
30
|
response = client.images.generate(
|
|
60
31
|
model="dall-e-3",
|
|
@@ -64,29 +35,22 @@ response = client.images.generate(
|
|
|
64
35
|
n=1
|
|
65
36
|
)
|
|
66
37
|
|
|
67
|
-
|
|
38
|
+
image_url = response.data[0].url
|
|
68
39
|
desktop = os.path.expanduser("~/Desktop")
|
|
69
40
|
filename = f"generated_{datetime.now().strftime('%H%M%S')}.png"
|
|
70
41
|
filepath = os.path.join(desktop, filename)
|
|
71
|
-
urllib.request.urlretrieve(
|
|
72
|
-
print(f"
|
|
42
|
+
urllib.request.urlretrieve(image_url, filepath)
|
|
43
|
+
print(f"Image saved to Desktop: {filename}")
|
|
73
44
|
```
|
|
74
45
|
|
|
75
46
|
## Prompt Best Practices
|
|
76
47
|
|
|
77
48
|
### Be Specific
|
|
78
|
-
|
|
79
|
-
✅ "A fluffy orange tabby cat sitting on a windowsill, soft morning light, photorealistic style"
|
|
49
|
+
- "A fluffy orange tabby cat sitting on a windowsill, soft morning light, photorealistic style"
|
|
80
50
|
|
|
81
51
|
### Include Style
|
|
82
|
-
- "photorealistic"
|
|
83
|
-
- "
|
|
84
|
-
- "watercolor painting"
|
|
85
|
-
- "3D render"
|
|
86
|
-
- "pencil sketch"
|
|
87
|
-
- "oil painting"
|
|
88
|
-
- "anime style"
|
|
89
|
-
- "minimalist illustration"
|
|
52
|
+
- "photorealistic", "digital art", "watercolor painting", "3D render"
|
|
53
|
+
- "pencil sketch", "oil painting", "anime style", "minimalist illustration"
|
|
90
54
|
|
|
91
55
|
### Include Details
|
|
92
56
|
- Lighting: "golden hour", "studio lighting", "dramatic shadows"
|
|
@@ -104,34 +68,10 @@ print(f"✅ Image saved to Desktop: {filename}")
|
|
|
104
68
|
|
|
105
69
|
## Quality Options
|
|
106
70
|
|
|
107
|
-
| Quality | Description |
|
|
108
|
-
|
|
109
|
-
| standard | Good for most uses |
|
|
110
|
-
| hd | More detailed, sharper |
|
|
111
|
-
|
|
112
|
-
## Common Requests
|
|
113
|
-
|
|
114
|
-
### "Generate a logo for [company]"
|
|
115
|
-
```python
|
|
116
|
-
prompt = "Modern minimalist logo for [COMPANY NAME], clean design, professional, vector style, white background, simple geometric shapes"
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### "Create a profile picture"
|
|
120
|
-
```python
|
|
121
|
-
prompt = "Professional headshot style portrait, [DESCRIPTION], studio lighting, neutral background, photorealistic"
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### "Make wallpaper for my desktop"
|
|
125
|
-
```python
|
|
126
|
-
# Use landscape size
|
|
127
|
-
size = "1792x1024"
|
|
128
|
-
prompt = "[SCENE DESCRIPTION], cinematic, 4K quality, desktop wallpaper"
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### "Draw an illustration of [X]"
|
|
132
|
-
```python
|
|
133
|
-
prompt = "Illustration of [X], digital art style, vibrant colors, detailed, artistic"
|
|
134
|
-
```
|
|
71
|
+
| Quality | Description |
|
|
72
|
+
|---------|-------------|
|
|
73
|
+
| standard | Good for most uses |
|
|
74
|
+
| hd | More detailed, sharper |
|
|
135
75
|
|
|
136
76
|
## Workflow
|
|
137
77
|
|
|
@@ -143,7 +83,6 @@ prompt = "Illustration of [X], digital art style, vibrant colors, detailed, arti
|
|
|
143
83
|
|
|
144
84
|
## Important Notes
|
|
145
85
|
|
|
146
|
-
-
|
|
147
|
-
- Images expire from URL after ~1 hour, so always save locally
|
|
148
|
-
-
|
|
149
|
-
- Always save to Desktop for easy access
|
|
86
|
+
- Always save generated images to `~/Desktop/` for easy access
|
|
87
|
+
- Images expire from the URL after ~1 hour, so always save locally
|
|
88
|
+
- Always install openai package first if needed: `source ~/.lemonade/.venv/bin/activate && pip install -q openai`
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: openai-image-gen
|
|
3
3
|
description: Batch-generate images via OpenAI Images API. Random prompt sampler + `index.html` gallery.
|
|
4
4
|
homepage: https://platform.openai.com/docs/api-reference/images
|
|
5
|
-
metadata: {"lemonade":{"emoji":"🖼️","requires":{"bins":["python3"]
|
|
5
|
+
metadata: {"lemonade":{"emoji":"🖼️","requires":{"bins":["python3"]},"install":[{"id":"python-brew","kind":"brew","formula":"python","bins":["python3"],"label":"Install Python (brew)"}]}}
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# OpenAI Image Gen
|
|
@@ -74,6 +74,19 @@ def get_model_defaults(model: str) -> tuple[str, str]:
|
|
|
74
74
|
return ("1024x1024", "high")
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
def resolve_api_url_and_key() -> tuple[str, str]:
|
|
78
|
+
"""Resolve the images API base URL and auth token.
|
|
79
|
+
Prefers the Lemonade backend proxy; falls back to direct OpenAI key."""
|
|
80
|
+
backend = (os.environ.get("LEMON_BACKEND_URL") or "").strip()
|
|
81
|
+
gw_token = (os.environ.get("GATEWAY_TOKEN") or "").strip()
|
|
82
|
+
if backend and gw_token:
|
|
83
|
+
return f"{backend}/api/lemonade/proxy/v1/images/generations", gw_token
|
|
84
|
+
api_key = (os.environ.get("OPENAI_API_KEY") or "").strip()
|
|
85
|
+
if api_key:
|
|
86
|
+
return "https://api.openai.com/v1/images/generations", api_key
|
|
87
|
+
return "", ""
|
|
88
|
+
|
|
89
|
+
|
|
77
90
|
def request_images(
|
|
78
91
|
api_key: str,
|
|
79
92
|
prompt: str,
|
|
@@ -83,8 +96,9 @@ def request_images(
|
|
|
83
96
|
background: str = "",
|
|
84
97
|
output_format: str = "",
|
|
85
98
|
style: str = "",
|
|
99
|
+
api_url: str = "",
|
|
86
100
|
) -> dict:
|
|
87
|
-
url = "https://api.openai.com/v1/images/generations"
|
|
101
|
+
url = api_url or "https://api.openai.com/v1/images/generations"
|
|
88
102
|
args = {
|
|
89
103
|
"model": model,
|
|
90
104
|
"prompt": prompt,
|
|
@@ -173,9 +187,9 @@ def main() -> int:
|
|
|
173
187
|
ap.add_argument("--out-dir", default="", help="Output directory (default: ./tmp/openai-image-gen-<ts>).")
|
|
174
188
|
args = ap.parse_args()
|
|
175
189
|
|
|
176
|
-
api_key = (
|
|
190
|
+
api_url, api_key = resolve_api_url_and_key()
|
|
177
191
|
if not api_key:
|
|
178
|
-
print("
|
|
192
|
+
print("No API credentials available for image generation", file=sys.stderr)
|
|
179
193
|
return 2
|
|
180
194
|
|
|
181
195
|
# Apply model-specific defaults if not specified
|
|
@@ -211,6 +225,7 @@ def main() -> int:
|
|
|
211
225
|
args.background,
|
|
212
226
|
args.output_format,
|
|
213
227
|
args.style,
|
|
228
|
+
api_url=api_url,
|
|
214
229
|
)
|
|
215
230
|
data = res.get("data", [{}])[0]
|
|
216
231
|
image_b64 = data.get("b64_json")
|