mercury-agent 0.5.0 → 0.5.1

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 (123) hide show
  1. package/README.md +451 -451
  2. package/container/Dockerfile +127 -127
  3. package/container/Dockerfile.base +109 -109
  4. package/container/Dockerfile.power +17 -17
  5. package/container/agent-package.json +8 -8
  6. package/container/build.sh +54 -54
  7. package/docs/ROADMAP.md +3 -4
  8. package/docs/archive/summarization/2026-07-02-recent-dev-summary.md +71 -0
  9. package/docs/auth/dashboard.md +28 -28
  10. package/docs/auth/overview.md +109 -109
  11. package/docs/auth/whatsapp.md +173 -173
  12. package/docs/authoring-profiles.md +174 -174
  13. package/docs/configuration.md +54 -54
  14. package/docs/container-lifecycle.md +349 -349
  15. package/docs/{bugs/bwrap-privileged-linux-docker.md → debug/major/2026-07-02-bwrap-privileged-linux-docker.md} +21 -1
  16. package/docs/{bugs/e2big-prompt-delivery-fix.md → debug/major/2026-07-02-e2big-prompt-delivery-fix.md} +27 -1
  17. package/docs/{bugs/registry-pull-no-local-fallback.md → debug/major/2026-07-02-registry-pull-no-local-fallback.md} +27 -1
  18. package/docs/debug/summarization/2026-07-02-common-bug-patterns.md +72 -0
  19. package/docs/deployment.md +199 -199
  20. package/docs/extensions.md +375 -375
  21. package/docs/graceful-shutdown.md +62 -62
  22. package/docs/kb-distillation.md +77 -77
  23. package/docs/media/overview.md +140 -140
  24. package/docs/media/whatsapp.md +171 -171
  25. package/docs/memory.md +137 -137
  26. package/docs/permissions.md +217 -217
  27. package/docs/pipeline.md +228 -228
  28. package/docs/prd-chat-memory.md +76 -76
  29. package/docs/prd-config-load.md +82 -82
  30. package/docs/rate-limiting.md +229 -229
  31. package/docs/scheduler.md +288 -288
  32. package/docs/setup-discord.md +100 -100
  33. package/docs/setup-slack.md +119 -119
  34. package/docs/setup-whatsapp.md +94 -94
  35. package/docs/subagents.md +166 -166
  36. package/docs/web-search.md +62 -62
  37. package/examples/extensions/README.md +12 -12
  38. package/examples/extensions/charts/index.ts +13 -13
  39. package/examples/extensions/charts/skill/SKILL.md +98 -98
  40. package/examples/extensions/gws/README.md +52 -52
  41. package/examples/extensions/gws/skill/SKILL.md +57 -57
  42. package/examples/extensions/gws/skill/references/calendar.md +101 -101
  43. package/examples/extensions/gws/skill/references/docs.md +65 -65
  44. package/examples/extensions/gws/skill/references/drive.md +79 -79
  45. package/examples/extensions/gws/skill/references/gmail.md +85 -85
  46. package/examples/extensions/gws/skill/references/sheets.md +60 -60
  47. package/examples/extensions/napkin/skill/SKILL.md +728 -728
  48. package/examples/extensions/pdf/skill/LICENSE.txt +30 -30
  49. package/examples/extensions/pdf/skill/SKILL.md +314 -314
  50. package/examples/extensions/pdf/skill/forms.md +294 -294
  51. package/examples/extensions/pdf/skill/reference.md +611 -611
  52. package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -65
  53. package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -11
  54. package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -33
  55. package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -37
  56. package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -122
  57. package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -115
  58. package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -98
  59. package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -107
  60. package/examples/extensions/permission-guard/index.ts +65 -65
  61. package/examples/extensions/pinchtab/skill/SKILL.md +224 -224
  62. package/examples/extensions/pinchtab/skill/TRUST.md +69 -69
  63. package/examples/extensions/pinchtab/skill/references/api.md +297 -297
  64. package/examples/extensions/pinchtab/skill/references/env.md +45 -45
  65. package/examples/extensions/pinchtab/skill/references/profiles.md +107 -107
  66. package/examples/extensions/tradestation/host/refresh.ts +102 -102
  67. package/examples/extensions/tradestation/index.ts +153 -153
  68. package/examples/extensions/tradestation/skill/SKILL.md +67 -67
  69. package/examples/extensions/voice-synth/index.ts +94 -94
  70. package/examples/extensions/voice-synth/skill/SKILL.md +38 -38
  71. package/examples/extensions/voice-transcribe/requirements.txt +8 -8
  72. package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -179
  73. package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -53
  74. package/examples/extensions/yahoo-mail/cli/package.json +13 -13
  75. package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -78
  76. package/package.json +106 -106
  77. package/resources/agents/explore.md +50 -50
  78. package/resources/agents/worker.md +24 -24
  79. package/resources/connection-env-vars.json +25 -25
  80. package/resources/pi-extensions/subagent/agents.ts +126 -126
  81. package/resources/pi-extensions/subagent/index.ts +964 -964
  82. package/resources/profiles/coding/AGENTS.md +43 -43
  83. package/resources/profiles/coding/mercury-profile.yaml +15 -15
  84. package/resources/profiles/general/AGENTS.md +31 -31
  85. package/resources/profiles/general/mercury-profile.yaml +15 -15
  86. package/resources/profiles/research/AGENTS.md +40 -40
  87. package/resources/profiles/research/mercury-profile.yaml +15 -15
  88. package/resources/skills/config/SKILL.md +25 -25
  89. package/resources/skills/context/SKILL.md +33 -33
  90. package/resources/skills/conversation-recap/SKILL.md +19 -19
  91. package/resources/skills/mutes/SKILL.md +31 -31
  92. package/resources/skills/permissions/SKILL.md +19 -19
  93. package/resources/skills/preferences/SKILL.md +31 -31
  94. package/resources/skills/recall/SKILL.md +24 -24
  95. package/resources/skills/roles/SKILL.md +18 -18
  96. package/resources/skills/spaces/SKILL.md +18 -18
  97. package/resources/skills/tasks/SKILL.md +45 -45
  98. package/resources/templates/AGENTS.md +157 -157
  99. package/resources/templates/env.template +38 -38
  100. package/resources/templates/mercury.example.yaml +99 -99
  101. package/src/agent/container-runner.ts +1346 -1346
  102. package/src/cli/mercury.ts +38 -6
  103. package/src/cli/mrctl.ts +636 -636
  104. package/src/config-file.ts +540 -540
  105. package/src/config.ts +339 -339
  106. package/src/core/api.ts +125 -125
  107. package/src/core/caller-token.ts +101 -101
  108. package/src/core/permissions.ts +228 -228
  109. package/src/core/profiles.ts +271 -271
  110. package/src/core/routes/capability.ts +70 -70
  111. package/src/core/routes/index.ts +15 -15
  112. package/src/core/runtime.ts +1530 -1530
  113. package/src/dashboard/index.html +729 -729
  114. package/src/extensions/api.ts +273 -273
  115. package/src/extensions/loader.ts +286 -286
  116. package/src/extensions/types.ts +517 -517
  117. package/src/main.ts +605 -605
  118. package/docs/pending-updates/applicative-profiles.md +0 -15
  119. package/docs/pending-updates/caller-bound-capability-token.md +0 -15
  120. package/docs/pending-updates/dm-auto-space.md +0 -15
  121. /package/docs/archive/{2026-07-01-applicative-profiles.md → applicative-profiles/2026-07-01-applicative-profiles.md} +0 -0
  122. /package/docs/archive/{2026-07-01-caller-bound-capability-token.md → applicative-profiles/2026-07-01-caller-bound-capability-token.md} +0 -0
  123. /package/docs/archive/{2026-07-01-dm-auto-space.md → applicative-profiles/2026-07-01-dm-auto-space.md} +0 -0
