@heylemon/lemonade 0.2.6 → 0.2.8
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 +34 -41
- package/dist/agents/tools/browser-tool.js +2 -2
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/gateway/openai-http.js +1 -1
- package/dist/gateway/openresponses-http.js +10 -5
- package/dist/gateway/skills-http.js +15 -2
- package/docs/IntegrationAndBrowserRules.md +41 -39
- package/package.json +1 -1
- package/skills/browser/SKILL.md +5 -11
|
@@ -175,7 +175,7 @@ export function buildAgentSystemPrompt(params) {
|
|
|
175
175
|
web_search: "Search the web (Brave API)",
|
|
176
176
|
web_fetch: "Fetch and extract readable content from a URL",
|
|
177
177
|
// Channel docking: add login tools here when a channel needs interactive linking.
|
|
178
|
-
browser: "Control
|
|
178
|
+
browser: "Control Lemonade's dedicated browser (never the user's personal browser)",
|
|
179
179
|
canvas: "Present/eval/snapshot the Canvas",
|
|
180
180
|
nodes: "List/describe/notify/camera/screen on paired nodes",
|
|
181
181
|
cron: "Manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
|
|
@@ -317,7 +317,7 @@ export function buildAgentSystemPrompt(params) {
|
|
|
317
317
|
"- apply_patch: apply multi-file patches",
|
|
318
318
|
`- ${execToolName}: run shell commands (supports background via yieldMs/background)`,
|
|
319
319
|
`- ${processToolName}: manage background exec sessions`,
|
|
320
|
-
"- browser: control
|
|
320
|
+
"- browser: control Lemonade's dedicated browser (never the user's personal browser)",
|
|
321
321
|
"- canvas: present/eval/snapshot the Canvas",
|
|
322
322
|
"- nodes: list/describe/notify/camera/screen on paired nodes",
|
|
323
323
|
"- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
|
|
@@ -341,25 +341,38 @@ export function buildAgentSystemPrompt(params) {
|
|
|
341
341
|
"For screenshots of native macOS windows: use Peekaboo (`peekaboo image`) via exec if the skill is available.",
|
|
342
342
|
"",
|
|
343
343
|
"## URLs & Quick Open",
|
|
344
|
-
"When the user wants to *see* a page, video, or search result — open it in their browser. Don't over-automate simple requests.",
|
|
345
344
|
"",
|
|
346
345
|
"### Decision tree",
|
|
347
|
-
"1.
|
|
346
|
+
"1. Service has a `lemon-*` CLI tool (Gmail, Calendar, Drive, Docs, Sheets, Slides, Notion, Slack, YouTube) → **always use the CLI tool**. Never open these in a browser or via URI.",
|
|
348
347
|
"2. User wants an *answer* from the web → use `web_search` (+ `web_fetch` if needed).",
|
|
349
|
-
"3. User wants to *interact* with a page (fill forms, click buttons, scrape data) → use
|
|
350
|
-
"",
|
|
351
|
-
"
|
|
352
|
-
"
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
"",
|
|
357
|
-
"
|
|
358
|
-
|
|
348
|
+
"3. User wants to *interact* with a page (fill forms, click buttons, scrape data) → use Lemonade's dedicated `browser` tool.",
|
|
349
|
+
"4. User wants to *view* a general website (no CLI tool exists) → use Lemonade's dedicated `browser` tool to navigate there.",
|
|
350
|
+
"",
|
|
351
|
+
"### Integration CLI tools (always preferred)",
|
|
352
|
+
"For connected services, use the CLI — it's faster, already authenticated, and doesn't require a browser:",
|
|
353
|
+
"| Service | CLI tool | Example |",
|
|
354
|
+
"|---------|----------|---------|",
|
|
355
|
+
'| Gmail | `lemon-gmail` | `lemon-gmail search "from:boss subject:urgent"` |',
|
|
356
|
+
"| Calendar | `lemon-calendar` | `lemon-calendar list today` |",
|
|
357
|
+
'| Drive | `lemon-drive` | `lemon-drive search "quarterly report"` |',
|
|
358
|
+
'| Docs | `lemon-docs` | `lemon-docs create "Meeting Notes"` |',
|
|
359
|
+
'| Sheets | `lemon-sheets` | `lemon-sheets search "budget"` |',
|
|
360
|
+
'| Slides | `lemon-slides` | `lemon-slides search "deck"` |',
|
|
361
|
+
'| Notion | `lemon-notion` | `lemon-notion search "project plan"` |',
|
|
362
|
+
"| Slack | `lemon-slack` or `message` tool | `message channel:slack ...` |",
|
|
363
|
+
'| YouTube | `lemon-youtube` | `lemon-youtube search "tutorial"` |',
|
|
364
|
+
"**Never open** `mail.google.com`, `calendar.google.com`, `drive.google.com`, `docs.google.com`, `sheets.google.com`, `slides.google.com`, `notion.so`, `app.slack.com`, or `youtube.com` in any browser. Use the CLI.",
|
|
365
|
+
'**Creating documents:** Use `lemon-docs create "Title"`, `lemon-sheets create "Title"`, etc. Do NOT open `docs.new`, `sheets.new`, or any `.new` domain.',
|
|
366
|
+
"",
|
|
367
|
+
"### Browser tool (Lemonade's dedicated browser only)",
|
|
368
|
+
"For general websites without a CLI tool, use Lemonade's dedicated `browser` tool (Playwright-managed).",
|
|
369
|
+
'**Never open URLs in the user\'s personal browser.** Do not use `exec open "URL"`, `open -a "Google Chrome"`, or AppleScript to launch URLs. All web browsing goes through the `browser` tool with `profile="lemonade"`.',
|
|
370
|
+
"",
|
|
371
|
+
"### Common search/action URIs (via browser tool)",
|
|
372
|
+
"Use browser_navigate with these URLs for general web tasks (non-integration sites only):",
|
|
359
373
|
"| Task | URI pattern |",
|
|
360
374
|
"|------|------------|",
|
|
361
375
|
"| Google search | `https://google.com/search?q={query}` |",
|
|
362
|
-
"| YouTube search | `https://youtube.com/results?search_query={query}` |",
|
|
363
376
|
"| Google Maps search | `https://maps.google.com/maps?q={query}` |",
|
|
364
377
|
"| Google Maps directions | `https://maps.google.com/maps/dir/{from}/{to}` |",
|
|
365
378
|
"| Amazon search | `https://amazon.com/s?k={query}` |",
|
|
@@ -372,33 +385,13 @@ export function buildAgentSystemPrompt(params) {
|
|
|
372
385
|
"| LinkedIn search | `https://linkedin.com/search/results/all/?keywords={query}` |",
|
|
373
386
|
"URL-encode the query (`%20` for spaces or use `+`).",
|
|
374
387
|
"",
|
|
375
|
-
"### Quick-create shortcuts (.new domains)",
|
|
376
|
-
"These instantly create a new document/resource in the user's browser:",
|
|
377
|
-
"| Task | URL |",
|
|
378
|
-
"|------|-----|",
|
|
379
|
-
"| New Google Doc | `https://docs.new` |",
|
|
380
|
-
"| New Google Sheet | `https://sheets.new` |",
|
|
381
|
-
"| New Google Slides | `https://slides.new` |",
|
|
382
|
-
"| New Google Form | `https://forms.new` |",
|
|
383
|
-
"| New Google Meet | `https://meet.new` |",
|
|
384
|
-
"| New Google Calendar event | `https://cal.new` |",
|
|
385
|
-
"| New Google Drawing | `https://drawings.new` |",
|
|
386
|
-
"| New Google Site | `https://sites.new` |",
|
|
387
|
-
"| New GitHub repo | `https://repo.new` |",
|
|
388
|
-
"| New GitHub gist | `https://gist.new` |",
|
|
389
|
-
"| New CodePen | `https://pen.new` |",
|
|
390
|
-
"| New Figma file | `https://figma.new` |",
|
|
391
|
-
"| New Notion page | `https://notion.new` |",
|
|
392
|
-
"| New Linear issue | `https://linear.new` |",
|
|
393
|
-
"These are faster than using CLI tools when the user just wants to open a blank document in their browser.",
|
|
394
|
-
"",
|
|
395
388
|
"### Examples",
|
|
396
|
-
'- "search YouTube for funny cats" → `
|
|
397
|
-
'- "show me flights to Tokyo" → `
|
|
398
|
-
'- "open amazon" → `
|
|
399
|
-
'- "find Italian restaurants near me" → `
|
|
400
|
-
'- "create a new doc" → `
|
|
401
|
-
'- "
|
|
389
|
+
'- "search YouTube for funny cats" → `lemon-youtube search "funny cats"` (CLI, not browser)',
|
|
390
|
+
'- "show me flights to Tokyo" → `browser` navigate to `https://google.com/travel/flights?q=flights+to+tokyo`',
|
|
391
|
+
'- "open amazon" → `browser` navigate to `https://amazon.com`',
|
|
392
|
+
'- "find Italian restaurants near me" → `browser` navigate to `https://maps.google.com/maps?q=italian+restaurants+near+me`',
|
|
393
|
+
'- "create a new doc" → `lemon-docs create "Untitled"` (CLI, not browser)',
|
|
394
|
+
'- "check my email" → `lemon-gmail list` (CLI, not browser)',
|
|
402
395
|
'- "what is the capital of France?" → use `web_search` (user wants the answer, not a page)',
|
|
403
396
|
"",
|
|
404
397
|
"## IDE & Coding Agent Control",
|
|
@@ -143,8 +143,8 @@ export function createBrowserTool(opts) {
|
|
|
143
143
|
label: "Browser",
|
|
144
144
|
name: "browser",
|
|
145
145
|
description: [
|
|
146
|
-
"Control
|
|
147
|
-
|
|
146
|
+
"Control Lemonade's dedicated browser via the browser control server (status/start/stop/tabs/open/snapshot/screenshot/actions).",
|
|
147
|
+
"Always use profile=\"lemonade\" (Lemonade's dedicated, isolated browser). Never use the user's personal browser.",
|
|
148
148
|
"NEVER ask the user to click any extension icon or toolbar button. Just use the browser tools directly — they auto-connect.",
|
|
149
149
|
'When a node-hosted browser proxy is available, the tool may auto-route to it. Pin a node with node=<id|name> or target="node".',
|
|
150
150
|
"When using refs from snapshot (e.g. e12), keep the same tab: prefer passing targetId from the snapshot response into subsequent actions (act/click/type/etc).",
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
623501c2b7c89888f7ad88c7e32239e05753751e4d9b227608e441ee9bc813ca
|
|
@@ -49,7 +49,7 @@ function buildAgentPrompt(messagesUnknown) {
|
|
|
49
49
|
if (!role || !content)
|
|
50
50
|
continue;
|
|
51
51
|
if (role === "system" || role === "developer") {
|
|
52
|
-
systemParts.push(content);
|
|
52
|
+
systemParts.push(`<client_instruction>\n${content}\n</client_instruction>`);
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
55
55
|
const normalizedRole = role === "function" ? "tool" : role;
|
|
@@ -109,7 +109,7 @@ export function buildAgentPrompt(input) {
|
|
|
109
109
|
if (!content)
|
|
110
110
|
continue;
|
|
111
111
|
if (item.role === "system" || item.role === "developer") {
|
|
112
|
-
systemParts.push(content);
|
|
112
|
+
systemParts.push(`<client_instruction>\n${content}\n</client_instruction>`);
|
|
113
113
|
continue;
|
|
114
114
|
}
|
|
115
115
|
const normalizedRole = item.role === "assistant" ? "assistant" : "user";
|
|
@@ -288,11 +288,12 @@ export async function handleOpenResponsesHttpRequest(req, res, opts) {
|
|
|
288
288
|
},
|
|
289
289
|
limits: limits.files,
|
|
290
290
|
});
|
|
291
|
+
const safeName = file.filename.replace(/[<>"&\n\r]/g, "_");
|
|
291
292
|
if (file.text?.trim()) {
|
|
292
|
-
fileContexts.push(`<file name="${
|
|
293
|
+
fileContexts.push(`<file name="${safeName}">\n${file.text}\n</file>`);
|
|
293
294
|
}
|
|
294
295
|
else if (file.images && file.images.length > 0) {
|
|
295
|
-
fileContexts.push(`<file name="${
|
|
296
|
+
fileContexts.push(`<file name="${safeName}">[PDF content rendered to images]</file>`);
|
|
296
297
|
}
|
|
297
298
|
if (file.images && file.images.length > 0) {
|
|
298
299
|
images = images.concat(file.images);
|
|
@@ -332,9 +333,13 @@ export async function handleOpenResponsesHttpRequest(req, res, opts) {
|
|
|
332
333
|
const prompt = buildAgentPrompt(payload.input);
|
|
333
334
|
const fileContext = fileContexts.length > 0 ? fileContexts.join("\n\n") : undefined;
|
|
334
335
|
const toolChoiceContext = toolChoicePrompt?.trim();
|
|
335
|
-
// Handle instructions + file context as extra system prompt
|
|
336
|
+
// Handle instructions + file context as extra system prompt.
|
|
337
|
+
// Client-supplied instructions are wrapped in tags to prevent prompt injection.
|
|
338
|
+
const wrappedInstructions = payload.instructions
|
|
339
|
+
? `<client_instruction>\n${payload.instructions}\n</client_instruction>`
|
|
340
|
+
: undefined;
|
|
336
341
|
const extraSystemPrompt = [
|
|
337
|
-
|
|
342
|
+
wrappedInstructions,
|
|
338
343
|
prompt.extraSystemPrompt,
|
|
339
344
|
toolChoiceContext,
|
|
340
345
|
fileContext,
|
|
@@ -57,7 +57,19 @@ export async function handleSkillsHttpRequest(req, res, opts) {
|
|
|
57
57
|
.replace(/^\/api\/skills\/?/, "")
|
|
58
58
|
.split("/")
|
|
59
59
|
.filter(Boolean);
|
|
60
|
-
const
|
|
60
|
+
const rawSkillName = pathParts[0] ? decodeURIComponent(pathParts[0]) : undefined;
|
|
61
|
+
// Validate skill name to prevent path traversal
|
|
62
|
+
const SAFE_SKILL_NAME_RE = /^[a-z0-9][a-z0-9_-]*$/;
|
|
63
|
+
const skillName = rawSkillName && SAFE_SKILL_NAME_RE.test(rawSkillName) ? rawSkillName : undefined;
|
|
64
|
+
if (rawSkillName && !skillName) {
|
|
65
|
+
sendJson(res, 400, {
|
|
66
|
+
error: {
|
|
67
|
+
message: "Invalid skill name. Use only lowercase letters, numbers, hyphens, and underscores.",
|
|
68
|
+
type: "invalid_request_error",
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
61
73
|
try {
|
|
62
74
|
if (!skillName) {
|
|
63
75
|
// /api/skills
|
|
@@ -85,8 +97,9 @@ export async function handleSkillsHttpRequest(req, res, opts) {
|
|
|
85
97
|
}
|
|
86
98
|
}
|
|
87
99
|
catch (err) {
|
|
100
|
+
console.error("[skills-http] Internal error:", err);
|
|
88
101
|
sendJson(res, 500, {
|
|
89
|
-
error: { message:
|
|
102
|
+
error: { message: "An internal error occurred", type: "internal_error" },
|
|
90
103
|
});
|
|
91
104
|
return true;
|
|
92
105
|
}
|
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
Reference for the agent: when to use integrations vs browser, and how to avoid invalid IDs or wrong tools.
|
|
4
4
|
|
|
5
|
-
## Browser mode (dedicated
|
|
5
|
+
## Browser mode (dedicated browser only)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Lemonade uses its own dedicated browser (Playwright-managed, separate from the user's personal browser). **Never open URLs in the user's personal browser.**
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- **
|
|
9
|
+
- Use **only** the browser_* tools (browser_navigate, browser_click, browser_type, browser_snapshot, etc.) for all web browsing.
|
|
10
|
+
- Do **not** use `open "URL"`, `open -a "Google Chrome"`, or any shell/AppleScript command to open URLs in the user's browser.
|
|
11
|
+
- Always use `profile="lemonade"` (the default, isolated Lemonade-managed browser).
|
|
11
12
|
|
|
12
|
-
## Browser profiles
|
|
13
|
+
## Browser profiles
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
- **`lemonade` profile** (default, always use): Lemonade's dedicated Playwright browser. Isolated from the user's personal browsing. Session cookies persist between uses.
|
|
16
|
+
- Do **not** use `profile="chrome"`. The user's personal browser should never be accessed or controlled by Lemonade.
|
|
15
17
|
|
|
16
|
-
##
|
|
18
|
+
## General web browsing (via dedicated browser)
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
For sites without a `lemon-*` CLI, use the `browser` tool to navigate. Never use `exec open` or the user's personal browser.
|
|
19
21
|
|
|
20
|
-
**Search:**
|
|
22
|
+
**Search URIs (via browser_navigate):**
|
|
21
23
|
| Service | URL pattern |
|
|
22
24
|
|---------|-------------|
|
|
23
25
|
| Google | `https://www.google.com/search?q=QUERY` |
|
|
24
|
-
| YouTube | `https://www.youtube.com/results?search_query=QUERY` |
|
|
25
26
|
| Amazon | `https://www.amazon.com/s?k=QUERY` |
|
|
26
27
|
| Wikipedia | `https://en.wikipedia.org/wiki/Special:Search/QUERY` |
|
|
27
28
|
| Google Maps | `https://www.google.com/maps/search/QUERY` |
|
|
@@ -32,16 +33,15 @@ Many common actions can be done instantly with direct URLs — no Composio integ
|
|
|
32
33
|
| Twitter/X | `https://x.com/search?q=QUERY` |
|
|
33
34
|
| LinkedIn | `https://www.linkedin.com/search/results/all/?keywords=QUERY` |
|
|
34
35
|
|
|
35
|
-
**
|
|
36
|
-
|
|
|
37
|
-
|
|
38
|
-
| YouTube
|
|
39
|
-
| Google Doc | `
|
|
40
|
-
| Google Sheet | `
|
|
41
|
-
| Notion page | `
|
|
42
|
-
| GitHub repo | `https://github.com/OWNER/REPO` |
|
|
36
|
+
**Do NOT use browser for these — use CLI tools instead:**
|
|
37
|
+
| Service | Use CLI instead |
|
|
38
|
+
|---------|----------------|
|
|
39
|
+
| YouTube search | `lemon-youtube search QUERY` |
|
|
40
|
+
| Google Doc | `lemon-docs` CLI |
|
|
41
|
+
| Google Sheet | `lemon-sheets` CLI |
|
|
42
|
+
| Notion page | `lemon-notion` CLI |
|
|
43
43
|
|
|
44
|
-
**macOS apps via URI:**
|
|
44
|
+
**macOS native apps via URI (exec open is OK for native apps, not web):**
|
|
45
45
|
| App | Example |
|
|
46
46
|
|-----|---------|
|
|
47
47
|
| Apple Maps | `maps://?q=QUERY` |
|
|
@@ -49,12 +49,12 @@ Many common actions can be done instantly with direct URLs — no Composio integ
|
|
|
49
49
|
| FaceTime | `facetime://PHONE_OR_EMAIL` |
|
|
50
50
|
| Messages | `imessage://PHONE_OR_EMAIL` |
|
|
51
51
|
|
|
52
|
-
URL-encode spaces as `%20` in query parameters.
|
|
52
|
+
URL-encode spaces as `%20` in query parameters. Native macOS app URIs (`maps://`, `music://`, `imessage://`, `facetime://`) can use `exec open` since they open native apps, not web browsers.
|
|
53
53
|
|
|
54
54
|
## Browser vs integrations
|
|
55
55
|
|
|
56
56
|
- **Always use CLI/integration tools** for: Gmail, Google Calendar, Google Drive, Google Docs, Google Sheets, Notion, Slack, YouTube. The CLI is faster, already authenticated, and more reliable.
|
|
57
|
-
- **Browser fallback is ONLY for when the CLI tool itself is broken:** binary not found, "command not found", connection refused, service genuinely not connected. These are infrastructure failures.
|
|
57
|
+
- **Browser fallback is ONLY for when the CLI tool itself is broken:** binary not found, "command not found", connection refused, service genuinely not connected. These are infrastructure failures. When falling back, use Lemonade's dedicated browser (`profile="lemonade"`), never the user's personal browser.
|
|
58
58
|
- **Browser fallback is NOT for when a CLI operation returns no results:** "user not found", "file not found", "channel not found", empty search results. These are normal outcomes — retry with different input, list available items, or ask the user for clarification.
|
|
59
59
|
- If an integration is **not** connected: offer the connect link (`lemon://connect?provider=<id>`) so the user can connect with one tap. **Do not run** `open "lemon://connect?..."` in the terminal — the Lemon app opens the connection page when it sees the URL in your reply.
|
|
60
60
|
|
|
@@ -108,25 +108,25 @@ This searches AND plays the top result in one atomic command. URL-encode spaces
|
|
|
108
108
|
|
|
109
109
|
- Use `lemon-notion` CLI when Notion is connected.
|
|
110
110
|
- For creating or updating content, always resolve parent page or database via search; never guess UUIDs.
|
|
111
|
-
- If not connected, offer `lemon://connect?provider=notion
|
|
111
|
+
- If not connected, offer `lemon://connect?provider=notion`. If CLI is broken, fall back to Lemonade's dedicated browser (`profile="lemonade"`).
|
|
112
112
|
|
|
113
113
|
## Gmail
|
|
114
114
|
|
|
115
115
|
- Use `lemon-gmail` CLI when Gmail is connected.
|
|
116
116
|
- Use message/thread IDs from search or list only.
|
|
117
|
-
- If not connected, offer `lemon://connect?provider=gmail
|
|
117
|
+
- If not connected, offer `lemon://connect?provider=gmail`. If CLI is broken, fall back to Lemonade's dedicated browser (`profile="lemonade"`).
|
|
118
118
|
|
|
119
119
|
## Google Calendar
|
|
120
120
|
|
|
121
121
|
- Use `lemon-calendar` CLI when Calendar is connected.
|
|
122
122
|
- Get `calendarId` and `eventId` from list/search or user; never generate them.
|
|
123
|
-
- If not connected, offer `lemon://connect?provider=googlecalendar
|
|
123
|
+
- If not connected, offer `lemon://connect?provider=googlecalendar`. If CLI is broken, fall back to Lemonade's dedicated browser (`profile="lemonade"`).
|
|
124
124
|
|
|
125
125
|
## Google Drive / Docs / Sheets
|
|
126
126
|
|
|
127
127
|
- Use `lemon-drive`, `lemon-docs`, `lemon-sheets`, `lemon-slides` CLIs when connected.
|
|
128
128
|
- Get file/document/sheet IDs from list/search or from the user (e.g. from a Drive/Docs/Sheets URL); never generate IDs.
|
|
129
|
-
- If not connected, offer the appropriate `lemon://connect?provider=googledrive` (or googledocs, googlesheets)
|
|
129
|
+
- If not connected, offer the appropriate `lemon://connect?provider=googledrive` (or googledocs, googlesheets). If CLI is broken, fall back to Lemonade's dedicated browser (`profile="lemonade"`).
|
|
130
130
|
|
|
131
131
|
## Slack
|
|
132
132
|
|
|
@@ -136,7 +136,7 @@ This searches AND plays the top result in one atomic command. URL-encode spaces
|
|
|
136
136
|
|
|
137
137
|
## YouTube
|
|
138
138
|
|
|
139
|
-
- Use `lemon-youtube` CLI when YouTube is connected.
|
|
139
|
+
- Use `lemon-youtube` CLI when YouTube is connected. Always use the CLI for YouTube tasks (search, transcript, video info).
|
|
140
140
|
- Available commands:
|
|
141
141
|
- `lemon-youtube search <query> [max_results]` — Search videos
|
|
142
142
|
- `lemon-youtube info <url_or_id>` — Get video details (title, description, stats)
|
|
@@ -144,7 +144,7 @@ This searches AND plays the top result in one atomic command. URL-encode spaces
|
|
|
144
144
|
- `lemon-youtube channel info <channel_id>` — Channel statistics
|
|
145
145
|
- `lemon-youtube channel videos <channel_id> [max]` — List channel videos
|
|
146
146
|
- `lemon-youtube status` — Check connection
|
|
147
|
-
- If not connected, offer `lemon://connect?provider=youtube
|
|
147
|
+
- If not connected, offer `lemon://connect?provider=youtube`. If CLI is broken, fall back to Lemonade's dedicated browser (`profile="lemonade"`).
|
|
148
148
|
|
|
149
149
|
## Media apps (Spotify, Apple Music)
|
|
150
150
|
|
|
@@ -171,15 +171,17 @@ Open System Settings panes via **URI only** — do not instruct the user to clic
|
|
|
171
171
|
|
|
172
172
|
## Summary table
|
|
173
173
|
|
|
174
|
-
| Service | Prefer | Fallback
|
|
175
|
-
|
|
176
|
-
| Gmail | `lemon-gmail` CLI |
|
|
177
|
-
| Calendar | `lemon-calendar` CLI |
|
|
178
|
-
| Drive | `lemon-drive` CLI |
|
|
179
|
-
| Docs | `lemon-docs` CLI |
|
|
180
|
-
| Sheets | `lemon-sheets` CLI |
|
|
181
|
-
| Notion | `lemon-notion` CLI |
|
|
182
|
-
| Slack | `lemon-slack` CLI | **NEVER** (CLI only)
|
|
183
|
-
| YouTube | `lemon-youtube` CLI |
|
|
184
|
-
| Spotify | AppleScript ONLY | —
|
|
185
|
-
| Other sites |
|
|
174
|
+
| Service | Prefer | Fallback (CLI broken only) | IDs |
|
|
175
|
+
|---------------|---------------------------|---------------------------------------|-----|
|
|
176
|
+
| Gmail | `lemon-gmail` CLI | Dedicated browser (`lemonade` profile)| From search/list only |
|
|
177
|
+
| Calendar | `lemon-calendar` CLI | Dedicated browser (`lemonade` profile)| From list/search or user |
|
|
178
|
+
| Drive | `lemon-drive` CLI | Dedicated browser (`lemonade` profile)| From list/search or user |
|
|
179
|
+
| Docs | `lemon-docs` CLI | Dedicated browser (`lemonade` profile)| From list/search or user |
|
|
180
|
+
| Sheets | `lemon-sheets` CLI | Dedicated browser (`lemonade` profile)| From list/search or user |
|
|
181
|
+
| Notion | `lemon-notion` CLI | Dedicated browser (`lemonade` profile)| From NOTION_SEARCH only |
|
|
182
|
+
| Slack | `lemon-slack` CLI | **NEVER** (CLI only) | From API/context only |
|
|
183
|
+
| YouTube | `lemon-youtube` CLI | Dedicated browser (`lemonade` profile)| From search/list only |
|
|
184
|
+
| Spotify | AppleScript ONLY | — | N/A (search by name) |
|
|
185
|
+
| Other sites | Dedicated browser | — | N/A |
|
|
186
|
+
|
|
187
|
+
**Important:** Never use the user's personal browser. All browser fallbacks use Lemonade's dedicated browser with `profile="lemonade"`.
|
package/package.json
CHANGED
package/skills/browser/SKILL.md
CHANGED
|
@@ -53,21 +53,15 @@ Before using browser for any of these services, **use the `lemon-*` CLI tool ins
|
|
|
53
53
|
| `browser_snapshot` | Get page content/structure |
|
|
54
54
|
| `browser_scroll` | Scroll the page |
|
|
55
55
|
|
|
56
|
-
## Browser
|
|
56
|
+
## Browser Profile
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Always use `profile="lemonade"` (the default). This is Lemonade's dedicated Playwright browser, isolated from the user's personal browser. Session cookies persist between uses. When a new integration is connected, the service URL is automatically opened here so future visits may be authenticated.
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
- **`lemonade` profile** (isolated): Dedicated Playwright browser. Session cookies persist between uses. When a new integration is connected, the service URL is automatically opened here so future visits may be authenticated.
|
|
60
|
+
**Never use `profile="chrome"` or access the user's personal browser.** All web browsing is done through Lemonade's dedicated browser only.
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
## Dedicated browser only
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Your system prompt ({{BROWSER_INSTRUCTIONS}}) tells you which mode you're in:
|
|
68
|
-
|
|
69
|
-
- **Dedicated browser:** Use **only** browser_* tools for web tasks. Do **not** use `open -a "Google Chrome"` or AppleScript to open URLs — the dedicated browser is controlled only via browser_* tools.
|
|
70
|
-
- **User's browser (e.g. Chrome, Brave):** Use the named browser for opening URLs (`open -a "BrowserName" "URL"` or AppleScript `tell application "BrowserName"`). browser_* tools control that same browser.
|
|
64
|
+
Lemonade always uses its own dedicated browser. Do **not** use `open -a "Google Chrome"`, `open "URL"`, or AppleScript to open URLs in the user's personal browser. The dedicated browser is controlled only via browser_* tools.
|
|
71
65
|
|
|
72
66
|
## ⚠️ IMPORTANT: No Clicking Required ⚠️
|
|
73
67
|
|