@heylemon/lemonade 0.4.4 → 0.4.7
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/bin/lemon-composio +26 -9
- package/dist/agents/system-prompt.js +21 -21
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/package.json +1 -1
- package/skills/gmail/SKILL.md +2 -11
- package/skills/integrations/SKILL.md +13 -7
- package/skills/meetings/SKILL.md +7 -6
- package/skills/social-media/SKILL.md +14 -27
package/bin/lemon-composio
CHANGED
|
@@ -36,17 +36,32 @@ case "$1" in
|
|
|
36
36
|
|
|
37
37
|
execute)
|
|
38
38
|
# Execute any Composio tool by slug
|
|
39
|
-
# Usage: lemon-composio execute TOOL_SLUG '{"param": "value"}'
|
|
40
|
-
[[ -z "$2" ]] && echo "Usage: lemon-composio execute <TOOL_SLUG> [json_parameters]" && exit 1
|
|
39
|
+
# Usage: lemon-composio execute TOOL_SLUG '{"param": "value"}' [--account=<id>]
|
|
40
|
+
[[ -z "$2" ]] && echo "Usage: lemon-composio execute <TOOL_SLUG> [json_parameters] [--account=<id>]" && exit 1
|
|
41
41
|
|
|
42
42
|
tool_slug="$2"
|
|
43
43
|
params="${3:-{\}}"
|
|
44
|
+
account_id=""
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
for arg in "${@:3}"; do
|
|
47
|
+
case "$arg" in
|
|
48
|
+
--account=*) account_id="${arg#*=}" ;;
|
|
49
|
+
esac
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
# Build the request body (include accountId only when specified)
|
|
53
|
+
if [[ -n "$account_id" ]]; then
|
|
54
|
+
EXEC_JSON=$(jq -n \
|
|
55
|
+
--arg toolName "$tool_slug" \
|
|
56
|
+
--argjson parameters "$params" \
|
|
57
|
+
--arg accountId "$account_id" \
|
|
58
|
+
'{toolName: $toolName, parameters: $parameters, accountId: $accountId}')
|
|
59
|
+
else
|
|
60
|
+
EXEC_JSON=$(jq -n \
|
|
61
|
+
--arg toolName "$tool_slug" \
|
|
62
|
+
--argjson parameters "$params" \
|
|
63
|
+
'{toolName: $toolName, parameters: $parameters}')
|
|
64
|
+
fi
|
|
50
65
|
|
|
51
66
|
echo "$EXEC_JSON" | curl -s -X POST \
|
|
52
67
|
-H "Authorization: Bearer ${GATEWAY_TOKEN}" \
|
|
@@ -72,11 +87,13 @@ Commands:
|
|
|
72
87
|
lemon-composio search "post to linkedin"
|
|
73
88
|
lemon-composio search "issues" --toolkit=github
|
|
74
89
|
|
|
75
|
-
execute <TOOL_SLUG> [json_parameters]
|
|
90
|
+
execute <TOOL_SLUG> [json_parameters] [--account=<id>]
|
|
76
91
|
Execute a Composio tool by its slug.
|
|
92
|
+
Use --account to target a specific connected account when
|
|
93
|
+
multiple accounts exist for the same provider.
|
|
77
94
|
Examples:
|
|
78
95
|
lemon-composio execute JIRA_CREATE_ISSUE '{"summary":"Bug fix","project_key":"PROJ"}'
|
|
79
|
-
lemon-composio execute
|
|
96
|
+
lemon-composio execute GMAIL_SEND_EMAIL '{"to":"a@b.com"}' --account=int_abc
|
|
80
97
|
|
|
81
98
|
status
|
|
82
99
|
Show which integrations the user has connected.
|
|
@@ -117,7 +117,7 @@ function buildConfirmationSection(isMinimal) {
|
|
|
117
117
|
"",
|
|
118
118
|
"Format:",
|
|
119
119
|
"```",
|
|
120
|
-
"
|
|
120
|
+
"CONFIRM: [brief action description]",
|
|
121
121
|
"",
|
|
122
122
|
"Action: [what will happen]",
|
|
123
123
|
"To: [recipient/target]",
|
|
@@ -335,21 +335,22 @@ export function buildAgentSystemPrompt(params) {
|
|
|
335
335
|
"Keep narration brief and value-dense; avoid repeating obvious steps.",
|
|
336
336
|
"Use plain human language for narration unless in a technical context.",
|
|
337
337
|
"",
|
|
338
|
-
"
|
|
338
|
+
"CRITICAL: NEVER narrate your internal search/discovery process to the user. When searching for tools, trying different queries, checking connection status, etc. — do all of that SILENTLY. The user should only see the FINAL result or a brief status like 'Checking your LinkedIn...' Do NOT say things like 'Let me try a more specific search', 'Let me search for tools that can...', 'I found tools but...', 'Let me try one more search'. Just do the work and give the answer.",
|
|
339
339
|
"",
|
|
340
|
-
"
|
|
340
|
+
"CRITICAL: NEVER expose technical details to the user. NEVER mention tool names (e.g. LINKEDIN_GET_POST_CONTENT), tool slugs, API names, Composio, integration details, connection status, or internal implementation. The user doesn't know or care about tools — they just want results. Speak in plain human language only.",
|
|
341
341
|
"",
|
|
342
|
-
"
|
|
342
|
+
"CRITICAL: NEVER give up or tell the user to do it themselves. If CLI tools can't do it, use the browser. If the browser requires login, ask the user to log in and wait. If the user IS logged in, just do the task — navigate to their profile, find what they asked for, and give them the answer. You have a browser — USE IT. Do NOT say 'You might want to check LinkedIn directly' or 'I cannot do this'. You CAN do it via the browser.",
|
|
343
343
|
"",
|
|
344
344
|
"## Action Bias",
|
|
345
345
|
"ALWAYS execute tasks directly instead of presenting options or asking how the user wants it done.",
|
|
346
346
|
"If the user asks you to do something (take a screenshot, send a file, etc.), just do it — pick the best approach and act.",
|
|
347
347
|
"Never reply with a list of approaches/options when a single tool call would suffice.",
|
|
348
|
+
"CRITICAL: NEVER stop after announcing what you're going to do. Do NOT say 'I'll check your LinkedIn' and then stop. Say it AND immediately do it in the same response — search, open browser, navigate, find the answer, and return it. The user should never have to ask twice. One request = one complete answer.",
|
|
348
349
|
"For screenshots of native macOS windows: use Peekaboo (`peekaboo image`) via exec if the skill is available.",
|
|
349
350
|
"",
|
|
350
351
|
"## Third-Party App Requests (Trello, Jira, LinkedIn, Asana, HubSpot, Salesforce, Todoist, etc.)",
|
|
351
352
|
"",
|
|
352
|
-
"
|
|
353
|
+
"CRITICAL RULE: For ANY service not in the dedicated CLI list below, try `lemon-composio` FIRST. There are NO other CLIs. Running `trello`, `jira`, `composio`, `asana`, `hubspot`, or any bare command will FAIL. The ONLY command that works is `lemon-composio search` and `lemon-composio execute`. Do NOT run `which trello`, `trello --help`, `composio`, or try to discover CLIs. They do not exist.",
|
|
353
354
|
"",
|
|
354
355
|
"Dedicated `lemon-*` CLIs (the COMPLETE list): lemon-gmail, lemon-calendar, lemon-drive, lemon-docs, lemon-sheets, lemon-slides, lemon-notion, lemon-slack, lemon-youtube, lemon-twitter, lemon-composio.",
|
|
355
356
|
"ANYTHING not in this list → use `lemon-composio search`.",
|
|
@@ -366,17 +367,7 @@ export function buildAgentSystemPrompt(params) {
|
|
|
366
367
|
"3. Do NOT disconnect without explicit user confirmation.",
|
|
367
368
|
"",
|
|
368
369
|
"### Task requests (do something WITH a service)",
|
|
369
|
-
"When the user mentions ANY service not in the dedicated CLI list,
|
|
370
|
-
'1. Run `lemon-composio search "<what the user wants>"` — this is your FIRST action. No web search. No `which`. No `--help`. No questions.',
|
|
371
|
-
"2. If result shows `connected: true` → execute the tool immediately with `lemon-composio execute`.",
|
|
372
|
-
"3. If the search returns results but none match the exact action, try broader/different search terms SILENTLY. Do NOT tell the user you're retrying searches.",
|
|
373
|
-
"4. If the service IS connected but the specific action truly doesn't exist, open the browser to do it. Tell the user briefly: \"Let me do this in the browser — I'll have better control there.\" Do NOT mention Composio, tools, searches, integrations, or any technical details.",
|
|
374
|
-
'5. If result shows `connected: false` → include the `connectUrl` from the search result as plain text (no backticks, no bold, no brackets) e.g. lemon://connect?provider=jira. The app will automatically open the auth page. Say "Connecting [service name] for you: lemon://connect?provider=X" Then STOP and wait for them to complete the auth.',
|
|
375
|
-
"6. Once the user confirms they connected → execute the tool.",
|
|
376
|
-
"7. If `lemon-composio` has no results OR `lemon://connect` fails → use the browser as fallback. Open the service website, let the user log in, and complete the task via browser tools.",
|
|
377
|
-
"",
|
|
378
|
-
"### Already-connected services",
|
|
379
|
-
"If `lemon-composio search` shows a service as `connected: true`, do NOT try to connect it again. Do NOT output lemon://connect for an already-connected service. Just use the available tools directly.",
|
|
370
|
+
"When the user mentions ANY service not in the dedicated CLI list, use `lemon-composio` — see the 'Dynamic tool discovery' section below for the full flow. Do ALL searching SILENTLY — the user should never see your search process.",
|
|
380
371
|
"",
|
|
381
372
|
"### Account & Login Policy",
|
|
382
373
|
"NEVER create accounts or sign up for services on behalf of the user. If a service requires login or account creation in the browser:",
|
|
@@ -432,10 +423,10 @@ export function buildAgentSystemPrompt(params) {
|
|
|
432
423
|
"",
|
|
433
424
|
"The response includes `connectedProviders` (all services the user has connected) and `serviceConnected` (whether the searched service is connected). Use these to determine connection status — even if no tools matched the query, `serviceConnected: true` means the user IS connected. Do NOT try to re-connect.",
|
|
434
425
|
"",
|
|
435
|
-
"Then based on results:",
|
|
436
|
-
|
|
437
|
-
"2. **No tools found but `serviceConnected: true`** → The user IS connected but this specific action isn't available as a tool. Try a broader search first (e.g. just the service name). If still nothing, tell the user: \"Let me do this in the browser — I'll have better control there.\" Then use the browser. Do NOT try to connect again.",
|
|
438
|
-
|
|
426
|
+
"Do ALL searching SILENTLY — never narrate retries or internal search process. Then based on results:",
|
|
427
|
+
"1. **Tools found + connected** → Execute immediately with `lemon-composio execute`. If the first search doesn't find the right tool, try broader/different search terms SILENTLY before giving up.",
|
|
428
|
+
"2. **No tools found but `serviceConnected: true`** → The user IS connected but this specific action isn't available as a tool. Try a broader search first (e.g. just the service name). If still nothing, tell the user: \"Let me do this in the browser — I'll have better control there.\" Then use the browser. Do NOT try to connect again. NEVER output a connect URL for an already-connected service.",
|
|
429
|
+
'3. **Not connected (`serviceConnected: false`)** → Include the `connectUrl` from the result as plain text (no backticks, no bold, no brackets): lemon://connect?provider=X. Say "Connecting [service name] for you: lemon://connect?provider=X" Then STOP and wait for them to complete the auth. Once the user confirms, execute the tool.',
|
|
439
430
|
'4. **Connect fails or no results at all** → Tell the user: "Let me do this in the browser — I\'ll have better control there." Then use the browser directly.',
|
|
440
431
|
"",
|
|
441
432
|
"Example flows:",
|
|
@@ -445,6 +436,15 @@ export function buildAgentSystemPrompt(params) {
|
|
|
445
436
|
"",
|
|
446
437
|
"**Check what's connected:** `lemon-composio status`",
|
|
447
438
|
"",
|
|
439
|
+
"### Multi-account support",
|
|
440
|
+
"Search results and status now include `connectedAccounts` — an array of all connected accounts with `provider`, `email`, and `accountId`.",
|
|
441
|
+
"Each tool in search results also has an `accounts` array showing which accounts can run that tool.",
|
|
442
|
+
"When the user has multiple accounts for the same provider (e.g. two Gmail accounts), pick the right one based on context:",
|
|
443
|
+
'- If the user says "work email" or "personal calendar", match by the account email.',
|
|
444
|
+
'- If unclear which account to use, ask once: "You have multiple Gmail accounts connected (work@company.com, personal@gmail.com). Which one should I use?"',
|
|
445
|
+
"- Pass the chosen account to execute: `lemon-composio execute TOOL_SLUG '{...}' --account=<accountId>`",
|
|
446
|
+
"- If only one account exists for the provider, you don't need `--account` — it will be used automatically.",
|
|
447
|
+
"",
|
|
448
448
|
"### Browser tool (Lemonade's dedicated browser only)",
|
|
449
449
|
"For general websites without a CLI tool, or as fallback when Composio fails, use Lemonade's dedicated `browser` tool (Playwright-managed).",
|
|
450
450
|
'**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"`.',
|
|
@@ -693,7 +693,7 @@ export function buildAgentSystemPrompt(params) {
|
|
|
693
693
|
}
|
|
694
694
|
// Skip silent replies for subagent/none modes
|
|
695
695
|
if (!isMinimal) {
|
|
696
|
-
lines.push("## Silent Replies", `When you have nothing to say, respond with ONLY: ${SILENT_REPLY_TOKEN}`, "", "
|
|
696
|
+
lines.push("## Silent Replies", `When you have nothing to say, respond with ONLY: ${SILENT_REPLY_TOKEN}`, "", "Rules:", "- It must be your ENTIRE message — nothing else", `- Never append it to an actual response (never include "${SILENT_REPLY_TOKEN}" in real replies)`, "- Never wrap it in markdown or code blocks", "", `❌ Wrong: "Here's help... ${SILENT_REPLY_TOKEN}"`, `❌ Wrong: "${SILENT_REPLY_TOKEN}"`, `✅ Right: ${SILENT_REPLY_TOKEN}`, "");
|
|
697
697
|
}
|
|
698
698
|
// Skip heartbeats for subagent/none modes
|
|
699
699
|
if (!isMinimal) {
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
be64d0d57f69ca463e3b2ef7886f231d8d7b8e3ec39975cb49e8ce91204fc307
|
package/package.json
CHANGED
package/skills/gmail/SKILL.md
CHANGED
|
@@ -31,18 +31,9 @@ The recap covers:
|
|
|
31
31
|
|
|
32
32
|
To create it, use the `cron` tool with `action=add`. Check `cron action=list` first to avoid duplicates.
|
|
33
33
|
|
|
34
|
-
## Resolving Recipients
|
|
34
|
+
## Resolving Recipients
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
1. **Slack directory first** (fastest): Use the `message` tool with `action: "search-users"`, `channel: "slack"`, `query: "masood"`. This returns `name`, `handle`, and **`email`**. If found, use that email.
|
|
39
|
-
2. **Gmail contacts**: Run `lemon-gmail find-contact "masood"` to search Google Contacts.
|
|
40
|
-
3. **Sent email history**: Run `lemon-gmail sent-to "masood"` to find emails you've previously sent to someone with that name.
|
|
41
|
-
4. **Ask the user**: If all lookups return nothing, ask: "I couldn't find Masood's email address. Could you provide it?"
|
|
42
|
-
|
|
43
|
-
**NEVER fabricate an email address** like `masood@example.com` or guess a domain. Always resolve from real data or ask.
|
|
44
|
-
|
|
45
|
-
**ALWAYS confirm** before sending: "I found Masood Ali (masood.ali@company.com). Should I send the email to this address?"
|
|
36
|
+
**NEVER fabricate email addresses.** See the email skill for the full resolution flow (Slack → Gmail contacts → sent history → ask user). Always confirm the resolved email before sending.
|
|
46
37
|
|
|
47
38
|
## Sending with Attachments
|
|
48
39
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: integrations
|
|
3
|
-
description:
|
|
3
|
+
description: Manage and connect Lemon integrations
|
|
4
4
|
metadata:
|
|
5
5
|
lemonade:
|
|
6
6
|
emoji: "🔗"
|
|
7
|
-
note: "Dynamic skills are auto-generated
|
|
7
|
+
note: "Dynamic skills are auto-generated when services are connected"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Lemon Integrations
|
|
@@ -25,11 +25,7 @@ when you connect services in Lemon Settings > Integrations.
|
|
|
25
25
|
|
|
26
26
|
Provider IDs: gmail, slack, googlecalendar, googledrive, notion, youtube, jira, github, linear, trello, asana, etc.
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
- Full CLI paths for your machine
|
|
30
|
-
- Proper authentication tokens
|
|
31
|
-
|
|
32
|
-
If integrations aren't working, restart the Lemon app to regenerate them.
|
|
28
|
+
Integration skills are auto-generated when you connect services. If integrations aren't working, restart the Lemon app to regenerate them.
|
|
33
29
|
|
|
34
30
|
## Connection Flow (Priority Order)
|
|
35
31
|
|
|
@@ -59,6 +55,16 @@ Some services (Jira, Trello, Asana, Confluence, etc.) require knowing the user's
|
|
|
59
55
|
- **ClickUp:** https://app.clickup.com
|
|
60
56
|
- **Monday.com:** https://monday.com
|
|
61
57
|
|
|
58
|
+
## Multi-Account Support
|
|
59
|
+
|
|
60
|
+
Users can connect multiple accounts for the same provider (e.g. two Gmail accounts, two Slack workspaces). When executing tools:
|
|
61
|
+
|
|
62
|
+
- **Search results** include a `connectedAccounts` array with each account's `provider`, `email`, and `accountId`. Each tool also lists which `accounts` can run it.
|
|
63
|
+
- **If only one account** exists for the provider, it's used automatically — no need to specify.
|
|
64
|
+
- **If multiple accounts** exist, pick the right one based on context (e.g. "send from my work email" → match by email). If unclear, ask the user once.
|
|
65
|
+
- **To target a specific account:** `lemon-composio execute TOOL_SLUG '{"params"}' --account=<accountId>`
|
|
66
|
+
- **Status** (`lemon-composio status`) also returns `connectedAccounts` so you can see all accounts at a glance.
|
|
67
|
+
|
|
62
68
|
## Browser Fallback
|
|
63
69
|
|
|
64
70
|
When CLI tools or Composio can't do something, ALWAYS use the browser. NEVER give up or tell the user to do it themselves.
|
package/skills/meetings/SKILL.md
CHANGED
|
@@ -28,14 +28,15 @@ lemon-calendar list
|
|
|
28
28
|
|
|
29
29
|
Zoom does not have a `lemon-*` CLI. If the user specifically needs Zoom (not Google Meet), use the Composio integration if connected.
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### Using Zoom via Composio
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
|
|
35
|
-
https://voice-wisal.voice-f05.workers.dev/api/lemonade/tools/status
|
|
34
|
+
lemon-composio search "create zoom meeting"
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
If tools are found and connected, execute immediately. If Zoom is not connected, output the connect URL as plain text:
|
|
38
|
+
|
|
39
|
+
lemon://connect?provider=zoom
|
|
39
40
|
|
|
40
41
|
## If NOT Connected
|
|
41
42
|
|
|
@@ -52,6 +53,6 @@ Include the connect URL as plain text in your reply. The app will automatically
|
|
|
52
53
|
## Remember
|
|
53
54
|
|
|
54
55
|
- **`lemon-calendar` first** — For Google Calendar + Meet
|
|
55
|
-
-
|
|
56
|
+
- **`lemon-composio`** — For Zoom and other meeting services without a dedicated CLI
|
|
57
|
+
- **Browser as last resort** — Only if CLI and Composio both fail
|
|
56
58
|
- **Always include timezone** — Essential for meetings
|
|
57
|
-
- **Be honest** — Offer to connect if not set up
|
|
@@ -4,8 +4,9 @@ Post to LinkedIn, Twitter/X, and other social platforms.
|
|
|
4
4
|
|
|
5
5
|
## Priority Order
|
|
6
6
|
|
|
7
|
-
1. **`lemon-twitter`** CLI for Twitter/X
|
|
8
|
-
2.
|
|
7
|
+
1. **`lemon-twitter`** CLI for Twitter/X
|
|
8
|
+
2. **`lemon-composio`** for LinkedIn and other social platforms
|
|
9
|
+
3. **Browser** — Fallback only if CLI/Composio fails or service is not connected
|
|
9
10
|
|
|
10
11
|
## Twitter/X
|
|
11
12
|
|
|
@@ -29,40 +30,26 @@ lemon-twitter search "query"
|
|
|
29
30
|
|
|
30
31
|
## LinkedIn
|
|
31
32
|
|
|
32
|
-
LinkedIn does not
|
|
33
|
+
LinkedIn does not have a dedicated `lemon-*` CLI. Use `lemon-composio` to search and execute LinkedIn tools.
|
|
33
34
|
|
|
34
|
-
###
|
|
35
|
+
### Posting, checking activity, etc.
|
|
35
36
|
|
|
36
37
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
lemon-composio search "create linkedin post"
|
|
39
|
+
lemon-composio search "linkedin activity"
|
|
39
40
|
```
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
If tools are found and connected, execute immediately. If the specific action isn't available as a tool, use the browser as fallback.
|
|
42
43
|
|
|
43
|
-
### If Connected
|
|
44
|
+
### If Not Connected
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
curl -X POST \
|
|
47
|
-
-H "Authorization: Bearer $GATEWAY_TOKEN" \
|
|
48
|
-
-H "Content-Type: application/json" \
|
|
49
|
-
-d '{
|
|
50
|
-
"toolName": "LINKEDIN_CREATE_POST",
|
|
51
|
-
"parameters": {
|
|
52
|
-
"text": "Your post content here",
|
|
53
|
-
"visibility": "PUBLIC"
|
|
54
|
-
}
|
|
55
|
-
}' \
|
|
56
|
-
https://voice-wisal.voice-f05.workers.dev/api/lemonade/tools/execute
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### If NOT Connected
|
|
46
|
+
Output the connect URL as plain text:
|
|
60
47
|
|
|
61
|
-
|
|
48
|
+
lemon://connect?provider=linkedin
|
|
62
49
|
|
|
63
|
-
|
|
50
|
+
### If Connect Fails
|
|
64
51
|
|
|
65
|
-
|
|
52
|
+
Use the browser as fallback — navigate to linkedin.com and complete the task directly.
|
|
66
53
|
|
|
67
54
|
## Content Guidelines
|
|
68
55
|
|
|
@@ -78,7 +65,7 @@ If connect fails, use the browser as fallback: navigate to `linkedin.com/feed`,
|
|
|
78
65
|
- Hashtags and mentions common
|
|
79
66
|
- Good for: quick updates, engagement
|
|
80
67
|
|
|
81
|
-
##
|
|
68
|
+
## ALWAYS Confirm Before Posting
|
|
82
69
|
|
|
83
70
|
**Never post without user approval.**
|
|
84
71
|
|