@madarco/agentbox 0.12.0 → 0.14.0
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/CHANGELOG.md +96 -0
- package/README.md +21 -7
- package/dist/{_cloud-attach-XKO4SHR3.js → _cloud-attach-GUBB5RH2.js} +4 -4
- package/dist/{chunk-R5XIDQFR.js → chunk-BKU34KYY.js} +170 -6
- package/dist/chunk-BKU34KYY.js.map +1 -0
- package/dist/{chunk-HFV6THYG.js → chunk-BYCLD6D6.js} +308 -36
- package/dist/chunk-BYCLD6D6.js.map +1 -0
- package/dist/chunk-LDMYHWUS.js +346 -0
- package/dist/chunk-LDMYHWUS.js.map +1 -0
- package/dist/{chunk-2LF5YILI.js → chunk-RSKG7AFU.js} +80 -6
- package/dist/chunk-RSKG7AFU.js.map +1 -0
- package/dist/{chunk-DHJ7OMIP.js → chunk-TBSIJVSN.js} +149 -47
- package/dist/chunk-TBSIJVSN.js.map +1 -0
- package/dist/{chunk-IZXPJPPV.js → chunk-TCS5HXJX.js} +389 -176
- package/dist/chunk-TCS5HXJX.js.map +1 -0
- package/dist/{chunk-ECLLV5JH.js → chunk-VATTS2MR.js} +156 -5
- package/dist/chunk-VATTS2MR.js.map +1 -0
- package/dist/{chunk-SNTHHWKY.js → chunk-XKH7NTT7.js} +80 -22
- package/dist/chunk-XKH7NTT7.js.map +1 -0
- package/dist/dist-34RKQ74M.js +662 -0
- package/dist/dist-34RKQ74M.js.map +1 -0
- package/dist/{dist-47LVLYUV.js → dist-3IMQNTTV.js} +14 -69
- package/dist/dist-3IMQNTTV.js.map +1 -0
- package/dist/{dist-RZZSSUNB.js → dist-4DPOL5A7.js} +5 -3
- package/dist/{dist-24PY2ZMO.js → dist-57M6ZA7H.js} +25 -177
- package/dist/dist-57M6ZA7H.js.map +1 -0
- package/dist/{dist-SWUOU34W.js → dist-J2IHD5T7.js} +37 -226
- package/dist/dist-J2IHD5T7.js.map +1 -0
- package/dist/index.js +1524 -921
- package/dist/index.js.map +1 -1
- package/dist/{prepared-state-MQHD3M5F-KE4DT3GX.js → prepared-state-MQHD3M5F-Q27AZU53.js} +2 -2
- package/package.json +9 -7
- package/runtime/docker/Dockerfile.box +21 -26
- package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +37 -1
- package/runtime/docker/packages/ctl/dist/bin.cjs +46 -17
- package/runtime/docker/packages/sandbox-docker/scripts/agentbox-vnc-start +17 -6
- package/runtime/docker/packages/sandbox-docker/scripts/chromium-resolver +57 -0
- package/runtime/docker/packages/sandbox-docker/scripts/claude-managed-settings.json +2 -1
- package/runtime/e2b/agentbox-checkpoint-cleanup +52 -0
- package/runtime/e2b/agentbox-codex-hooks.json +68 -0
- package/runtime/e2b/agentbox-open +28 -0
- package/runtime/e2b/agentbox-setup-skill.md +233 -0
- package/runtime/e2b/agentbox-vnc-start +102 -0
- package/runtime/e2b/attach-helper.cjs +167 -0
- package/runtime/e2b/claude-managed-settings.json +116 -0
- package/runtime/e2b/ctl.cjs +23864 -0
- package/runtime/e2b/custom-system-CLAUDE.md +46 -0
- package/runtime/e2b/gh-shim +344 -0
- package/runtime/e2b/git-shim +131 -0
- package/runtime/e2b/scripts/build-template.sh +295 -0
- package/runtime/hetzner/agentbox-setup-skill.md +37 -1
- package/runtime/hetzner/agentbox-vnc-start +17 -6
- package/runtime/hetzner/claude-managed-settings.json +2 -1
- package/runtime/hetzner/ctl.cjs +46 -17
- package/runtime/relay/bin.cjs +305 -230
- package/runtime/vercel/agentbox-setup-skill.md +37 -1
- package/runtime/vercel/agentbox-vnc-start +17 -6
- package/runtime/vercel/claude-managed-settings.json +2 -1
- package/runtime/vercel/ctl.cjs +46 -17
- package/share/agentbox-setup/SKILL.md +37 -1
- package/share/host-skills/agentbox-info/SKILL.md +26 -34
- package/dist/chunk-2LF5YILI.js.map +0 -1
- package/dist/chunk-DHJ7OMIP.js.map +0 -1
- package/dist/chunk-ECLLV5JH.js.map +0 -1
- package/dist/chunk-HFV6THYG.js.map +0 -1
- package/dist/chunk-IZXPJPPV.js.map +0 -1
- package/dist/chunk-R5XIDQFR.js.map +0 -1
- package/dist/chunk-SNTHHWKY.js.map +0 -1
- package/dist/dist-24PY2ZMO.js.map +0 -1
- package/dist/dist-47LVLYUV.js.map +0 -1
- package/dist/dist-SWUOU34W.js.map +0 -1
- /package/dist/{_cloud-attach-XKO4SHR3.js.map → _cloud-attach-GUBB5RH2.js.map} +0 -0
- /package/dist/{dist-RZZSSUNB.js.map → dist-4DPOL5A7.js.map} +0 -0
- /package/dist/{prepared-state-MQHD3M5F-KE4DT3GX.js.map → prepared-state-MQHD3M5F-Q27AZU53.js.map} +0 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# AgentBox E2B base-template installer.
|
|
3
|
+
#
|
|
4
|
+
# Run once by `Template.build`'s `.runCmd` step during `agentbox prepare
|
|
5
|
+
# --provider e2b`. After it completes, E2B finalises the template — that
|
|
6
|
+
# template id is what every per-box create boots from.
|
|
7
|
+
#
|
|
8
|
+
# Differences from the vercel installer (packages/sandbox-vercel/scripts/
|
|
9
|
+
# provision.sh), which this mirrors:
|
|
10
|
+
# - apt-get / dpkg, not dnf (E2B base = Debian 12 bookworm).
|
|
11
|
+
# - NO docker / dockerd / iptables — E2B microVMs can't run nested
|
|
12
|
+
# containers (same shape as vercel).
|
|
13
|
+
# - The `vscode` user is created with a free uid (E2B's `code` group holds
|
|
14
|
+
# 1000 on the base template, so useradd picks the next free uid; there are
|
|
15
|
+
# no bind mounts so the exact uid is irrelevant — only ownership of
|
|
16
|
+
# /workspace + /home/vscode matters).
|
|
17
|
+
#
|
|
18
|
+
# Required inputs (uploaded via Template.copy before this runs):
|
|
19
|
+
# /tmp/agentbox-ctl -- prebuilt @agentbox/ctl bundle (cjs)
|
|
20
|
+
# /tmp/agentbox-vnc-start -- VNC startup helper
|
|
21
|
+
# /tmp/agentbox-checkpoint-cleanup -- pre-snapshot cleanup helper
|
|
22
|
+
# /tmp/agentbox-open -- in-box xdg-open shim
|
|
23
|
+
# /tmp/agentbox-gh-shim -- in-box `gh` shim (routes to host gh)
|
|
24
|
+
# /tmp/agentbox-git-shim -- in-box `git` shim (routes via relay)
|
|
25
|
+
# /tmp/agentbox-custom-CLAUDE.md -- /etc/claude-code/CLAUDE.md content
|
|
26
|
+
# /tmp/agentbox-managed-settings.json -- /etc/claude-code/managed-settings.json
|
|
27
|
+
# /tmp/agentbox-codex-hooks.json -- /usr/local/share/agentbox/codex-hooks.json
|
|
28
|
+
# /tmp/agentbox-setup-skill.md -- /usr/local/share/agentbox/setup-guide.md
|
|
29
|
+
#
|
|
30
|
+
# Output: noisy progress to stdout (streamed into ~/.agentbox/logs/prepare.log).
|
|
31
|
+
# Each major step prints `>>> BEGIN <step>` / `<<< END <step>`.
|
|
32
|
+
|
|
33
|
+
set -euo pipefail
|
|
34
|
+
|
|
35
|
+
step() { printf '\n>>> BEGIN %s\n' "$1"; }
|
|
36
|
+
done_() { printf '<<< END %s\n' "$1"; }
|
|
37
|
+
|
|
38
|
+
if [ "$(id -u)" -ne 0 ]; then
|
|
39
|
+
echo "build-template.sh: must run as root (got uid $(id -u))" >&2
|
|
40
|
+
exit 64
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
44
|
+
|
|
45
|
+
step "apt base packages"
|
|
46
|
+
# E2B base ships Debian 12 with node + git + sudo already installed; we still
|
|
47
|
+
# need tmux, build deps, the X11 stack, etc.
|
|
48
|
+
apt-get update -y -q
|
|
49
|
+
apt-get install -y -q --no-install-recommends \
|
|
50
|
+
ca-certificates \
|
|
51
|
+
git \
|
|
52
|
+
tar \
|
|
53
|
+
gzip \
|
|
54
|
+
curl \
|
|
55
|
+
wget \
|
|
56
|
+
sudo \
|
|
57
|
+
python3 \
|
|
58
|
+
python3-pip \
|
|
59
|
+
python3-venv \
|
|
60
|
+
tmux \
|
|
61
|
+
vim \
|
|
62
|
+
libcap2-bin \
|
|
63
|
+
rsync \
|
|
64
|
+
xclip \
|
|
65
|
+
autocutsel
|
|
66
|
+
done_ "apt base packages"
|
|
67
|
+
|
|
68
|
+
step "node sanity"
|
|
69
|
+
# E2B base ships node 20; just confirm it's on PATH.
|
|
70
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
71
|
+
echo "build-template.sh: node not found on the E2B base template — unexpected" >&2
|
|
72
|
+
exit 65
|
|
73
|
+
fi
|
|
74
|
+
node --version
|
|
75
|
+
done_ "node sanity"
|
|
76
|
+
|
|
77
|
+
step "vscode user + sudoers"
|
|
78
|
+
# Don't force a uid: the E2B base template's `code` group/user holds 1000,
|
|
79
|
+
# and there are no bind mounts so uid-parity with the docker provider
|
|
80
|
+
# doesn't matter. Ownership + passwordless sudo is what counts.
|
|
81
|
+
if ! id vscode >/dev/null 2>&1; then
|
|
82
|
+
useradd -m -s /bin/bash vscode
|
|
83
|
+
fi
|
|
84
|
+
install -d -m 0755 -o vscode -g vscode /home/vscode
|
|
85
|
+
echo 'vscode ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/90-agentbox-vscode
|
|
86
|
+
chmod 0440 /etc/sudoers.d/90-agentbox-vscode
|
|
87
|
+
visudo -cf /etc/sudoers >/dev/null
|
|
88
|
+
done_ "vscode user + sudoers"
|
|
89
|
+
|
|
90
|
+
step "agentbox base dirs + /workspace ownership"
|
|
91
|
+
mkdir -p /workspace /run/agentbox /var/log/agentbox /etc/agentbox /etc/claude-code \
|
|
92
|
+
/usr/local/share/agentbox
|
|
93
|
+
chmod 755 /workspace
|
|
94
|
+
chown vscode:vscode /workspace /run/agentbox /var/log/agentbox
|
|
95
|
+
done_ "agentbox base dirs + /workspace ownership"
|
|
96
|
+
|
|
97
|
+
step "node setcap (bind <1024 without root)"
|
|
98
|
+
# Grant node the capability so the WebProxy can bind port 80 without sudo.
|
|
99
|
+
# Best-effort — if setcap is unavailable the WebProxy can still be launched
|
|
100
|
+
# via sudo. (E2B's `getHost` accepts any port; agentbox uses 8080 across
|
|
101
|
+
# cloud providers, so this is belt-and-braces.)
|
|
102
|
+
NODE_BIN="$(readlink -f "$(command -v node)")"
|
|
103
|
+
setcap cap_net_bind_service=+ep "$NODE_BIN" || echo "build-template.sh: setcap failed (continuing)"
|
|
104
|
+
done_ "node setcap (bind <1024 without root)"
|
|
105
|
+
|
|
106
|
+
step "corepack (pnpm + yarn shims)"
|
|
107
|
+
npm install -g corepack@latest 2>&1 | tail -2 || true
|
|
108
|
+
corepack enable pnpm yarn 2>/dev/null || true
|
|
109
|
+
sudo -u vscode -H mkdir -p /home/vscode/.cache/node/corepack
|
|
110
|
+
done_ "corepack (pnpm + yarn shims)"
|
|
111
|
+
|
|
112
|
+
step "git system-wide safe.directory"
|
|
113
|
+
git config --system --add safe.directory '*' 2>/dev/null || true
|
|
114
|
+
sudo -u vscode -H git config --global --add safe.directory '*' 2>/dev/null || true
|
|
115
|
+
done_ "git system-wide safe.directory"
|
|
116
|
+
|
|
117
|
+
step "agentbox-ctl install"
|
|
118
|
+
install -m 0755 /tmp/agentbox-ctl /usr/local/bin/agentbox-ctl
|
|
119
|
+
done_ "agentbox-ctl install"
|
|
120
|
+
|
|
121
|
+
step "baked helper scripts (vnc / cleanup / xdg-open)"
|
|
122
|
+
install -m 0755 /tmp/agentbox-vnc-start /usr/local/bin/agentbox-vnc-start
|
|
123
|
+
install -m 0755 /tmp/agentbox-checkpoint-cleanup /usr/local/bin/agentbox-checkpoint-cleanup
|
|
124
|
+
install -m 0755 /tmp/agentbox-open /usr/local/bin/agentbox-open
|
|
125
|
+
ln -sf /usr/local/bin/agentbox-open /usr/local/bin/xdg-open
|
|
126
|
+
# NOTE: the gh + git shims are installed LAST (see "relay shims" near the end).
|
|
127
|
+
# Installing them here would put the relay-routing `git` on PATH ahead of
|
|
128
|
+
# /usr/bin/git and route this script's own remaining git/clone commands through
|
|
129
|
+
# a relay that doesn't exist during the bake.
|
|
130
|
+
done_ "baked helper scripts (vnc / cleanup / xdg-open)"
|
|
131
|
+
|
|
132
|
+
step "baked config files (claude / codex / setup guide / tmux.conf)"
|
|
133
|
+
install -m 0644 /tmp/agentbox-custom-CLAUDE.md /etc/claude-code/CLAUDE.md
|
|
134
|
+
install -m 0644 /tmp/agentbox-managed-settings.json /etc/claude-code/managed-settings.json
|
|
135
|
+
install -m 0644 /tmp/agentbox-codex-hooks.json /usr/local/share/agentbox/codex-hooks.json
|
|
136
|
+
install -m 0644 /tmp/agentbox-setup-skill.md /usr/local/share/agentbox/setup-guide.md
|
|
137
|
+
|
|
138
|
+
cat > /etc/tmux.conf <<'TMUX'
|
|
139
|
+
set -g default-terminal "tmux-256color"
|
|
140
|
+
set -as terminal-overrides ",*:Tc"
|
|
141
|
+
set -as terminal-overrides ",*:RGB"
|
|
142
|
+
set -as terminal-features ",*:hyperlinks"
|
|
143
|
+
set -as terminal-features ",*:RGB"
|
|
144
|
+
set -g allow-passthrough on
|
|
145
|
+
set -g set-clipboard on
|
|
146
|
+
set -g extended-keys on
|
|
147
|
+
set -as terminal-features ",*:extkeys"
|
|
148
|
+
set -g mouse on
|
|
149
|
+
bind -T copy-mode WheelUpPane send -N2 -X scroll-up
|
|
150
|
+
bind -T copy-mode WheelDownPane send -N2 -X scroll-down
|
|
151
|
+
bind -T copy-mode-vi WheelUpPane send -N2 -X scroll-up
|
|
152
|
+
bind -T copy-mode-vi WheelDownPane send -N2 -X scroll-down
|
|
153
|
+
set -g history-limit 50000
|
|
154
|
+
set -g escape-time 0
|
|
155
|
+
TMUX
|
|
156
|
+
done_ "baked config files (claude / codex / setup guide / tmux.conf)"
|
|
157
|
+
|
|
158
|
+
step "credential pivot symlinks (vscode home)"
|
|
159
|
+
sudo -u vscode -H mkdir -p \
|
|
160
|
+
/home/vscode/.claude \
|
|
161
|
+
/home/vscode/.claude/skills/agentbox-setup \
|
|
162
|
+
/home/vscode/.codex \
|
|
163
|
+
/home/vscode/.local/share/opencode \
|
|
164
|
+
/home/vscode/.agentbox-creds/claude \
|
|
165
|
+
/home/vscode/.agentbox-creds/codex \
|
|
166
|
+
/home/vscode/.agentbox-creds/opencode
|
|
167
|
+
sudo -u vscode -H ln -sf /home/vscode/.agentbox-creds/claude/.credentials.json \
|
|
168
|
+
/home/vscode/.claude/.credentials.json
|
|
169
|
+
sudo -u vscode -H ln -sf /home/vscode/.agentbox-creds/codex/auth.json \
|
|
170
|
+
/home/vscode/.codex/auth.json
|
|
171
|
+
sudo -u vscode -H ln -sf /home/vscode/.agentbox-creds/opencode/auth.json \
|
|
172
|
+
/home/vscode/.local/share/opencode/auth.json
|
|
173
|
+
sudo -u vscode -H ln -sf /home/vscode/.claude/_claude.json /home/vscode/.claude.json
|
|
174
|
+
sudo -u vscode -H cp /usr/local/share/agentbox/setup-guide.md \
|
|
175
|
+
/home/vscode/.claude/skills/agentbox-setup/SKILL.md
|
|
176
|
+
done_ "credential pivot symlinks (vscode home)"
|
|
177
|
+
|
|
178
|
+
step "login-shell shim (/etc/profile.d/agentbox.sh)"
|
|
179
|
+
cat > /etc/profile.d/agentbox.sh <<'PROFILE'
|
|
180
|
+
# Auto-loaded by login shells; box.env is written at create time.
|
|
181
|
+
if [ -r /etc/agentbox/box.env ]; then
|
|
182
|
+
set -a
|
|
183
|
+
. /etc/agentbox/box.env
|
|
184
|
+
set +a
|
|
185
|
+
fi
|
|
186
|
+
case ":$PATH:" in
|
|
187
|
+
*:/home/vscode/.local/bin:*) : ;;
|
|
188
|
+
*) PATH=/home/vscode/.local/bin:$PATH ;;
|
|
189
|
+
esac
|
|
190
|
+
# Force /usr/local/bin to win PATH so the relay-routing shims at
|
|
191
|
+
# /usr/local/bin/{git,gh} aren't shadowed by /usr/bin/{git,gh}. Strip any
|
|
192
|
+
# existing occurrence and re-prepend.
|
|
193
|
+
PATH=/usr/local/bin:$(printf '%s' "$PATH" | sed -e 's#:/usr/local/bin:#:#g' -e 's#^/usr/local/bin:##' -e 's#:/usr/local/bin$##' -e 's#^/usr/local/bin$##')
|
|
194
|
+
export PATH
|
|
195
|
+
export COLORTERM=${COLORTERM:-truecolor}
|
|
196
|
+
export DISABLE_AUTOUPDATER=${DISABLE_AUTOUPDATER:-1}
|
|
197
|
+
export DISPLAY=${DISPLAY:-:1}
|
|
198
|
+
export AGENT_BROWSER_EXECUTABLE_PATH=${AGENT_BROWSER_EXECUTABLE_PATH:-/usr/local/bin/chromium}
|
|
199
|
+
export BROWSER=${BROWSER:-/usr/local/bin/agentbox-open}
|
|
200
|
+
PROFILE
|
|
201
|
+
chmod 0644 /etc/profile.d/agentbox.sh
|
|
202
|
+
done_ "login-shell shim (/etc/profile.d/agentbox.sh)"
|
|
203
|
+
|
|
204
|
+
step "VNC stack (TigerVNC + websockify + noVNC)"
|
|
205
|
+
# Best-effort: VNC is a convenience (agentbox screen). A package that isn't in
|
|
206
|
+
# the Debian repos shouldn't fail the whole bake.
|
|
207
|
+
apt-get install -y -q --no-install-recommends \
|
|
208
|
+
tigervnc-standalone-server xterm 2>&1 | tail -3 || \
|
|
209
|
+
echo "build-template.sh: tigervnc install failed (VNC may be unavailable)"
|
|
210
|
+
# Install websockify into a per-user venv (PEP 668 forbids system pip on
|
|
211
|
+
# Debian 12). The venv goes under /usr/local/share so agentbox-vnc-start can
|
|
212
|
+
# find it regardless of the launching user.
|
|
213
|
+
python3 -m venv /usr/local/share/agentbox/venv 2>/dev/null || true
|
|
214
|
+
/usr/local/share/agentbox/venv/bin/pip install --quiet websockify 2>&1 | tail -2 || \
|
|
215
|
+
echo "build-template.sh: websockify install failed (VNC may be unavailable)"
|
|
216
|
+
ln -sf /usr/local/share/agentbox/venv/bin/websockify /usr/local/bin/websockify
|
|
217
|
+
# noVNC static assets — clone shallow into a stable path the vnc-start script
|
|
218
|
+
# can serve.
|
|
219
|
+
if [ ! -d /usr/local/share/novnc ]; then
|
|
220
|
+
git clone --depth 1 https://github.com/novnc/noVNC /usr/local/share/novnc 2>&1 | tail -2 || \
|
|
221
|
+
echo "build-template.sh: noVNC clone failed (VNC may be unavailable)"
|
|
222
|
+
fi
|
|
223
|
+
sudo -u vscode -H mkdir -p /home/vscode/.vnc
|
|
224
|
+
done_ "VNC stack (TigerVNC + websockify + noVNC)"
|
|
225
|
+
|
|
226
|
+
step "agent CLIs (codex + opencode + agent-browser, global npm)"
|
|
227
|
+
npm install -g @openai/codex opencode-ai agent-browser 2>&1 | tail -3 || \
|
|
228
|
+
echo "build-template.sh: one or more agent npm installs failed (continuing)"
|
|
229
|
+
done_ "agent CLIs (codex + opencode + agent-browser, global npm)"
|
|
230
|
+
|
|
231
|
+
step "Claude Code (native installer, run as vscode)"
|
|
232
|
+
# Anthropic's canonical installer drops `claude` at /home/vscode/.local/bin/.
|
|
233
|
+
sudo -u vscode -H bash -lc 'curl -fsSL https://claude.ai/install.sh | bash -s stable'
|
|
234
|
+
done_ "Claude Code (native installer, run as vscode)"
|
|
235
|
+
|
|
236
|
+
step "Chrome runtime libs (apt)"
|
|
237
|
+
# agent-browser launches Chromium at AGENT_BROWSER_EXECUTABLE_PATH
|
|
238
|
+
# (/usr/local/bin/chromium, set in the login-shell shim above). Bake the libs
|
|
239
|
+
# Playwright's Chromium needs. Match the docker provider's Debian apt list.
|
|
240
|
+
apt-get install -y -q --no-install-recommends \
|
|
241
|
+
libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
|
|
242
|
+
libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
|
|
243
|
+
libgbm1 libpango-1.0-0 libcairo2 libasound2 \
|
|
244
|
+
fonts-liberation
|
|
245
|
+
done_ "Chrome runtime libs (apt)"
|
|
246
|
+
|
|
247
|
+
step "playwright + Chromium download (as vscode)"
|
|
248
|
+
# Run the download as vscode so the cache lands under
|
|
249
|
+
# /home/vscode/.cache/ms-playwright. Resolve a stable symlink at
|
|
250
|
+
# /usr/local/bin/chromium so AGENT_BROWSER_EXECUTABLE_PATH stays predictable
|
|
251
|
+
# across Chromium revision bumps.
|
|
252
|
+
npm install -g playwright 2>&1 | tail -3
|
|
253
|
+
sudo -u vscode -H bash -lc 'playwright install chromium'
|
|
254
|
+
CHROME_BIN="$(sudo -u vscode -H bash -lc 'ls /home/vscode/.cache/ms-playwright/chromium-*/chrome-linux*/chrome 2>/dev/null | sort | tail -1')"
|
|
255
|
+
if [ -z "$CHROME_BIN" ] || [ ! -x "$CHROME_BIN" ]; then
|
|
256
|
+
echo "build-template.sh: could not resolve Playwright Chromium binary" >&2
|
|
257
|
+
exit 70
|
|
258
|
+
fi
|
|
259
|
+
# Fail loud if a shared lib is missing — surfaces an incomplete apt set at bake
|
|
260
|
+
# time, not at first agent-browser launch.
|
|
261
|
+
LDD_OUT="$(ldd "$CHROME_BIN" 2>&1 || true)"
|
|
262
|
+
if printf '%s\n' "$LDD_OUT" | grep -q 'not found'; then
|
|
263
|
+
echo "build-template.sh: Chromium has unresolved shared libs:" >&2
|
|
264
|
+
printf '%s\n' "$LDD_OUT" | grep 'not found' >&2
|
|
265
|
+
exit 71
|
|
266
|
+
fi
|
|
267
|
+
ln -sf "$CHROME_BIN" /usr/local/bin/chromium
|
|
268
|
+
done_ "playwright + Chromium download (as vscode)"
|
|
269
|
+
|
|
270
|
+
step "apt cleanup"
|
|
271
|
+
apt-get clean -y -q 2>/dev/null || true
|
|
272
|
+
rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
|
273
|
+
done_ "apt cleanup"
|
|
274
|
+
|
|
275
|
+
# Relay-routing shims, installed LAST — after every git/gh use in this script
|
|
276
|
+
# (the noVNC `git clone` and any npm/installer step). At RUNTIME agent calls to
|
|
277
|
+
# `gh ...` / `git push|pull|fetch|clone` must route through the host relay; the
|
|
278
|
+
# login-shell shim above forces /usr/local/bin ahead of /usr/bin so these win.
|
|
279
|
+
# During the bake there is no relay, so they must not shadow the real binaries
|
|
280
|
+
# until provisioning is done. Installed from /tmp just before the trim step.
|
|
281
|
+
step "relay shims (gh + git)"
|
|
282
|
+
install -m 0755 /tmp/agentbox-gh-shim /usr/local/bin/gh
|
|
283
|
+
install -m 0755 /tmp/agentbox-git-shim /usr/local/bin/git
|
|
284
|
+
done_ "relay shims (gh + git)"
|
|
285
|
+
|
|
286
|
+
step "trim /tmp/agentbox-*"
|
|
287
|
+
rm -f /tmp/agentbox-ctl /tmp/agentbox-vnc-start \
|
|
288
|
+
/tmp/agentbox-checkpoint-cleanup /tmp/agentbox-open \
|
|
289
|
+
/tmp/agentbox-gh-shim /tmp/agentbox-git-shim \
|
|
290
|
+
/tmp/agentbox-custom-CLAUDE.md /tmp/agentbox-managed-settings.json \
|
|
291
|
+
/tmp/agentbox-codex-hooks.json /tmp/agentbox-setup-skill.md
|
|
292
|
+
mv /tmp/agentbox-build-template.sh /var/log/agentbox/build-template.sh 2>/dev/null || true
|
|
293
|
+
done_ "trim /tmp/agentbox-*"
|
|
294
|
+
|
|
295
|
+
printf '\n*** build-template.sh: complete — template ready for finalisation.\n'
|
|
@@ -48,7 +48,42 @@ Look at `/workspace`:
|
|
|
48
48
|
- No cycles in `needs:`.
|
|
49
49
|
- **Always generate a dependency-install task** and make it the root of the `needs:` graph (every service that needs deps gets `needs: [install, …]`). Future boxes start from a snapshot of the final filesystem so they won't need this, but updates or moving to a cloud provider might need to rebuild the container from scratch. The filesystem can be then later captured by `agentbox-ctl checkpoint --set-default`. The task must be **idempotent and self-healing**: `agentbox-ctl` re-runs pending tasks on every box stop/start (the daemon dies with the container and is relaunched), so a plain `rm -rf node_modules && install` would wipe + reinstall on every start. Guard the rebuild with a marker file *inside* `node_modules` (the `.agentbox-installed` convention AgentBox uses internally): rebuild only when the marker is absent (fresh box), and be a fast no-op once it exists. Detect the package manager from the lockfile — never hardcode `pnpm`. See the worked example below.
|
|
50
50
|
- **Add a comment to the beginning** of the file to explain what you did and what issues you encountered, so that future run might use this information in case the project evolves and you need to update the agentbox.yaml file.
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
### Stateful services: data persistence & re-seeding (read this for databases)
|
|
53
|
+
|
|
54
|
+
**A checkpoint does NOT capture docker-in-docker data.** `agentbox checkpoint` is a `docker commit` of the box's writable filesystem (the system + `/workspace`). The in-box `dockerd` keeps its storage in a *separate* per-box volume (`/var/lib/docker`), which is **not** part of that image — it's fresh on every new box and wiped on `agentbox destroy`. So a database or cache you run as a **docker container** (e.g. `docker run … postgres`) starts **empty on every new box** created from a checkpoint (every `agentbox claude` / `agentbox create`), even though `/workspace` and any marker files you wrote were restored. (A DB run as a **native process** with its data dir on the box filesystem — e.g. `postgres -D /var/lib/postgresql/data` — *is* captured by the checkpoint, since it lives in the writable layer.)
|
|
55
|
+
|
|
56
|
+
**Consequence for migrate/seed tasks of a containerized DB: do not gate them on a filesystem marker.** A marker like `node_modules/.agentbox-installed` is correct for deps (they live in `/workspace`, which the checkpoint captures), but **wrong** for DB data living in a docker volume: the marker is restored from the checkpoint while the DB is empty, so a marker-guarded seed wrongly skips and the app boots against an empty database. Instead, **gate on the actual data** — connect to the DB and check whether a sentinel table/row exists, and seed only when it's missing:
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
seed:
|
|
60
|
+
# Re-seed when the DB is empty. The postgres data lives in the in-box
|
|
61
|
+
# docker volume, which is NOT captured by `agentbox checkpoint` — so a box
|
|
62
|
+
# started from a checkpoint has the workspace warm but an empty DB. We can't
|
|
63
|
+
# use a filesystem marker here (it would be restored while the DB is blank);
|
|
64
|
+
# instead probe the DB and seed only if the data is absent. Fast no-op once
|
|
65
|
+
# the data is present.
|
|
66
|
+
command: |
|
|
67
|
+
set -e
|
|
68
|
+
export PGPASSWORD=postgres
|
|
69
|
+
# Probe for existing data. If the table is missing the query errors,
|
|
70
|
+
# stderr is suppressed, stdout is empty, the grep fails — so we seed.
|
|
71
|
+
if psql -h 127.0.0.1 -p 5432 -U postgres -d app -tAc \
|
|
72
|
+
"SELECT EXISTS (SELECT 1 FROM users LIMIT 1)" 2>/dev/null | grep -q t; then
|
|
73
|
+
echo "data present — skip seed"
|
|
74
|
+
exit 0
|
|
75
|
+
fi
|
|
76
|
+
pnpm db:seed
|
|
77
|
+
needs: [install, migrate]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Lifecycle nuance (this is why the data check, not a marker, is right):**
|
|
81
|
+
|
|
82
|
+
- **Box stop → start** (`agentbox stop`/`start`): the supervisor daemon dies with the container and is relaunched, so it **re-runs all tasks** from `pending`. The per-box docker volume *does* survive stop/start, so the DB still has data — the data check makes the seed a fast no-op.
|
|
83
|
+
- **New box from a checkpoint** (`agentbox claude`/`create`): tasks run and the DB volume is empty → the check fails → the seed runs. Correct.
|
|
84
|
+
- **Resume after pause** (`agentbox pause`/`unpause`): the daemon is frozen and thawed, **not** restarted, so tasks do **not** re-run at all — nothing to seed, the running DB is untouched.
|
|
85
|
+
|
|
86
|
+
(Migrations are usually safe to re-run as-is: migration tools track applied migrations in their own table, which on a fresh box is empty, so they simply re-apply. Only the *data* seed needs the existence check.) Install the DB client the seed/migrate tasks need (e.g. `postgresql-client`) in the `install` task — don't `docker exec` the DB container for these checks (nested `docker exec` fails inside a box with a `setns` error); reach it over TCP with the client tools instead.
|
|
52
87
|
|
|
53
88
|
## 3. Wire readiness probes (services only)
|
|
54
89
|
|
|
@@ -184,6 +219,7 @@ Tell the user (verbatim):
|
|
|
184
219
|
## 9. Checkpoint the warm state - DON't SKIP THIS STEP
|
|
185
220
|
|
|
186
221
|
Checkpoint (snapshot) this box writable layer: once the box is warmed up (deps installed, services ready), checkpoint it with `agentbox-ctl checkpoint --name setup --replace --set-default` so future boxes start ready.
|
|
222
|
+
Remember the checkpoint captures the writable layer (`/workspace` + system), **not** docker-in-docker volumes — so a containerized DB's data does not carry into new boxes. That's expected; the data-existence-gated seed task from section 2 re-seeds those automatically. (If you need the data itself to persist into new boxes, run the DB as a native process with its data dir on the box filesystem, or bind a `/workspace` path as the container's data volume so it lands in the checkpoint.)
|
|
187
223
|
Run this command exactly once. The `--name setup --replace` makes it idempotent — if it ever needs to run again it overwrites the existing `setup` checkpoint instead of stacking duplicates.
|
|
188
224
|
On all providers except Vercel, this doesn't need to be confirmed by the user. It will pause the container for several seconds so warn the user about it and write Done when it's done.
|
|
189
225
|
On Vercel: this actually STOPS the sandbox, so warn the user about it. Also the system will ask confirmation.
|
|
@@ -23,10 +23,22 @@ mkdir -p "$HOME/.vnc"
|
|
|
23
23
|
# VncAuth truncates >8 chars at compare time, which is fine — the host writes
|
|
24
24
|
# an 8-char password. Write to a temp file + rename so a failure (e.g.,
|
|
25
25
|
# vncpasswd missing) doesn't leave an empty file that Xvnc would then reject.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
#
|
|
27
|
+
# Debian 12 (E2B base) doesn't package vncpasswd at all — tigervnc-tools is
|
|
28
|
+
# Ubuntu-only. When vncpasswd is missing, fall back to `-SecurityTypes None`
|
|
29
|
+
# and rely on the cloud provider's signed preview URL as the access boundary
|
|
30
|
+
# (same effective model: holding the URL = holding the credential). Other
|
|
31
|
+
# providers (docker, hetzner, daytona, vercel) keep VncAuth.
|
|
32
|
+
VNC_SECURITY_ARGS=(-SecurityTypes VncAuth -PasswordFile "$HOME/.vnc/passwd")
|
|
33
|
+
if command -v vncpasswd >/dev/null 2>&1; then
|
|
34
|
+
TMP_PASSWD="$(mktemp "$HOME/.vnc/passwd.XXXXXX")"
|
|
35
|
+
printf '%s\n' "$PASS" | vncpasswd -f > "$TMP_PASSWD"
|
|
36
|
+
chmod 600 "$TMP_PASSWD"
|
|
37
|
+
mv "$TMP_PASSWD" "$HOME/.vnc/passwd"
|
|
38
|
+
else
|
|
39
|
+
echo "agentbox-vnc-start: vncpasswd not installed; starting Xvnc with -SecurityTypes None (preview URL is the access boundary)" >&2
|
|
40
|
+
VNC_SECURITY_ARGS=(-SecurityTypes None)
|
|
41
|
+
fi
|
|
30
42
|
|
|
31
43
|
mkdir -p /var/log/agentbox 2>/dev/null || true
|
|
32
44
|
|
|
@@ -37,8 +49,7 @@ mkdir -p /var/log/agentbox 2>/dev/null || true
|
|
|
37
49
|
# accept cut-text from noVNC, set both the X CLIPBOARD and PRIMARY selections.
|
|
38
50
|
Xvnc :1 \
|
|
39
51
|
-localhost \
|
|
40
|
-
|
|
41
|
-
-PasswordFile "$HOME/.vnc/passwd" \
|
|
52
|
+
"${VNC_SECURITY_ARGS[@]}" \
|
|
42
53
|
-geometry 1280x800 \
|
|
43
54
|
-depth 24 \
|
|
44
55
|
-AlwaysShared \
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "AgentBox enterprise-managed Claude Code settings, baked into the box image at /etc/claude-code/managed-settings.json. Highest precedence and NOT synced from the host ~/.claude, so claude-hooks-filter.ts never touches it; per Claude Code, hook arrays MERGE across settings sources, so the user's own hooks still run. These hooks report Claude's activity to the box supervisor (agentbox-ctl claude-state -> ctl socket -> relay -> ~/.agentbox/boxes/<id>/status.json) so `agentbox status/list/inspect` can show it even when the box is paused. Each command is exit-0 fast and shell-backgrounded so a hook can never block or fail a Claude turn. The ExitPlanMode / AskUserQuestion entries run SYNCHRONOUSLY (no &) because they consume the hook's stdin payload; the catchall PreToolUse 'working' hook races with them, but the supervisor's sticky-state semantics swallow that race (a 'working' set while in end-plan/question is ignored unless --clear-pending is set, which only the matching PostToolUse hook passes).",
|
|
2
|
+
"$comment": "AgentBox enterprise-managed Claude Code settings, baked into the box image at /etc/claude-code/managed-settings.json. Highest precedence and NOT synced from the host ~/.claude, so claude-hooks-filter.ts never touches it; per Claude Code, hook arrays MERGE across settings sources, so the user's own hooks still run. These hooks report Claude's activity to the box supervisor (agentbox-ctl claude-state -> ctl socket -> relay -> ~/.agentbox/boxes/<id>/status.json) so `agentbox status/list/inspect` can show it even when the box is paused. Each command is exit-0 fast and shell-backgrounded so a hook can never block or fail a Claude turn. The ExitPlanMode / AskUserQuestion entries run SYNCHRONOUSLY (no &) because they consume the hook's stdin payload; the catchall PreToolUse 'working' hook races with them, but the supervisor's sticky-state semantics swallow that race (a 'working' set while in end-plan/question is ignored unless --clear-pending is set, which only the matching PostToolUse hook passes). skipDangerousModePermissionPrompt pre-accepts the bypass-permissions disclaimer at policy precedence — AgentBox boxes are isolated, and `agentbox claude` defaults to --dangerously-skip-permissions, so the one-time accept gate would just trap every fresh box.",
|
|
3
|
+
"skipDangerousModePermissionPrompt": true,
|
|
3
4
|
"hooks": {
|
|
4
5
|
"UserPromptSubmit": [
|
|
5
6
|
{
|
package/runtime/hetzner/ctl.cjs
CHANGED
|
@@ -3344,15 +3344,15 @@ var require_windows = __commonJS({
|
|
|
3344
3344
|
}
|
|
3345
3345
|
return false;
|
|
3346
3346
|
}
|
|
3347
|
-
function checkStat(
|
|
3348
|
-
if (!
|
|
3347
|
+
function checkStat(stat3, path6, options) {
|
|
3348
|
+
if (!stat3.isSymbolicLink() && !stat3.isFile()) {
|
|
3349
3349
|
return false;
|
|
3350
3350
|
}
|
|
3351
3351
|
return checkPathExt(path6, options);
|
|
3352
3352
|
}
|
|
3353
3353
|
function isexe(path6, options, cb) {
|
|
3354
|
-
fs.stat(path6, function(er,
|
|
3355
|
-
cb(er, er ? false : checkStat(
|
|
3354
|
+
fs.stat(path6, function(er, stat3) {
|
|
3355
|
+
cb(er, er ? false : checkStat(stat3, path6, options));
|
|
3356
3356
|
});
|
|
3357
3357
|
}
|
|
3358
3358
|
function sync(path6, options) {
|
|
@@ -3369,20 +3369,20 @@ var require_mode = __commonJS({
|
|
|
3369
3369
|
isexe.sync = sync;
|
|
3370
3370
|
var fs = require("fs");
|
|
3371
3371
|
function isexe(path6, options, cb) {
|
|
3372
|
-
fs.stat(path6, function(er,
|
|
3373
|
-
cb(er, er ? false : checkStat(
|
|
3372
|
+
fs.stat(path6, function(er, stat3) {
|
|
3373
|
+
cb(er, er ? false : checkStat(stat3, options));
|
|
3374
3374
|
});
|
|
3375
3375
|
}
|
|
3376
3376
|
function sync(path6, options) {
|
|
3377
3377
|
return checkStat(fs.statSync(path6), options);
|
|
3378
3378
|
}
|
|
3379
|
-
function checkStat(
|
|
3380
|
-
return
|
|
3379
|
+
function checkStat(stat3, options) {
|
|
3380
|
+
return stat3.isFile() && checkMode(stat3, options);
|
|
3381
3381
|
}
|
|
3382
|
-
function checkMode(
|
|
3383
|
-
var mod =
|
|
3384
|
-
var uid =
|
|
3385
|
-
var gid =
|
|
3382
|
+
function checkMode(stat3, options) {
|
|
3383
|
+
var mod = stat3.mode;
|
|
3384
|
+
var uid = stat3.uid;
|
|
3385
|
+
var gid = stat3.gid;
|
|
3386
3386
|
var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
|
|
3387
3387
|
var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
|
|
3388
3388
|
var u2 = parseInt("100", 8);
|
|
@@ -12239,11 +12239,11 @@ var replacements = Object.entries(specialMainSymbols);
|
|
|
12239
12239
|
// ../../node_modules/.pnpm/yoctocolors@2.1.2/node_modules/yoctocolors/base.js
|
|
12240
12240
|
var import_node_tty = __toESM(require("tty"), 1);
|
|
12241
12241
|
var hasColors = import_node_tty.default?.WriteStream?.prototype?.hasColors?.() ?? false;
|
|
12242
|
-
var format = (
|
|
12242
|
+
var format = (open2, close) => {
|
|
12243
12243
|
if (!hasColors) {
|
|
12244
12244
|
return (input) => input;
|
|
12245
12245
|
}
|
|
12246
|
-
const openCode = `\x1B[${
|
|
12246
|
+
const openCode = `\x1B[${open2}m`;
|
|
12247
12247
|
const closeCode = `\x1B[${close}m`;
|
|
12248
12248
|
return (input) => {
|
|
12249
12249
|
const string = input + "";
|
|
@@ -18472,8 +18472,8 @@ var KEY_REGISTRY = [
|
|
|
18472
18472
|
{
|
|
18473
18473
|
key: "box.provider",
|
|
18474
18474
|
type: "enum",
|
|
18475
|
-
enumValues: ["docker", "daytona", "hetzner", "vercel"],
|
|
18476
|
-
description: "Sandbox backend new boxes are created on: local Docker containers, Daytona Cloud sandboxes, Hetzner Cloud VPSes, or
|
|
18475
|
+
enumValues: ["docker", "daytona", "hetzner", "vercel", "e2b"],
|
|
18476
|
+
description: "Sandbox backend new boxes are created on: local Docker containers, Daytona Cloud sandboxes, Hetzner Cloud VPSes, Vercel Sandboxes, or E2B microVMs."
|
|
18477
18477
|
},
|
|
18478
18478
|
{
|
|
18479
18479
|
key: "box.hostSnapshot",
|
|
@@ -18509,6 +18509,12 @@ var KEY_REGISTRY = [
|
|
|
18509
18509
|
description: "Per-provider override of `box.defaultCheckpoint` for vercel. Wins over the global when set; set via `agentbox checkpoint set-default --provider vercel`.",
|
|
18510
18510
|
advanced: true
|
|
18511
18511
|
},
|
|
18512
|
+
{
|
|
18513
|
+
key: "box.defaultCheckpointE2b",
|
|
18514
|
+
type: "string",
|
|
18515
|
+
description: "Per-provider override of `box.defaultCheckpoint` for e2b. Wins over the global when set; set via `agentbox checkpoint set-default --provider e2b`.",
|
|
18516
|
+
advanced: true
|
|
18517
|
+
},
|
|
18512
18518
|
{
|
|
18513
18519
|
key: "box.size",
|
|
18514
18520
|
type: "string",
|
|
@@ -18538,6 +18544,12 @@ var KEY_REGISTRY = [
|
|
|
18538
18544
|
description: "Per-provider override of `box.size` for vercel. Reserved \u2014 vercel sizing is controlled via `box.vercelVcpus`.",
|
|
18539
18545
|
advanced: true
|
|
18540
18546
|
},
|
|
18547
|
+
{
|
|
18548
|
+
key: "box.sizeE2b",
|
|
18549
|
+
type: "string",
|
|
18550
|
+
description: "Per-provider override of `box.size` for e2b. Reserved \u2014 e2b sizing is template-level (set at `agentbox prepare --provider e2b` time via --vcpus / --memory).",
|
|
18551
|
+
advanced: true
|
|
18552
|
+
},
|
|
18541
18553
|
{
|
|
18542
18554
|
key: "checkpoint.maxLayers",
|
|
18543
18555
|
type: "int",
|
|
@@ -18609,6 +18621,12 @@ var KEY_REGISTRY = [
|
|
|
18609
18621
|
description: "Per-provider override of `box.image` for vercel (snapshot id, e.g. `snap_\u2026`). Written by `agentbox prepare --provider vercel`.",
|
|
18610
18622
|
advanced: true
|
|
18611
18623
|
},
|
|
18624
|
+
{
|
|
18625
|
+
key: "box.imageE2b",
|
|
18626
|
+
type: "string",
|
|
18627
|
+
description: "Per-provider override of `box.image` for e2b (template id or `name:tag`, e.g. `agentbox-base:latest`). Written by `agentbox prepare --provider e2b`.",
|
|
18628
|
+
advanced: true
|
|
18629
|
+
},
|
|
18612
18630
|
{
|
|
18613
18631
|
key: "box.imageRegistry",
|
|
18614
18632
|
type: "string",
|
|
@@ -18690,7 +18708,12 @@ var KEY_REGISTRY = [
|
|
|
18690
18708
|
key: "attach.openIn",
|
|
18691
18709
|
type: "enum",
|
|
18692
18710
|
enumValues: ["split", "window", "tab", "same"],
|
|
18693
|
-
description: "Where `agentbox claude|codex|opencode` opens the attached session when run from tmux or iTerm2: `split` (tmux split-window / iTerm2 vertical split, default), `window` (tmux new-window / new iTerm2 window), `tab` (tmux new-window / new iTerm2 tab), or `same` (attach inline in the current terminal). Outside tmux/iTerm2 every value behaves like `same`."
|
|
18711
|
+
description: "Where `agentbox claude|codex|opencode` opens the attached session when run from tmux, cmux, or iTerm2: `split` (tmux split-window / cmux new-split / iTerm2 vertical split, default \u2014 same workspace), `window` (tmux new-window / cmux new-workspace / new iTerm2 window), `tab` (tmux new-window / cmux new-surface tab in the current pane, same workspace / new iTerm2 tab), or `same` (attach inline in the current terminal). Outside tmux/cmux/iTerm2 every value behaves like `same`."
|
|
18712
|
+
},
|
|
18713
|
+
{
|
|
18714
|
+
key: "attach.cmuxStatus",
|
|
18715
|
+
type: "bool",
|
|
18716
|
+
description: "When attached inside cmux, reflect the box agent's live activity on its cmux workspace (colour + description: blue=working, amber=needs input, idle clears; restored on detach) and, when the agent needs input, flag the box's own tab via a cmux notification (tab badge + reorder + desktop notification) so it stands out among sibling tabs. cmux only; no-op in other terminals."
|
|
18694
18717
|
},
|
|
18695
18718
|
{
|
|
18696
18719
|
key: "code.ide",
|
|
@@ -19539,6 +19562,10 @@ async function resolveCloudBackend(name) {
|
|
|
19539
19562
|
const pkg = "@agentbox/sandbox-vercel";
|
|
19540
19563
|
return loadCloudBackend(pkg, async () => (await import(pkg)).vercelBackend);
|
|
19541
19564
|
}
|
|
19565
|
+
if (name === "e2b") {
|
|
19566
|
+
const pkg = "@agentbox/sandbox-e2b";
|
|
19567
|
+
return loadCloudBackend(pkg, async () => (await import(pkg)).e2bBackend);
|
|
19568
|
+
}
|
|
19542
19569
|
throw new Error(`no host executor for cloud backend '${name}'`);
|
|
19543
19570
|
}
|
|
19544
19571
|
async function loadCloudBackend(pkg, load2) {
|
|
@@ -21092,6 +21119,8 @@ async function startRelayServer(opts) {
|
|
|
21092
21119
|
return handle;
|
|
21093
21120
|
}
|
|
21094
21121
|
var QUEUE_DIR = (0, import_path6.join)(STATE_DIR, "queue");
|
|
21122
|
+
var TERMINAL_RETENTION_MS = 60 * 60 * 1e3;
|
|
21123
|
+
var SWEEP_INTERVAL_MS = 60 * 1e3;
|
|
21095
21124
|
var QUEUE_LOGS_DIR = (0, import_path6.join)(STATE_DIR, "logs");
|
|
21096
21125
|
|
|
21097
21126
|
// src/config.ts
|