@symerian/symi 3.0.17 → 3.0.18
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/{audio-preflight-CBDFctZN.js → audio-preflight-BfmZbg4Y.js} +4 -4
- package/dist/{audio-preflight-gsZSpG-6.js → audio-preflight-DcuC-liM.js} +4 -4
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +8 -8
- package/dist/bundled/session-memory/handler.js +7 -7
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{chrome-nPMY1XTJ.js → chrome-Bo7cbvFK.js} +5 -5
- package/dist/{chrome-BjVab8gM.js → chrome-DYp18Q0t.js} +5 -5
- package/dist/{deliver-D-QFqm31.js → deliver-ChSIbiMM.js} +1 -1
- package/dist/{deliver-B4-bcot9.js → deliver-DEgRQM4J.js} +1 -1
- package/dist/extensionAPI.js +7 -7
- package/dist/{image-CDwtQjmt.js → image-Bx-hvoNJ.js} +1 -1
- package/dist/{image-CcS-vzTA.js → image-CQl_mjWk.js} +1 -1
- package/dist/llm-slug-generator.js +7 -7
- package/dist/{manager-BnEdHzmO.js → manager-D_pn0urG.js} +1 -1
- package/dist/{manager-09r0qPze.js → manager-YQxK2t0C.js} +1 -1
- package/dist/{pi-embedded-CWsY69-4.js → pi-embedded-CLw_ZzEZ.js} +16 -16
- package/dist/{pi-embedded-helpers-BBMy-lqr.js → pi-embedded-helpers-B5I53aw6.js} +4 -4
- package/dist/{pi-embedded-helpers-ChEYbgVj.js → pi-embedded-helpers-sUAEIC9X.js} +4 -4
- package/dist/plugin-sdk/{accounts-BfyWsC_i.js → accounts-CWFytwbR.js} +3 -3
- package/dist/plugin-sdk/{active-listener-DcJW7xAT.js → active-listener-BkZ4jHrL.js} +2 -2
- package/dist/plugin-sdk/{agent-scope-ChbGV6of.js → agent-scope-C9gfY_Gk.js} +2 -2
- package/dist/plugin-sdk/{audio-preflight-D3GtNLqW.js → audio-preflight-HKbdzXLZ.js} +21 -21
- package/dist/plugin-sdk/{bindings-CN2Qmefj.js → bindings-BaKIqPPy.js} +2 -2
- package/dist/plugin-sdk/{channel-web-DTyqujjA.js → channel-web-D5nWiTH1.js} +18 -18
- package/dist/plugin-sdk/{chrome-BKzAKr3K.js → chrome-klTSnz-9.js} +3 -3
- package/dist/plugin-sdk/{chunk-DhDkBujV.js → chunk-BbrYSny_.js} +1 -1
- package/dist/plugin-sdk/{command-format-CVrYFyZS.js → command-format-BN6tyZt6.js} +1 -1
- package/dist/plugin-sdk/{commands-registry-17yfZkHZ.js → commands-registry-CTzKKtY6.js} +4 -4
- package/dist/plugin-sdk/{config-7wk65zKC.js → config-Crv2qEdJ.js} +9 -9
- package/dist/plugin-sdk/{consolidate-exbAW0ml.js → consolidate-DT1QH65Q.js} +2 -2
- package/dist/plugin-sdk/{deliver-TxAcw7J5.js → deliver-7rOvAlrc.js} +12 -12
- package/dist/plugin-sdk/{diagnostic-Debx4frd.js → diagnostic-0nsxhWp7.js} +1 -1
- package/dist/plugin-sdk/{fs-safe-wBYbAkJF.js → fs-safe-DfWYBeWF.js} +1 -1
- package/dist/plugin-sdk/{gemini-auth-7U2pm2Ky.js → gemini-auth-C0N0_u49.js} +1 -1
- package/dist/plugin-sdk/{image-BtDVmYA5.js → image-WOSl2apK.js} +4 -4
- package/dist/plugin-sdk/index.js +43 -43
- package/dist/plugin-sdk/{ir-CKMvRrGW.js → ir-9J84MTls.js} +4 -4
- package/dist/plugin-sdk/{local-roots-c_gaPs01.js → local-roots-OLRDbvyY.js} +3 -3
- package/dist/plugin-sdk/{login-DUym1Jy0.js → login-C7x4q0i2.js} +7 -7
- package/dist/plugin-sdk/{login-qr-B-WBdvrX.js → login-qr-Dv5_MoAW.js} +9 -9
- package/dist/plugin-sdk/{manager-B71SCzos.js → manager-C83tK17x.js} +8 -8
- package/dist/plugin-sdk/{manifest-registry-Dnic6Chh.js → manifest-registry-CJMV-PI7.js} +1 -1
- package/dist/plugin-sdk/{markdown-tables-Dur7OTlM.js → markdown-tables-DXNKz5y_.js} +1 -1
- package/dist/plugin-sdk/{message-channel-BrAhJJV_.js → message-channel-aGy1HbQQ.js} +1 -1
- package/dist/plugin-sdk/{model-selection-B9qaVQSJ.js → model-selection-C-3-tpe7.js} +4 -4
- package/dist/plugin-sdk/{outbound-DB1wDM8b.js → outbound-DquCeSy5.js} +6 -6
- package/dist/plugin-sdk/{pi-auth-json-ZO118hoy.js → pi-auth-json-D9PDCXGn.js} +1 -1
- package/dist/plugin-sdk/{pi-embedded-helpers-s_U0Un7j.js → pi-embedded-helpers-D3ygfH7l.js} +16 -16
- package/dist/plugin-sdk/{plugins-DF81oSaI.js → plugins-DOwnSg9D.js} +4 -4
- package/dist/plugin-sdk/{pw-ai-CTwP02uv.js → pw-ai-rlengLjb.js} +8 -8
- package/dist/plugin-sdk/{qmd-manager-CBaSGant.js → qmd-manager-BzxFjRFa.js} +4 -4
- package/dist/plugin-sdk/{registry-CZVURNhF.js → registry-5iFfixlB.js} +2 -2
- package/dist/plugin-sdk/{replies-hwRbkU3z.js → replies-BXOzO_H5.js} +7 -7
- package/dist/plugin-sdk/{reply-prefix-CaXmzZlx.js → reply-prefix-INAKTqCU.js} +1 -1
- package/dist/plugin-sdk/{resolve-outbound-target-fxVSOBmk.js → resolve-outbound-target-DvbxHtqp.js} +2 -2
- package/dist/plugin-sdk/{resolve-route-ClCyiOeu.js → resolve-route-URXlY3AK.js} +3 -3
- package/dist/plugin-sdk/{runner-Cq5jvwQ7.js → runner-Bv0_DWoH.js} +9 -9
- package/dist/plugin-sdk/{session-B_TkB65Y.js → session-C3r8l7ou.js} +4 -4
- package/dist/plugin-sdk/{skill-commands-0LF9HTGr.js → skill-commands-KjLUGIdZ.js} +5 -5
- package/dist/plugin-sdk/{skills-BIT_O7J0.js → skills-BrsD4L5c.js} +7 -7
- package/dist/plugin-sdk/{sqlite-Bx5Y5U5X.js → sqlite-CjW7ME1H.js} +1 -1
- package/dist/plugin-sdk/{subsystem-CXqYeDy-.js → subsystem-DcOg1xJr.js} +1 -1
- package/dist/plugin-sdk/{synthesis-DtsYAj1E.js → synthesis-CY7YAasV.js} +38 -38
- package/dist/plugin-sdk/{target-errors-B8mokOeH.js → target-errors-BVWJGWFq.js} +2 -2
- package/dist/plugin-sdk/{thinking-Ca0DhqzO.js → thinking-CtsTDPOi.js} +3 -3
- package/dist/plugin-sdk/{tokens-CvlONEqh.js → tokens-8lqOTZCB.js} +1 -1
- package/dist/plugin-sdk/{tool-images-DpBaWEHT.js → tool-images-Cl_rGIUZ.js} +2 -2
- package/dist/plugin-sdk/{tool-loop-detection-BOvUFa0f.js → tool-loop-detection-Da4WUT_P.js} +2 -2
- package/dist/plugin-sdk/{unified-runner-CnM7lyNd.js → unified-runner-nwMnsZyj.js} +60 -60
- package/dist/plugin-sdk/web-BlweOZDp.js +54 -0
- package/dist/plugin-sdk/{whatsapp-actions-CvnfsFJm.js → whatsapp-actions-DpfaGYs7.js} +21 -21
- package/dist/{pw-ai-BW8_KeDf.js → pw-ai-BqxJG-Wh.js} +1 -1
- package/dist/{pw-ai-j9IE1K0-.js → pw-ai-C-NSGye0.js} +1 -1
- package/dist/{runner-8ALr2UII.js → runner-COGFTeDw.js} +1 -1
- package/dist/{runner-C4-9kFdR.js → runner-DhCi2lT1.js} +1 -1
- package/dist/{synthesis-Cph3LhA1.js → synthesis-CXZu24Vx.js} +7 -7
- package/dist/{synthesis-Cus0A2dL.js → synthesis-DrPxcMlQ.js} +7 -7
- package/dist/{unified-runner-CX80YMTk.js → unified-runner-iByUazvW.js} +16 -16
- package/dist/{web-ChozvJ7I.js → web-EsMQBIYf.js} +7 -7
- package/dist/{web-DFlsbXmQ.js → web-PPg5y6xI.js} +7 -7
- package/package.json +1 -1
- package/dist/plugin-sdk/web-CIPJBHAU.js +0 -54
- package/skills/1password/SKILL.md +0 -71
- package/skills/1password/references/cli-examples.md +0 -29
- package/skills/1password/references/get-started.md +0 -17
- package/skills/apple-notes/SKILL.md +0 -78
- package/skills/apple-reminders/SKILL.md +0 -119
- package/skills/bear-notes/SKILL.md +0 -108
- package/skills/blogwatcher/SKILL.md +0 -70
- package/skills/blucli/SKILL.md +0 -48
- package/skills/bluebubbles/SKILL.md +0 -132
- package/skills/camsnap/SKILL.md +0 -46
- package/skills/canvas/SKILL.md +0 -204
- package/skills/connect-email/SKILL.md +0 -142
- package/skills/document-generation/SKILL.md +0 -83
- package/skills/eightctl/SKILL.md +0 -51
- package/skills/food-order/SKILL.md +0 -49
- package/skills/gemini/SKILL.md +0 -44
- package/skills/gh-issues/SKILL.md +0 -865
- package/skills/gifgrep/SKILL.md +0 -80
- package/skills/github/SKILL.md +0 -164
- package/skills/gog/SKILL.md +0 -117
- package/skills/goplaces/SKILL.md +0 -53
- package/skills/healthcheck/SKILL.md +0 -246
- package/skills/himalaya/SKILL.md +0 -258
- package/skills/himalaya/references/configuration.md +0 -184
- package/skills/himalaya/references/message-composition.md +0 -199
- package/skills/imsg/SKILL.md +0 -122
- package/skills/long-task/SKILL.md +0 -58
- package/skills/long-task/scripts/detach-task.sh +0 -187
- package/skills/nano-banana-pro/SKILL.md +0 -59
- package/skills/nano-banana-pro/scripts/generate_image.py +0 -184
- package/skills/nano-pdf/SKILL.md +0 -39
- package/skills/notion/SKILL.md +0 -173
- package/skills/obsidian/SKILL.md +0 -82
- package/skills/openai-image-gen/SKILL.md +0 -90
- package/skills/openai-image-gen/scripts/gen.py +0 -240
- package/skills/openai-whisper/SKILL.md +0 -39
- package/skills/openai-whisper-api/SKILL.md +0 -53
- package/skills/openai-whisper-api/scripts/transcribe.sh +0 -85
- package/skills/openhue/SKILL.md +0 -113
- package/skills/oracle/SKILL.md +0 -126
- package/skills/ordercli/SKILL.md +0 -79
- package/skills/peekaboo/SKILL.md +0 -191
- package/skills/reactions-extensive/SKILL.md +0 -30
- package/skills/reactions-minimal/SKILL.md +0 -31
- package/skills/safe-edit/SKILL.md +0 -51
- package/skills/sag/SKILL.md +0 -88
- package/skills/sherpa-onnx-tts/SKILL.md +0 -104
- package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -178
- package/skills/songsee/SKILL.md +0 -50
- package/skills/sonoscli/SKILL.md +0 -66
- package/skills/spotify-player/SKILL.md +0 -65
- package/skills/symihub/SKILL.md +0 -78
- package/skills/things-mac/SKILL.md +0 -87
- package/skills/tmux/SKILL.md +0 -153
- package/skills/tmux/scripts/find-sessions.sh +0 -112
- package/skills/tmux/scripts/wait-for-text.sh +0 -83
- package/skills/trello/SKILL.md +0 -96
- package/skills/video-frames/SKILL.md +0 -47
- package/skills/video-frames/scripts/frame.sh +0 -81
- package/skills/voice-call/SKILL.md +0 -46
- package/skills/wacli/SKILL.md +0 -73
- package/skills/weather/SKILL.md +0 -113
- package/skills/xurl/SKILL.md +0 -462
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: connect-email
|
|
3
|
-
description: Connect a user's email account (Outlook 365 or Gmail) to Symi. Use when the user asks to connect, link, set up, configure, or troubleshoot email — including any mention of "my email", "work email", "outlook", "gmail", "microsoft 365", "m365", "google workspace", or "inbox". Precheck for an existing connection, ask Gmail or Outlook, then walk through the matching setup. Covers the `/outlook login` device-code flow and the full Gmail `hooks.gmail` Pub/Sub setup.
|
|
4
|
-
triggers: [connect-email, connect, email]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Connect Email
|
|
8
|
-
|
|
9
|
-
Symi has two email integrations. **Do not invent steps. Do not claim email is unsupported.** Follow this skill end-to-end.
|
|
10
|
-
|
|
11
|
-
| Integration | Use when | How to connect |
|
|
12
|
-
| --------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
13
|
-
| **Outlook 365** | Microsoft 365 work/school account, personal `outlook.com` / `hotmail.com` / `live.com` | User sends `/outlook login` in chat → Microsoft device-code flow → tools become available immediately |
|
|
14
|
-
| **Gmail** | Google Workspace, personal Gmail — **and** the user wants incoming mail to auto-create Symi sessions | Google Cloud Pub/Sub + `hooks.gmail` config (multi-step setup) |
|
|
15
|
-
|
|
16
|
-
## Step 0 — Precheck the connection state
|
|
17
|
-
|
|
18
|
-
Before asking "Gmail or Outlook?", check what's already connected so you don't ask a user who's already set up.
|
|
19
|
-
|
|
20
|
-
1. **Outlook.** Your current system prompt already contains a line starting with `[Outlook 365]`, injected by the `outlook` plugin's `before_prompt_build` hook. If it reads _"Connected as <email>"_, Outlook is active — acknowledge it ("I can see you're already connected as X") and ask whether the user wants to add a second account or do something else.
|
|
21
|
-
2. **Gmail.** Read `~/.symi/symi.json`. If it has a `hooks.gmail` block with at least `account` and `topic` set, Gmail is configured — again, acknowledge before offering to re-setup.
|
|
22
|
-
|
|
23
|
-
If neither is connected — or the user explicitly wants a _different_ account than what's shown — continue.
|
|
24
|
-
|
|
25
|
-
## Step 1 — Ask the user: Gmail or Outlook?
|
|
26
|
-
|
|
27
|
-
One plain question. Do not assume. The correct branch depends on which mail provider the user actually has.
|
|
28
|
-
|
|
29
|
-
## Step 2a — Outlook branch
|
|
30
|
-
|
|
31
|
-
1. Ask the user to **type `/outlook login` in chat themselves**. Chat commands are intercepted by the command dispatcher only when the user sends them — if you emit `/outlook login` as assistant text it is just text, not a command.
|
|
32
|
-
2. They will receive a reply with a Microsoft device-code URL (typically `https://login.microsoft.com/device`) and an 8-character code. The code expires in 15 minutes.
|
|
33
|
-
3. The user opens the URL in any browser, signs in with their Microsoft account, pastes the code, and approves access.
|
|
34
|
-
4. Tokens are persisted to `~/.symi/credentials/outlook.json` (mode 0600). From the next turn, the `before_prompt_build` hook will inject `[Outlook 365] Connected as <email>` into your system context automatically.
|
|
35
|
-
5. Ask the user to send `/outlook status` to confirm. On success these seven tools are live for your use:
|
|
36
|
-
- `outlook_list` — list messages in a folder (`inbox`, `sentitems`, `drafts`, `archive`, `junkemail`), optional unread filter
|
|
37
|
-
- `outlook_read` — fetch the full body of a message by id (auto-marks read)
|
|
38
|
-
- `outlook_send` — new message with To/CC, subject, body
|
|
39
|
-
- `outlook_reply` — reply or reply-all to an existing message id
|
|
40
|
-
- `outlook_search` — keyword search across subject / body / sender
|
|
41
|
-
- `outlook_folders` — list folders with unread / total counts
|
|
42
|
-
- `outlook_move` — move a message to another folder
|
|
43
|
-
|
|
44
|
-
### Outlook limitations to tell the user up front
|
|
45
|
-
|
|
46
|
-
- **Plain-text body only.** No HTML formatting, no attachments (send or receive).
|
|
47
|
-
- **Pull-only.** Symi does not receive incoming Outlook mail as Symi conversations. The user has to ask ("any new mail?") and you call `outlook_list` / `outlook_search`. There is no push, webhook, or background poll for Outlook today — if the user wants inbound-triggered sessions, they need Gmail.
|
|
48
|
-
- **No Graph API retry/backoff yet.** A transient Graph 5xx surfaces as an error on the first try; re-running the tool usually succeeds.
|
|
49
|
-
|
|
50
|
-
## Step 2b — Gmail branch (full walkthrough)
|
|
51
|
-
|
|
52
|
-
Gmail is heavier because Google requires Pub/Sub for push notifications. End result: when new mail lands in the watched label, Google publishes to a Pub/Sub topic; a push subscription POSTs to Symi's webhook; Symi creates a `hook:gmail:<id>` session that you then reply into as the agent.
|
|
53
|
-
|
|
54
|
-
### Prerequisites — verify with the user before starting
|
|
55
|
-
|
|
56
|
-
- [ ] Access to a **Google Cloud project** (they can create one free at [console.cloud.google.com](https://console.cloud.google.com)).
|
|
57
|
-
- [ ] `gcloud` CLI installed. On macOS: `brew install --cask google-cloud-sdk`. On Linux: follow the [gcloud install guide](https://cloud.google.com/sdk/docs/install).
|
|
58
|
-
- [ ] OAuth credentials for the Gmail API, managed via `gogcli`. See `skills/gog/SKILL.md` for gogcli setup (`gog auth credentials /path/to/client_secret.json` then `gog auth add <email> --services gmail`).
|
|
59
|
-
- [ ] Symi's webhook endpoint reachable by Google's push service. Either the Symi host is publicly reachable, **or** Tailscale is configured (`tailscale.mode: "serve"` for private, `"funnel"` for public-over-Tailscale).
|
|
60
|
-
|
|
61
|
-
If any prerequisite is missing, stop and help the user install/configure it before continuing.
|
|
62
|
-
|
|
63
|
-
### Step-by-step setup
|
|
64
|
-
|
|
65
|
-
1. **Authenticate gcloud** — `gcloud auth login` and `gcloud config set project <project-id>`.
|
|
66
|
-
2. **Set up gogcli OAuth** — follow the `gog` skill: `gog auth credentials /path/to/client_secret.json`, then `gog auth add <email> --services gmail`.
|
|
67
|
-
3. **Create the Pub/Sub topic**
|
|
68
|
-
```bash
|
|
69
|
-
gcloud pubsub topics create symi-gmail
|
|
70
|
-
```
|
|
71
|
-
4. **Grant Gmail permission to publish to the topic**
|
|
72
|
-
```bash
|
|
73
|
-
gcloud pubsub topics add-iam-policy-binding symi-gmail \
|
|
74
|
-
--member=serviceAccount:gmail-api-push@system.gserviceaccount.com \
|
|
75
|
-
--role=roles/pubsub.publisher
|
|
76
|
-
```
|
|
77
|
-
5. **Create the push subscription** (pointing at Symi's webhook URL)
|
|
78
|
-
```bash
|
|
79
|
-
gcloud pubsub subscriptions create symi-gmail-sub \
|
|
80
|
-
--topic=symi-gmail \
|
|
81
|
-
--push-endpoint=<SYMI_WEBHOOK_URL>/gmail-pubsub
|
|
82
|
-
```
|
|
83
|
-
6. **Register the Gmail watch** — call `users.watch` on the Gmail API with the topic and the label to watch (normally `INBOX`). The helpers in `src/hooks/gmail-setup-utils.ts` can do this from the gateway; ask the user whether they want you to run the setup via the gateway CLI or execute the `curl` against the Gmail API manually.
|
|
84
|
-
7. **Add `hooks.gmail` to `~/.symi/symi.json`**:
|
|
85
|
-
|
|
86
|
-
```json
|
|
87
|
-
{
|
|
88
|
-
"hooks": {
|
|
89
|
-
"gmail": {
|
|
90
|
-
"account": "user@example.com",
|
|
91
|
-
"label": "INBOX",
|
|
92
|
-
"topic": "projects/<project-id>/topics/symi-gmail",
|
|
93
|
-
"subscription": "projects/<project-id>/subscriptions/symi-gmail-sub",
|
|
94
|
-
"pushToken": "<random-shared-secret>",
|
|
95
|
-
"hookUrl": "http://127.0.0.1:8788/gmail-pubsub",
|
|
96
|
-
"includeBody": true,
|
|
97
|
-
"maxBytes": 20480,
|
|
98
|
-
"renewEveryMinutes": 720,
|
|
99
|
-
"serve": { "bind": "127.0.0.1", "port": 8788, "path": "/gmail-pubsub" },
|
|
100
|
-
"tailscale": { "mode": "off" }
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Key fields:
|
|
107
|
-
- `account` — the Gmail address being watched.
|
|
108
|
-
- `label` — Gmail label/folder to watch (default `INBOX`).
|
|
109
|
-
- `topic` / `subscription` — fully-qualified Pub/Sub resource names (`projects/<id>/topics/<name>`).
|
|
110
|
-
- `pushToken` — shared secret Symi checks on incoming push requests so spoofed pushes are rejected.
|
|
111
|
-
- `hookUrl` — URL the push subscription POSTs to; must match `serve.bind` + `serve.port` + `serve.path`, or be a Tailscale serve/funnel exposing them.
|
|
112
|
-
- `includeBody` — include the email body in the prompt. `maxBytes` truncates oversized emails.
|
|
113
|
-
- `renewEveryMinutes` — Gmail `watch` expires after ~7 days; default 720 (12h) re-registers well ahead.
|
|
114
|
-
- `tailscale.mode` — `"off"` if Symi is publicly reachable; `"serve"` for a private tailnet webhook; `"funnel"` for Tailscale-exposed public endpoint.
|
|
115
|
-
- `allowUnsafeExternalContent` — leave unset. Setting `true` disables Symi's external-content safety wrapper on email content — only use after explicit user acknowledgement.
|
|
116
|
-
|
|
117
|
-
8. **Restart the gateway** so it picks up the new hook config:
|
|
118
|
-
```bash
|
|
119
|
-
systemctl --user restart symi-gateway # Linux
|
|
120
|
-
```
|
|
121
|
-
On macOS with the headless tmux wrapper, kill and relaunch the tmux session running `gateway-headless.sh`. Changes under `hooks.gmail` are not hot-reloaded today.
|
|
122
|
-
9. **Verify** — have the user send a test email to `account`. Expected chain: Google publishes to the topic → Pub/Sub pushes to Symi's `/gmail-pubsub` endpoint → a `hook:gmail:<id>` session is created → you reply to it in the normal Symi conversation flow. Confirm the user sees the test email arrive as a Symi session.
|
|
123
|
-
|
|
124
|
-
### Gmail limitations to tell the user
|
|
125
|
-
|
|
126
|
-
- Inbound only works while the watch is live. If `renewEveryMinutes` lapses, the Pub/Sub subscription fails, or the IAM binding gets removed, mail stops arriving — the gateway doctor (`symi doctor`) has checks for this.
|
|
127
|
-
- Outgoing mail uses the reply path of whichever session/agent handles the inbound — it is not a native SMTP sender tool like `outlook_send`. For "compose a new email from scratch" workflows, Outlook is simpler.
|
|
128
|
-
- `maxBytes` truncates very large emails so the prompt stays usable — set higher if the user routinely needs full message bodies.
|
|
129
|
-
|
|
130
|
-
## Which should I recommend?
|
|
131
|
-
|
|
132
|
-
- **Microsoft 365 / outlook.com / hotmail.com / live.com** → Outlook. Two-minute setup.
|
|
133
|
-
- **Gmail or Google Workspace**, user wants to **send mail on demand only** → Gmail via the `gog` CLI tools (no Pub/Sub needed) is simpler than the full `hooks.gmail` flow — mention this option.
|
|
134
|
-
- **Gmail or Google Workspace**, user wants **incoming mail to auto-create Symi sessions** → Full Gmail Pub/Sub setup (Step 2b).
|
|
135
|
-
- User wants _both send and auto-receive in Outlook_ → not available today; push/poll for Outlook is not implemented.
|
|
136
|
-
|
|
137
|
-
## References
|
|
138
|
-
|
|
139
|
-
- Gmail Pub/Sub concept doc: `docs/automation/gmail-pubsub.md`
|
|
140
|
-
- gog (Google Workspace CLI): `skills/gog/SKILL.md`
|
|
141
|
-
- Outlook plugin source: `extensions/outlook/` (tools in `src/tools.ts`, OAuth in `src/auth.ts`)
|
|
142
|
-
- Config types: `src/config/types.hooks.ts` (`HooksGmailConfig`)
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: document-generation
|
|
3
|
-
description: Generate Word (.docx), Excel (.xlsx), PowerPoint (.pptx), and PDF documents via npm packages bundled with Symi. Write a short Node.js script (.cjs for CommonJS), execute via exec with host=gateway. Use when the user asks to create, generate, or export documents.
|
|
4
|
-
triggers: [document, docx, xlsx, pptx, pdf, word, excel, powerpoint, generate, export, file]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Document Generation
|
|
8
|
-
|
|
9
|
-
Symi ships with these npm packages bundled for document generation via the `exec` tool:
|
|
10
|
-
|
|
11
|
-
- **`docx`** — create `.docx` (Word) files with headings, paragraphs, tables, images, styles.
|
|
12
|
-
- **`exceljs`** — create `.xlsx` (Excel) files with sheets, formulas, formatting, charts.
|
|
13
|
-
- **`pptxgenjs`** — create `.pptx` (PowerPoint) files with slides, layouts, text, images, charts.
|
|
14
|
-
- **`pdfkit`** — create `.pdf` files with text, images, tables, vector graphics.
|
|
15
|
-
|
|
16
|
-
These are real `dependencies` in Symi's `package.json` — they install with Symi automatically. No separate setup step.
|
|
17
|
-
|
|
18
|
-
## How to invoke
|
|
19
|
-
|
|
20
|
-
When the user asks to **create, generate, or export** a document:
|
|
21
|
-
|
|
22
|
-
1. Write a short Node.js script. Save it with the `.cjs` extension so CommonJS `require()` resolves correctly even though Symi's own package is `"type": "module"`.
|
|
23
|
-
2. Execute via the `exec` tool with `host: "gateway"` — the packages are installed in Symi's own `node_modules`, which the gateway host can resolve from.
|
|
24
|
-
3. Write the output to a path the user can pick up — typically the workspace dir, `~/Downloads/`, or wherever the user named.
|
|
25
|
-
|
|
26
|
-
## Minimal example — Word doc
|
|
27
|
-
|
|
28
|
-
```js
|
|
29
|
-
// gen.cjs
|
|
30
|
-
const { Document, Packer, Paragraph, TextRun, HeadingLevel } = require("docx");
|
|
31
|
-
const fs = require("fs");
|
|
32
|
-
|
|
33
|
-
const doc = new Document({
|
|
34
|
-
sections: [
|
|
35
|
-
{
|
|
36
|
-
children: [
|
|
37
|
-
new Paragraph({ heading: HeadingLevel.TITLE, children: [new TextRun("Report")] }),
|
|
38
|
-
new Paragraph({ children: [new TextRun("Body content here.")] }),
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
Packer.toBuffer(doc).then((buf) => {
|
|
45
|
-
fs.writeFileSync("/tmp/report.docx", buf);
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Then `exec({ host: "gateway", command: "node gen.cjs" })`.
|
|
50
|
-
|
|
51
|
-
The script must run on the gateway host because that's where Symi's `node_modules` live — the sandbox and remote nodes do NOT have these packages.
|
|
52
|
-
|
|
53
|
-
## Other formats
|
|
54
|
-
|
|
55
|
-
```js
|
|
56
|
-
// xlsx
|
|
57
|
-
const ExcelJS = require("exceljs");
|
|
58
|
-
const wb = new ExcelJS.Workbook();
|
|
59
|
-
const sheet = wb.addWorksheet("Sheet1");
|
|
60
|
-
sheet.getCell("A1").value = "Hello";
|
|
61
|
-
await wb.xlsx.writeFile("/tmp/out.xlsx");
|
|
62
|
-
|
|
63
|
-
// pptx
|
|
64
|
-
const PptxGenJS = require("pptxgenjs");
|
|
65
|
-
const pptx = new PptxGenJS();
|
|
66
|
-
const slide = pptx.addSlide();
|
|
67
|
-
slide.addText("Hello", { x: 1, y: 1, w: 4, h: 1 });
|
|
68
|
-
await pptx.writeFile({ fileName: "/tmp/out.pptx" });
|
|
69
|
-
|
|
70
|
-
// pdf
|
|
71
|
-
const PDFDocument = require("pdfkit");
|
|
72
|
-
const fs = require("fs");
|
|
73
|
-
const pdf = new PDFDocument();
|
|
74
|
-
pdf.pipe(fs.createWriteStream("/tmp/out.pdf"));
|
|
75
|
-
pdf.text("Hello");
|
|
76
|
-
pdf.end();
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## What NOT to do
|
|
80
|
-
|
|
81
|
-
- **Don't use Pandoc, LibreOffice, or other CLI converters** unless the user specifically asks. The bundled npm packages are faster, more reliable, and don't require external binaries.
|
|
82
|
-
- **Don't try to generate documents from the sandbox host** — the packages live in Symi's own `node_modules` on the gateway host.
|
|
83
|
-
- **Don't dump 10KB of HTML and call it a "document"**. Use the structured generators above.
|
package/skills/eightctl/SKILL.md
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: eightctl
|
|
3
|
-
description: Control Eight Sleep pods (status, temperature, alarms, schedules).
|
|
4
|
-
homepage: https://eightctl.sh
|
|
5
|
-
metadata:
|
|
6
|
-
{
|
|
7
|
-
"symi":
|
|
8
|
-
{
|
|
9
|
-
"emoji": "🎛️",
|
|
10
|
-
"requires": { "bins": ["eightctl"] },
|
|
11
|
-
"install":
|
|
12
|
-
[
|
|
13
|
-
{
|
|
14
|
-
"id": "go",
|
|
15
|
-
"kind": "go",
|
|
16
|
-
"module": "github.com/steipete/eightctl/cmd/eightctl@latest",
|
|
17
|
-
"bins": ["eightctl"],
|
|
18
|
-
"label": "Install eightctl (go)",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
triggers: [eightctl]
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
# eightctl
|
|
27
|
-
|
|
28
|
-
Use `eightctl` for Eight Sleep pod control. Requires auth.
|
|
29
|
-
|
|
30
|
-
Auth
|
|
31
|
-
|
|
32
|
-
- Config: `~/.config/eightctl/config.yaml`
|
|
33
|
-
- Env: `EIGHTCTL_EMAIL`, `EIGHTCTL_PASSWORD`
|
|
34
|
-
|
|
35
|
-
Quick start
|
|
36
|
-
|
|
37
|
-
- `eightctl status`
|
|
38
|
-
- `eightctl on|off`
|
|
39
|
-
- `eightctl temp 20`
|
|
40
|
-
|
|
41
|
-
Common tasks
|
|
42
|
-
|
|
43
|
-
- Alarms: `eightctl alarm list|create|dismiss`
|
|
44
|
-
- Schedules: `eightctl schedule list|create|update`
|
|
45
|
-
- Audio: `eightctl audio state|play|pause`
|
|
46
|
-
- Base: `eightctl base info|angle`
|
|
47
|
-
|
|
48
|
-
Notes
|
|
49
|
-
|
|
50
|
-
- API is unofficial and rate-limited; avoid repeated logins.
|
|
51
|
-
- Confirm before changing temperature or alarms.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: food-order
|
|
3
|
-
description: Reorder Foodora orders + track ETA/status with ordercli. Never confirm without explicit user approval. Triggers: order food, reorder, track ETA.
|
|
4
|
-
homepage: https://ordercli.sh
|
|
5
|
-
metadata: {"symi":{"emoji":"🥡","requires":{"bins":["ordercli"]},"install":[{"id":"go","kind":"go","module":"github.com/steipete/ordercli/cmd/ordercli@latest","bins":["ordercli"],"label":"Install ordercli (go)"}]}}
|
|
6
|
-
triggers: [food-order, food, order]
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Food order (Foodora via ordercli)
|
|
10
|
-
|
|
11
|
-
Goal: reorder a previous Foodora order safely (preview first; confirm only on explicit user “yes/confirm/place the order”).
|
|
12
|
-
|
|
13
|
-
Hard safety rules
|
|
14
|
-
|
|
15
|
-
- Never run `ordercli foodora reorder ... --confirm` unless user explicitly confirms placing the order.
|
|
16
|
-
- Prefer preview-only steps first; show what will happen; ask for confirmation.
|
|
17
|
-
- If user is unsure: stop at preview and ask questions.
|
|
18
|
-
|
|
19
|
-
Setup (once)
|
|
20
|
-
|
|
21
|
-
- Country: `ordercli foodora countries` → `ordercli foodora config set --country AT`
|
|
22
|
-
- Login (password): `ordercli foodora login --email you@example.com --password-stdin`
|
|
23
|
-
- Login (no password, preferred): `ordercli foodora session chrome --url https://www.foodora.at/ --profile "Default"`
|
|
24
|
-
|
|
25
|
-
Find what to reorder
|
|
26
|
-
|
|
27
|
-
- Recent list: `ordercli foodora history --limit 10`
|
|
28
|
-
- Details: `ordercli foodora history show <orderCode>`
|
|
29
|
-
- If needed (machine-readable): `ordercli foodora history show <orderCode> --json`
|
|
30
|
-
|
|
31
|
-
Preview reorder (no cart changes)
|
|
32
|
-
|
|
33
|
-
- `ordercli foodora reorder <orderCode>`
|
|
34
|
-
|
|
35
|
-
Place reorder (cart change; explicit confirmation required)
|
|
36
|
-
|
|
37
|
-
- Confirm first, then run: `ordercli foodora reorder <orderCode> --confirm`
|
|
38
|
-
- Multiple addresses? Ask user for the right `--address-id` (take from their Foodora account / prior order data) and run:
|
|
39
|
-
- `ordercli foodora reorder <orderCode> --confirm --address-id <id>`
|
|
40
|
-
|
|
41
|
-
Track the order
|
|
42
|
-
|
|
43
|
-
- ETA/status (active list): `ordercli foodora orders`
|
|
44
|
-
- Live updates: `ordercli foodora orders --watch`
|
|
45
|
-
- Single order detail: `ordercli foodora order <orderCode>`
|
|
46
|
-
|
|
47
|
-
Debug / safe testing
|
|
48
|
-
|
|
49
|
-
- Use a throwaway config: `ordercli --config /tmp/ordercli.json ...`
|
package/skills/gemini/SKILL.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: gemini
|
|
3
|
-
description: Gemini CLI for one-shot Q&A, summaries, and generation.
|
|
4
|
-
homepage: https://ai.google.dev/
|
|
5
|
-
metadata:
|
|
6
|
-
{
|
|
7
|
-
"symi":
|
|
8
|
-
{
|
|
9
|
-
"emoji": "♊️",
|
|
10
|
-
"requires": { "bins": ["gemini"] },
|
|
11
|
-
"install":
|
|
12
|
-
[
|
|
13
|
-
{
|
|
14
|
-
"id": "brew",
|
|
15
|
-
"kind": "brew",
|
|
16
|
-
"formula": "gemini-cli",
|
|
17
|
-
"bins": ["gemini"],
|
|
18
|
-
"label": "Install Gemini CLI (brew)",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
triggers: [gemini]
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
# Gemini CLI
|
|
27
|
-
|
|
28
|
-
Use Gemini in one-shot mode with a positional prompt (avoid interactive mode).
|
|
29
|
-
|
|
30
|
-
Quick start
|
|
31
|
-
|
|
32
|
-
- `gemini "Answer this question..."`
|
|
33
|
-
- `gemini --model <name> "Prompt..."`
|
|
34
|
-
- `gemini --output-format json "Return JSON"`
|
|
35
|
-
|
|
36
|
-
Extensions
|
|
37
|
-
|
|
38
|
-
- List: `gemini --list-extensions`
|
|
39
|
-
- Manage: `gemini extensions <command>`
|
|
40
|
-
|
|
41
|
-
Notes
|
|
42
|
-
|
|
43
|
-
- If auth is required, run `gemini` once interactively and follow the login flow.
|
|
44
|
-
- Avoid `--yolo` for safety.
|