mercury-agent 0.4.5

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.
Files changed (218) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +438 -0
  3. package/container/Dockerfile +127 -0
  4. package/container/Dockerfile.base +109 -0
  5. package/container/Dockerfile.power +17 -0
  6. package/container/agent-package.json +8 -0
  7. package/container/build.sh +54 -0
  8. package/docs/TODOS.md +147 -0
  9. package/docs/auth/dashboard.md +28 -0
  10. package/docs/auth/overview.md +109 -0
  11. package/docs/auth/whatsapp.md +173 -0
  12. package/docs/configuration.md +54 -0
  13. package/docs/container-lifecycle.md +349 -0
  14. package/docs/context-architecture.md +87 -0
  15. package/docs/deployment.md +199 -0
  16. package/docs/extensions.md +375 -0
  17. package/docs/graceful-shutdown.md +62 -0
  18. package/docs/kb-distillation.md +77 -0
  19. package/docs/media/overview.md +140 -0
  20. package/docs/media/whatsapp.md +171 -0
  21. package/docs/memory.md +137 -0
  22. package/docs/permissions.md +217 -0
  23. package/docs/pipeline.md +228 -0
  24. package/docs/prd-chat-memory.md +76 -0
  25. package/docs/prd-config-load.md +82 -0
  26. package/docs/rate-limiting.md +166 -0
  27. package/docs/scheduler.md +288 -0
  28. package/docs/setup-discord.md +100 -0
  29. package/docs/setup-slack.md +119 -0
  30. package/docs/setup-whatsapp.md +94 -0
  31. package/docs/subagents.md +166 -0
  32. package/docs/web-search.md +62 -0
  33. package/examples/extensions/README.md +12 -0
  34. package/examples/extensions/charts/index.ts +13 -0
  35. package/examples/extensions/charts/skill/SKILL.md +98 -0
  36. package/examples/extensions/gws/README.md +52 -0
  37. package/examples/extensions/gws/index.ts +106 -0
  38. package/examples/extensions/gws/skill/SKILL.md +57 -0
  39. package/examples/extensions/gws/skill/references/calendar.md +101 -0
  40. package/examples/extensions/gws/skill/references/docs.md +65 -0
  41. package/examples/extensions/gws/skill/references/drive.md +79 -0
  42. package/examples/extensions/gws/skill/references/gmail.md +85 -0
  43. package/examples/extensions/gws/skill/references/sheets.md +60 -0
  44. package/examples/extensions/napkin/index.ts +821 -0
  45. package/examples/extensions/napkin/prompts/consolidation-monthly.md +73 -0
  46. package/examples/extensions/napkin/prompts/consolidation-weekly.md +67 -0
  47. package/examples/extensions/napkin/prompts/kb-distillation.md +176 -0
  48. package/examples/extensions/napkin/skill/SKILL.md +728 -0
  49. package/examples/extensions/pdf/index.ts +23 -0
  50. package/examples/extensions/pdf/skill/LICENSE.txt +30 -0
  51. package/examples/extensions/pdf/skill/SKILL.md +314 -0
  52. package/examples/extensions/pdf/skill/forms.md +294 -0
  53. package/examples/extensions/pdf/skill/reference.md +612 -0
  54. package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -0
  55. package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -0
  56. package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -0
  57. package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -0
  58. package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -0
  59. package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -0
  60. package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -0
  61. package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -0
  62. package/examples/extensions/permission-guard/index.ts +65 -0
  63. package/examples/extensions/pinchtab/index.ts +199 -0
  64. package/examples/extensions/pinchtab/lib/session-injector.ts +144 -0
  65. package/examples/extensions/pinchtab/skill/SKILL.md +224 -0
  66. package/examples/extensions/pinchtab/skill/TRUST.md +69 -0
  67. package/examples/extensions/pinchtab/skill/references/api.md +297 -0
  68. package/examples/extensions/pinchtab/skill/references/env.md +45 -0
  69. package/examples/extensions/pinchtab/skill/references/profiles.md +107 -0
  70. package/examples/extensions/tradestation/host/refresh.ts +102 -0
  71. package/examples/extensions/tradestation/index.ts +153 -0
  72. package/examples/extensions/tradestation/skill/SKILL.md +67 -0
  73. package/examples/extensions/tradestation/skill/scripts/ts-cli.ts +111 -0
  74. package/examples/extensions/voice-synth/index.ts +94 -0
  75. package/examples/extensions/voice-synth/skill/SKILL.md +38 -0
  76. package/examples/extensions/voice-transcribe/index.ts +381 -0
  77. package/examples/extensions/voice-transcribe/requirements.txt +8 -0
  78. package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -0
  79. package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -0
  80. package/examples/extensions/web-search/index.ts +22 -0
  81. package/examples/extensions/web-search/skill/SKILL.md +114 -0
  82. package/examples/extensions/web-search/skill/references/apartments.md +178 -0
  83. package/examples/extensions/web-search/skill/references/car-purchase.md +132 -0
  84. package/examples/extensions/web-search/skill/references/car-rental.md +113 -0
  85. package/examples/extensions/web-search/skill/references/flights.md +133 -0
  86. package/examples/extensions/web-search/skill/references/hotels.md +148 -0
  87. package/examples/extensions/yahoo-mail/cli/bun.lock +66 -0
  88. package/examples/extensions/yahoo-mail/cli/package.json +13 -0
  89. package/examples/extensions/yahoo-mail/cli/ymail.mjs +353 -0
  90. package/examples/extensions/yahoo-mail/index.ts +57 -0
  91. package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -0
  92. package/package.json +106 -0
  93. package/resources/agents/explore.md +50 -0
  94. package/resources/agents/worker.md +24 -0
  95. package/resources/builtin-extensions.txt +3 -0
  96. package/resources/connection-env-vars.json +25 -0
  97. package/resources/extensions/.gitkeep +0 -0
  98. package/resources/pi-extensions/subagent/agents.ts +126 -0
  99. package/resources/pi-extensions/subagent/index.ts +964 -0
  100. package/resources/profiles/coding/AGENTS.md +43 -0
  101. package/resources/profiles/coding/mercury-profile.yaml +15 -0
  102. package/resources/profiles/general/AGENTS.md +31 -0
  103. package/resources/profiles/general/mercury-profile.yaml +15 -0
  104. package/resources/profiles/research/AGENTS.md +40 -0
  105. package/resources/profiles/research/mercury-profile.yaml +15 -0
  106. package/resources/skills/config/SKILL.md +25 -0
  107. package/resources/skills/context/SKILL.md +33 -0
  108. package/resources/skills/conversation-recap/SKILL.md +19 -0
  109. package/resources/skills/media/SKILL.md +27 -0
  110. package/resources/skills/mutes/SKILL.md +31 -0
  111. package/resources/skills/permissions/SKILL.md +19 -0
  112. package/resources/skills/preferences/SKILL.md +31 -0
  113. package/resources/skills/recall/SKILL.md +24 -0
  114. package/resources/skills/roles/SKILL.md +18 -0
  115. package/resources/skills/spaces/SKILL.md +18 -0
  116. package/resources/skills/tasks/SKILL.md +45 -0
  117. package/resources/templates/AGENTS.md +157 -0
  118. package/resources/templates/env.template +34 -0
  119. package/resources/templates/mercury.example.yaml +75 -0
  120. package/src/adapters/discord-native.ts +534 -0
  121. package/src/adapters/discord.ts +38 -0
  122. package/src/adapters/setup.ts +89 -0
  123. package/src/adapters/slack.ts +9 -0
  124. package/src/adapters/whatsapp-media.ts +337 -0
  125. package/src/adapters/whatsapp.ts +629 -0
  126. package/src/agent/api-socket.ts +127 -0
  127. package/src/agent/container-entry.ts +967 -0
  128. package/src/agent/container-error.ts +49 -0
  129. package/src/agent/container-runner.ts +1272 -0
  130. package/src/agent/model-capabilities-core.ts +23 -0
  131. package/src/agent/model-capabilities.ts +231 -0
  132. package/src/agent/pi-failure-class.ts +83 -0
  133. package/src/agent/pi-jsonl-parser.ts +306 -0
  134. package/src/agent/preferences-prompt.ts +20 -0
  135. package/src/agent/user-error-messages.ts +78 -0
  136. package/src/bridges/discord.ts +171 -0
  137. package/src/bridges/slack.ts +177 -0
  138. package/src/bridges/teams.ts +160 -0
  139. package/src/bridges/telegram.ts +571 -0
  140. package/src/bridges/whatsapp.ts +290 -0
  141. package/src/chat-shim.ts +259 -0
  142. package/src/cli/mercury.ts +2508 -0
  143. package/src/cli/mrctl-http.ts +27 -0
  144. package/src/cli/mrctl.ts +611 -0
  145. package/src/cli/whatsapp-auth.ts +260 -0
  146. package/src/config-file.ts +397 -0
  147. package/src/config-model-chain.ts +30 -0
  148. package/src/config.ts +316 -0
  149. package/src/core/api-types.ts +58 -0
  150. package/src/core/api.ts +105 -0
  151. package/src/core/commands.ts +76 -0
  152. package/src/core/conversation.ts +47 -0
  153. package/src/core/handler.ts +206 -0
  154. package/src/core/media.ts +200 -0
  155. package/src/core/mute-duration.ts +22 -0
  156. package/src/core/outbox.ts +76 -0
  157. package/src/core/permissions.ts +192 -0
  158. package/src/core/profiles.ts +245 -0
  159. package/src/core/rate-limiter.ts +127 -0
  160. package/src/core/router.ts +191 -0
  161. package/src/core/routes/chat.ts +172 -0
  162. package/src/core/routes/config-builtin.ts +107 -0
  163. package/src/core/routes/config.ts +81 -0
  164. package/src/core/routes/connections.ts +190 -0
  165. package/src/core/routes/console.ts +668 -0
  166. package/src/core/routes/control.ts +46 -0
  167. package/src/core/routes/conversations.ts +66 -0
  168. package/src/core/routes/dashboard.ts +2491 -0
  169. package/src/core/routes/extensions.ts +37 -0
  170. package/src/core/routes/index.ts +14 -0
  171. package/src/core/routes/media.ts +72 -0
  172. package/src/core/routes/messages.ts +37 -0
  173. package/src/core/routes/mutes.ts +89 -0
  174. package/src/core/routes/prefs.ts +95 -0
  175. package/src/core/routes/roles.ts +125 -0
  176. package/src/core/routes/spaces.ts +60 -0
  177. package/src/core/routes/storage.ts +126 -0
  178. package/src/core/routes/tasks.ts +189 -0
  179. package/src/core/routes/tradestation.ts +268 -0
  180. package/src/core/routes/tts.ts +51 -0
  181. package/src/core/runtime.ts +1140 -0
  182. package/src/core/space-queue.ts +103 -0
  183. package/src/core/storage-cleanup.ts +140 -0
  184. package/src/core/storage-guard.ts +24 -0
  185. package/src/core/task-scheduler.ts +132 -0
  186. package/src/core/telegram-format.ts +178 -0
  187. package/src/core/trigger.ts +142 -0
  188. package/src/dashboard/index.html +729 -0
  189. package/src/dashboard/tokens.css +53 -0
  190. package/src/extensions/api.ts +252 -0
  191. package/src/extensions/catalog.ts +117 -0
  192. package/src/extensions/config-registry.ts +83 -0
  193. package/src/extensions/context.ts +36 -0
  194. package/src/extensions/hooks.ts +156 -0
  195. package/src/extensions/image-builder.ts +617 -0
  196. package/src/extensions/installer.ts +306 -0
  197. package/src/extensions/jobs.ts +122 -0
  198. package/src/extensions/loader.ts +271 -0
  199. package/src/extensions/permission-guard.ts +52 -0
  200. package/src/extensions/reserved.ts +28 -0
  201. package/src/extensions/skills.ts +123 -0
  202. package/src/extensions/types.ts +462 -0
  203. package/src/logger.ts +174 -0
  204. package/src/main.ts +586 -0
  205. package/src/server.ts +391 -0
  206. package/src/storage/db.ts +1624 -0
  207. package/src/storage/memory.ts +45 -0
  208. package/src/storage/pi-auth.ts +95 -0
  209. package/src/text/markdown.ts +117 -0
  210. package/src/text/rtl.ts +38 -0
  211. package/src/tradestation/host-api.ts +77 -0
  212. package/src/tradestation/pending-orders.ts +69 -0
  213. package/src/tts/azure.ts +52 -0
  214. package/src/tts/google.ts +128 -0
  215. package/src/tts/index.ts +8 -0
  216. package/src/tts/language.ts +20 -0
  217. package/src/tts/synthesize.ts +133 -0
  218. package/src/types.ts +295 -0
