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.
- package/LICENSE +22 -0
- package/README.md +438 -0
- package/container/Dockerfile +127 -0
- package/container/Dockerfile.base +109 -0
- package/container/Dockerfile.power +17 -0
- package/container/agent-package.json +8 -0
- package/container/build.sh +54 -0
- package/docs/TODOS.md +147 -0
- package/docs/auth/dashboard.md +28 -0
- package/docs/auth/overview.md +109 -0
- package/docs/auth/whatsapp.md +173 -0
- package/docs/configuration.md +54 -0
- package/docs/container-lifecycle.md +349 -0
- package/docs/context-architecture.md +87 -0
- package/docs/deployment.md +199 -0
- package/docs/extensions.md +375 -0
- package/docs/graceful-shutdown.md +62 -0
- package/docs/kb-distillation.md +77 -0
- package/docs/media/overview.md +140 -0
- package/docs/media/whatsapp.md +171 -0
- package/docs/memory.md +137 -0
- package/docs/permissions.md +217 -0
- package/docs/pipeline.md +228 -0
- package/docs/prd-chat-memory.md +76 -0
- package/docs/prd-config-load.md +82 -0
- package/docs/rate-limiting.md +166 -0
- package/docs/scheduler.md +288 -0
- package/docs/setup-discord.md +100 -0
- package/docs/setup-slack.md +119 -0
- package/docs/setup-whatsapp.md +94 -0
- package/docs/subagents.md +166 -0
- package/docs/web-search.md +62 -0
- package/examples/extensions/README.md +12 -0
- package/examples/extensions/charts/index.ts +13 -0
- package/examples/extensions/charts/skill/SKILL.md +98 -0
- package/examples/extensions/gws/README.md +52 -0
- package/examples/extensions/gws/index.ts +106 -0
- package/examples/extensions/gws/skill/SKILL.md +57 -0
- package/examples/extensions/gws/skill/references/calendar.md +101 -0
- package/examples/extensions/gws/skill/references/docs.md +65 -0
- package/examples/extensions/gws/skill/references/drive.md +79 -0
- package/examples/extensions/gws/skill/references/gmail.md +85 -0
- package/examples/extensions/gws/skill/references/sheets.md +60 -0
- package/examples/extensions/napkin/index.ts +821 -0
- package/examples/extensions/napkin/prompts/consolidation-monthly.md +73 -0
- package/examples/extensions/napkin/prompts/consolidation-weekly.md +67 -0
- package/examples/extensions/napkin/prompts/kb-distillation.md +176 -0
- package/examples/extensions/napkin/skill/SKILL.md +728 -0
- package/examples/extensions/pdf/index.ts +23 -0
- package/examples/extensions/pdf/skill/LICENSE.txt +30 -0
- package/examples/extensions/pdf/skill/SKILL.md +314 -0
- package/examples/extensions/pdf/skill/forms.md +294 -0
- package/examples/extensions/pdf/skill/reference.md +612 -0
- package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -0
- package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -0
- package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -0
- package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -0
- package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -0
- package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -0
- package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -0
- package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/examples/extensions/permission-guard/index.ts +65 -0
- package/examples/extensions/pinchtab/index.ts +199 -0
- package/examples/extensions/pinchtab/lib/session-injector.ts +144 -0
- package/examples/extensions/pinchtab/skill/SKILL.md +224 -0
- package/examples/extensions/pinchtab/skill/TRUST.md +69 -0
- package/examples/extensions/pinchtab/skill/references/api.md +297 -0
- package/examples/extensions/pinchtab/skill/references/env.md +45 -0
- package/examples/extensions/pinchtab/skill/references/profiles.md +107 -0
- package/examples/extensions/tradestation/host/refresh.ts +102 -0
- package/examples/extensions/tradestation/index.ts +153 -0
- package/examples/extensions/tradestation/skill/SKILL.md +67 -0
- package/examples/extensions/tradestation/skill/scripts/ts-cli.ts +111 -0
- package/examples/extensions/voice-synth/index.ts +94 -0
- package/examples/extensions/voice-synth/skill/SKILL.md +38 -0
- package/examples/extensions/voice-transcribe/index.ts +381 -0
- package/examples/extensions/voice-transcribe/requirements.txt +8 -0
- package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -0
- package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -0
- package/examples/extensions/web-search/index.ts +22 -0
- package/examples/extensions/web-search/skill/SKILL.md +114 -0
- package/examples/extensions/web-search/skill/references/apartments.md +178 -0
- package/examples/extensions/web-search/skill/references/car-purchase.md +132 -0
- package/examples/extensions/web-search/skill/references/car-rental.md +113 -0
- package/examples/extensions/web-search/skill/references/flights.md +133 -0
- package/examples/extensions/web-search/skill/references/hotels.md +148 -0
- package/examples/extensions/yahoo-mail/cli/bun.lock +66 -0
- package/examples/extensions/yahoo-mail/cli/package.json +13 -0
- package/examples/extensions/yahoo-mail/cli/ymail.mjs +353 -0
- package/examples/extensions/yahoo-mail/index.ts +57 -0
- package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -0
- package/package.json +106 -0
- package/resources/agents/explore.md +50 -0
- package/resources/agents/worker.md +24 -0
- package/resources/builtin-extensions.txt +3 -0
- package/resources/connection-env-vars.json +25 -0
- package/resources/extensions/.gitkeep +0 -0
- package/resources/pi-extensions/subagent/agents.ts +126 -0
- package/resources/pi-extensions/subagent/index.ts +964 -0
- package/resources/profiles/coding/AGENTS.md +43 -0
- package/resources/profiles/coding/mercury-profile.yaml +15 -0
- package/resources/profiles/general/AGENTS.md +31 -0
- package/resources/profiles/general/mercury-profile.yaml +15 -0
- package/resources/profiles/research/AGENTS.md +40 -0
- package/resources/profiles/research/mercury-profile.yaml +15 -0
- package/resources/skills/config/SKILL.md +25 -0
- package/resources/skills/context/SKILL.md +33 -0
- package/resources/skills/conversation-recap/SKILL.md +19 -0
- package/resources/skills/media/SKILL.md +27 -0
- package/resources/skills/mutes/SKILL.md +31 -0
- package/resources/skills/permissions/SKILL.md +19 -0
- package/resources/skills/preferences/SKILL.md +31 -0
- package/resources/skills/recall/SKILL.md +24 -0
- package/resources/skills/roles/SKILL.md +18 -0
- package/resources/skills/spaces/SKILL.md +18 -0
- package/resources/skills/tasks/SKILL.md +45 -0
- package/resources/templates/AGENTS.md +157 -0
- package/resources/templates/env.template +34 -0
- package/resources/templates/mercury.example.yaml +75 -0
- package/src/adapters/discord-native.ts +534 -0
- package/src/adapters/discord.ts +38 -0
- package/src/adapters/setup.ts +89 -0
- package/src/adapters/slack.ts +9 -0
- package/src/adapters/whatsapp-media.ts +337 -0
- package/src/adapters/whatsapp.ts +629 -0
- package/src/agent/api-socket.ts +127 -0
- package/src/agent/container-entry.ts +967 -0
- package/src/agent/container-error.ts +49 -0
- package/src/agent/container-runner.ts +1272 -0
- package/src/agent/model-capabilities-core.ts +23 -0
- package/src/agent/model-capabilities.ts +231 -0
- package/src/agent/pi-failure-class.ts +83 -0
- package/src/agent/pi-jsonl-parser.ts +306 -0
- package/src/agent/preferences-prompt.ts +20 -0
- package/src/agent/user-error-messages.ts +78 -0
- package/src/bridges/discord.ts +171 -0
- package/src/bridges/slack.ts +177 -0
- package/src/bridges/teams.ts +160 -0
- package/src/bridges/telegram.ts +571 -0
- package/src/bridges/whatsapp.ts +290 -0
- package/src/chat-shim.ts +259 -0
- package/src/cli/mercury.ts +2508 -0
- package/src/cli/mrctl-http.ts +27 -0
- package/src/cli/mrctl.ts +611 -0
- package/src/cli/whatsapp-auth.ts +260 -0
- package/src/config-file.ts +397 -0
- package/src/config-model-chain.ts +30 -0
- package/src/config.ts +316 -0
- package/src/core/api-types.ts +58 -0
- package/src/core/api.ts +105 -0
- package/src/core/commands.ts +76 -0
- package/src/core/conversation.ts +47 -0
- package/src/core/handler.ts +206 -0
- package/src/core/media.ts +200 -0
- package/src/core/mute-duration.ts +22 -0
- package/src/core/outbox.ts +76 -0
- package/src/core/permissions.ts +192 -0
- package/src/core/profiles.ts +245 -0
- package/src/core/rate-limiter.ts +127 -0
- package/src/core/router.ts +191 -0
- package/src/core/routes/chat.ts +172 -0
- package/src/core/routes/config-builtin.ts +107 -0
- package/src/core/routes/config.ts +81 -0
- package/src/core/routes/connections.ts +190 -0
- package/src/core/routes/console.ts +668 -0
- package/src/core/routes/control.ts +46 -0
- package/src/core/routes/conversations.ts +66 -0
- package/src/core/routes/dashboard.ts +2491 -0
- package/src/core/routes/extensions.ts +37 -0
- package/src/core/routes/index.ts +14 -0
- package/src/core/routes/media.ts +72 -0
- package/src/core/routes/messages.ts +37 -0
- package/src/core/routes/mutes.ts +89 -0
- package/src/core/routes/prefs.ts +95 -0
- package/src/core/routes/roles.ts +125 -0
- package/src/core/routes/spaces.ts +60 -0
- package/src/core/routes/storage.ts +126 -0
- package/src/core/routes/tasks.ts +189 -0
- package/src/core/routes/tradestation.ts +268 -0
- package/src/core/routes/tts.ts +51 -0
- package/src/core/runtime.ts +1140 -0
- package/src/core/space-queue.ts +103 -0
- package/src/core/storage-cleanup.ts +140 -0
- package/src/core/storage-guard.ts +24 -0
- package/src/core/task-scheduler.ts +132 -0
- package/src/core/telegram-format.ts +178 -0
- package/src/core/trigger.ts +142 -0
- package/src/dashboard/index.html +729 -0
- package/src/dashboard/tokens.css +53 -0
- package/src/extensions/api.ts +252 -0
- package/src/extensions/catalog.ts +117 -0
- package/src/extensions/config-registry.ts +83 -0
- package/src/extensions/context.ts +36 -0
- package/src/extensions/hooks.ts +156 -0
- package/src/extensions/image-builder.ts +617 -0
- package/src/extensions/installer.ts +306 -0
- package/src/extensions/jobs.ts +122 -0
- package/src/extensions/loader.ts +271 -0
- package/src/extensions/permission-guard.ts +52 -0
- package/src/extensions/reserved.ts +28 -0
- package/src/extensions/skills.ts +123 -0
- package/src/extensions/types.ts +462 -0
- package/src/logger.ts +174 -0
- package/src/main.ts +586 -0
- package/src/server.ts +391 -0
- package/src/storage/db.ts +1624 -0
- package/src/storage/memory.ts +45 -0
- package/src/storage/pi-auth.ts +95 -0
- package/src/text/markdown.ts +117 -0
- package/src/text/rtl.ts +38 -0
- package/src/tradestation/host-api.ts +77 -0
- package/src/tradestation/pending-orders.ts +69 -0
- package/src/tts/azure.ts +52 -0
- package/src/tts/google.ts +128 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/language.ts +20 -0
- package/src/tts/synthesize.ts +133 -0
- 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
|