@symerian/symi 3.0.17 → 3.0.19
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/extensions/copilot-proxy/README.md +0 -24
- package/extensions/copilot-proxy/index.ts +0 -154
- package/extensions/copilot-proxy/node_modules/.bin/symi +0 -21
- package/extensions/copilot-proxy/package.json +0 -15
- package/extensions/copilot-proxy/symi.plugin.json +0 -9
- package/extensions/device-pair/index.ts +0 -642
- package/extensions/device-pair/symi.plugin.json +0 -20
- package/extensions/diagnostics-otel/index.ts +0 -15
- package/extensions/diagnostics-otel/node_modules/.bin/acorn +0 -21
- package/extensions/diagnostics-otel/node_modules/.bin/symi +0 -21
- package/extensions/diagnostics-otel/package.json +0 -27
- package/extensions/diagnostics-otel/src/service.test.ts +0 -290
- package/extensions/diagnostics-otel/src/service.ts +0 -666
- package/extensions/diagnostics-otel/symi.plugin.json +0 -8
- package/extensions/google-antigravity-auth/README.md +0 -24
- package/extensions/google-antigravity-auth/index.ts +0 -424
- package/extensions/google-antigravity-auth/node_modules/.bin/symi +0 -21
- package/extensions/google-antigravity-auth/package.json +0 -15
- package/extensions/google-antigravity-auth/symi.plugin.json +0 -9
- package/extensions/google-gemini-cli-auth/README.md +0 -35
- package/extensions/google-gemini-cli-auth/index.ts +0 -75
- package/extensions/google-gemini-cli-auth/node_modules/.bin/symi +0 -21
- package/extensions/google-gemini-cli-auth/oauth.test.ts +0 -162
- package/extensions/google-gemini-cli-auth/oauth.ts +0 -636
- package/extensions/google-gemini-cli-auth/package.json +0 -15
- package/extensions/google-gemini-cli-auth/symi.plugin.json +0 -9
- package/extensions/learning-loop/index.ts +0 -159
- package/extensions/learning-loop/node_modules/.bin/symi +0 -21
- package/extensions/learning-loop/package.json +0 -18
- package/extensions/learning-loop/src/analytics/gateway-methods.ts +0 -230
- package/extensions/learning-loop/src/analytics/metrics-aggregator.ts +0 -153
- package/extensions/learning-loop/src/capture/run-tracker.ts +0 -181
- package/extensions/learning-loop/src/capture/serializer.ts +0 -74
- package/extensions/learning-loop/src/db.ts +0 -583
- package/extensions/learning-loop/src/feedback/explicit-feedback.ts +0 -58
- package/extensions/learning-loop/src/feedback/implicit-signals.ts +0 -89
- package/extensions/learning-loop/src/graph/edge-inference.ts +0 -189
- package/extensions/learning-loop/src/graph/graph-retrieval.ts +0 -144
- package/extensions/learning-loop/src/graph/graph-store.ts +0 -183
- package/extensions/learning-loop/src/hooks.ts +0 -244
- package/extensions/learning-loop/src/injection/cache.ts +0 -73
- package/extensions/learning-loop/src/injection/context-injector.ts +0 -104
- package/extensions/learning-loop/src/injection/prompt-builder.ts +0 -43
- package/extensions/learning-loop/src/learning/embedding-bridge.ts +0 -54
- package/extensions/learning-loop/src/learning/learning-extractor.ts +0 -217
- package/extensions/learning-loop/src/learning/learning-store.ts +0 -158
- package/extensions/learning-loop/src/learning/retrieval.ts +0 -87
- package/extensions/learning-loop/src/math/confidence-intervals.ts +0 -62
- package/extensions/learning-loop/src/math/ewma.ts +0 -51
- package/extensions/learning-loop/src/math/weighted-scorer.ts +0 -42
- package/extensions/learning-loop/src/schema.ts +0 -176
- package/extensions/learning-loop/src/scoring/normalization.ts +0 -32
- package/extensions/learning-loop/src/scoring/quality-engine.ts +0 -78
- package/extensions/learning-loop/src/scoring/signal-extractors.ts +0 -155
- package/extensions/learning-loop/src/test/context-injector.test.ts +0 -142
- package/extensions/learning-loop/src/test/fixes.test.ts +0 -1286
- package/extensions/learning-loop/src/test/graph.test.ts +0 -711
- package/extensions/learning-loop/src/test/integration.test.ts +0 -312
- package/extensions/learning-loop/src/test/learning-store.test.ts +0 -191
- package/extensions/learning-loop/src/test/math.test.ts +0 -148
- package/extensions/learning-loop/src/test/quality-engine.test.ts +0 -231
- package/extensions/learning-loop/src/test/run-tracker.test.ts +0 -143
- package/extensions/learning-loop/src/types.ts +0 -281
- package/extensions/learning-loop/symi.plugin.json +0 -46
- package/extensions/llm-task/README.md +0 -97
- package/extensions/llm-task/index.ts +0 -6
- package/extensions/llm-task/package.json +0 -12
- package/extensions/llm-task/src/llm-task-tool.test.ts +0 -138
- package/extensions/llm-task/src/llm-task-tool.ts +0 -249
- package/extensions/llm-task/symi.plugin.json +0 -21
- package/extensions/memory-lancedb/config.ts +0 -161
- package/extensions/memory-lancedb/index.test.ts +0 -330
- package/extensions/memory-lancedb/index.ts +0 -670
- package/extensions/memory-lancedb/node_modules/.bin/arrow2csv +0 -21
- package/extensions/memory-lancedb/node_modules/.bin/openai +0 -21
- package/extensions/memory-lancedb/node_modules/.bin/symi +0 -21
- package/extensions/memory-lancedb/package.json +0 -20
- package/extensions/memory-lancedb/symi.plugin.json +0 -71
- package/extensions/minimax-portal-auth/README.md +0 -33
- package/extensions/minimax-portal-auth/index.ts +0 -161
- package/extensions/minimax-portal-auth/node_modules/.bin/symi +0 -21
- package/extensions/minimax-portal-auth/oauth.ts +0 -247
- package/extensions/minimax-portal-auth/package.json +0 -15
- package/extensions/minimax-portal-auth/symi.plugin.json +0 -9
- package/extensions/model-equalizer/index.ts +0 -80
- package/extensions/model-equalizer/skills/model-equalizer/SKILL.md +0 -58
- package/extensions/model-equalizer/src/detection.ts +0 -62
- package/extensions/model-equalizer/src/enhancer.ts +0 -63
- package/extensions/model-equalizer/src/test/detection.test.ts +0 -218
- package/extensions/model-equalizer/src/test/enhancer.test.ts +0 -137
- package/extensions/model-equalizer/src/test/integration.test.ts +0 -185
- package/extensions/model-equalizer/src/types.ts +0 -24
- package/extensions/model-equalizer/symi.plugin.json +0 -12
- package/extensions/phone-control/index.ts +0 -421
- package/extensions/phone-control/symi.plugin.json +0 -10
- package/extensions/pipeline/README.md +0 -75
- package/extensions/pipeline/SKILL.md +0 -97
- package/extensions/pipeline/index.ts +0 -18
- package/extensions/pipeline/package.json +0 -11
- package/extensions/pipeline/src/pipeline-tool.test.ts +0 -345
- package/extensions/pipeline/src/pipeline-tool.ts +0 -266
- package/extensions/pipeline/src/windows-spawn.test.ts +0 -148
- package/extensions/pipeline/src/windows-spawn.ts +0 -193
- package/extensions/pipeline/symi.plugin.json +0 -10
- package/extensions/qwen-portal-auth/README.md +0 -24
- package/extensions/qwen-portal-auth/index.ts +0 -134
- package/extensions/qwen-portal-auth/oauth.ts +0 -190
- package/extensions/qwen-portal-auth/symi.plugin.json +0 -9
- package/extensions/talk-voice/index.ts +0 -150
- package/extensions/talk-voice/symi.plugin.json +0 -10
- package/extensions/thread-ownership/index.test.ts +0 -180
- package/extensions/thread-ownership/index.ts +0 -133
- package/extensions/thread-ownership/symi.plugin.json +0 -28
- 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
package/skills/blucli/SKILL.md
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: blucli
|
|
3
|
-
description: BluOS CLI (blu) for discovery, playback, grouping, and volume.
|
|
4
|
-
homepage: https://blucli.sh
|
|
5
|
-
metadata:
|
|
6
|
-
{
|
|
7
|
-
"symi":
|
|
8
|
-
{
|
|
9
|
-
"emoji": "🫐",
|
|
10
|
-
"requires": { "bins": ["blu"] },
|
|
11
|
-
"install":
|
|
12
|
-
[
|
|
13
|
-
{
|
|
14
|
-
"id": "go",
|
|
15
|
-
"kind": "go",
|
|
16
|
-
"module": "github.com/steipete/blucli/cmd/blu@latest",
|
|
17
|
-
"bins": ["blu"],
|
|
18
|
-
"label": "Install blucli (go)",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
triggers: [blucli]
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
# blucli (blu)
|
|
27
|
-
|
|
28
|
-
Use `blu` to control Bluesound/NAD players.
|
|
29
|
-
|
|
30
|
-
Quick start
|
|
31
|
-
|
|
32
|
-
- `blu devices` (pick target)
|
|
33
|
-
- `blu --device <id> status`
|
|
34
|
-
- `blu play|pause|stop`
|
|
35
|
-
- `blu volume set 15`
|
|
36
|
-
|
|
37
|
-
Target selection (in priority order)
|
|
38
|
-
|
|
39
|
-
- `--device <id|name|alias>`
|
|
40
|
-
- `BLU_DEVICE`
|
|
41
|
-
- config default (if set)
|
|
42
|
-
|
|
43
|
-
Common tasks
|
|
44
|
-
|
|
45
|
-
- Grouping: `blu group status|add|remove`
|
|
46
|
-
- TuneIn search/play: `blu tunein search "query"`, `blu tunein play "query"`
|
|
47
|
-
|
|
48
|
-
Prefer `--json` for scripts. Confirm the target device before changing playback.
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: bluebubbles
|
|
3
|
-
description: Use when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="bluebubbles".
|
|
4
|
-
metadata: { "symi": { "emoji": "🫧", "requires": { "config": ["channels.bluebubbles"] } } }
|
|
5
|
-
triggers: [bluebubbles]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# BlueBubbles Actions
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
BlueBubbles is Symi’s recommended iMessage integration. Use the `message` tool with `channel: "bluebubbles"` to send messages and manage iMessage conversations: send texts and attachments, react (tapbacks), edit/unsend, reply in threads, and manage group participants/names/icons.
|
|
13
|
-
|
|
14
|
-
## Inputs to collect
|
|
15
|
-
|
|
16
|
-
- `target` (prefer `chat_guid:...`; also `+15551234567` in E.164 or `user@example.com`)
|
|
17
|
-
- `message` text for send/edit/reply
|
|
18
|
-
- `messageId` for react/edit/unsend/reply
|
|
19
|
-
- Attachment `path` for local files, or `buffer` + `filename` for base64
|
|
20
|
-
|
|
21
|
-
If the user is vague ("text my mom"), ask for the recipient handle or chat guid and the exact message content.
|
|
22
|
-
|
|
23
|
-
## Actions
|
|
24
|
-
|
|
25
|
-
### Send a message
|
|
26
|
-
|
|
27
|
-
```json
|
|
28
|
-
{
|
|
29
|
-
"action": "send",
|
|
30
|
-
"channel": "bluebubbles",
|
|
31
|
-
"target": "+15551234567",
|
|
32
|
-
"message": "hello from Symi"
|
|
33
|
-
}
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### React (tapback)
|
|
37
|
-
|
|
38
|
-
```json
|
|
39
|
-
{
|
|
40
|
-
"action": "react",
|
|
41
|
-
"channel": "bluebubbles",
|
|
42
|
-
"target": "+15551234567",
|
|
43
|
-
"messageId": "<message-guid>",
|
|
44
|
-
"emoji": "❤️"
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Remove a reaction
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"action": "react",
|
|
53
|
-
"channel": "bluebubbles",
|
|
54
|
-
"target": "+15551234567",
|
|
55
|
-
"messageId": "<message-guid>",
|
|
56
|
-
"emoji": "❤️",
|
|
57
|
-
"remove": true
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Edit a previously sent message
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{
|
|
65
|
-
"action": "edit",
|
|
66
|
-
"channel": "bluebubbles",
|
|
67
|
-
"target": "+15551234567",
|
|
68
|
-
"messageId": "<message-guid>",
|
|
69
|
-
"message": "updated text"
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Unsend a message
|
|
74
|
-
|
|
75
|
-
```json
|
|
76
|
-
{
|
|
77
|
-
"action": "unsend",
|
|
78
|
-
"channel": "bluebubbles",
|
|
79
|
-
"target": "+15551234567",
|
|
80
|
-
"messageId": "<message-guid>"
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Reply to a specific message
|
|
85
|
-
|
|
86
|
-
```json
|
|
87
|
-
{
|
|
88
|
-
"action": "reply",
|
|
89
|
-
"channel": "bluebubbles",
|
|
90
|
-
"target": "+15551234567",
|
|
91
|
-
"replyTo": "<message-guid>",
|
|
92
|
-
"message": "replying to that"
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Send an attachment
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"action": "sendAttachment",
|
|
101
|
-
"channel": "bluebubbles",
|
|
102
|
-
"target": "+15551234567",
|
|
103
|
-
"path": "/tmp/photo.jpg",
|
|
104
|
-
"caption": "here you go"
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### Send with an iMessage effect
|
|
109
|
-
|
|
110
|
-
```json
|
|
111
|
-
{
|
|
112
|
-
"action": "sendWithEffect",
|
|
113
|
-
"channel": "bluebubbles",
|
|
114
|
-
"target": "+15551234567",
|
|
115
|
-
"message": "big news",
|
|
116
|
-
"effect": "balloons"
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Notes
|
|
121
|
-
|
|
122
|
-
- Requires gateway config `channels.bluebubbles` (serverUrl/password/webhookPath).
|
|
123
|
-
- Prefer `chat_guid` targets when you have them (especially for group chats).
|
|
124
|
-
- BlueBubbles supports rich actions, but some are macOS-version dependent (for example, edit may be broken on macOS 26 Tahoe).
|
|
125
|
-
- The gateway may expose both short and full message ids; full ids are more durable across restarts.
|
|
126
|
-
- Developer reference for the underlying plugin lives in `extensions/bluebubbles/README.md`.
|
|
127
|
-
|
|
128
|
-
## Ideas to try
|
|
129
|
-
|
|
130
|
-
- React with a tapback to acknowledge a request.
|
|
131
|
-
- Reply in-thread when a user references a specific message.
|
|
132
|
-
- Send a file attachment with a short caption.
|
package/skills/camsnap/SKILL.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: camsnap
|
|
3
|
-
description: Capture frames or clips from RTSP/ONVIF cameras.
|
|
4
|
-
homepage: https://camsnap.ai
|
|
5
|
-
metadata:
|
|
6
|
-
{
|
|
7
|
-
"symi":
|
|
8
|
-
{
|
|
9
|
-
"emoji": "📸",
|
|
10
|
-
"requires": { "bins": ["camsnap"] },
|
|
11
|
-
"install":
|
|
12
|
-
[
|
|
13
|
-
{
|
|
14
|
-
"id": "brew",
|
|
15
|
-
"kind": "brew",
|
|
16
|
-
"formula": "steipete/tap/camsnap",
|
|
17
|
-
"bins": ["camsnap"],
|
|
18
|
-
"label": "Install camsnap (brew)",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
triggers: [camsnap]
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
# camsnap
|
|
27
|
-
|
|
28
|
-
Use `camsnap` to grab snapshots, clips, or motion events from configured cameras.
|
|
29
|
-
|
|
30
|
-
Setup
|
|
31
|
-
|
|
32
|
-
- Config file: `~/.config/camsnap/config.yaml`
|
|
33
|
-
- Add camera: `camsnap add --name kitchen --host 192.168.0.10 --user user --pass pass`
|
|
34
|
-
|
|
35
|
-
Common commands
|
|
36
|
-
|
|
37
|
-
- Discover: `camsnap discover --info`
|
|
38
|
-
- Snapshot: `camsnap snap kitchen --out shot.jpg`
|
|
39
|
-
- Clip: `camsnap clip kitchen --dur 5s --out clip.mp4`
|
|
40
|
-
- Motion watch: `camsnap watch kitchen --threshold 0.2 --action '...'`
|
|
41
|
-
- Doctor: `camsnap doctor --probe`
|
|
42
|
-
|
|
43
|
-
Notes
|
|
44
|
-
|
|
45
|
-
- Requires `ffmpeg` on PATH.
|
|
46
|
-
- Prefer a short test capture before longer clips.
|
package/skills/canvas/SKILL.md
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: canvas
|
|
3
|
-
description: Display HTML content on connected Symi nodes (Mac app, iOS, Android). Use for games, visualizations, dashboards, generated HTML, and interactive demos.
|
|
4
|
-
triggers: [canvas, display, html, visualize, dashboard, demo]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Canvas Skill
|
|
8
|
-
|
|
9
|
-
Display HTML content on connected Symi nodes (Mac app, iOS, Android).
|
|
10
|
-
|
|
11
|
-
## Overview
|
|
12
|
-
|
|
13
|
-
The canvas tool lets you present web content on any connected node's canvas view. Great for:
|
|
14
|
-
|
|
15
|
-
- Displaying games, visualizations, dashboards
|
|
16
|
-
- Showing generated HTML content
|
|
17
|
-
- Interactive demos
|
|
18
|
-
|
|
19
|
-
## How It Works
|
|
20
|
-
|
|
21
|
-
### Architecture
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
|
|
25
|
-
│ Canvas Host │────▶│ Node Bridge │────▶│ Node App │
|
|
26
|
-
│ (HTTP Server) │ │ (TCP Server) │ │ (Mac/iOS/ │
|
|
27
|
-
│ Port 18793 │ │ Port 18790 │ │ Android) │
|
|
28
|
-
└─────────────────┘ └──────────────────┘ └─────────────┘
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
1. **Canvas Host Server**: Serves static HTML/CSS/JS files from `canvasHost.root` directory
|
|
32
|
-
2. **Node Bridge**: Communicates canvas URLs to connected nodes
|
|
33
|
-
3. **Node Apps**: Render the content in a WebView
|
|
34
|
-
|
|
35
|
-
### Tailscale Integration
|
|
36
|
-
|
|
37
|
-
The canvas host server binds based on `gateway.bind` setting:
|
|
38
|
-
|
|
39
|
-
| Bind Mode | Server Binds To | Canvas URL Uses |
|
|
40
|
-
| ---------- | ------------------- | -------------------------- |
|
|
41
|
-
| `loopback` | 127.0.0.1 | localhost (local only) |
|
|
42
|
-
| `lan` | LAN interface | LAN IP address |
|
|
43
|
-
| `tailnet` | Tailscale interface | Tailscale hostname |
|
|
44
|
-
| `auto` | Best available | Tailscale > LAN > loopback |
|
|
45
|
-
|
|
46
|
-
**Key insight:** The `canvasHostHostForBridge` is derived from `bridgeHost`. When bound to Tailscale, nodes receive URLs like:
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
http://<tailscale-hostname>:18793/__symi__/canvas/<file>.html
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This is why localhost URLs don't work - the node receives the Tailscale hostname from the bridge!
|
|
53
|
-
|
|
54
|
-
## Actions
|
|
55
|
-
|
|
56
|
-
| Action | Description |
|
|
57
|
-
| ---------- | ------------------------------------ |
|
|
58
|
-
| `present` | Show canvas with optional target URL |
|
|
59
|
-
| `hide` | Hide the canvas |
|
|
60
|
-
| `navigate` | Navigate to a new URL |
|
|
61
|
-
| `eval` | Execute JavaScript in the canvas |
|
|
62
|
-
| `snapshot` | Capture screenshot of canvas |
|
|
63
|
-
|
|
64
|
-
## Configuration
|
|
65
|
-
|
|
66
|
-
In `~/.symi/symi.json`:
|
|
67
|
-
|
|
68
|
-
```json
|
|
69
|
-
{
|
|
70
|
-
"canvasHost": {
|
|
71
|
-
"enabled": true,
|
|
72
|
-
"port": 18793,
|
|
73
|
-
"root": "/Users/you/symi/canvas",
|
|
74
|
-
"liveReload": true
|
|
75
|
-
},
|
|
76
|
-
"gateway": {
|
|
77
|
-
"bind": "auto"
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Live Reload
|
|
83
|
-
|
|
84
|
-
When `liveReload: true` (default), the canvas host:
|
|
85
|
-
|
|
86
|
-
- Watches the root directory for changes (via chokidar)
|
|
87
|
-
- Injects a WebSocket client into HTML files
|
|
88
|
-
- Automatically reloads connected canvases when files change
|
|
89
|
-
|
|
90
|
-
Great for development!
|
|
91
|
-
|
|
92
|
-
## Workflow
|
|
93
|
-
|
|
94
|
-
### 1. Create HTML content
|
|
95
|
-
|
|
96
|
-
Place files in the canvas root directory (default `~/symi/canvas/`):
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
cat > ~/symi/canvas/my-game.html << 'HTML'
|
|
100
|
-
<!DOCTYPE html>
|
|
101
|
-
<html>
|
|
102
|
-
<head><title>My Game</title></head>
|
|
103
|
-
<body>
|
|
104
|
-
<h1>Hello Canvas!</h1>
|
|
105
|
-
</body>
|
|
106
|
-
</html>
|
|
107
|
-
HTML
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### 2. Find your canvas host URL
|
|
111
|
-
|
|
112
|
-
Check how your gateway is bound:
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
|
-
cat ~/.symi/symi.json | jq '.gateway.bind'
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Then construct the URL:
|
|
119
|
-
|
|
120
|
-
- **loopback**: `http://127.0.0.1:18793/__symi__/canvas/<file>.html`
|
|
121
|
-
- **lan/tailnet/auto**: `http://<hostname>:18793/__symi__/canvas/<file>.html`
|
|
122
|
-
|
|
123
|
-
Find your Tailscale hostname:
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//'
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### 3. Find connected nodes
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
symi nodes list
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Look for Mac/iOS/Android nodes with canvas capability.
|
|
136
|
-
|
|
137
|
-
### 4. Present content
|
|
138
|
-
|
|
139
|
-
```
|
|
140
|
-
canvas action:present node:<node-id> target:<full-url>
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
**Example:**
|
|
144
|
-
|
|
145
|
-
```
|
|
146
|
-
canvas action:present node:mac-63599bc4-b54d-4392-9048-b97abd58343a target:http://peters-mac-studio-1.sheep-coho.ts.net:18793/__symi__/canvas/snake.html
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### 5. Navigate, snapshot, or hide
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
canvas action:navigate node:<node-id> url:<new-url>
|
|
153
|
-
canvas action:snapshot node:<node-id>
|
|
154
|
-
canvas action:hide node:<node-id>
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## Debugging
|
|
158
|
-
|
|
159
|
-
### White screen / content not loading
|
|
160
|
-
|
|
161
|
-
**Cause:** URL mismatch between server bind and node expectation.
|
|
162
|
-
|
|
163
|
-
**Debug steps:**
|
|
164
|
-
|
|
165
|
-
1. Check server bind: `cat ~/.symi/symi.json | jq '.gateway.bind'`
|
|
166
|
-
2. Check what port canvas is on: `lsof -i :18793`
|
|
167
|
-
3. Test URL directly: `curl http://<hostname>:18793/__symi__/canvas/<file>.html`
|
|
168
|
-
|
|
169
|
-
**Solution:** Use the full hostname matching your bind mode, not localhost.
|
|
170
|
-
|
|
171
|
-
### "node required" error
|
|
172
|
-
|
|
173
|
-
Always specify `node:<node-id>` parameter.
|
|
174
|
-
|
|
175
|
-
### "node not connected" error
|
|
176
|
-
|
|
177
|
-
Node is offline. Use `symi nodes list` to find online nodes.
|
|
178
|
-
|
|
179
|
-
### Content not updating
|
|
180
|
-
|
|
181
|
-
If live reload isn't working:
|
|
182
|
-
|
|
183
|
-
1. Check `liveReload: true` in config
|
|
184
|
-
2. Ensure file is in the canvas root directory
|
|
185
|
-
3. Check for watcher errors in logs
|
|
186
|
-
|
|
187
|
-
## URL Path Structure
|
|
188
|
-
|
|
189
|
-
The canvas host serves from `/__symi__/canvas/` prefix:
|
|
190
|
-
|
|
191
|
-
```
|
|
192
|
-
http://<host>:18793/__symi__/canvas/index.html → ~/symi/canvas/index.html
|
|
193
|
-
http://<host>:18793/__symi__/canvas/games/snake.html → ~/symi/canvas/games/snake.html
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
The `/__symi__/canvas/` prefix is defined by `CANVAS_HOST_PATH` constant.
|
|
197
|
-
|
|
198
|
-
## Tips
|
|
199
|
-
|
|
200
|
-
- Keep HTML self-contained (inline CSS/JS) for best results
|
|
201
|
-
- Use the default index.html as a test page (has bridge diagnostics)
|
|
202
|
-
- The canvas persists until you `hide` it or navigate away
|
|
203
|
-
- Live reload makes development fast - just save and it updates!
|
|
204
|
-
- A2UI JSON push is WIP - use HTML files for now
|
|
@@ -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.
|