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 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,6 +1,6 @@
1
1
  {
2
2
  "name": "mercury-agent",
3
- "version": "0.4.26",
3
+ "version": "0.4.27",
4
4
  "description": "Personal AI assistant for chat platforms (WhatsApp, Slack, Discord, Telegram)",
5
5
  "license": "MIT",
6
6
  "author": "Avishai Tsabari",
@@ -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
- # admin_numbers: # 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
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
@@ -167,7 +167,7 @@ const mercuryFileSchema = z
167
167
  dm_auto_space: z
168
168
  .object({
169
169
  enabled: z.boolean().optional(),
170
- admin_numbers: z.array(z.string()).optional(),
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?.admin_numbers != null) {
298
- o.dmAutoSpaceAdminNumbers = f.dm_auto_space.admin_numbers.join(",");
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
- dmAutoSpaceAdminNumbers: "MERCURY_DM_AUTO_SPACE_ADMIN_NUMBERS",
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
- dmAutoSpaceAdminNumbers: z.string().default(""),
255
+ dmAutoSpaceAdminIds: z.string().default(""),
256
256
  dmAutoSpaceDefaultSystemPrompt: z.string().default(""),
257
257
  dmAutoSpaceDefaultMemberPermissions: z.string().default("prompt,prefs.get"),
258
258
  });
@@ -9,7 +9,7 @@ export interface ConversationResolution {
9
9
 
10
10
  export interface AutoSpaceConfig {
11
11
  enabled: boolean;
12
- adminNumbers: string[];
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.adminNumbers.some(
64
+ const isAdmin = autoSpace.adminIds.some(
65
65
  (n) => normalizePhone(n) === senderNormalized,
66
66
  );
67
67
 
@@ -28,7 +28,7 @@ export function createMessageHandler(opts: MessageHandlerOptions) {
28
28
  const autoSpaceConfig: AutoSpaceConfig | undefined = config.dmAutoSpaceEnabled
29
29
  ? {
30
30
  enabled: true,
31
- adminNumbers: config.dmAutoSpaceAdminNumbers
31
+ adminIds: config.dmAutoSpaceAdminIds
32
32
  .split(",")
33
33
  .map((s) => s.trim())
34
34
  .filter(Boolean),