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.
- package/README.md +452 -451
- package/container/Dockerfile +127 -127
- package/container/Dockerfile.base +109 -109
- package/container/Dockerfile.power +17 -17
- package/container/agent-package.json +8 -8
- package/container/build.sh +54 -54
- package/docs/ROADMAP.md +3 -4
- package/docs/archive/summarization/2026-07-02-recent-dev-summary.md +71 -0
- package/docs/auth/dashboard.md +28 -28
- package/docs/auth/overview.md +109 -109
- package/docs/auth/whatsapp.md +173 -173
- package/docs/authoring-profiles.md +174 -174
- package/docs/configuration.md +54 -54
- package/docs/container-lifecycle.md +349 -349
- package/docs/{bugs/bwrap-privileged-linux-docker.md → debug/major/2026-07-02-bwrap-privileged-linux-docker.md} +21 -1
- package/docs/{bugs/e2big-prompt-delivery-fix.md → debug/major/2026-07-02-e2big-prompt-delivery-fix.md} +27 -1
- package/docs/{bugs/registry-pull-no-local-fallback.md → debug/major/2026-07-02-registry-pull-no-local-fallback.md} +27 -1
- package/docs/debug/summarization/2026-07-02-common-bug-patterns.md +72 -0
- package/docs/deployment.md +199 -199
- package/docs/extensions.md +375 -375
- package/docs/graceful-shutdown.md +62 -62
- package/docs/kb-distillation.md +77 -77
- package/docs/media/overview.md +140 -140
- package/docs/media/whatsapp.md +171 -171
- package/docs/memory.md +137 -137
- package/docs/permissions.md +217 -217
- package/docs/pipeline.md +228 -228
- package/docs/prd-chat-memory.md +76 -76
- package/docs/prd-config-load.md +82 -82
- package/docs/rate-limiting.md +229 -229
- package/docs/runbooks/publish-checklist.md +9 -1
- package/docs/scheduler.md +288 -288
- package/docs/setup-discord.md +100 -100
- package/docs/setup-slack.md +119 -119
- package/docs/setup-whatsapp.md +94 -94
- package/docs/subagents.md +166 -166
- package/docs/web-search.md +62 -62
- package/examples/extensions/README.md +12 -12
- package/examples/extensions/charts/index.ts +13 -13
- package/examples/extensions/charts/skill/SKILL.md +98 -98
- package/examples/extensions/gws/README.md +52 -52
- package/examples/extensions/gws/skill/SKILL.md +57 -57
- package/examples/extensions/gws/skill/references/calendar.md +101 -101
- package/examples/extensions/gws/skill/references/docs.md +65 -65
- package/examples/extensions/gws/skill/references/drive.md +79 -79
- package/examples/extensions/gws/skill/references/gmail.md +85 -85
- package/examples/extensions/gws/skill/references/sheets.md +60 -60
- package/examples/extensions/napkin/skill/SKILL.md +728 -728
- package/examples/extensions/pdf/skill/LICENSE.txt +30 -30
- package/examples/extensions/pdf/skill/SKILL.md +314 -314
- package/examples/extensions/pdf/skill/forms.md +294 -294
- package/examples/extensions/pdf/skill/reference.md +611 -611
- package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -65
- package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -11
- package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -33
- package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -37
- package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -122
- package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -115
- package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -98
- package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -107
- package/examples/extensions/permission-guard/index.ts +65 -65
- package/examples/extensions/pinchtab/skill/SKILL.md +224 -224
- package/examples/extensions/pinchtab/skill/TRUST.md +69 -69
- package/examples/extensions/pinchtab/skill/references/api.md +297 -297
- package/examples/extensions/pinchtab/skill/references/env.md +45 -45
- package/examples/extensions/pinchtab/skill/references/profiles.md +107 -107
- package/examples/extensions/tradestation/host/refresh.ts +102 -102
- package/examples/extensions/tradestation/index.ts +153 -153
- package/examples/extensions/tradestation/skill/SKILL.md +67 -67
- package/examples/extensions/voice-synth/index.ts +94 -94
- package/examples/extensions/voice-synth/skill/SKILL.md +38 -38
- package/examples/extensions/voice-transcribe/requirements.txt +8 -8
- package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -179
- package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -53
- package/examples/extensions/yahoo-mail/cli/package.json +13 -13
- package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -78
- package/package.json +106 -106
- package/resources/agents/explore.md +50 -50
- package/resources/agents/worker.md +24 -24
- package/resources/connection-env-vars.json +25 -25
- package/resources/pi-extensions/subagent/agents.ts +126 -126
- package/resources/pi-extensions/subagent/index.ts +964 -964
- package/resources/profiles/coding/AGENTS.md +43 -43
- package/resources/profiles/coding/mercury-profile.yaml +15 -15
- package/resources/profiles/general/AGENTS.md +31 -31
- package/resources/profiles/general/mercury-profile.yaml +15 -15
- package/resources/profiles/research/AGENTS.md +40 -40
- package/resources/profiles/research/mercury-profile.yaml +15 -15
- package/resources/skills/config/SKILL.md +25 -25
- package/resources/skills/context/SKILL.md +33 -33
- package/resources/skills/conversation-recap/SKILL.md +19 -19
- package/resources/skills/mutes/SKILL.md +31 -31
- package/resources/skills/permissions/SKILL.md +19 -19
- package/resources/skills/preferences/SKILL.md +31 -31
- package/resources/skills/recall/SKILL.md +24 -24
- package/resources/skills/roles/SKILL.md +18 -18
- package/resources/skills/spaces/SKILL.md +18 -18
- package/resources/skills/tasks/SKILL.md +45 -45
- package/resources/templates/AGENTS.md +157 -157
- package/resources/templates/env.template +38 -38
- package/resources/templates/mercury.example.yaml +99 -99
- package/src/agent/container-entry.ts +1 -1
- package/src/agent/container-runner.ts +1345 -1346
- package/src/cli/mercury.ts +39 -7
- package/src/cli/mrctl.ts +636 -636
- package/src/config-file.ts +540 -540
- package/src/config.ts +339 -339
- package/src/core/api.ts +125 -125
- package/src/core/caller-token.ts +101 -101
- package/src/core/permissions.ts +228 -228
- package/src/core/profiles.ts +271 -271
- package/src/core/routes/capability.ts +70 -70
- package/src/core/routes/index.ts +15 -15
- package/src/core/runtime.ts +1530 -1530
- package/src/dashboard/index.html +729 -729
- package/src/extensions/api.ts +273 -273
- package/src/extensions/loader.ts +286 -286
- package/src/extensions/types.ts +517 -517
- package/src/main.ts +605 -605
- package/docs/pending-updates/applicative-profiles.md +0 -15
- package/docs/pending-updates/caller-bound-capability-token.md +0 -15
- package/docs/pending-updates/dm-auto-space.md +0 -15
- /package/docs/archive/{2026-07-01-applicative-profiles.md → applicative-profiles/2026-07-01-applicative-profiles.md} +0 -0
- /package/docs/archive/{2026-07-01-caller-bound-capability-token.md → applicative-profiles/2026-07-01-caller-bound-capability-token.md} +0 -0
- /package/docs/archive/{2026-07-01-dm-auto-space.md → applicative-profiles/2026-07-01-dm-auto-space.md} +0 -0
package/container/Dockerfile
CHANGED
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1
|
|
2
|
-
# Mercury Agent Container
|
|
3
|
-
# Bun binary copied from official image — avoids bun.sh/install script deps
|
|
4
|
-
FROM oven/bun:1 AS bun-source
|
|
5
|
-
FROM node:22-slim AS node-source
|
|
6
|
-
FROM golang:1.24.1 AS go-source
|
|
7
|
-
|
|
8
|
-
FROM ubuntu:24.04
|
|
9
|
-
|
|
10
|
-
ENV DEBIAN_FRONTEND=noninteractive
|
|
11
|
-
|
|
12
|
-
# Install dev tools and language runtimes
|
|
13
|
-
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
14
|
-
# Core tools
|
|
15
|
-
ca-certificates git curl wget jq vim zsh openssh-client gpg unzip \
|
|
16
|
-
build-essential \
|
|
17
|
-
# Python
|
|
18
|
-
python3 python3-pip python3-venv \
|
|
19
|
-
# Sandboxing: bubblewrap for defense-in-depth in runc mode.
|
|
20
|
-
# Not used when CONTAINER_RUNTIME=runsc (gVisor handles isolation at the syscall boundary).
|
|
21
|
-
# Remove once runc mode is deprecated.
|
|
22
|
-
bubblewrap \
|
|
23
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
24
|
-
|
|
25
|
-
# Rename the built-in ubuntu user (UID 1000) to mercury
|
|
26
|
-
# Ubuntu 24.04 ships with an 'ubuntu' user at UID/GID 1000; useradd -u 1000 fails with exit code 4
|
|
27
|
-
RUN usermod -l mercury -d /home/mercury -m ubuntu && groupmod -n mercury ubuntu
|
|
28
|
-
|
|
29
|
-
# Copy Bun from official image
|
|
30
|
-
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
|
|
31
|
-
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
|
|
32
|
-
|
|
33
|
-
# Copy Node.js from official image (avoids flaky nodesource apt repository)
|
|
34
|
-
# npm/npx are symlinks in the upstream image; Docker COPY dereferences single-file
|
|
35
|
-
# symlinks, so recreate them with ln -s after copying node_modules.
|
|
36
|
-
COPY --from=node-source /usr/local/bin/node /usr/local/bin/node
|
|
37
|
-
COPY --from=node-source /usr/local/lib/node_modules /usr/local/lib/node_modules
|
|
38
|
-
COPY --from=node-source /usr/local/include/node /usr/local/include/node
|
|
39
|
-
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
|
|
40
|
-
ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
|
|
41
|
-
ENV HOME="/home/mercury"
|
|
42
|
-
ENV BUN_INSTALL="/home/mercury/.bun"
|
|
43
|
-
ENV PATH="$BUN_INSTALL/bin:/usr/local/bin:$PATH"
|
|
44
|
-
|
|
45
|
-
# Copy Go from official image (avoids curl installer and network flakiness)
|
|
46
|
-
COPY --from=go-source /usr/local/go /usr/local/go
|
|
47
|
-
ENV PATH="/usr/local/go/bin:$PATH"
|
|
48
|
-
|
|
49
|
-
# Install Playwright + Chromium (used by multiple extensions: web-browser, diagrams, charts)
|
|
50
|
-
# HOME=/home/mercury causes playwright to install browsers to /home/mercury/.cache/ms-playwright
|
|
51
|
-
RUN npx playwright install --with-deps chromium
|
|
52
|
-
|
|
53
|
-
# Point puppeteer to Playwright's Chromium so npm packages skip downloading their own
|
|
54
|
-
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
55
|
-
RUN ln -sf $(find /home/mercury/.cache/ms-playwright -name chrome -type f | head -1) /usr/local/bin/chromium
|
|
56
|
-
ENV PUPPETEER_EXECUTABLE_PATH=/usr/local/bin/chromium
|
|
57
|
-
|
|
58
|
-
# Allow Chromium to run without sandbox in Docker (required for non-root too)
|
|
59
|
-
RUN echo '{"args":["--no-sandbox"]}' > /home/mercury/.puppeteerrc.json
|
|
60
|
-
ENV CHROMIUM_FLAGS="--no-sandbox"
|
|
61
|
-
|
|
62
|
-
# Install CLIs
|
|
63
|
-
RUN bun add -g @mariozechner/pi-coding-agent@^0.67.2
|
|
64
|
-
|
|
65
|
-
WORKDIR /app
|
|
66
|
-
|
|
67
|
-
COPY container/agent-package.json /app/package.json
|
|
68
|
-
RUN bun install --production
|
|
69
|
-
|
|
70
|
-
# Patch pi: skip thinkingConfig for Gemma models (Google API rejects thinkingBudget for them,
|
|
71
|
-
# but pi marks gemma-4 as reasoning:true and sends thinkingBudget:0 to disable it)
|
|
72
|
-
RUN node <<'EOF'
|
|
73
|
-
const fs = require('fs'), path = require('path');
|
|
74
|
-
function patch(dir) {
|
|
75
|
-
try {
|
|
76
|
-
for (const f of fs.readdirSync(dir)) {
|
|
77
|
-
const p = path.join(dir, f);
|
|
78
|
-
try {
|
|
79
|
-
if (fs.statSync(p).isDirectory()) patch(p);
|
|
80
|
-
else if (f === 'google.js' && p.includes('@mariozechner/pi-ai')) {
|
|
81
|
-
let c = fs.readFileSync(p, 'utf8');
|
|
82
|
-
const noThinking = '&& !model.id.startsWith("gemma")';
|
|
83
|
-
const p1 = 'if (options.thinking?.enabled && model.reasoning) {';
|
|
84
|
-
const p2 = 'else if (model.reasoning && options.thinking && !options.thinking.enabled) {';
|
|
85
|
-
if (!c.includes(noThinking)) {
|
|
86
|
-
c = c.replace(p1, 'if (options.thinking?.enabled && model.reasoning ' + noThinking + ') {');
|
|
87
|
-
c = c.replace(p2, 'else if (model.reasoning && options.thinking && !options.thinking.enabled ' + noThinking + ') {');
|
|
88
|
-
fs.writeFileSync(p, c);
|
|
89
|
-
console.log('Patched:', p);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
} catch(e) {}
|
|
93
|
-
}
|
|
94
|
-
} catch(e) {}
|
|
95
|
-
}
|
|
96
|
-
patch('/home/mercury/.bun');
|
|
97
|
-
patch('/app/node_modules');
|
|
98
|
-
EOF
|
|
99
|
-
|
|
100
|
-
COPY src/agent/container-entry.ts /app/src/agent/container-entry.ts
|
|
101
|
-
COPY src/agent/model-capabilities-core.ts /app/src/agent/model-capabilities-core.ts
|
|
102
|
-
COPY src/agent/pi-failure-class.ts /app/src/agent/pi-failure-class.ts
|
|
103
|
-
COPY src/agent/pi-jsonl-parser.ts /app/src/agent/pi-jsonl-parser.ts
|
|
104
|
-
COPY src/agent/preferences-prompt.ts /app/src/agent/preferences-prompt.ts
|
|
105
|
-
COPY src/cli/mrctl.ts /app/src/cli/mrctl.ts
|
|
106
|
-
COPY src/cli/mrctl-http.ts /app/src/cli/mrctl-http.ts
|
|
107
|
-
COPY src/extensions/reserved.ts /app/src/extensions/reserved.ts
|
|
108
|
-
COPY src/extensions/permission-guard.ts /app/src/extensions/permission-guard.ts
|
|
109
|
-
COPY src/types.ts /app/src/types.ts
|
|
110
|
-
COPY resources/ /app/resources/
|
|
111
|
-
COPY examples/extensions/ /tmp/examples-extensions/
|
|
112
|
-
RUN while IFS= read -r ext || [ -n "$ext" ]; do \
|
|
113
|
-
ext=$(echo "$ext" | xargs); \
|
|
114
|
-
[ -z "$ext" ] && continue; \
|
|
115
|
-
cp -r "/tmp/examples-extensions/$ext" "/app/resources/extensions/$ext"; \
|
|
116
|
-
done < /app/resources/builtin-extensions.txt && \
|
|
117
|
-
rm -rf /tmp/examples-extensions/
|
|
118
|
-
|
|
119
|
-
RUN echo '#!/bin/sh\nbun run /app/src/cli/mrctl.ts "$@"' > /usr/local/bin/mrctl && \
|
|
120
|
-
chmod +x /usr/local/bin/mrctl
|
|
121
|
-
|
|
122
|
-
# Fix ownership of all mercury home dir artifacts before switching user
|
|
123
|
-
RUN chown -R mercury:mercury /home/mercury
|
|
124
|
-
|
|
125
|
-
USER mercury
|
|
126
|
-
|
|
127
|
-
ENTRYPOINT ["bun", "run", "/app/src/agent/container-entry.ts"]
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
# Mercury Agent Container
|
|
3
|
+
# Bun binary copied from official image — avoids bun.sh/install script deps
|
|
4
|
+
FROM oven/bun:1 AS bun-source
|
|
5
|
+
FROM node:22-slim AS node-source
|
|
6
|
+
FROM golang:1.24.1 AS go-source
|
|
7
|
+
|
|
8
|
+
FROM ubuntu:24.04
|
|
9
|
+
|
|
10
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
11
|
+
|
|
12
|
+
# Install dev tools and language runtimes
|
|
13
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
14
|
+
# Core tools
|
|
15
|
+
ca-certificates git curl wget jq vim zsh openssh-client gpg unzip \
|
|
16
|
+
build-essential \
|
|
17
|
+
# Python
|
|
18
|
+
python3 python3-pip python3-venv \
|
|
19
|
+
# Sandboxing: bubblewrap for defense-in-depth in runc mode.
|
|
20
|
+
# Not used when CONTAINER_RUNTIME=runsc (gVisor handles isolation at the syscall boundary).
|
|
21
|
+
# Remove once runc mode is deprecated.
|
|
22
|
+
bubblewrap \
|
|
23
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
24
|
+
|
|
25
|
+
# Rename the built-in ubuntu user (UID 1000) to mercury
|
|
26
|
+
# Ubuntu 24.04 ships with an 'ubuntu' user at UID/GID 1000; useradd -u 1000 fails with exit code 4
|
|
27
|
+
RUN usermod -l mercury -d /home/mercury -m ubuntu && groupmod -n mercury ubuntu
|
|
28
|
+
|
|
29
|
+
# Copy Bun from official image
|
|
30
|
+
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
|
|
31
|
+
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
|
|
32
|
+
|
|
33
|
+
# Copy Node.js from official image (avoids flaky nodesource apt repository)
|
|
34
|
+
# npm/npx are symlinks in the upstream image; Docker COPY dereferences single-file
|
|
35
|
+
# symlinks, so recreate them with ln -s after copying node_modules.
|
|
36
|
+
COPY --from=node-source /usr/local/bin/node /usr/local/bin/node
|
|
37
|
+
COPY --from=node-source /usr/local/lib/node_modules /usr/local/lib/node_modules
|
|
38
|
+
COPY --from=node-source /usr/local/include/node /usr/local/include/node
|
|
39
|
+
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
|
|
40
|
+
ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
|
|
41
|
+
ENV HOME="/home/mercury"
|
|
42
|
+
ENV BUN_INSTALL="/home/mercury/.bun"
|
|
43
|
+
ENV PATH="$BUN_INSTALL/bin:/usr/local/bin:$PATH"
|
|
44
|
+
|
|
45
|
+
# Copy Go from official image (avoids curl installer and network flakiness)
|
|
46
|
+
COPY --from=go-source /usr/local/go /usr/local/go
|
|
47
|
+
ENV PATH="/usr/local/go/bin:$PATH"
|
|
48
|
+
|
|
49
|
+
# Install Playwright + Chromium (used by multiple extensions: web-browser, diagrams, charts)
|
|
50
|
+
# HOME=/home/mercury causes playwright to install browsers to /home/mercury/.cache/ms-playwright
|
|
51
|
+
RUN npx playwright install --with-deps chromium
|
|
52
|
+
|
|
53
|
+
# Point puppeteer to Playwright's Chromium so npm packages skip downloading their own
|
|
54
|
+
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
55
|
+
RUN ln -sf $(find /home/mercury/.cache/ms-playwright -name chrome -type f | head -1) /usr/local/bin/chromium
|
|
56
|
+
ENV PUPPETEER_EXECUTABLE_PATH=/usr/local/bin/chromium
|
|
57
|
+
|
|
58
|
+
# Allow Chromium to run without sandbox in Docker (required for non-root too)
|
|
59
|
+
RUN echo '{"args":["--no-sandbox"]}' > /home/mercury/.puppeteerrc.json
|
|
60
|
+
ENV CHROMIUM_FLAGS="--no-sandbox"
|
|
61
|
+
|
|
62
|
+
# Install CLIs
|
|
63
|
+
RUN bun add -g @mariozechner/pi-coding-agent@^0.67.2
|
|
64
|
+
|
|
65
|
+
WORKDIR /app
|
|
66
|
+
|
|
67
|
+
COPY container/agent-package.json /app/package.json
|
|
68
|
+
RUN bun install --production
|
|
69
|
+
|
|
70
|
+
# Patch pi: skip thinkingConfig for Gemma models (Google API rejects thinkingBudget for them,
|
|
71
|
+
# but pi marks gemma-4 as reasoning:true and sends thinkingBudget:0 to disable it)
|
|
72
|
+
RUN node <<'EOF'
|
|
73
|
+
const fs = require('fs'), path = require('path');
|
|
74
|
+
function patch(dir) {
|
|
75
|
+
try {
|
|
76
|
+
for (const f of fs.readdirSync(dir)) {
|
|
77
|
+
const p = path.join(dir, f);
|
|
78
|
+
try {
|
|
79
|
+
if (fs.statSync(p).isDirectory()) patch(p);
|
|
80
|
+
else if (f === 'google.js' && p.includes('@mariozechner/pi-ai')) {
|
|
81
|
+
let c = fs.readFileSync(p, 'utf8');
|
|
82
|
+
const noThinking = '&& !model.id.startsWith("gemma")';
|
|
83
|
+
const p1 = 'if (options.thinking?.enabled && model.reasoning) {';
|
|
84
|
+
const p2 = 'else if (model.reasoning && options.thinking && !options.thinking.enabled) {';
|
|
85
|
+
if (!c.includes(noThinking)) {
|
|
86
|
+
c = c.replace(p1, 'if (options.thinking?.enabled && model.reasoning ' + noThinking + ') {');
|
|
87
|
+
c = c.replace(p2, 'else if (model.reasoning && options.thinking && !options.thinking.enabled ' + noThinking + ') {');
|
|
88
|
+
fs.writeFileSync(p, c);
|
|
89
|
+
console.log('Patched:', p);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} catch(e) {}
|
|
93
|
+
}
|
|
94
|
+
} catch(e) {}
|
|
95
|
+
}
|
|
96
|
+
patch('/home/mercury/.bun');
|
|
97
|
+
patch('/app/node_modules');
|
|
98
|
+
EOF
|
|
99
|
+
|
|
100
|
+
COPY src/agent/container-entry.ts /app/src/agent/container-entry.ts
|
|
101
|
+
COPY src/agent/model-capabilities-core.ts /app/src/agent/model-capabilities-core.ts
|
|
102
|
+
COPY src/agent/pi-failure-class.ts /app/src/agent/pi-failure-class.ts
|
|
103
|
+
COPY src/agent/pi-jsonl-parser.ts /app/src/agent/pi-jsonl-parser.ts
|
|
104
|
+
COPY src/agent/preferences-prompt.ts /app/src/agent/preferences-prompt.ts
|
|
105
|
+
COPY src/cli/mrctl.ts /app/src/cli/mrctl.ts
|
|
106
|
+
COPY src/cli/mrctl-http.ts /app/src/cli/mrctl-http.ts
|
|
107
|
+
COPY src/extensions/reserved.ts /app/src/extensions/reserved.ts
|
|
108
|
+
COPY src/extensions/permission-guard.ts /app/src/extensions/permission-guard.ts
|
|
109
|
+
COPY src/types.ts /app/src/types.ts
|
|
110
|
+
COPY resources/ /app/resources/
|
|
111
|
+
COPY examples/extensions/ /tmp/examples-extensions/
|
|
112
|
+
RUN while IFS= read -r ext || [ -n "$ext" ]; do \
|
|
113
|
+
ext=$(echo "$ext" | xargs); \
|
|
114
|
+
[ -z "$ext" ] && continue; \
|
|
115
|
+
cp -r "/tmp/examples-extensions/$ext" "/app/resources/extensions/$ext"; \
|
|
116
|
+
done < /app/resources/builtin-extensions.txt && \
|
|
117
|
+
rm -rf /tmp/examples-extensions/
|
|
118
|
+
|
|
119
|
+
RUN echo '#!/bin/sh\nbun run /app/src/cli/mrctl.ts "$@"' > /usr/local/bin/mrctl && \
|
|
120
|
+
chmod +x /usr/local/bin/mrctl
|
|
121
|
+
|
|
122
|
+
# Fix ownership of all mercury home dir artifacts before switching user
|
|
123
|
+
RUN chown -R mercury:mercury /home/mercury
|
|
124
|
+
|
|
125
|
+
USER mercury
|
|
126
|
+
|
|
127
|
+
ENTRYPOINT ["bun", "run", "/app/src/agent/container-entry.ts"]
|
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1
|
|
2
|
-
# Mercury Agent Container — Base tier
|
|
3
|
-
# Base: Microsoft Playwright image (Ubuntu 24.04 noble + Node 22 + Chromium + X11/GL deps preinstalled).
|
|
4
|
-
# Adds: Bun, poppler-utils, pandoc, imagemagick, pi-coding-agent, mercury (UID 1000) user.
|
|
5
|
-
FROM oven/bun:1 AS bun-source
|
|
6
|
-
FROM mcr.microsoft.com/playwright:v1.55.0-noble
|
|
7
|
-
|
|
8
|
-
ENV DEBIAN_FRONTEND=noninteractive
|
|
9
|
-
|
|
10
|
-
# Document-processing tools. Wrapped in a retry loop — archive.ubuntu.com is periodically flaky
|
|
11
|
-
# and a single apt miss shouldn't fail the whole image build.
|
|
12
|
-
RUN set -eux; \
|
|
13
|
-
for i in 1 2 3 4 5; do \
|
|
14
|
-
apt-get update && apt-get install -y --no-install-recommends \
|
|
15
|
-
poppler-utils pandoc imagemagick wget \
|
|
16
|
-
&& break \
|
|
17
|
-
|| { echo "apt attempt $i/5 failed, sleeping 15s" >&2; apt-get clean; sleep 15; }; \
|
|
18
|
-
done; \
|
|
19
|
-
rm -rf /var/lib/apt/lists/*
|
|
20
|
-
|
|
21
|
-
# Rename the built-in ubuntu user (UID 1000) to mercury.
|
|
22
|
-
# Playwright's noble base inherits the ubuntu user at UID/GID 1000; useradd -u 1000
|
|
23
|
-
# would fail. (pwuser is at UID 1001 — unused by us.)
|
|
24
|
-
RUN usermod -l mercury -d /home/mercury -m ubuntu && groupmod -n mercury ubuntu
|
|
25
|
-
|
|
26
|
-
# Copy Bun from official image
|
|
27
|
-
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
|
|
28
|
-
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
|
|
29
|
-
|
|
30
|
-
ENV HOME="/home/mercury"
|
|
31
|
-
ENV BUN_INSTALL="/home/mercury/.bun"
|
|
32
|
-
ENV PATH="$BUN_INSTALL/bin:/usr/local/bin:$PATH"
|
|
33
|
-
|
|
34
|
-
# Chromium lives in /ms-playwright/chromium-*/chrome-linux/chrome in the Playwright image.
|
|
35
|
-
# Symlink to /usr/local/bin/chromium so puppeteer-using npm packages find it.
|
|
36
|
-
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
37
|
-
RUN ln -sf "$(find /ms-playwright -name chrome -type f -executable | head -1)" /usr/local/bin/chromium
|
|
38
|
-
ENV PUPPETEER_EXECUTABLE_PATH=/usr/local/bin/chromium
|
|
39
|
-
|
|
40
|
-
# --no-sandbox: Chromium can't use its user namespace sandbox inside a container
|
|
41
|
-
RUN echo '{"args":["--no-sandbox"]}' > /home/mercury/.puppeteerrc.json
|
|
42
|
-
ENV CHROMIUM_FLAGS="--no-sandbox"
|
|
43
|
-
|
|
44
|
-
# Install CLIs
|
|
45
|
-
RUN bun add -g @mariozechner/pi-coding-agent@^0.67.2
|
|
46
|
-
|
|
47
|
-
WORKDIR /app
|
|
48
|
-
|
|
49
|
-
COPY container/agent-package.json /app/package.json
|
|
50
|
-
RUN bun install --production
|
|
51
|
-
|
|
52
|
-
# Patch pi: skip thinkingConfig for Gemma models (Google API rejects thinkingBudget for them,
|
|
53
|
-
# but pi marks gemma-4 as reasoning:true and sends thinkingBudget:0 to disable it)
|
|
54
|
-
RUN node <<'EOF'
|
|
55
|
-
const fs = require('fs'), path = require('path');
|
|
56
|
-
function patch(dir) {
|
|
57
|
-
try {
|
|
58
|
-
for (const f of fs.readdirSync(dir)) {
|
|
59
|
-
const p = path.join(dir, f);
|
|
60
|
-
try {
|
|
61
|
-
if (fs.statSync(p).isDirectory()) patch(p);
|
|
62
|
-
else if (f === 'google.js' && p.includes('@mariozechner/pi-ai')) {
|
|
63
|
-
let c = fs.readFileSync(p, 'utf8');
|
|
64
|
-
const noThinking = '&& !model.id.startsWith("gemma")';
|
|
65
|
-
const p1 = 'if (options.thinking?.enabled && model.reasoning) {';
|
|
66
|
-
const p2 = 'else if (model.reasoning && options.thinking && !options.thinking.enabled) {';
|
|
67
|
-
if (!c.includes(noThinking)) {
|
|
68
|
-
c = c.replace(p1, 'if (options.thinking?.enabled && model.reasoning ' + noThinking + ') {');
|
|
69
|
-
c = c.replace(p2, 'else if (model.reasoning && options.thinking && !options.thinking.enabled ' + noThinking + ') {');
|
|
70
|
-
fs.writeFileSync(p, c);
|
|
71
|
-
console.log('Patched:', p);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
} catch(e) {}
|
|
75
|
-
}
|
|
76
|
-
} catch(e) {}
|
|
77
|
-
}
|
|
78
|
-
patch('/home/mercury/.bun');
|
|
79
|
-
patch('/app/node_modules');
|
|
80
|
-
EOF
|
|
81
|
-
|
|
82
|
-
COPY src/agent/container-entry.ts /app/src/agent/container-entry.ts
|
|
83
|
-
COPY src/agent/model-capabilities-core.ts /app/src/agent/model-capabilities-core.ts
|
|
84
|
-
COPY src/agent/pi-failure-class.ts /app/src/agent/pi-failure-class.ts
|
|
85
|
-
COPY src/agent/pi-jsonl-parser.ts /app/src/agent/pi-jsonl-parser.ts
|
|
86
|
-
COPY src/agent/preferences-prompt.ts /app/src/agent/preferences-prompt.ts
|
|
87
|
-
COPY src/cli/mrctl.ts /app/src/cli/mrctl.ts
|
|
88
|
-
COPY src/cli/mrctl-http.ts /app/src/cli/mrctl-http.ts
|
|
89
|
-
COPY src/extensions/reserved.ts /app/src/extensions/reserved.ts
|
|
90
|
-
COPY src/extensions/permission-guard.ts /app/src/extensions/permission-guard.ts
|
|
91
|
-
COPY src/types.ts /app/src/types.ts
|
|
92
|
-
COPY resources/ /app/resources/
|
|
93
|
-
COPY examples/extensions/ /tmp/examples-extensions/
|
|
94
|
-
RUN while IFS= read -r ext || [ -n "$ext" ]; do \
|
|
95
|
-
ext=$(echo "$ext" | xargs); \
|
|
96
|
-
[ -z "$ext" ] && continue; \
|
|
97
|
-
cp -r "/tmp/examples-extensions/$ext" "/app/resources/extensions/$ext"; \
|
|
98
|
-
done < /app/resources/builtin-extensions.txt && \
|
|
99
|
-
rm -rf /tmp/examples-extensions/
|
|
100
|
-
|
|
101
|
-
RUN echo '#!/bin/sh\nbun run /app/src/cli/mrctl.ts "$@"' > /usr/local/bin/mrctl && \
|
|
102
|
-
chmod +x /usr/local/bin/mrctl
|
|
103
|
-
|
|
104
|
-
# Fix ownership of all mercury home dir artifacts before switching user
|
|
105
|
-
RUN chown -R mercury:mercury /home/mercury
|
|
106
|
-
|
|
107
|
-
USER mercury
|
|
108
|
-
|
|
109
|
-
ENTRYPOINT ["bun", "run", "/app/src/agent/container-entry.ts"]
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
# Mercury Agent Container — Base tier
|
|
3
|
+
# Base: Microsoft Playwright image (Ubuntu 24.04 noble + Node 22 + Chromium + X11/GL deps preinstalled).
|
|
4
|
+
# Adds: Bun, poppler-utils, pandoc, imagemagick, pi-coding-agent, mercury (UID 1000) user.
|
|
5
|
+
FROM oven/bun:1 AS bun-source
|
|
6
|
+
FROM mcr.microsoft.com/playwright:v1.55.0-noble
|
|
7
|
+
|
|
8
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
9
|
+
|
|
10
|
+
# Document-processing tools. Wrapped in a retry loop — archive.ubuntu.com is periodically flaky
|
|
11
|
+
# and a single apt miss shouldn't fail the whole image build.
|
|
12
|
+
RUN set -eux; \
|
|
13
|
+
for i in 1 2 3 4 5; do \
|
|
14
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
15
|
+
poppler-utils pandoc imagemagick wget \
|
|
16
|
+
&& break \
|
|
17
|
+
|| { echo "apt attempt $i/5 failed, sleeping 15s" >&2; apt-get clean; sleep 15; }; \
|
|
18
|
+
done; \
|
|
19
|
+
rm -rf /var/lib/apt/lists/*
|
|
20
|
+
|
|
21
|
+
# Rename the built-in ubuntu user (UID 1000) to mercury.
|
|
22
|
+
# Playwright's noble base inherits the ubuntu user at UID/GID 1000; useradd -u 1000
|
|
23
|
+
# would fail. (pwuser is at UID 1001 — unused by us.)
|
|
24
|
+
RUN usermod -l mercury -d /home/mercury -m ubuntu && groupmod -n mercury ubuntu
|
|
25
|
+
|
|
26
|
+
# Copy Bun from official image
|
|
27
|
+
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
|
|
28
|
+
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
|
|
29
|
+
|
|
30
|
+
ENV HOME="/home/mercury"
|
|
31
|
+
ENV BUN_INSTALL="/home/mercury/.bun"
|
|
32
|
+
ENV PATH="$BUN_INSTALL/bin:/usr/local/bin:$PATH"
|
|
33
|
+
|
|
34
|
+
# Chromium lives in /ms-playwright/chromium-*/chrome-linux/chrome in the Playwright image.
|
|
35
|
+
# Symlink to /usr/local/bin/chromium so puppeteer-using npm packages find it.
|
|
36
|
+
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
37
|
+
RUN ln -sf "$(find /ms-playwright -name chrome -type f -executable | head -1)" /usr/local/bin/chromium
|
|
38
|
+
ENV PUPPETEER_EXECUTABLE_PATH=/usr/local/bin/chromium
|
|
39
|
+
|
|
40
|
+
# --no-sandbox: Chromium can't use its user namespace sandbox inside a container
|
|
41
|
+
RUN echo '{"args":["--no-sandbox"]}' > /home/mercury/.puppeteerrc.json
|
|
42
|
+
ENV CHROMIUM_FLAGS="--no-sandbox"
|
|
43
|
+
|
|
44
|
+
# Install CLIs
|
|
45
|
+
RUN bun add -g @mariozechner/pi-coding-agent@^0.67.2
|
|
46
|
+
|
|
47
|
+
WORKDIR /app
|
|
48
|
+
|
|
49
|
+
COPY container/agent-package.json /app/package.json
|
|
50
|
+
RUN bun install --production
|
|
51
|
+
|
|
52
|
+
# Patch pi: skip thinkingConfig for Gemma models (Google API rejects thinkingBudget for them,
|
|
53
|
+
# but pi marks gemma-4 as reasoning:true and sends thinkingBudget:0 to disable it)
|
|
54
|
+
RUN node <<'EOF'
|
|
55
|
+
const fs = require('fs'), path = require('path');
|
|
56
|
+
function patch(dir) {
|
|
57
|
+
try {
|
|
58
|
+
for (const f of fs.readdirSync(dir)) {
|
|
59
|
+
const p = path.join(dir, f);
|
|
60
|
+
try {
|
|
61
|
+
if (fs.statSync(p).isDirectory()) patch(p);
|
|
62
|
+
else if (f === 'google.js' && p.includes('@mariozechner/pi-ai')) {
|
|
63
|
+
let c = fs.readFileSync(p, 'utf8');
|
|
64
|
+
const noThinking = '&& !model.id.startsWith("gemma")';
|
|
65
|
+
const p1 = 'if (options.thinking?.enabled && model.reasoning) {';
|
|
66
|
+
const p2 = 'else if (model.reasoning && options.thinking && !options.thinking.enabled) {';
|
|
67
|
+
if (!c.includes(noThinking)) {
|
|
68
|
+
c = c.replace(p1, 'if (options.thinking?.enabled && model.reasoning ' + noThinking + ') {');
|
|
69
|
+
c = c.replace(p2, 'else if (model.reasoning && options.thinking && !options.thinking.enabled ' + noThinking + ') {');
|
|
70
|
+
fs.writeFileSync(p, c);
|
|
71
|
+
console.log('Patched:', p);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch(e) {}
|
|
75
|
+
}
|
|
76
|
+
} catch(e) {}
|
|
77
|
+
}
|
|
78
|
+
patch('/home/mercury/.bun');
|
|
79
|
+
patch('/app/node_modules');
|
|
80
|
+
EOF
|
|
81
|
+
|
|
82
|
+
COPY src/agent/container-entry.ts /app/src/agent/container-entry.ts
|
|
83
|
+
COPY src/agent/model-capabilities-core.ts /app/src/agent/model-capabilities-core.ts
|
|
84
|
+
COPY src/agent/pi-failure-class.ts /app/src/agent/pi-failure-class.ts
|
|
85
|
+
COPY src/agent/pi-jsonl-parser.ts /app/src/agent/pi-jsonl-parser.ts
|
|
86
|
+
COPY src/agent/preferences-prompt.ts /app/src/agent/preferences-prompt.ts
|
|
87
|
+
COPY src/cli/mrctl.ts /app/src/cli/mrctl.ts
|
|
88
|
+
COPY src/cli/mrctl-http.ts /app/src/cli/mrctl-http.ts
|
|
89
|
+
COPY src/extensions/reserved.ts /app/src/extensions/reserved.ts
|
|
90
|
+
COPY src/extensions/permission-guard.ts /app/src/extensions/permission-guard.ts
|
|
91
|
+
COPY src/types.ts /app/src/types.ts
|
|
92
|
+
COPY resources/ /app/resources/
|
|
93
|
+
COPY examples/extensions/ /tmp/examples-extensions/
|
|
94
|
+
RUN while IFS= read -r ext || [ -n "$ext" ]; do \
|
|
95
|
+
ext=$(echo "$ext" | xargs); \
|
|
96
|
+
[ -z "$ext" ] && continue; \
|
|
97
|
+
cp -r "/tmp/examples-extensions/$ext" "/app/resources/extensions/$ext"; \
|
|
98
|
+
done < /app/resources/builtin-extensions.txt && \
|
|
99
|
+
rm -rf /tmp/examples-extensions/
|
|
100
|
+
|
|
101
|
+
RUN echo '#!/bin/sh\nbun run /app/src/cli/mrctl.ts "$@"' > /usr/local/bin/mrctl && \
|
|
102
|
+
chmod +x /usr/local/bin/mrctl
|
|
103
|
+
|
|
104
|
+
# Fix ownership of all mercury home dir artifacts before switching user
|
|
105
|
+
RUN chown -R mercury:mercury /home/mercury
|
|
106
|
+
|
|
107
|
+
USER mercury
|
|
108
|
+
|
|
109
|
+
ENTRYPOINT ["bun", "run", "/app/src/agent/container-entry.ts"]
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1
|
|
2
|
-
# Mercury Agent Container — Power tier
|
|
3
|
-
# Extends Base with: python3 + pip + venv, build-essential, jq, ffmpeg, bubblewrap
|
|
4
|
-
# The patch script, mrctl, and entrypoint are all inherited from Base — not duplicated here.
|
|
5
|
-
ARG BASE_TAG
|
|
6
|
-
FROM ghcr.io/avishai-tsabari/mercury-agent:${BASE_TAG}-base
|
|
7
|
-
|
|
8
|
-
USER root
|
|
9
|
-
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
10
|
-
python3 python3-pip python3-venv build-essential \
|
|
11
|
-
jq \
|
|
12
|
-
ffmpeg \
|
|
13
|
-
# Sandboxing: bubblewrap for defense-in-depth in runc mode.
|
|
14
|
-
# Not used when CONTAINER_RUNTIME=runsc (gVisor handles isolation at the syscall boundary).
|
|
15
|
-
bubblewrap \
|
|
16
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
17
|
-
USER mercury
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
# Mercury Agent Container — Power tier
|
|
3
|
+
# Extends Base with: python3 + pip + venv, build-essential, jq, ffmpeg, bubblewrap
|
|
4
|
+
# The patch script, mrctl, and entrypoint are all inherited from Base — not duplicated here.
|
|
5
|
+
ARG BASE_TAG
|
|
6
|
+
FROM ghcr.io/avishai-tsabari/mercury-agent:${BASE_TAG}-base
|
|
7
|
+
|
|
8
|
+
USER root
|
|
9
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
10
|
+
python3 python3-pip python3-venv build-essential \
|
|
11
|
+
jq \
|
|
12
|
+
ffmpeg \
|
|
13
|
+
# Sandboxing: bubblewrap for defense-in-depth in runc mode.
|
|
14
|
+
# Not used when CONTAINER_RUNTIME=runsc (gVisor handles isolation at the syscall boundary).
|
|
15
|
+
bubblewrap \
|
|
16
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
17
|
+
USER mercury
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mercury-agent-app",
|
|
3
|
-
"private": true,
|
|
4
|
-
"type": "module",
|
|
5
|
-
"dependencies": {
|
|
6
|
-
"@earendil-works/pi-coding-agent": "~0.79.6"
|
|
7
|
-
}
|
|
8
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "mercury-agent-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@earendil-works/pi-coding-agent": "~0.79.6"
|
|
7
|
+
}
|
|
8
|
+
}
|
package/container/build.sh
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Build the Mercury agent container images
|
|
3
|
-
set -e
|
|
4
|
-
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
-
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
7
|
-
cd "$PROJECT_ROOT"
|
|
8
|
-
|
|
9
|
-
IMAGE_NAME="mercury-agent"
|
|
10
|
-
|
|
11
|
-
# Parse arguments
|
|
12
|
-
BUILD_ALL=false
|
|
13
|
-
BUILD_LATEST=false
|
|
14
|
-
BUILD_MINIMAL=false
|
|
15
|
-
|
|
16
|
-
if [ $# -eq 0 ]; then
|
|
17
|
-
BUILD_LATEST=true
|
|
18
|
-
elif [ "$1" = "all" ]; then
|
|
19
|
-
BUILD_ALL=true
|
|
20
|
-
elif [ "$1" = "latest" ]; then
|
|
21
|
-
BUILD_LATEST=true
|
|
22
|
-
elif [ "$1" = "minimal" ]; then
|
|
23
|
-
BUILD_MINIMAL=true
|
|
24
|
-
else
|
|
25
|
-
echo "Usage: $0 [all|latest|minimal]"
|
|
26
|
-
echo ""
|
|
27
|
-
echo "Presets:"
|
|
28
|
-
echo " latest Full devcontainer with Node, Python, Go, git (~2.8GB)"
|
|
29
|
-
echo " minimal Bun + pi + browser only (~1.9GB)"
|
|
30
|
-
echo " all Build both presets"
|
|
31
|
-
echo ""
|
|
32
|
-
echo "Default: latest"
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
if [ "$BUILD_ALL" = true ] || [ "$BUILD_LATEST" = true ]; then
|
|
37
|
-
echo "Building ${IMAGE_NAME}:latest (full devcontainer)..."
|
|
38
|
-
docker build -f container/Dockerfile -t "${IMAGE_NAME}:latest" .
|
|
39
|
-
echo "✓ Built ${IMAGE_NAME}:latest"
|
|
40
|
-
echo ""
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
if [ "$BUILD_ALL" = true ] || [ "$BUILD_MINIMAL" = true ]; then
|
|
44
|
-
echo "Building ${IMAGE_NAME}:minimal (bun-only)..."
|
|
45
|
-
docker build -f container/Dockerfile.minimal -t "${IMAGE_NAME}:minimal" .
|
|
46
|
-
echo "✓ Built ${IMAGE_NAME}:minimal"
|
|
47
|
-
echo ""
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
echo "Build complete!"
|
|
51
|
-
if [ "$BUILD_ALL" = true ]; then
|
|
52
|
-
echo " ${IMAGE_NAME}:latest - Full devcontainer (~2.8GB)"
|
|
53
|
-
echo " ${IMAGE_NAME}:minimal - Bun + pi + browser (~1.9GB)"
|
|
54
|
-
fi
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Build the Mercury agent container images
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
7
|
+
cd "$PROJECT_ROOT"
|
|
8
|
+
|
|
9
|
+
IMAGE_NAME="mercury-agent"
|
|
10
|
+
|
|
11
|
+
# Parse arguments
|
|
12
|
+
BUILD_ALL=false
|
|
13
|
+
BUILD_LATEST=false
|
|
14
|
+
BUILD_MINIMAL=false
|
|
15
|
+
|
|
16
|
+
if [ $# -eq 0 ]; then
|
|
17
|
+
BUILD_LATEST=true
|
|
18
|
+
elif [ "$1" = "all" ]; then
|
|
19
|
+
BUILD_ALL=true
|
|
20
|
+
elif [ "$1" = "latest" ]; then
|
|
21
|
+
BUILD_LATEST=true
|
|
22
|
+
elif [ "$1" = "minimal" ]; then
|
|
23
|
+
BUILD_MINIMAL=true
|
|
24
|
+
else
|
|
25
|
+
echo "Usage: $0 [all|latest|minimal]"
|
|
26
|
+
echo ""
|
|
27
|
+
echo "Presets:"
|
|
28
|
+
echo " latest Full devcontainer with Node, Python, Go, git (~2.8GB)"
|
|
29
|
+
echo " minimal Bun + pi + browser only (~1.9GB)"
|
|
30
|
+
echo " all Build both presets"
|
|
31
|
+
echo ""
|
|
32
|
+
echo "Default: latest"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [ "$BUILD_ALL" = true ] || [ "$BUILD_LATEST" = true ]; then
|
|
37
|
+
echo "Building ${IMAGE_NAME}:latest (full devcontainer)..."
|
|
38
|
+
docker build -f container/Dockerfile -t "${IMAGE_NAME}:latest" .
|
|
39
|
+
echo "✓ Built ${IMAGE_NAME}:latest"
|
|
40
|
+
echo ""
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if [ "$BUILD_ALL" = true ] || [ "$BUILD_MINIMAL" = true ]; then
|
|
44
|
+
echo "Building ${IMAGE_NAME}:minimal (bun-only)..."
|
|
45
|
+
docker build -f container/Dockerfile.minimal -t "${IMAGE_NAME}:minimal" .
|
|
46
|
+
echo "✓ Built ${IMAGE_NAME}:minimal"
|
|
47
|
+
echo ""
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo "Build complete!"
|
|
51
|
+
if [ "$BUILD_ALL" = true ]; then
|
|
52
|
+
echo " ${IMAGE_NAME}:latest - Full devcontainer (~2.8GB)"
|
|
53
|
+
echo " ${IMAGE_NAME}:minimal - Bun + pi + browser (~1.9GB)"
|
|
54
|
+
fi
|