mercury-agent 0.5.0 → 0.5.2
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/README.md +452 -451
- package/container/Dockerfile +127 -127
- package/container/Dockerfile.base +109 -109
- package/container/Dockerfile.power +17 -17
- package/container/agent-package.json +8 -8
- package/container/build.sh +54 -54
- package/docs/ROADMAP.md +3 -4
- package/docs/archive/summarization/2026-07-02-recent-dev-summary.md +71 -0
- package/docs/auth/dashboard.md +28 -28
- package/docs/auth/overview.md +109 -109
- package/docs/auth/whatsapp.md +173 -173
- package/docs/authoring-profiles.md +174 -174
- package/docs/configuration.md +54 -54
- package/docs/container-lifecycle.md +349 -349
- package/docs/{bugs/bwrap-privileged-linux-docker.md → debug/major/2026-07-02-bwrap-privileged-linux-docker.md} +21 -1
- package/docs/{bugs/e2big-prompt-delivery-fix.md → debug/major/2026-07-02-e2big-prompt-delivery-fix.md} +27 -1
- package/docs/{bugs/registry-pull-no-local-fallback.md → debug/major/2026-07-02-registry-pull-no-local-fallback.md} +27 -1
- package/docs/debug/summarization/2026-07-02-common-bug-patterns.md +72 -0
- package/docs/deployment.md +199 -199
- package/docs/extensions.md +375 -375
- package/docs/graceful-shutdown.md +62 -62
- package/docs/kb-distillation.md +77 -77
- package/docs/media/overview.md +140 -140
- package/docs/media/whatsapp.md +171 -171
- package/docs/memory.md +137 -137
- package/docs/permissions.md +217 -217
- package/docs/pipeline.md +228 -228
- package/docs/prd-chat-memory.md +76 -76
- package/docs/prd-config-load.md +82 -82
- package/docs/rate-limiting.md +229 -229
- package/docs/runbooks/publish-checklist.md +9 -1
- package/docs/scheduler.md +288 -288
- package/docs/setup-discord.md +100 -100
- package/docs/setup-slack.md +119 -119
- package/docs/setup-whatsapp.md +94 -94
- package/docs/subagents.md +166 -166
- package/docs/web-search.md +62 -62
- package/examples/extensions/README.md +12 -12
- package/examples/extensions/charts/index.ts +13 -13
- package/examples/extensions/charts/skill/SKILL.md +98 -98
- package/examples/extensions/gws/README.md +52 -52
- package/examples/extensions/gws/skill/SKILL.md +57 -57
- package/examples/extensions/gws/skill/references/calendar.md +101 -101
- package/examples/extensions/gws/skill/references/docs.md +65 -65
- package/examples/extensions/gws/skill/references/drive.md +79 -79
- package/examples/extensions/gws/skill/references/gmail.md +85 -85
- package/examples/extensions/gws/skill/references/sheets.md +60 -60
- package/examples/extensions/napkin/skill/SKILL.md +728 -728
- package/examples/extensions/pdf/skill/LICENSE.txt +30 -30
- package/examples/extensions/pdf/skill/SKILL.md +314 -314
- package/examples/extensions/pdf/skill/forms.md +294 -294
- package/examples/extensions/pdf/skill/reference.md +611 -611
- package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -65
- package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -11
- package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -33
- package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -37
- package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -122
- package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -115
- package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -98
- package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -107
- package/examples/extensions/permission-guard/index.ts +65 -65
- package/examples/extensions/pinchtab/skill/SKILL.md +224 -224
- package/examples/extensions/pinchtab/skill/TRUST.md +69 -69
- package/examples/extensions/pinchtab/skill/references/api.md +297 -297
- package/examples/extensions/pinchtab/skill/references/env.md +45 -45
- package/examples/extensions/pinchtab/skill/references/profiles.md +107 -107
- package/examples/extensions/tradestation/host/refresh.ts +102 -102
- package/examples/extensions/tradestation/index.ts +153 -153
- package/examples/extensions/tradestation/skill/SKILL.md +67 -67
- package/examples/extensions/voice-synth/index.ts +94 -94
- package/examples/extensions/voice-synth/skill/SKILL.md +38 -38
- package/examples/extensions/voice-transcribe/requirements.txt +8 -8
- package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -179
- package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -53
- package/examples/extensions/yahoo-mail/cli/package.json +13 -13
- package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -78
- package/package.json +106 -106
- package/resources/agents/explore.md +50 -50
- package/resources/agents/worker.md +24 -24
- package/resources/connection-env-vars.json +25 -25
- package/resources/pi-extensions/subagent/agents.ts +126 -126
- package/resources/pi-extensions/subagent/index.ts +964 -964
- package/resources/profiles/coding/AGENTS.md +43 -43
- package/resources/profiles/coding/mercury-profile.yaml +15 -15
- package/resources/profiles/general/AGENTS.md +31 -31
- package/resources/profiles/general/mercury-profile.yaml +15 -15
- package/resources/profiles/research/AGENTS.md +40 -40
- package/resources/profiles/research/mercury-profile.yaml +15 -15
- package/resources/skills/config/SKILL.md +25 -25
- package/resources/skills/context/SKILL.md +33 -33
- package/resources/skills/conversation-recap/SKILL.md +19 -19
- package/resources/skills/mutes/SKILL.md +31 -31
- package/resources/skills/permissions/SKILL.md +19 -19
- package/resources/skills/preferences/SKILL.md +31 -31
- package/resources/skills/recall/SKILL.md +24 -24
- package/resources/skills/roles/SKILL.md +18 -18
- package/resources/skills/spaces/SKILL.md +18 -18
- package/resources/skills/tasks/SKILL.md +45 -45
- package/resources/templates/AGENTS.md +157 -157
- package/resources/templates/env.template +38 -38
- package/resources/templates/mercury.example.yaml +99 -99
- package/src/agent/container-entry.ts +1 -1
- package/src/agent/container-runner.ts +1345 -1346
- package/src/cli/mercury.ts +39 -7
- package/src/cli/mrctl.ts +636 -636
- package/src/config-file.ts +540 -540
- package/src/config.ts +339 -339
- package/src/core/api.ts +125 -125
- package/src/core/caller-token.ts +101 -101
- package/src/core/permissions.ts +228 -228
- package/src/core/profiles.ts +271 -271
- package/src/core/routes/capability.ts +70 -70
- package/src/core/routes/index.ts +15 -15
- package/src/core/runtime.ts +1530 -1530
- package/src/dashboard/index.html +729 -729
- package/src/extensions/api.ts +273 -273
- package/src/extensions/loader.ts +286 -286
- package/src/extensions/types.ts +517 -517
- package/src/main.ts +605 -605
- package/docs/pending-updates/applicative-profiles.md +0 -15
- package/docs/pending-updates/caller-bound-capability-token.md +0 -15
- package/docs/pending-updates/dm-auto-space.md +0 -15
- /package/docs/archive/{2026-07-01-applicative-profiles.md → applicative-profiles/2026-07-01-applicative-profiles.md} +0 -0
- /package/docs/archive/{2026-07-01-caller-bound-capability-token.md → applicative-profiles/2026-07-01-caller-bound-capability-token.md} +0 -0
- /package/docs/archive/{2026-07-01-dm-auto-space.md → applicative-profiles/2026-07-01-dm-auto-space.md} +0 -0
package/docs/media/whatsapp.md
CHANGED
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
# WhatsApp Media Handling
|
|
2
|
-
|
|
3
|
-
Downloads media from WhatsApp messages using the Baileys library.
|
|
4
|
-
|
|
5
|
-
## Supported Media Types
|
|
6
|
-
|
|
7
|
-
| WhatsApp Type | Detected As | Default MIME | Extensions |
|
|
8
|
-
|---------------|-------------|--------------|------------|
|
|
9
|
-
| `imageMessage` | `image` | `image/jpeg` | jpg, png, gif, webp |
|
|
10
|
-
| `videoMessage` | `video` | `video/mp4` | mp4, 3gp |
|
|
11
|
-
| `audioMessage` (ptt=true) | `voice` | `audio/ogg` | ogg |
|
|
12
|
-
| `audioMessage` (ptt=false) | `audio` | `audio/mpeg` | mp3, m4a, aac, ogg |
|
|
13
|
-
| `documentMessage` | `document` | `application/octet-stream` | pdf, doc, docx, xls, xlsx, txt, etc. |
|
|
14
|
-
| `stickerMessage` | `image` | `image/webp` | webp |
|
|
15
|
-
|
|
16
|
-
## Data Flow
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
WAMessage (Baileys)
|
|
20
|
-
│
|
|
21
|
-
▼
|
|
22
|
-
detectWhatsAppMedia(msg.message)
|
|
23
|
-
│
|
|
24
|
-
├─▶ null (no media)
|
|
25
|
-
│
|
|
26
|
-
▼
|
|
27
|
-
WhatsAppMediaInfo { type, mimeType, fileLength?, filename? }
|
|
28
|
-
│
|
|
29
|
-
▼
|
|
30
|
-
downloadWhatsAppMedia(msg, sock, options)
|
|
31
|
-
│
|
|
32
|
-
├─▶ null (too large / download failed)
|
|
33
|
-
│
|
|
34
|
-
▼
|
|
35
|
-
MessageAttachment { path, type, mimeType, sizeBytes?, filename? }
|
|
36
|
-
│
|
|
37
|
-
▼
|
|
38
|
-
Saved to: {workspace}/inbox/{timestamp}-{type}.{ext}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Implementation
|
|
42
|
-
|
|
43
|
-
### Detection
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// src/adapters/whatsapp-media.ts
|
|
47
|
-
function detectWhatsAppMedia(message: proto.IMessage): WhatsAppMediaInfo | null
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Checks message for media fields in order:
|
|
51
|
-
1. `audioMessage?.ptt` → voice note
|
|
52
|
-
2. `audioMessage` → audio
|
|
53
|
-
3. `imageMessage` → image
|
|
54
|
-
4. `videoMessage` → video
|
|
55
|
-
5. `documentMessage` → document
|
|
56
|
-
6. `stickerMessage` → image
|
|
57
|
-
|
|
58
|
-
### Download
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// src/adapters/whatsapp-media.ts
|
|
62
|
-
async function downloadWhatsAppMedia(
|
|
63
|
-
msg: WAMessage,
|
|
64
|
-
sock: WASocket,
|
|
65
|
-
options: MediaDownloadOptions,
|
|
66
|
-
): Promise<MessageAttachment | null>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Uses Baileys' `downloadMediaMessage()`:
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
const buffer = await downloadMediaMessage(
|
|
73
|
-
msg,
|
|
74
|
-
"buffer",
|
|
75
|
-
{},
|
|
76
|
-
{
|
|
77
|
-
logger: silentLogger,
|
|
78
|
-
reuploadRequest: sock.updateMediaMessage,
|
|
79
|
-
},
|
|
80
|
-
);
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Adapter Integration
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
// src/adapters/whatsapp.ts
|
|
87
|
-
createWhatsAppBaileysAdapter({
|
|
88
|
-
mediaEnabled: true,
|
|
89
|
-
mediaMaxSizeBytes: 10 * 1024 * 1024,
|
|
90
|
-
getWorkspace: (spaceId) => ensureSpaceWorkspace(spacesDir, spaceId),
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Size Limits
|
|
95
|
-
|
|
96
|
-
Files are checked against `mediaMaxSizeBytes` twice:
|
|
97
|
-
|
|
98
|
-
1. **Before download** — using `fileLength` from message metadata (may be missing)
|
|
99
|
-
2. **After download** — using actual buffer size
|
|
100
|
-
|
|
101
|
-
Files exceeding the limit are logged and skipped:
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
[WARN] Skipping large media file messageId=ABC type=video sizeBytes=52428800 maxBytes=10485760
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## Reply Context
|
|
108
|
-
|
|
109
|
-
When replying to a message with media, the reply context includes media info:
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// Attributes added to <reply_to>
|
|
113
|
-
media_type="image"
|
|
114
|
-
media_mime="image/jpeg"
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Example:
|
|
118
|
-
```xml
|
|
119
|
-
<reply_to name="John" jid="123@wa" message_id="ABC" media_type="image" media_mime="image/jpeg">
|
|
120
|
-
[image]
|
|
121
|
-
</reply_to>
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## File Naming
|
|
125
|
-
|
|
126
|
-
Pattern: `{timestamp}-{type}.{ext}` or `{timestamp}-{filename}` for documents
|
|
127
|
-
|
|
128
|
-
| Input | Output |
|
|
129
|
-
|-------|--------|
|
|
130
|
-
| image/jpeg | `1709012345-image.jpg` |
|
|
131
|
-
| audio/ogg (voice) | `1709012345-voice.ogg` |
|
|
132
|
-
| application/pdf, "report.pdf" | `1709012345-report.pdf` |
|
|
133
|
-
|
|
134
|
-
## MIME to Extension Mapping
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
const MIME_TO_EXT: Record<string, string> = {
|
|
138
|
-
"image/jpeg": "jpg",
|
|
139
|
-
"image/png": "png",
|
|
140
|
-
"image/gif": "gif",
|
|
141
|
-
"image/webp": "webp",
|
|
142
|
-
"audio/ogg": "ogg",
|
|
143
|
-
"audio/mpeg": "mp3",
|
|
144
|
-
"audio/mp4": "m4a",
|
|
145
|
-
"video/mp4": "mp4",
|
|
146
|
-
"video/3gpp": "3gp",
|
|
147
|
-
"application/pdf": "pdf",
|
|
148
|
-
// ... etc
|
|
149
|
-
};
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Unknown MIME types default to `.bin`.
|
|
153
|
-
|
|
154
|
-
## Limitations
|
|
155
|
-
|
|
156
|
-
1. **No re-download** — Media is downloaded once when the message arrives. If the file is deleted, it's gone.
|
|
157
|
-
|
|
158
|
-
2. **No transcription** — Voice notes are saved as audio files. pi cannot play them. Future: add Whisper transcription.
|
|
159
|
-
|
|
160
|
-
3. **Reply context doesn't include file** — When replying to a media message, we include metadata but not the actual file path. The original attachment would need to be looked up.
|
|
161
|
-
|
|
162
|
-
4. **Ephemeral media** — WhatsApp media URLs expire. Download must happen immediately when the message arrives.
|
|
163
|
-
|
|
164
|
-
## Error Handling
|
|
165
|
-
|
|
166
|
-
| Error | Behavior |
|
|
167
|
-
|-------|----------|
|
|
168
|
-
| Download fails | Log error, continue without attachment |
|
|
169
|
-
| Buffer empty | Log error, return null |
|
|
170
|
-
| Size exceeded | Log warning, discard buffer |
|
|
171
|
-
| Write fails | Throw error (propagates up) |
|
|
1
|
+
# WhatsApp Media Handling
|
|
2
|
+
|
|
3
|
+
Downloads media from WhatsApp messages using the Baileys library.
|
|
4
|
+
|
|
5
|
+
## Supported Media Types
|
|
6
|
+
|
|
7
|
+
| WhatsApp Type | Detected As | Default MIME | Extensions |
|
|
8
|
+
|---------------|-------------|--------------|------------|
|
|
9
|
+
| `imageMessage` | `image` | `image/jpeg` | jpg, png, gif, webp |
|
|
10
|
+
| `videoMessage` | `video` | `video/mp4` | mp4, 3gp |
|
|
11
|
+
| `audioMessage` (ptt=true) | `voice` | `audio/ogg` | ogg |
|
|
12
|
+
| `audioMessage` (ptt=false) | `audio` | `audio/mpeg` | mp3, m4a, aac, ogg |
|
|
13
|
+
| `documentMessage` | `document` | `application/octet-stream` | pdf, doc, docx, xls, xlsx, txt, etc. |
|
|
14
|
+
| `stickerMessage` | `image` | `image/webp` | webp |
|
|
15
|
+
|
|
16
|
+
## Data Flow
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
WAMessage (Baileys)
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
detectWhatsAppMedia(msg.message)
|
|
23
|
+
│
|
|
24
|
+
├─▶ null (no media)
|
|
25
|
+
│
|
|
26
|
+
▼
|
|
27
|
+
WhatsAppMediaInfo { type, mimeType, fileLength?, filename? }
|
|
28
|
+
│
|
|
29
|
+
▼
|
|
30
|
+
downloadWhatsAppMedia(msg, sock, options)
|
|
31
|
+
│
|
|
32
|
+
├─▶ null (too large / download failed)
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
MessageAttachment { path, type, mimeType, sizeBytes?, filename? }
|
|
36
|
+
│
|
|
37
|
+
▼
|
|
38
|
+
Saved to: {workspace}/inbox/{timestamp}-{type}.{ext}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Implementation
|
|
42
|
+
|
|
43
|
+
### Detection
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// src/adapters/whatsapp-media.ts
|
|
47
|
+
function detectWhatsAppMedia(message: proto.IMessage): WhatsAppMediaInfo | null
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Checks message for media fields in order:
|
|
51
|
+
1. `audioMessage?.ptt` → voice note
|
|
52
|
+
2. `audioMessage` → audio
|
|
53
|
+
3. `imageMessage` → image
|
|
54
|
+
4. `videoMessage` → video
|
|
55
|
+
5. `documentMessage` → document
|
|
56
|
+
6. `stickerMessage` → image
|
|
57
|
+
|
|
58
|
+
### Download
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// src/adapters/whatsapp-media.ts
|
|
62
|
+
async function downloadWhatsAppMedia(
|
|
63
|
+
msg: WAMessage,
|
|
64
|
+
sock: WASocket,
|
|
65
|
+
options: MediaDownloadOptions,
|
|
66
|
+
): Promise<MessageAttachment | null>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Uses Baileys' `downloadMediaMessage()`:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const buffer = await downloadMediaMessage(
|
|
73
|
+
msg,
|
|
74
|
+
"buffer",
|
|
75
|
+
{},
|
|
76
|
+
{
|
|
77
|
+
logger: silentLogger,
|
|
78
|
+
reuploadRequest: sock.updateMediaMessage,
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Adapter Integration
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// src/adapters/whatsapp.ts
|
|
87
|
+
createWhatsAppBaileysAdapter({
|
|
88
|
+
mediaEnabled: true,
|
|
89
|
+
mediaMaxSizeBytes: 10 * 1024 * 1024,
|
|
90
|
+
getWorkspace: (spaceId) => ensureSpaceWorkspace(spacesDir, spaceId),
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Size Limits
|
|
95
|
+
|
|
96
|
+
Files are checked against `mediaMaxSizeBytes` twice:
|
|
97
|
+
|
|
98
|
+
1. **Before download** — using `fileLength` from message metadata (may be missing)
|
|
99
|
+
2. **After download** — using actual buffer size
|
|
100
|
+
|
|
101
|
+
Files exceeding the limit are logged and skipped:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
[WARN] Skipping large media file messageId=ABC type=video sizeBytes=52428800 maxBytes=10485760
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Reply Context
|
|
108
|
+
|
|
109
|
+
When replying to a message with media, the reply context includes media info:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Attributes added to <reply_to>
|
|
113
|
+
media_type="image"
|
|
114
|
+
media_mime="image/jpeg"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Example:
|
|
118
|
+
```xml
|
|
119
|
+
<reply_to name="John" jid="123@wa" message_id="ABC" media_type="image" media_mime="image/jpeg">
|
|
120
|
+
[image]
|
|
121
|
+
</reply_to>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## File Naming
|
|
125
|
+
|
|
126
|
+
Pattern: `{timestamp}-{type}.{ext}` or `{timestamp}-{filename}` for documents
|
|
127
|
+
|
|
128
|
+
| Input | Output |
|
|
129
|
+
|-------|--------|
|
|
130
|
+
| image/jpeg | `1709012345-image.jpg` |
|
|
131
|
+
| audio/ogg (voice) | `1709012345-voice.ogg` |
|
|
132
|
+
| application/pdf, "report.pdf" | `1709012345-report.pdf` |
|
|
133
|
+
|
|
134
|
+
## MIME to Extension Mapping
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const MIME_TO_EXT: Record<string, string> = {
|
|
138
|
+
"image/jpeg": "jpg",
|
|
139
|
+
"image/png": "png",
|
|
140
|
+
"image/gif": "gif",
|
|
141
|
+
"image/webp": "webp",
|
|
142
|
+
"audio/ogg": "ogg",
|
|
143
|
+
"audio/mpeg": "mp3",
|
|
144
|
+
"audio/mp4": "m4a",
|
|
145
|
+
"video/mp4": "mp4",
|
|
146
|
+
"video/3gpp": "3gp",
|
|
147
|
+
"application/pdf": "pdf",
|
|
148
|
+
// ... etc
|
|
149
|
+
};
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Unknown MIME types default to `.bin`.
|
|
153
|
+
|
|
154
|
+
## Limitations
|
|
155
|
+
|
|
156
|
+
1. **No re-download** — Media is downloaded once when the message arrives. If the file is deleted, it's gone.
|
|
157
|
+
|
|
158
|
+
2. **No transcription** — Voice notes are saved as audio files. pi cannot play them. Future: add Whisper transcription.
|
|
159
|
+
|
|
160
|
+
3. **Reply context doesn't include file** — When replying to a media message, we include metadata but not the actual file path. The original attachment would need to be looked up.
|
|
161
|
+
|
|
162
|
+
4. **Ephemeral media** — WhatsApp media URLs expire. Download must happen immediately when the message arrives.
|
|
163
|
+
|
|
164
|
+
## Error Handling
|
|
165
|
+
|
|
166
|
+
| Error | Behavior |
|
|
167
|
+
|-------|----------|
|
|
168
|
+
| Download fails | Log error, continue without attachment |
|
|
169
|
+
| Buffer empty | Log error, return null |
|
|
170
|
+
| Size exceeded | Log warning, discard buffer |
|
|
171
|
+
| Write fails | Throw error (propagates up) |
|
package/docs/memory.md
CHANGED
|
@@ -1,137 +1,137 @@
|
|
|
1
|
-
# Memory
|
|
2
|
-
|
|
3
|
-
Mercury stores memory per **space** in the space workspace directory. Memory behavior is extension-driven (for example, via a napkin extension).
|
|
4
|
-
|
|
5
|
-
## How It Works
|
|
6
|
-
|
|
7
|
-
Each space gets a workspace at:
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
.mercury/spaces/<space-id>/
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Core directories Mercury manages:
|
|
14
|
-
|
|
15
|
-
```text
|
|
16
|
-
.mercury/spaces/<space-id>/
|
|
17
|
-
├── inbox/ # Media received from users
|
|
18
|
-
├── outbox/ # Files produced by the agent
|
|
19
|
-
├── AGENTS.md # Space instructions
|
|
20
|
-
└── .mercury.session.jsonl
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Additional vault structure (for example `.obsidian/`, `knowledge/`, `daily/`, `entities/`) is created by installed extensions.
|
|
24
|
-
|
|
25
|
-
## Vault Structure
|
|
26
|
-
|
|
27
|
-
There is no single required memory schema in core Mercury. The exact structure depends on your extension setup.
|
|
28
|
-
|
|
29
|
-
A common pattern (napkin example) is:
|
|
30
|
-
|
|
31
|
-
```text
|
|
32
|
-
knowledge/
|
|
33
|
-
├── people/
|
|
34
|
-
├── projects/
|
|
35
|
-
├── references/
|
|
36
|
-
└── daily/
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Conversations do not get their own vaults — multiple platform conversations can link into the same space.
|
|
40
|
-
|
|
41
|
-
## Agent Capabilities
|
|
42
|
-
|
|
43
|
-
The agent discovers extension commands via installed skills (for example `napkin` skill in `.mercury/extensions/napkin/skill/`).
|
|
44
|
-
|
|
45
|
-
### Reading
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
napkin search "query" # Find relevant files
|
|
49
|
-
napkin read "filename" # Read a specific file
|
|
50
|
-
napkin link back --file "name" # See what links to a file
|
|
51
|
-
napkin daily read # Read today's daily note
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Writing
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
napkin create --name "Liat" --path entities --content "..."
|
|
58
|
-
napkin append --file "Liat" --content "..."
|
|
59
|
-
napkin property set --file "Liat" --name birthday --value "April 15"
|
|
60
|
-
napkin daily append --content "- Discussed vacation plans"
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Wikilinks
|
|
64
|
-
|
|
65
|
-
The agent uses `[[wikilinks]]` when mentioning entities. This creates a navigable graph:
|
|
66
|
-
|
|
67
|
-
```markdown
|
|
68
|
-
---
|
|
69
|
-
type: person
|
|
70
|
-
relationship: wife
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
# Liat
|
|
74
|
-
|
|
75
|
-
[[Michael]]'s wife. Planning a surprise party at [[Dizengoff Italian Place]].
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## User Interaction
|
|
79
|
-
|
|
80
|
-
Users manage memory through natural chat:
|
|
81
|
-
|
|
82
|
-
| User says | What happens |
|
|
83
|
-
|-----------|--------------|
|
|
84
|
-
| "Remember that Liat's birthday is April 15" | Agent writes to `entities/Liat.md` |
|
|
85
|
-
| "What do you know about Liat?" | Agent reads and summarizes the entity file |
|
|
86
|
-
| "Forget everything about the project" | Agent deletes the entity file |
|
|
87
|
-
|
|
88
|
-
## Entity Format
|
|
89
|
-
|
|
90
|
-
Entities are markdown files with optional YAML frontmatter:
|
|
91
|
-
|
|
92
|
-
```markdown
|
|
93
|
-
---
|
|
94
|
-
type: person
|
|
95
|
-
birthday: April 15
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
# Liat
|
|
99
|
-
|
|
100
|
-
Context and notes about Liat.
|
|
101
|
-
|
|
102
|
-
_2026-02-20:_ Booked the Italian place for April 12.
|
|
103
|
-
_2026-02-25:_ Changed venue to [[Cafe Nimrod]].
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
- **Frontmatter** — Structured attributes (replace semantics)
|
|
107
|
-
- **Body** — Accumulated context (append semantics, timestamped)
|
|
108
|
-
- **Wikilinks** — Connections to other entities
|
|
109
|
-
|
|
110
|
-
## Conditional Context
|
|
111
|
-
|
|
112
|
-
Mercury can skip loading the full session for standalone prompts (e.g. "what's 2+2?"), reducing token usage. After the run, the prompt and reply are merged back into the session so history stays complete.
|
|
113
|
-
|
|
114
|
-
See [conditional-context.md](conditional-context.md) for details and configuration.
|
|
115
|
-
|
|
116
|
-
## Persistence
|
|
117
|
-
|
|
118
|
-
Memory persists because the agent writes to disk during conversation. When a session compacts or restarts, the vault files remain — the agent reads them fresh on next interaction.
|
|
119
|
-
|
|
120
|
-
The vault is plain markdown. You can:
|
|
121
|
-
- Open it in Obsidian and browse the graph
|
|
122
|
-
- Edit files directly from the host
|
|
123
|
-
- Back it up like any other directory
|
|
124
|
-
|
|
125
|
-
## Space preferences (built-in)
|
|
126
|
-
|
|
127
|
-
Short, structured **per-space** hints (sources, habits, rules) can be stored in SQLite and managed from chat via `mrctl prefs` (see the built-in **preferences** skill). The host injects them into each run as a `<preferences>` block in the user prompt. See [prd-chat-memory.md](prd-chat-memory.md).
|
|
128
|
-
|
|
129
|
-
## Configuration
|
|
130
|
-
|
|
131
|
-
Memory behavior is controlled by installed extensions and their config.
|
|
132
|
-
|
|
133
|
-
To use a shared Obsidian vault across tools, symlink or mount it:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
ln -s /path/to/your/vault .mercury/spaces/main
|
|
137
|
-
```
|
|
1
|
+
# Memory
|
|
2
|
+
|
|
3
|
+
Mercury stores memory per **space** in the space workspace directory. Memory behavior is extension-driven (for example, via a napkin extension).
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
Each space gets a workspace at:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
.mercury/spaces/<space-id>/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Core directories Mercury manages:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
.mercury/spaces/<space-id>/
|
|
17
|
+
├── inbox/ # Media received from users
|
|
18
|
+
├── outbox/ # Files produced by the agent
|
|
19
|
+
├── AGENTS.md # Space instructions
|
|
20
|
+
└── .mercury.session.jsonl
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Additional vault structure (for example `.obsidian/`, `knowledge/`, `daily/`, `entities/`) is created by installed extensions.
|
|
24
|
+
|
|
25
|
+
## Vault Structure
|
|
26
|
+
|
|
27
|
+
There is no single required memory schema in core Mercury. The exact structure depends on your extension setup.
|
|
28
|
+
|
|
29
|
+
A common pattern (napkin example) is:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
knowledge/
|
|
33
|
+
├── people/
|
|
34
|
+
├── projects/
|
|
35
|
+
├── references/
|
|
36
|
+
└── daily/
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Conversations do not get their own vaults — multiple platform conversations can link into the same space.
|
|
40
|
+
|
|
41
|
+
## Agent Capabilities
|
|
42
|
+
|
|
43
|
+
The agent discovers extension commands via installed skills (for example `napkin` skill in `.mercury/extensions/napkin/skill/`).
|
|
44
|
+
|
|
45
|
+
### Reading
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
napkin search "query" # Find relevant files
|
|
49
|
+
napkin read "filename" # Read a specific file
|
|
50
|
+
napkin link back --file "name" # See what links to a file
|
|
51
|
+
napkin daily read # Read today's daily note
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Writing
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
napkin create --name "Liat" --path entities --content "..."
|
|
58
|
+
napkin append --file "Liat" --content "..."
|
|
59
|
+
napkin property set --file "Liat" --name birthday --value "April 15"
|
|
60
|
+
napkin daily append --content "- Discussed vacation plans"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Wikilinks
|
|
64
|
+
|
|
65
|
+
The agent uses `[[wikilinks]]` when mentioning entities. This creates a navigable graph:
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
---
|
|
69
|
+
type: person
|
|
70
|
+
relationship: wife
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
# Liat
|
|
74
|
+
|
|
75
|
+
[[Michael]]'s wife. Planning a surprise party at [[Dizengoff Italian Place]].
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## User Interaction
|
|
79
|
+
|
|
80
|
+
Users manage memory through natural chat:
|
|
81
|
+
|
|
82
|
+
| User says | What happens |
|
|
83
|
+
|-----------|--------------|
|
|
84
|
+
| "Remember that Liat's birthday is April 15" | Agent writes to `entities/Liat.md` |
|
|
85
|
+
| "What do you know about Liat?" | Agent reads and summarizes the entity file |
|
|
86
|
+
| "Forget everything about the project" | Agent deletes the entity file |
|
|
87
|
+
|
|
88
|
+
## Entity Format
|
|
89
|
+
|
|
90
|
+
Entities are markdown files with optional YAML frontmatter:
|
|
91
|
+
|
|
92
|
+
```markdown
|
|
93
|
+
---
|
|
94
|
+
type: person
|
|
95
|
+
birthday: April 15
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
# Liat
|
|
99
|
+
|
|
100
|
+
Context and notes about Liat.
|
|
101
|
+
|
|
102
|
+
_2026-02-20:_ Booked the Italian place for April 12.
|
|
103
|
+
_2026-02-25:_ Changed venue to [[Cafe Nimrod]].
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- **Frontmatter** — Structured attributes (replace semantics)
|
|
107
|
+
- **Body** — Accumulated context (append semantics, timestamped)
|
|
108
|
+
- **Wikilinks** — Connections to other entities
|
|
109
|
+
|
|
110
|
+
## Conditional Context
|
|
111
|
+
|
|
112
|
+
Mercury can skip loading the full session for standalone prompts (e.g. "what's 2+2?"), reducing token usage. After the run, the prompt and reply are merged back into the session so history stays complete.
|
|
113
|
+
|
|
114
|
+
See [conditional-context.md](conditional-context.md) for details and configuration.
|
|
115
|
+
|
|
116
|
+
## Persistence
|
|
117
|
+
|
|
118
|
+
Memory persists because the agent writes to disk during conversation. When a session compacts or restarts, the vault files remain — the agent reads them fresh on next interaction.
|
|
119
|
+
|
|
120
|
+
The vault is plain markdown. You can:
|
|
121
|
+
- Open it in Obsidian and browse the graph
|
|
122
|
+
- Edit files directly from the host
|
|
123
|
+
- Back it up like any other directory
|
|
124
|
+
|
|
125
|
+
## Space preferences (built-in)
|
|
126
|
+
|
|
127
|
+
Short, structured **per-space** hints (sources, habits, rules) can be stored in SQLite and managed from chat via `mrctl prefs` (see the built-in **preferences** skill). The host injects them into each run as a `<preferences>` block in the user prompt. See [prd-chat-memory.md](prd-chat-memory.md).
|
|
128
|
+
|
|
129
|
+
## Configuration
|
|
130
|
+
|
|
131
|
+
Memory behavior is controlled by installed extensions and their config.
|
|
132
|
+
|
|
133
|
+
To use a shared Obsidian vault across tools, symlink or mount it:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
ln -s /path/to/your/vault .mercury/spaces/main
|
|
137
|
+
```
|