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.
Files changed (125) hide show
  1. package/README.md +452 -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/runbooks/publish-checklist.md +9 -1
  32. package/docs/scheduler.md +288 -288
  33. package/docs/setup-discord.md +100 -100
  34. package/docs/setup-slack.md +119 -119
  35. package/docs/setup-whatsapp.md +94 -94
  36. package/docs/subagents.md +166 -166
  37. package/docs/web-search.md +62 -62
  38. package/examples/extensions/README.md +12 -12
  39. package/examples/extensions/charts/index.ts +13 -13
  40. package/examples/extensions/charts/skill/SKILL.md +98 -98
  41. package/examples/extensions/gws/README.md +52 -52
  42. package/examples/extensions/gws/skill/SKILL.md +57 -57
  43. package/examples/extensions/gws/skill/references/calendar.md +101 -101
  44. package/examples/extensions/gws/skill/references/docs.md +65 -65
  45. package/examples/extensions/gws/skill/references/drive.md +79 -79
  46. package/examples/extensions/gws/skill/references/gmail.md +85 -85
  47. package/examples/extensions/gws/skill/references/sheets.md +60 -60
  48. package/examples/extensions/napkin/skill/SKILL.md +728 -728
  49. package/examples/extensions/pdf/skill/LICENSE.txt +30 -30
  50. package/examples/extensions/pdf/skill/SKILL.md +314 -314
  51. package/examples/extensions/pdf/skill/forms.md +294 -294
  52. package/examples/extensions/pdf/skill/reference.md +611 -611
  53. package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -65
  54. package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -11
  55. package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -33
  56. package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -37
  57. package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -122
  58. package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -115
  59. package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -98
  60. package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -107
  61. package/examples/extensions/permission-guard/index.ts +65 -65
  62. package/examples/extensions/pinchtab/skill/SKILL.md +224 -224
  63. package/examples/extensions/pinchtab/skill/TRUST.md +69 -69
  64. package/examples/extensions/pinchtab/skill/references/api.md +297 -297
  65. package/examples/extensions/pinchtab/skill/references/env.md +45 -45
  66. package/examples/extensions/pinchtab/skill/references/profiles.md +107 -107
  67. package/examples/extensions/tradestation/host/refresh.ts +102 -102
  68. package/examples/extensions/tradestation/index.ts +153 -153
  69. package/examples/extensions/tradestation/skill/SKILL.md +67 -67
  70. package/examples/extensions/voice-synth/index.ts +94 -94
  71. package/examples/extensions/voice-synth/skill/SKILL.md +38 -38
  72. package/examples/extensions/voice-transcribe/requirements.txt +8 -8
  73. package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -179
  74. package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -53
  75. package/examples/extensions/yahoo-mail/cli/package.json +13 -13
  76. package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -78
  77. package/package.json +106 -106
  78. package/resources/agents/explore.md +50 -50
  79. package/resources/agents/worker.md +24 -24
  80. package/resources/connection-env-vars.json +25 -25
  81. package/resources/pi-extensions/subagent/agents.ts +126 -126
  82. package/resources/pi-extensions/subagent/index.ts +964 -964
  83. package/resources/profiles/coding/AGENTS.md +43 -43
  84. package/resources/profiles/coding/mercury-profile.yaml +15 -15
  85. package/resources/profiles/general/AGENTS.md +31 -31
  86. package/resources/profiles/general/mercury-profile.yaml +15 -15
  87. package/resources/profiles/research/AGENTS.md +40 -40
  88. package/resources/profiles/research/mercury-profile.yaml +15 -15
  89. package/resources/skills/config/SKILL.md +25 -25
  90. package/resources/skills/context/SKILL.md +33 -33
  91. package/resources/skills/conversation-recap/SKILL.md +19 -19
  92. package/resources/skills/mutes/SKILL.md +31 -31
  93. package/resources/skills/permissions/SKILL.md +19 -19
  94. package/resources/skills/preferences/SKILL.md +31 -31
  95. package/resources/skills/recall/SKILL.md +24 -24
  96. package/resources/skills/roles/SKILL.md +18 -18
  97. package/resources/skills/spaces/SKILL.md +18 -18
  98. package/resources/skills/tasks/SKILL.md +45 -45
  99. package/resources/templates/AGENTS.md +157 -157
  100. package/resources/templates/env.template +38 -38
  101. package/resources/templates/mercury.example.yaml +99 -99
  102. package/src/agent/container-entry.ts +1 -1
  103. package/src/agent/container-runner.ts +1345 -1346
  104. package/src/cli/mercury.ts +39 -7
  105. package/src/cli/mrctl.ts +636 -636
  106. package/src/config-file.ts +540 -540
  107. package/src/config.ts +339 -339
  108. package/src/core/api.ts +125 -125
  109. package/src/core/caller-token.ts +101 -101
  110. package/src/core/permissions.ts +228 -228
  111. package/src/core/profiles.ts +271 -271
  112. package/src/core/routes/capability.ts +70 -70
  113. package/src/core/routes/index.ts +15 -15
  114. package/src/core/runtime.ts +1530 -1530
  115. package/src/dashboard/index.html +729 -729
  116. package/src/extensions/api.ts +273 -273
  117. package/src/extensions/loader.ts +286 -286
  118. package/src/extensions/types.ts +517 -517
  119. package/src/main.ts +605 -605
  120. package/docs/pending-updates/applicative-profiles.md +0 -15
  121. package/docs/pending-updates/caller-bound-capability-token.md +0 -15
  122. package/docs/pending-updates/dm-auto-space.md +0 -15
  123. /package/docs/archive/{2026-07-01-applicative-profiles.md → applicative-profiles/2026-07-01-applicative-profiles.md} +0 -0
  124. /package/docs/archive/{2026-07-01-caller-bound-capability-token.md → applicative-profiles/2026-07-01-caller-bound-capability-token.md} +0 -0
  125. /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
+ }