@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.
@@ -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.",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.1",
3
- "commit": "4fb691db7cce1151b7e7b56b76b337a9409ac009",
4
- "builtAt": "2026-02-22T12:34:47.819Z"
2
+ "version": "0.2.2",
3
+ "commit": "86be80740f2b0083dd4e3816f9c7d85e53780b2b",
4
+ "builtAt": "2026-02-22T13:52:37.675Z"
5
5
  }
@@ -1 +1 @@
1
- 8fcbb831164907bf1103be7d74c1e028f9d54dadb32f21942d50feb871d2fe18
1
+ b91bfc9de067fe8db99816d14e4bf59e599bae482cd3f3511d73b463997f3112
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heylemon/lemonade",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "AI gateway CLI for Lemon - local AI assistant with integrations",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
@@ -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 DALL-E 3 API.
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 that calls the OpenAI API:
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 base64
17
+ import urllib.request
18
18
  from datetime import datetime
19
19
 
20
- # Get API key from environment
21
- client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
20
+ backend_url = os.environ.get("LEMON_BACKEND_URL", "")
21
+ gateway_token = os.environ.get("GATEWAY_TOKEN", "")
22
22
 
23
- # Generate image
24
- response = client.images.generate(
25
- model="dall-e-3",
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
- # Get the URL
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
- # Save to desktop
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(response.data[0].url, filepath)
72
- print(f"Image saved to Desktop: {filename}")
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
- "A cat"
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
- - "digital art"
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 | Cost |
108
- |---------|-------------|------|
109
- | standard | Good for most uses | Lower |
110
- | hd | More detailed, sharper | Higher |
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
- - DALL-E 3 costs ~$0.04-0.08 per image
147
- - Images expire from URL after ~1 hour, so always save locally
148
- - The `OPENAI_API_KEY` environment variable is already configured
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"],"env":["OPENAI_API_KEY"]},"primaryEnv":"OPENAI_API_KEY","install":[{"id":"python-brew","kind":"brew","formula":"python","bins":["python3"],"label":"Install Python (brew)"}]}}
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 = (os.environ.get("OPENAI_API_KEY") or "").strip()
190
+ api_url, api_key = resolve_api_url_and_key()
177
191
  if not api_key:
178
- print("Missing OPENAI_API_KEY", file=sys.stderr)
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")