@@ -0,0 +1,166 @@
1
+ # Subagents
2
+
3
+ Mercury supports delegating tasks to specialized sub-agents using pi's subagent extension. Each sub-agent runs in its own isolated context window, keeping the main conversation clean.
4
+
5
+ ## How It Works
6
+
7
+ When the agent invokes the `subagent` tool, it spawns a separate `pi` process with:
8
+ - Its own context window (isolated from main conversation)
9
+ - A specific system prompt (from the agent definition)
10
+ - Optionally a different model (e.g., Haiku for fast recon)
11
+
12
+ ```
13
+ Main Agent
14
+
15
+ └─► subagent tool
16
+
17
+ ├─► Spawn pi process
18
+ │ • --mode json
19
+ │ • --model <agent-model>
20
+ │ • --tools <agent-tools>
21
+ │ • --append-system-prompt <agent.md>
22
+
23
+ ├─► Stream messages back
24
+
25
+ └─► Return final output to main agent
26
+ ```
27
+
28
+ ## Built-in Agents
29
+
30
+ | Agent | Purpose | Model | Tools |
31
+ |-------|---------|-------|-------|
32
+ | `explore` | Fast codebase reconnaissance | Haiku | read, grep, find, ls, bash |
33
+ | `worker` | General-purpose tasks | Sonnet | all |
34
+
35
+ ### explore
36
+
37
+ Quickly investigates a codebase and returns structured findings. Outputs:
38
+ - Files retrieved with line ranges
39
+ - Key code snippets (types, interfaces, functions)
40
+ - Architecture overview
41
+ - Where to start
42
+
43
+ ### worker
44
+
45
+ General-purpose agent with full capabilities. Works autonomously and reports:
46
+ - What was done
47
+ - Files changed
48
+ - Notes for handoff
49
+
50
+ ## Execution Modes
51
+
52
+ ### Single Agent
53
+
54
+ Delegate one task to one agent:
55
+
56
+ ```
57
+ "Use explore to find all rate limiting code"
58
+ ```
59
+
60
+ ### Parallel Execution
61
+
62
+ Run multiple agents concurrently (max 8 tasks, 4 concurrent):
63
+
64
+ ```
65
+ "Run 2 workers in parallel: one to refactor the router, one to update tests"
66
+ ```
67
+
68
+ ### Chained Workflow
69
+
70
+ Sequential execution where each agent receives the previous output via `{previous}`:
71
+
72
+ ```
73
+ "Use a chain: first have explore find the auth code, then have worker add rate limiting"
74
+ ```
75
+
76
+ ## File Locations
77
+
78
+ After `mercury init`, subagent files are scaffolded to:
79
+
80
+ ```
81
+ .mercury/global/
82
+ ├── extensions/subagent/
83
+ │ ├── index.ts # Subagent tool implementation
84
+ │ └── agents.ts # Agent discovery logic
85
+ └── agents/
86
+ ├── explore.md # Explorer agent definition
87
+ └── worker.md # Worker agent definition
88
+ ```
89
+
90
+ ## Adding Custom Agents
91
+
92
+ Create a new `.md` file in `.mercury/global/agents/`:
93
+
94
+ ```markdown
95
+ ---
96
+ name: researcher
97
+ description: Deep research specialist for complex questions
98
+ tools: read, grep, find, ls, bash
99
+ model: claude-sonnet-4-5
100
+ ---
101
+
102
+ You are a research specialist. Thoroughly investigate questions and provide comprehensive answers.
103
+
104
+ ## Strategy
105
+ 1. Break down the question
106
+ 2. Search for relevant information
107
+ 3. Synthesize findings
108
+
109
+ ## Output Format
110
+ - Summary
111
+ - Key findings
112
+ - Sources
113
+ ```
114
+
115
+ ### Frontmatter Fields
116
+
117
+ | Field | Required | Description |
118
+ |-------|----------|-------------|
119
+ | `name` | Yes | Agent identifier (used in subagent calls) |
120
+ | `description` | Yes | Brief description of the agent's purpose |
121
+ | `tools` | No | Comma-separated list of allowed tools |
122
+ | `model` | No | Model to use (defaults to current model) |
123
+
124
+ The body after the frontmatter becomes the agent's system prompt.
125
+
126
+ ## Agent Discovery
127
+
128
+ Agents are discovered from:
129
+ 1. **User agents**: `~/.pi/agent/agents/` (default scope)
130
+ 2. **Project agents**: `.mercury/global/agents/` (requires `agentScope: "both"`)
131
+
132
+ Project agents require user confirmation before running (security measure for repo-controlled code).
133
+
134
+ ## Configuration
135
+
136
+ The subagent tool accepts these parameters:
137
+
138
+ | Parameter | Type | Description |
139
+ |-----------|------|-------------|
140
+ | `agent` | string | Agent name (single mode) |
141
+ | `task` | string | Task description (single mode) |
142
+ | `tasks` | array | Array of `{agent, task}` (parallel mode) |
143
+ | `chain` | array | Array of `{agent, task}` (chain mode) |
144
+ | `agentScope` | string | `"user"`, `"project"`, or `"both"` |
145
+ | `cwd` | string | Working directory for the agent |
146
+
147
+ ## Limits
148
+
149
+ | Limit | Value |
150
+ |-------|-------|
151
+ | Max parallel tasks | 8 |
152
+ | Max concurrency | 4 |
153
+
154
+ ## Example Usage
155
+
156
+ In the chat, users can request subagent work naturally:
157
+
158
+ ```
159
+ @Mercury Use explore to find how authentication works in this codebase
160
+
161
+ @Mercury Run a chain: explore finds the database models, then worker adds a new "status" field to the User model
162
+
163
+ @Mercury Run 2 workers in parallel: one fixes the bug in router.ts, one adds a test for it
164
+ ```
165
+
166
+ The main agent interprets these requests and invokes the subagent tool accordingly.
@@ -0,0 +1,62 @@
1
+ # Web Search
2
+
3
+ Web search is **extension-based** in Mercury.
4
+
5
+ Mercury core does not ship a built-in browser/search CLI. Instead, install a web automation extension (for example, `pinchtab`) and let the agent use that tool directly.
6
+
7
+ ---
8
+
9
+ ## Recommended Setup
10
+
11
+ Use the real example extension at:
12
+
13
+ - `examples/extensions/pinchtab/`
14
+
15
+ It demonstrates:
16
+
17
+ - installing browser tooling in the derived image
18
+ - `before_container` hook for runtime env injection
19
+ - system-prompt guidance for consistent search behavior
20
+
21
+ ---
22
+
23
+ ## Typical Flow
24
+
25
+ 1. Start browser automation tool (`pinchtab`)
26
+ 2. Navigate to search engine URL (e.g. Brave Search)
27
+ 3. Extract text/snapshot content
28
+ 4. Summarize and cite key findings
29
+
30
+ Example command pattern used by agents (see `examples/extensions/pinchtab/` for `pinchtab_ensure` — wait until the bridge listens on `:9867` before calling the CLI; otherwise you get `connection refused`):
31
+
32
+ ```bash
33
+ pinchtab_ensure || exit 1
34
+ pinchtab nav "https://search.brave.com/search?q=your+query"
35
+ sleep 3
36
+ pinchtab text
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Why Extension-Based
42
+
43
+ - keeps Mercury core lean
44
+ - lets each deployment pick its own browser/search stack
45
+ - allows per-space RBAC for web tooling (`pinchtab` permission)
46
+ - avoids locking users into one provider/tool
47
+
48
+ ---
49
+
50
+ ## Security & RBAC
51
+
52
+ Extension CLIs are called directly in bash, with RBAC enforced by Mercury's in-container permission guard.
53
+
54
+ If a caller lacks permission for a web extension CLI, execution is blocked.
55
+
56
+ ---
57
+
58
+ ## Related Docs
59
+
60
+ - [extensions.md](./extensions.md)
61
+ - [pipeline.md](./pipeline.md)
62
+ - [container-lifecycle.md](./container-lifecycle.md)
@@ -0,0 +1,12 @@
1
+ # Extension Examples
2
+
3
+ Real-world Mercury extensions. Copy any of these into `.mercury/extensions/` to use.
4
+
5
+ | Extension | What it does | Features used |
6
+ |-----------|-------------|---------------|
7
+ | **charts** | Chart generation via `charts-cli` | cli, skill, permission |
8
+ | **pdf** | PDF processing (OCR, form filling, conversion) | cli, skill, permission |
9
+ | **gws** | Google Workspace (Drive/Gmail/Calendar/etc.) | cli, skill, permission (admin-only default) |
10
+ | **pinchtab** | Browser automation via Playwright | cli, skill, permission, `before_container` hook (env + system prompt) |
11
+ | **napkin** | Obsidian vault management + KB distillation | cli, skill, permission, `workspace_init` hook, `before_container` hook, job, config, widget, store |
12
+
@@ -0,0 +1,13 @@
1
+ export default function (mercury: {
2
+ cli(opts: { name: string; install: string }): void;
3
+ permission(opts: { defaultRoles: string[] }): void;
4
+ skill(relativePath: string): void;
5
+ }) {
6
+ mercury.cli({
7
+ name: "charts",
8
+ install: "npm install -g charts-cli",
9
+ });
10
+
11
+ mercury.permission({ defaultRoles: ["admin", "member"] });
12
+ mercury.skill("./skill");
13
+ }
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: charts
3
+ description: Generate SVG/PNG charts (bar, line, pie, scatter, radar, heatmap, funnel, gauge, sankey, etc.) from ECharts JSON configs
4
+ ---
5
+
6
+ # Charts CLI
7
+
8
+ Generate charts from the command line using ECharts. No browser needed.
9
+
10
+ ## Usage
11
+
12
+ ### List available chart types
13
+
14
+ ```bash
15
+ charts schema --list
16
+ ```
17
+
18
+ ### Get schema for a chart type
19
+
20
+ ```bash
21
+ charts schema bar
22
+ charts schema pie
23
+ charts schema xAxis
24
+ ```
25
+
26
+ ### Render a chart
27
+
28
+ ```bash
29
+ # Pipe JSON config
30
+ cat option.json | charts render -o outbox/chart.png
31
+
32
+ # Or render from file
33
+ charts render --config option.json -o outbox/chart.png
34
+ ```
35
+
36
+ ### Options
37
+
38
+ | Option | Description |
39
+ |--------|-------------|
40
+ | `-o, --output <file>` | Output path (`.svg` or `.png`) |
41
+ | `-W, --width <n>` | Width in pixels (default: 800) |
42
+ | `-H, --height <n>` | Height in pixels (default: 400) |
43
+ | `--theme <name>` | `dark`, `vintage`, or path to JSON |
44
+ | `--format <type>` | `svg` or `png` (auto-detected from extension) |
45
+
46
+ ### Supported chart types
47
+
48
+ bar, line, pie, scatter, radar, funnel, gauge, treemap, boxplot, heatmap, candlestick, sankey
49
+
50
+ ## Visual style rules
51
+
52
+ Always apply these defaults unless the user asks for something else.
53
+
54
+ ### Global defaults
55
+
56
+ - `backgroundColor: "#ffffff"`
57
+ - Title: centered, top 14, fontSize 16, fontWeight bold, color `#111827`
58
+ - Grid: `{ left: 60, right: 32, top: 60, bottom: 48 }`
59
+ - Color palette: `#4f46e5`, `#0d9488`, `#d97706`, `#dc2626`, `#7c3aed`, `#0891b2`
60
+
61
+ ### Axis styling
62
+
63
+ - xAxis: hide ticks, axis line `#d1d5db`, label color `#4b5563`, fontSize 13
64
+ - yAxis: hide line + ticks, label color `#9ca3af`, dashed split lines `#e5e7eb`
65
+
66
+ ### Bar
67
+
68
+ - `barWidth: "50%"`
69
+ - Rounded top corners: `borderRadius: [5,5,0,0]`
70
+ - Labels on top
71
+
72
+ ### Line
73
+
74
+ - `smooth: true`
75
+ - `symbol: "circle"`, `symbolSize: 7`, line width 3
76
+ - Single-series line charts should usually use light area fill
77
+
78
+ ### Pie / donut
79
+
80
+ - No axes
81
+ - Use white segment borders
82
+ - Prefer `-W 800 -H 500`
83
+
84
+ ### Scatter
85
+
86
+ - Both axes `type: "value"`
87
+ - `symbolSize: 8`, opacity `0.7`
88
+
89
+ ### Radar / Funnel / Gauge / Heatmap / Sankey / Treemap / Boxplot / Candlestick
90
+
91
+ Use the same conventions as documented by `charts schema` and keep styling clean and modern.
92
+
93
+ ## Workflow
94
+
95
+ 1. Use `charts schema <type>` to inspect the config shape
96
+ 2. Build the ECharts JSON option
97
+ 3. Render to a file in `outbox/`
98
+ 4. Reply briefly describing the chart so Mercury sends the file back to the user
@@ -0,0 +1,52 @@
1
+ # gws Extension (Google Workspace CLI)
2
+
3
+ Admin-gated Mercury extension for Google Workspace APIs via [`@googleworkspace/cli`](https://github.com/googleworkspace/cli).
4
+
5
+ ## What this example shows
6
+
7
+ - `mercury.cli()` to install `gws`
8
+ - `mercury.permission()` with admin-only default access
9
+ - `mercury.skill()` so the agent knows how to use `gws`
10
+
11
+ ## Install
12
+
13
+ Copy into your Mercury project:
14
+
15
+ ```bash
16
+ mkdir -p .mercury/extensions/gws
17
+ cp -R examples/extensions/gws/* .mercury/extensions/gws/
18
+ ```
19
+
20
+ Then restart Mercury (or reinstall service).
21
+
22
+ ## Auth setup (host machine)
23
+
24
+ 1. Install and authenticate `gws` on the host:
25
+
26
+ ```bash
27
+ npm i -g @googleworkspace/cli
28
+ gws auth login
29
+ ```
30
+
31
+ 2. Export credentials once:
32
+
33
+ ```bash
34
+ gws auth export --unmasked > .mercury/global/gws-credentials.json
35
+ ```
36
+
37
+ 3. Add to `.env`:
38
+
39
+ ```bash
40
+ MERCURY_GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/home/mercury/.pi/agent/gws-credentials.json
41
+ ```
42
+
43
+ (You can also use `MERCURY_GOOGLE_WORKSPACE_CLI_TOKEN`, but it expires quickly.)
44
+
45
+ ## Verify
46
+
47
+ ```bash
48
+ mercury chat --space main --caller "<admin-caller-id>" \
49
+ "run exactly: gws drive files list --params '{\"pageSize\": 3}'"
50
+ ```
51
+
52
+ A non-admin caller should be blocked by RBAC.
@@ -0,0 +1,106 @@
1
+ type ConnectionCategory =
2
+ | "email"
3
+ | "drive"
4
+ | "calendar"
5
+ | "finance"
6
+ | "messaging"
7
+ | "docs"
8
+ | "workspace"
9
+ | "other";
10
+
11
+ type ConnectionAuthType =
12
+ | "oauth2"
13
+ | "apikey"
14
+ | "app-password"
15
+ | "credentials-file"
16
+ | "custom";
17
+
18
+ type MercuryExt = {
19
+ cli(opts: { name: string; install: string }): void;
20
+ permission(opts: { defaultRoles: string[] }): void;
21
+ env(def: { from: string; as?: string }): void;
22
+ skill(relativePath: string): void;
23
+ connection(def: {
24
+ displayName: string;
25
+ iconUrl?: string;
26
+ category: ConnectionCategory;
27
+ authType: ConnectionAuthType;
28
+ credentialEnvVar?: string;
29
+ scopes?: string[];
30
+ }): void;
31
+ on(
32
+ event: "before_container",
33
+ handler: (
34
+ event: { spaceId: string; callerId: string },
35
+ ctx: {
36
+ db: { getExtState(e: string, k: string): string | null };
37
+ hasCallerPermission(
38
+ spaceId: string,
39
+ callerId: string,
40
+ permission: string,
41
+ ): boolean;
42
+ },
43
+ ) => Promise<{ env?: Record<string, string> } | undefined>,
44
+ ): void;
45
+ };
46
+
47
+ import manifest from "../../../resources/connection-env-vars.json";
48
+
49
+ const gwsEnv = manifest.gws;
50
+
51
+ /** Path where credentials are materialized inside the inner container's own /tmp. */
52
+ const CREDENTIALS_FILE = "/tmp/gws-credentials.json";
53
+
54
+ export default function (mercury: MercuryExt) {
55
+ mercury.cli({
56
+ name: "gws",
57
+ install: "npm install -g @googleworkspace/cli",
58
+ });
59
+
60
+ mercury.permission({ defaultRoles: ["admin"] });
61
+
62
+ mercury.env({ from: gwsEnv.env.credentials });
63
+ mercury.env({ from: gwsEnv.env.legacyCredentialsFile });
64
+
65
+ mercury.connection({
66
+ displayName: "Google Workspace",
67
+ category: "workspace",
68
+ authType: "oauth2",
69
+ credentialEnvVar: gwsEnv.credentialEnvVar,
70
+ scopes: [
71
+ "https://www.googleapis.com/auth/gmail.modify",
72
+ "https://www.googleapis.com/auth/drive",
73
+ "https://www.googleapis.com/auth/calendar",
74
+ "https://www.googleapis.com/auth/documents",
75
+ "https://www.googleapis.com/auth/spreadsheets",
76
+ "https://www.googleapis.com/auth/userinfo.email",
77
+ ],
78
+ });
79
+
80
+ // Inner containers don't share the outer container's volume — they mount host
81
+ // filesystem paths. So we can't write a credentials file from this hook and
82
+ // have the inner container see it. Instead, pass the target path via env var
83
+ // and let the skill materialize the file from GWS_CREDENTIALS_JSON at runtime.
84
+ mercury.on("before_container", async () => {
85
+ const raw = process.env[gwsEnv.env.credentials];
86
+ if (!raw) return undefined;
87
+
88
+ try {
89
+ JSON.parse(raw);
90
+ } catch {
91
+ console.error(
92
+ `[gws.before_container] ${gwsEnv.env.credentials} is not valid JSON — skipping`,
93
+ );
94
+ return undefined;
95
+ }
96
+
97
+ return {
98
+ env: {
99
+ GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE: CREDENTIALS_FILE,
100
+ GWS_CREDENTIALS_JSON: raw,
101
+ },
102
+ };
103
+ });
104
+
105
+ mercury.skill("./skill");
106
+ }
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: gws
3
+ description: Access Gmail, Google Drive, Google Calendar, Docs, and Sheets via the gws CLI. Use for email (read, send, triage inbox, reply, forward), calendar (today's agenda, add or reschedule events, meeting prep), Drive (list, find, organize files), and Docs/Sheets (read, summarize, append). Triggers on any Google Workspace or Gmail request.
4
+ allowed-tools: Bash
5
+ ---
6
+
7
+ # Google Workspace (gws)
8
+
9
+ Use the `gws` CLI via Bash for all Google Workspace operations.
10
+
11
+ ## Presentation rules — always enforce
12
+
13
+ **Never paste raw gws output into a reply.** Translate every result into plain language before responding.
14
+
15
+ | Raw output field | What to show instead |
16
+ |---|---|
17
+ | `name` or `summary` | The display name only |
18
+ | `mimeType: application/vnd.google-apps.document` | "Google Doc" |
19
+ | `mimeType: application/vnd.google-apps.spreadsheet` | "spreadsheet" |
20
+ | `mimeType: application/vnd.google-apps.folder` | "folder" |
21
+ | `mimeType: application/pdf` | "PDF" |
22
+ | Any `id` field | Never shown; use internally only for follow-up commands |
23
+ | JSON objects or arrays | Summarise in prose |
24
+ | Email `labelIds`, `threadId`, `messageId` | Never shown |
25
+
26
+ ## Credentials setup (run once per session before any gws command)
27
+
28
+ `GWS_CREDENTIALS_JSON` contains the credentials as a JSON string. Materialize it to the path gws expects, then verify auth:
29
+
30
+ ```bash
31
+ [ -n "$GWS_CREDENTIALS_JSON" ] && echo "$GWS_CREDENTIALS_JSON" > "${GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE:-/tmp/gws-credentials.json}" && export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE="${GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE:-/tmp/gws-credentials.json}"
32
+ gws auth status
33
+ ```
34
+
35
+ If `auth_method` is not `none`, credentials are ready. Skip this step on subsequent calls in the same session (the file persists in /tmp for the container lifetime).
36
+
37
+ ## Dispatch table
38
+
39
+ Match the user's intent to the right category and read the reference file before acting:
40
+
41
+ | User intent | Category | Reference file |
42
+ |---|---|---|
43
+ | email, inbox, gmail, send message, unread, triage | Gmail | `references/gmail.md` |
44
+ | drive, files, folder, upload, download, share | Drive | `references/drive.md` |
45
+ | calendar, agenda, event, meeting, schedule | Calendar | `references/calendar.md` |
46
+ | doc, document, write, append, summarise | Docs | `references/docs.md` |
47
+ | sheet, spreadsheet, row, data | Sheets | `references/sheets.md` |
48
+
49
+ **Always read the reference file for the matched category before running a command.**
50
+
51
+ ## Fallback
52
+
53
+ If no helper covers the case, use the raw API:
54
+ ```bash
55
+ gws <service> --help # list available subcommands
56
+ ```
57
+ Still translate the output before replying.
@@ -0,0 +1,101 @@
1
+ # Calendar Reference
2
+
3
+ Use `gws calendar` for all calendar operations.
4
+
5
+ ## Today's agenda
6
+
7
+ ```bash
8
+ gws calendar +agenda --today
9
+ ```
10
+
11
+ ## This week's agenda
12
+
13
+ ```bash
14
+ gws calendar +agenda --week
15
+ ```
16
+
17
+ ## Next N days
18
+
19
+ ```bash
20
+ gws calendar +agenda --days 3
21
+ ```
22
+
23
+ ## Filter to a specific calendar
24
+
25
+ ```bash
26
+ gws calendar +agenda --today --calendar 'Work'
27
+ gws calendar +agenda --week --calendar 'Personal'
28
+ ```
29
+
30
+ ## Timezone override
31
+
32
+ ```bash
33
+ gws calendar +agenda --today --timezone America/New_York
34
+ ```
35
+
36
+ ## Create an event
37
+
38
+ ```bash
39
+ gws calendar +insert \
40
+ --summary 'Team Standup' \
41
+ --start '2026-04-24T09:00:00-05:00' \
42
+ --end '2026-04-24T09:30:00-05:00'
43
+
44
+ # With location and attendees
45
+ gws calendar +insert \
46
+ --summary 'Project Review' \
47
+ --start '2026-04-24T14:00:00-05:00' \
48
+ --end '2026-04-24T15:00:00-05:00' \
49
+ --location 'Conference Room A' \
50
+ --attendee alice@example.com \
51
+ --attendee bob@example.com
52
+
53
+ # With Google Meet link
54
+ gws calendar +insert \
55
+ --summary 'Remote Sync' \
56
+ --start '2026-04-24T10:00:00-05:00' \
57
+ --end '2026-04-24T10:30:00-05:00' \
58
+ --meet
59
+ ```
60
+
61
+ Use RFC3339 format for times (e.g. `2026-04-24T09:00:00+03:00`). Always confirm date, time, and timezone with the user before creating.
62
+
63
+ ## Reschedule an event
64
+
65
+ Get the event ID from `+agenda` output (store internally — never show to user):
66
+
67
+ ```bash
68
+ # Get event ID
69
+ gws calendar events list --params '{"calendarId":"primary","q":"Team Standup","maxResults":5}'
70
+
71
+ # Update start/end times (replace timezone with the user's local timezone)
72
+ gws calendar events update \
73
+ --params '{"calendarId":"primary","eventId":"<EVENT_ID>"}' \
74
+ --json '{"start":{"dateTime":"2026-04-25T09:00:00-05:00","timeZone":"America/New_York"},"end":{"dateTime":"2026-04-25T09:30:00-05:00","timeZone":"America/New_York"}}'
75
+ ```
76
+
77
+ ## Meeting prep (attendees, agenda for an upcoming event)
78
+
79
+ ```bash
80
+ # Find the event
81
+ gws calendar events list --params '{"calendarId":"primary","q":"<MEETING_NAME>","maxResults":3}'
82
+
83
+ # Get full event details including attendees
84
+ gws calendar events get --params '{"calendarId":"primary","eventId":"<EVENT_ID>"}'
85
+ ```
86
+
87
+ Present: title, date/time, location (if any), attendee names — never show email addresses or event IDs unless the user asks.
88
+
89
+ ## Raw API fallback
90
+
91
+ ```bash
92
+ gws calendar events list --params '{"calendarId":"primary","timeMin":"<ISO_DATE>","maxResults":10}'
93
+ gws calendar --help # list all subcommands
94
+ ```
95
+
96
+ ## Output format rules
97
+
98
+ - Agenda: "9:00 AM — Team Standup (30 min)" or "All day — Public Holiday"
99
+ - Event created: "Added 'Team Standup' to your calendar for Friday April 24 at 9:00 AM"
100
+ - Reschedule confirmation: "Moved 'Team Standup' to Saturday April 25 at 9:00 AM"
101
+ - Never show event IDs, calendar IDs, or raw dateTime strings