mercury-agent 0.4.28 → 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 (122) 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/ARCHITECTURE.md +4 -0
  8. package/docs/ROADMAP.md +4 -5
  9. package/docs/{backlog/applicative-profiles.md → archive/applicative-profiles/2026-07-01-applicative-profiles.md} +29 -18
  10. package/docs/{backlog/caller-bound-capability-token.md → archive/applicative-profiles/2026-07-01-caller-bound-capability-token.md} +15 -11
  11. package/docs/archive/summarization/2026-07-02-recent-dev-summary.md +71 -0
  12. package/docs/auth/dashboard.md +28 -28
  13. package/docs/auth/overview.md +109 -109
  14. package/docs/auth/whatsapp.md +173 -173
  15. package/docs/authoring-profiles.md +174 -0
  16. package/docs/configuration.md +54 -54
  17. package/docs/container-lifecycle.md +349 -349
  18. package/docs/{bugs/bwrap-privileged-linux-docker.md → debug/major/2026-07-02-bwrap-privileged-linux-docker.md} +21 -1
  19. package/docs/{bugs/e2big-prompt-delivery-fix.md → debug/major/2026-07-02-e2big-prompt-delivery-fix.md} +27 -1
  20. package/docs/{bugs/registry-pull-no-local-fallback.md → debug/major/2026-07-02-registry-pull-no-local-fallback.md} +27 -1
  21. package/docs/debug/summarization/2026-07-02-common-bug-patterns.md +72 -0
  22. package/docs/deployment.md +199 -199
  23. package/docs/extensions.md +375 -375
  24. package/docs/graceful-shutdown.md +62 -62
  25. package/docs/kb-distillation.md +77 -77
  26. package/docs/media/overview.md +140 -140
  27. package/docs/media/whatsapp.md +171 -171
  28. package/docs/memory.md +137 -137
  29. package/docs/permissions.md +217 -217
  30. package/docs/pipeline.md +228 -228
  31. package/docs/prd-chat-memory.md +76 -76
  32. package/docs/prd-config-load.md +82 -82
  33. package/docs/rate-limiting.md +229 -229
  34. package/docs/scheduler.md +288 -288
  35. package/docs/setup-discord.md +100 -100
  36. package/docs/setup-slack.md +119 -119
  37. package/docs/setup-whatsapp.md +94 -94
  38. package/docs/subagents.md +166 -166
  39. package/docs/web-search.md +62 -62
  40. package/examples/extensions/README.md +12 -12
  41. package/examples/extensions/charts/index.ts +13 -13
  42. package/examples/extensions/charts/skill/SKILL.md +98 -98
  43. package/examples/extensions/gws/README.md +52 -52
  44. package/examples/extensions/gws/skill/SKILL.md +57 -57
  45. package/examples/extensions/gws/skill/references/calendar.md +101 -101
  46. package/examples/extensions/gws/skill/references/docs.md +65 -65
  47. package/examples/extensions/gws/skill/references/drive.md +79 -79
  48. package/examples/extensions/gws/skill/references/gmail.md +85 -85
  49. package/examples/extensions/gws/skill/references/sheets.md +60 -60
  50. package/examples/extensions/napkin/skill/SKILL.md +728 -728
  51. package/examples/extensions/pdf/skill/LICENSE.txt +30 -30
  52. package/examples/extensions/pdf/skill/SKILL.md +314 -314
  53. package/examples/extensions/pdf/skill/forms.md +294 -294
  54. package/examples/extensions/pdf/skill/reference.md +611 -611
  55. package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -65
  56. package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -11
  57. package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -33
  58. package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -37
  59. package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -122
  60. package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -115
  61. package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -98
  62. package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -107
  63. package/examples/extensions/permission-guard/index.ts +65 -65
  64. package/examples/extensions/pinchtab/skill/SKILL.md +224 -224
  65. package/examples/extensions/pinchtab/skill/TRUST.md +69 -69
  66. package/examples/extensions/pinchtab/skill/references/api.md +297 -297
  67. package/examples/extensions/pinchtab/skill/references/env.md +45 -45
  68. package/examples/extensions/pinchtab/skill/references/profiles.md +107 -107
  69. package/examples/extensions/tradestation/host/refresh.ts +102 -102
  70. package/examples/extensions/tradestation/index.ts +153 -153
  71. package/examples/extensions/tradestation/skill/SKILL.md +67 -67
  72. package/examples/extensions/voice-synth/index.ts +94 -94
  73. package/examples/extensions/voice-synth/skill/SKILL.md +38 -38
  74. package/examples/extensions/voice-transcribe/requirements.txt +8 -8
  75. package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -179
  76. package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -53
  77. package/examples/extensions/yahoo-mail/cli/package.json +13 -13
  78. package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -78
  79. package/package.json +106 -106
  80. package/resources/agents/explore.md +50 -50
  81. package/resources/agents/worker.md +24 -24
  82. package/resources/connection-env-vars.json +25 -25
  83. package/resources/pi-extensions/subagent/agents.ts +126 -126
  84. package/resources/pi-extensions/subagent/index.ts +964 -964
  85. package/resources/profiles/coding/AGENTS.md +43 -43
  86. package/resources/profiles/coding/mercury-profile.yaml +15 -15
  87. package/resources/profiles/general/AGENTS.md +31 -31
  88. package/resources/profiles/general/mercury-profile.yaml +15 -15
  89. package/resources/profiles/research/AGENTS.md +40 -40
  90. package/resources/profiles/research/mercury-profile.yaml +15 -15
  91. package/resources/skills/config/SKILL.md +25 -25
  92. package/resources/skills/context/SKILL.md +33 -33
  93. package/resources/skills/conversation-recap/SKILL.md +19 -19
  94. package/resources/skills/mutes/SKILL.md +31 -31
  95. package/resources/skills/permissions/SKILL.md +19 -19
  96. package/resources/skills/preferences/SKILL.md +31 -31
  97. package/resources/skills/recall/SKILL.md +24 -24
  98. package/resources/skills/roles/SKILL.md +18 -18
  99. package/resources/skills/spaces/SKILL.md +18 -18
  100. package/resources/skills/tasks/SKILL.md +45 -45
  101. package/resources/templates/AGENTS.md +157 -157
  102. package/resources/templates/env.template +38 -38
  103. package/resources/templates/mercury.example.yaml +15 -0
  104. package/src/agent/container-runner.ts +23 -0
  105. package/src/cli/mercury.ts +38 -6
  106. package/src/cli/mrctl.ts +25 -0
  107. package/src/config-file.ts +3 -0
  108. package/src/config.ts +15 -0
  109. package/src/core/api.ts +23 -3
  110. package/src/core/caller-token.ts +101 -0
  111. package/src/core/permissions.ts +37 -5
  112. package/src/core/profiles.ts +110 -84
  113. package/src/core/routes/capability.ts +70 -0
  114. package/src/core/routes/index.ts +1 -0
  115. package/src/core/runtime.ts +14 -0
  116. package/src/dashboard/index.html +729 -729
  117. package/src/extensions/api.ts +21 -0
  118. package/src/extensions/loader.ts +15 -0
  119. package/src/extensions/types.ts +55 -0
  120. package/src/main.ts +19 -0
  121. package/docs/pending-updates/dm-auto-space.md +0 -15
  122. /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
+ }