@@ -1,126 +1,126 @@
1
- /**
2
- * Agent discovery and configuration
3
- */
4
-
5
- import * as fs from "node:fs";
6
- import * as path from "node:path";
7
- import { getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent";
8
-
9
- export type AgentScope = "user" | "project" | "both";
10
-
11
- export interface AgentConfig {
12
- name: string;
13
- description: string;
14
- tools?: string[];
15
- model?: string;
16
- systemPrompt: string;
17
- source: "user" | "project";
18
- filePath: string;
19
- }
20
-
21
- export interface AgentDiscoveryResult {
22
- agents: AgentConfig[];
23
- projectAgentsDir: string | null;
24
- }
25
-
26
- function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] {
27
- const agents: AgentConfig[] = [];
28
-
29
- if (!fs.existsSync(dir)) {
30
- return agents;
31
- }
32
-
33
- let entries: fs.Dirent[];
34
- try {
35
- entries = fs.readdirSync(dir, { withFileTypes: true });
36
- } catch {
37
- return agents;
38
- }
39
-
40
- for (const entry of entries) {
41
- if (!entry.name.endsWith(".md")) continue;
42
- if (!entry.isFile() && !entry.isSymbolicLink()) continue;
43
-
44
- const filePath = path.join(dir, entry.name);
45
- let content: string;
46
- try {
47
- content = fs.readFileSync(filePath, "utf-8");
48
- } catch {
49
- continue;
50
- }
51
-
52
- const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
53
-
54
- if (!frontmatter.name || !frontmatter.description) {
55
- continue;
56
- }
57
-
58
- const tools = frontmatter.tools
59
- ?.split(",")
60
- .map((t: string) => t.trim())
61
- .filter(Boolean);
62
-
63
- agents.push({
64
- name: frontmatter.name,
65
- description: frontmatter.description,
66
- tools: tools && tools.length > 0 ? tools : undefined,
67
- model: frontmatter.model,
68
- systemPrompt: body,
69
- source,
70
- filePath,
71
- });
72
- }
73
-
74
- return agents;
75
- }
76
-
77
- function isDirectory(p: string): boolean {
78
- try {
79
- return fs.statSync(p).isDirectory();
80
- } catch {
81
- return false;
82
- }
83
- }
84
-
85
- function findNearestProjectAgentsDir(cwd: string): string | null {
86
- let currentDir = cwd;
87
- while (true) {
88
- const candidate = path.join(currentDir, ".pi", "agents");
89
- if (isDirectory(candidate)) return candidate;
90
-
91
- const parentDir = path.dirname(currentDir);
92
- if (parentDir === currentDir) return null;
93
- currentDir = parentDir;
94
- }
95
- }
96
-
97
- export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
98
- const userDir = path.join(getAgentDir(), "agents");
99
- const projectAgentsDir = findNearestProjectAgentsDir(cwd);
100
-
101
- const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
102
- const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
103
-
104
- const agentMap = new Map<string, AgentConfig>();
105
-
106
- if (scope === "both") {
107
- for (const agent of userAgents) agentMap.set(agent.name, agent);
108
- for (const agent of projectAgents) agentMap.set(agent.name, agent);
109
- } else if (scope === "user") {
110
- for (const agent of userAgents) agentMap.set(agent.name, agent);
111
- } else {
112
- for (const agent of projectAgents) agentMap.set(agent.name, agent);
113
- }
114
-
115
- return { agents: Array.from(agentMap.values()), projectAgentsDir };
116
- }
117
-
118
- export function formatAgentList(agents: AgentConfig[], maxItems: number): { text: string; remaining: number } {
119
- if (agents.length === 0) return { text: "none", remaining: 0 };
120
- const listed = agents.slice(0, maxItems);
121
- const remaining = agents.length - listed.length;
122
- return {
123
- text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join("; "),
124
- remaining,
125
- };
126
- }
1
+ /**
2
+ * Agent discovery and configuration
3
+ */
4
+
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import { getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent";
8
+
9
+ export type AgentScope = "user" | "project" | "both";
10
+
11
+ export interface AgentConfig {
12
+ name: string;
13
+ description: string;
14
+ tools?: string[];
15
+ model?: string;
16
+ systemPrompt: string;
17
+ source: "user" | "project";
18
+ filePath: string;
19
+ }
20
+
21
+ export interface AgentDiscoveryResult {
22
+ agents: AgentConfig[];
23
+ projectAgentsDir: string | null;
24
+ }
25
+
26
+ function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] {
27
+ const agents: AgentConfig[] = [];
28
+
29
+ if (!fs.existsSync(dir)) {
30
+ return agents;
31
+ }
32
+
33
+ let entries: fs.Dirent[];
34
+ try {
35
+ entries = fs.readdirSync(dir, { withFileTypes: true });
36
+ } catch {
37
+ return agents;
38
+ }
39
+
40
+ for (const entry of entries) {
41
+ if (!entry.name.endsWith(".md")) continue;
42
+ if (!entry.isFile() && !entry.isSymbolicLink()) continue;
43
+
44
+ const filePath = path.join(dir, entry.name);
45
+ let content: string;
46
+ try {
47
+ content = fs.readFileSync(filePath, "utf-8");
48
+ } catch {
49
+ continue;
50
+ }
51
+
52
+ const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
53
+
54
+ if (!frontmatter.name || !frontmatter.description) {
55
+ continue;
56
+ }
57
+
58
+ const tools = frontmatter.tools
59
+ ?.split(",")
60
+ .map((t: string) => t.trim())
61
+ .filter(Boolean);
62
+
63
+ agents.push({
64
+ name: frontmatter.name,
65
+ description: frontmatter.description,
66
+ tools: tools && tools.length > 0 ? tools : undefined,
67
+ model: frontmatter.model,
68
+ systemPrompt: body,
69
+ source,
70
+ filePath,
71
+ });
72
+ }
73
+
74
+ return agents;
75
+ }
76
+
77
+ function isDirectory(p: string): boolean {
78
+ try {
79
+ return fs.statSync(p).isDirectory();
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ function findNearestProjectAgentsDir(cwd: string): string | null {
86
+ let currentDir = cwd;
87
+ while (true) {
88
+ const candidate = path.join(currentDir, ".pi", "agents");
89
+ if (isDirectory(candidate)) return candidate;
90
+
91
+ const parentDir = path.dirname(currentDir);
92
+ if (parentDir === currentDir) return null;
93
+ currentDir = parentDir;
94
+ }
95
+ }
96
+
97
+ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
98
+ const userDir = path.join(getAgentDir(), "agents");
99
+ const projectAgentsDir = findNearestProjectAgentsDir(cwd);
100
+
101
+ const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
102
+ const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
103
+
104
+ const agentMap = new Map<string, AgentConfig>();
105
+
106
+ if (scope === "both") {
107
+ for (const agent of userAgents) agentMap.set(agent.name, agent);
108
+ for (const agent of projectAgents) agentMap.set(agent.name, agent);
109
+ } else if (scope === "user") {
110
+ for (const agent of userAgents) agentMap.set(agent.name, agent);
111
+ } else {
112
+ for (const agent of projectAgents) agentMap.set(agent.name, agent);
113
+ }
114
+
115
+ return { agents: Array.from(agentMap.values()), projectAgentsDir };
116
+ }
117
+
118
+ export function formatAgentList(agents: AgentConfig[], maxItems: number): { text: string; remaining: number } {
119
+ if (agents.length === 0) return { text: "none", remaining: 0 };
120
+ const listed = agents.slice(0, maxItems);
121
+ const remaining = agents.length - listed.length;
122
+ return {
123
+ text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join("; "),
124
+ remaining,
125
+ };
126
+ }