mercury-agent 0.4.26 → 0.4.27
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 +23 -0
- package/package.json +1 -1
- package/resources/templates/mercury.example.yaml +84 -84
- package/src/config-file.ts +4 -4
- package/src/config.ts +1 -1
- package/src/core/conversation.ts +2 -2
- package/src/core/handler.ts +1 -1
package/README.md
CHANGED
|
@@ -131,6 +131,7 @@ Each space is a user-defined memory boundary with its own workspace and pi sessi
|
|
|
131
131
|
| **Media** | Images, documents, voice notes | [docs/media/overview.md](docs/media/overview.md) |
|
|
132
132
|
| **KB Distillation** | Extract lasting knowledge from chats | [docs/kb-distillation.md](docs/kb-distillation.md) |
|
|
133
133
|
| **Extensions** | TypeScript plugins for CLIs, skills, jobs, hooks | [docs/extensions.md](docs/extensions.md) |
|
|
134
|
+
| **DM Auto-Space** | Auto-create isolated spaces per customer DM | [docs/rate-limiting.md](docs/rate-limiting.md) |
|
|
134
135
|
|
|
135
136
|
---
|
|
136
137
|
|
|
@@ -377,6 +378,28 @@ Supported OAuth providers: Anthropic, GitHub Copilot, Google Gemini CLI, Antigra
|
|
|
377
378
|
| `MERCURY_TRIGGER_PATTERNS` | `@Mercury,Mercury` | Trigger patterns |
|
|
378
379
|
| `MERCURY_ADMINS` | — | Pre-seeded admin user IDs |
|
|
379
380
|
|
|
381
|
+
### DM Auto-Space
|
|
382
|
+
|
|
383
|
+
Auto-create isolated spaces for each customer who DMs your bot. Each customer gets their own space with persistent context, configurable permissions, and rate limits.
|
|
384
|
+
|
|
385
|
+
```yaml
|
|
386
|
+
# mercury.yaml
|
|
387
|
+
dm_auto_space:
|
|
388
|
+
enabled: true
|
|
389
|
+
admin_ids: # platform IDs — auto-link to "main" space
|
|
390
|
+
- "24417056866472" # WhatsApp LID, Telegram user ID, etc.
|
|
391
|
+
default_system_prompt: "You are a helpful assistant."
|
|
392
|
+
default_member_permissions: "prompt,prefs.get" # restrict customers to chat only
|
|
393
|
+
|
|
394
|
+
runtime:
|
|
395
|
+
rate_limit_daily_member: 20 # global daily cap for members (0 = unlimited)
|
|
396
|
+
rate_limit_daily_admin: 0 # global daily cap for admins (0 = unlimited)
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
`admin_ids` values are platform-specific identifiers — check the dashboard Conversations page to see the format (e.g. WhatsApp LID digits, Telegram numeric user ID).
|
|
400
|
+
|
|
401
|
+
Auto-created spaces are seeded with `trigger.match=always`, `context.mode=context`, and the configured member permissions. Per-space rate limits are manageable from the dashboard.
|
|
402
|
+
|
|
380
403
|
### Per-space Config
|
|
381
404
|
|
|
382
405
|
Conversations are discovered from incoming traffic. Unlinked conversations stay idle until you attach them to a space via `mercury link <conversation-id> <space-id>` or the dashboard.
|
package/package.json
CHANGED
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
# Copy to mercury.yaml in your project root (optional).
|
|
2
|
-
# Precedence: MERCURY_* env vars override this file when the env key is set.
|
|
3
|
-
# Secrets (API keys, tokens, MERCURY_API_SECRET, etc.) belong in .env only — not here.
|
|
4
|
-
|
|
5
|
-
# server:
|
|
6
|
-
# port: 8787
|
|
7
|
-
# bot_username: mercury
|
|
8
|
-
|
|
9
|
-
# model:
|
|
10
|
-
# chain:
|
|
11
|
-
# - provider: anthropic
|
|
12
|
-
# model: claude-sonnet-4-20250514
|
|
13
|
-
# # Legacy single primary + optional fallback (when chain is omitted):
|
|
14
|
-
# # provider: anthropic
|
|
15
|
-
# # model: claude-sonnet-4-20250514
|
|
16
|
-
# # fallback_provider: openai
|
|
17
|
-
# # fallback: gpt-4o-mini
|
|
18
|
-
# # max_retries_per_leg: 2
|
|
19
|
-
# # chain_budget_ms: 120000
|
|
20
|
-
# # capabilities: { tools: false }
|
|
21
|
-
|
|
22
|
-
# Top-level alias for model.chain (optional; model.chain wins if both are set):
|
|
23
|
-
# model_chain:
|
|
24
|
-
# - provider: google
|
|
25
|
-
# model: gemini-2.5-flash
|
|
26
|
-
|
|
27
|
-
# ingress:
|
|
28
|
-
# discord: false
|
|
29
|
-
# slack: false
|
|
30
|
-
# teams: false
|
|
31
|
-
# whatsapp: false
|
|
32
|
-
# telegram: false
|
|
33
|
-
|
|
34
|
-
# runtime:
|
|
35
|
-
# data_dir: .mercury
|
|
36
|
-
# # auth_path: ...
|
|
37
|
-
# # whatsapp_auth_dir: .mercury/whatsapp-auth
|
|
38
|
-
# max_concurrency: 2
|
|
39
|
-
# log_level: info
|
|
40
|
-
# log_format: text
|
|
41
|
-
# rate_limit_per_user: 10
|
|
42
|
-
# rate_limit_window_ms: 60000
|
|
43
|
-
# rate_limit_daily_member: 0 # 0 = unlimited; global daily message cap for members
|
|
44
|
-
# rate_limit_daily_admin: 0 # 0 = unlimited; global daily message cap for admins
|
|
45
|
-
|
|
46
|
-
# trigger:
|
|
47
|
-
# patterns: "@Mercury,Mercury"
|
|
48
|
-
# match: mention
|
|
49
|
-
|
|
50
|
-
# conditional_context:
|
|
51
|
-
# enabled: true
|
|
52
|
-
# classifier: heuristic
|
|
53
|
-
# # classifier_provider: groq
|
|
54
|
-
# # classifier_model: llama-3.3-70b-versatile
|
|
55
|
-
|
|
56
|
-
# compaction:
|
|
57
|
-
# keep_recent_tokens: 20000
|
|
58
|
-
# # After each full-session run, auto-compact if the pi session has more than this many entries (10–10000). Omit to disable.
|
|
59
|
-
# # auto_compact_threshold: 50
|
|
60
|
-
|
|
61
|
-
# agent:
|
|
62
|
-
# image: ghcr.io/avishai-tsabari/mercury-agent:latest
|
|
63
|
-
# container_timeout_ms: 300000
|
|
64
|
-
# container_bwrap_docker_compat: false
|
|
65
|
-
|
|
66
|
-
# discord:
|
|
67
|
-
# gateway_duration_ms: 600000
|
|
68
|
-
|
|
69
|
-
# telegram:
|
|
70
|
-
# format_enabled: true
|
|
71
|
-
|
|
72
|
-
# media:
|
|
73
|
-
# enabled: true
|
|
74
|
-
# max_size_mb: 10
|
|
75
|
-
|
|
76
|
-
# permissions:
|
|
77
|
-
# admins: ""
|
|
78
|
-
|
|
79
|
-
# dm_auto_space:
|
|
80
|
-
# enabled: false
|
|
81
|
-
#
|
|
82
|
-
# - "972501234567"
|
|
83
|
-
# default_system_prompt: "" # seeded into auto-created customer spaces
|
|
84
|
-
# default_member_permissions: "prompt,prefs.get" # restrict customers to chat only
|
|
1
|
+
# Copy to mercury.yaml in your project root (optional).
|
|
2
|
+
# Precedence: MERCURY_* env vars override this file when the env key is set.
|
|
3
|
+
# Secrets (API keys, tokens, MERCURY_API_SECRET, etc.) belong in .env only — not here.
|
|
4
|
+
|
|
5
|
+
# server:
|
|
6
|
+
# port: 8787
|
|
7
|
+
# bot_username: mercury
|
|
8
|
+
|
|
9
|
+
# model:
|
|
10
|
+
# chain:
|
|
11
|
+
# - provider: anthropic
|
|
12
|
+
# model: claude-sonnet-4-20250514
|
|
13
|
+
# # Legacy single primary + optional fallback (when chain is omitted):
|
|
14
|
+
# # provider: anthropic
|
|
15
|
+
# # model: claude-sonnet-4-20250514
|
|
16
|
+
# # fallback_provider: openai
|
|
17
|
+
# # fallback: gpt-4o-mini
|
|
18
|
+
# # max_retries_per_leg: 2
|
|
19
|
+
# # chain_budget_ms: 120000
|
|
20
|
+
# # capabilities: { tools: false }
|
|
21
|
+
|
|
22
|
+
# Top-level alias for model.chain (optional; model.chain wins if both are set):
|
|
23
|
+
# model_chain:
|
|
24
|
+
# - provider: google
|
|
25
|
+
# model: gemini-2.5-flash
|
|
26
|
+
|
|
27
|
+
# ingress:
|
|
28
|
+
# discord: false
|
|
29
|
+
# slack: false
|
|
30
|
+
# teams: false
|
|
31
|
+
# whatsapp: false
|
|
32
|
+
# telegram: false
|
|
33
|
+
|
|
34
|
+
# runtime:
|
|
35
|
+
# data_dir: .mercury
|
|
36
|
+
# # auth_path: ...
|
|
37
|
+
# # whatsapp_auth_dir: .mercury/whatsapp-auth
|
|
38
|
+
# max_concurrency: 2
|
|
39
|
+
# log_level: info
|
|
40
|
+
# log_format: text
|
|
41
|
+
# rate_limit_per_user: 10
|
|
42
|
+
# rate_limit_window_ms: 60000
|
|
43
|
+
# rate_limit_daily_member: 0 # 0 = unlimited; global daily message cap for members
|
|
44
|
+
# rate_limit_daily_admin: 0 # 0 = unlimited; global daily message cap for admins
|
|
45
|
+
|
|
46
|
+
# trigger:
|
|
47
|
+
# patterns: "@Mercury,Mercury"
|
|
48
|
+
# match: mention
|
|
49
|
+
|
|
50
|
+
# conditional_context:
|
|
51
|
+
# enabled: true
|
|
52
|
+
# classifier: heuristic
|
|
53
|
+
# # classifier_provider: groq
|
|
54
|
+
# # classifier_model: llama-3.3-70b-versatile
|
|
55
|
+
|
|
56
|
+
# compaction:
|
|
57
|
+
# keep_recent_tokens: 20000
|
|
58
|
+
# # After each full-session run, auto-compact if the pi session has more than this many entries (10–10000). Omit to disable.
|
|
59
|
+
# # auto_compact_threshold: 50
|
|
60
|
+
|
|
61
|
+
# agent:
|
|
62
|
+
# image: ghcr.io/avishai-tsabari/mercury-agent:latest
|
|
63
|
+
# container_timeout_ms: 300000
|
|
64
|
+
# container_bwrap_docker_compat: false
|
|
65
|
+
|
|
66
|
+
# discord:
|
|
67
|
+
# gateway_duration_ms: 600000
|
|
68
|
+
|
|
69
|
+
# telegram:
|
|
70
|
+
# format_enabled: true
|
|
71
|
+
|
|
72
|
+
# media:
|
|
73
|
+
# enabled: true
|
|
74
|
+
# max_size_mb: 10
|
|
75
|
+
|
|
76
|
+
# permissions:
|
|
77
|
+
# admins: ""
|
|
78
|
+
|
|
79
|
+
# dm_auto_space:
|
|
80
|
+
# enabled: false
|
|
81
|
+
# admin_ids: # auto-link to "main" space
|
|
82
|
+
# - "972501234567"
|
|
83
|
+
# default_system_prompt: "" # seeded into auto-created customer spaces
|
|
84
|
+
# default_member_permissions: "prompt,prefs.get" # restrict customers to chat only
|
package/src/config-file.ts
CHANGED
|
@@ -167,7 +167,7 @@ const mercuryFileSchema = z
|
|
|
167
167
|
dm_auto_space: z
|
|
168
168
|
.object({
|
|
169
169
|
enabled: z.boolean().optional(),
|
|
170
|
-
|
|
170
|
+
admin_ids: z.array(z.string()).optional(),
|
|
171
171
|
default_system_prompt: z.string().optional(),
|
|
172
172
|
default_member_permissions: z.string().optional(),
|
|
173
173
|
})
|
|
@@ -294,8 +294,8 @@ function flattenMercuryFile(f: MercuryFile): RawMercuryConfigInput {
|
|
|
294
294
|
if (f.dm_auto_space?.enabled != null) {
|
|
295
295
|
o.dmAutoSpaceEnabled = f.dm_auto_space.enabled;
|
|
296
296
|
}
|
|
297
|
-
if (f.dm_auto_space?.
|
|
298
|
-
o.
|
|
297
|
+
if (f.dm_auto_space?.admin_ids != null) {
|
|
298
|
+
o.dmAutoSpaceAdminIds = f.dm_auto_space.admin_ids.join(",");
|
|
299
299
|
}
|
|
300
300
|
if (f.dm_auto_space?.default_system_prompt != null) {
|
|
301
301
|
o.dmAutoSpaceDefaultSystemPrompt = f.dm_auto_space.default_system_prompt;
|
|
@@ -370,7 +370,7 @@ const CAMEL_TO_ENV: Record<string, string> = {
|
|
|
370
370
|
rateLimitDailyMember: "MERCURY_RATE_LIMIT_DAILY_MEMBER",
|
|
371
371
|
rateLimitDailyAdmin: "MERCURY_RATE_LIMIT_DAILY_ADMIN",
|
|
372
372
|
dmAutoSpaceEnabled: "MERCURY_DM_AUTO_SPACE_ENABLED",
|
|
373
|
-
|
|
373
|
+
dmAutoSpaceAdminIds: "MERCURY_DM_AUTO_SPACE_ADMIN_IDS",
|
|
374
374
|
dmAutoSpaceDefaultSystemPrompt: "MERCURY_DM_AUTO_SPACE_DEFAULT_SYSTEM_PROMPT",
|
|
375
375
|
dmAutoSpaceDefaultMemberPermissions:
|
|
376
376
|
"MERCURY_DM_AUTO_SPACE_DEFAULT_MEMBER_PERMISSIONS",
|
package/src/config.ts
CHANGED
|
@@ -252,7 +252,7 @@ const schema = z.object({
|
|
|
252
252
|
|
|
253
253
|
// ─── DM Auto-Space ─────────────────────────────────────────────────
|
|
254
254
|
dmAutoSpaceEnabled: booleanFromEnv.default(false),
|
|
255
|
-
|
|
255
|
+
dmAutoSpaceAdminIds: z.string().default(""),
|
|
256
256
|
dmAutoSpaceDefaultSystemPrompt: z.string().default(""),
|
|
257
257
|
dmAutoSpaceDefaultMemberPermissions: z.string().default("prompt,prefs.get"),
|
|
258
258
|
});
|
package/src/core/conversation.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface ConversationResolution {
|
|
|
9
9
|
|
|
10
10
|
export interface AutoSpaceConfig {
|
|
11
11
|
enabled: boolean;
|
|
12
|
-
|
|
12
|
+
adminIds: string[];
|
|
13
13
|
defaultSystemPrompt: string;
|
|
14
14
|
defaultMemberPermissions: string;
|
|
15
15
|
rateLimitDailyMember: number;
|
|
@@ -61,7 +61,7 @@ export function resolveConversation(
|
|
|
61
61
|
if (!autoSpace?.enabled || kind !== "dm") return null;
|
|
62
62
|
|
|
63
63
|
const senderNormalized = normalizePhone(externalId);
|
|
64
|
-
const isAdmin = autoSpace.
|
|
64
|
+
const isAdmin = autoSpace.adminIds.some(
|
|
65
65
|
(n) => normalizePhone(n) === senderNormalized,
|
|
66
66
|
);
|
|
67
67
|
|
package/src/core/handler.ts
CHANGED
|
@@ -28,7 +28,7 @@ export function createMessageHandler(opts: MessageHandlerOptions) {
|
|
|
28
28
|
const autoSpaceConfig: AutoSpaceConfig | undefined = config.dmAutoSpaceEnabled
|
|
29
29
|
? {
|
|
30
30
|
enabled: true,
|
|
31
|
-
|
|
31
|
+
adminIds: config.dmAutoSpaceAdminIds
|
|
32
32
|
.split(",")
|
|
33
33
|
.map((s) => s.trim())
|
|
34
34
|
.filter(Boolean),
|