@kokorolx/ai-sandbox-wrapper 2.1.0 → 2.2.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/README.md +8 -0
- package/bin/ai-run +102 -0
- package/dockerfiles/amp/Dockerfile +17 -0
- package/dockerfiles/base/Dockerfile +47 -0
- package/dockerfiles/opencode/Dockerfile +10 -0
- package/lib/install-amp.sh +13 -6
- package/lib/install-base.sh +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,14 @@ AI coding tools like Claude, Gemini, and Aider have full access to your filesyst
|
|
|
10
10
|
|
|
11
11
|
*Last updated: Tuesday, February 3, 2026*
|
|
12
12
|
|
|
13
|
+
## ✨ New in v2.2.0: Clipboard Fixes & Screenshot Detection
|
|
14
|
+
|
|
15
|
+
The **v2.2.0 release** solves the "air-gap" problem for text copying and streamlines screenshot workflows.
|
|
16
|
+
|
|
17
|
+
- ✅ **OSC 52 Clipboard Support**: Copy text from inside Linux containers directly to your macOS clipboard (works over SSH too!).
|
|
18
|
+
- ✅ **Auto-Detect Screenshot Folder**: Automatically finds where your Mac saves screenshots and offers to whitelist it. No more permission errors when dragging images into AI tools.
|
|
19
|
+
- ✅ **Seamless Drag & Drop**: Just drag screenshots into the terminal window.
|
|
20
|
+
|
|
13
21
|
## ✨ New in v2.1.0: Stability & Native Persistence
|
|
14
22
|
|
|
15
23
|
The **v2.1.0 release** focuses on architectural stability and a more intuitive persistence model.
|
package/bin/ai-run
CHANGED
|
@@ -334,6 +334,52 @@ fi
|
|
|
334
334
|
# Set AI_IMAGE_SOURCE=registry in ~/.ai-env to use pre-built images
|
|
335
335
|
AI_IMAGE_SOURCE="${AI_IMAGE_SOURCE:-local}"
|
|
336
336
|
|
|
337
|
+
# ============================================================================
|
|
338
|
+
# SCREENSHOT DIRECTORY DETECTION (macOS Only)
|
|
339
|
+
# ============================================================================
|
|
340
|
+
if [[ "$(uname)" == "Darwin" ]] && [[ -t 0 ]]; then
|
|
341
|
+
# 1. Detect location (default to Desktop if key missing)
|
|
342
|
+
SCREENSHOT_DIR=$(defaults read com.apple.screencapture location 2>/dev/null || echo "$HOME/Desktop")
|
|
343
|
+
# Expand tilde if present
|
|
344
|
+
SCREENSHOT_DIR="${SCREENSHOT_DIR/#\~/$HOME}"
|
|
345
|
+
|
|
346
|
+
# 2. Check if valid directory
|
|
347
|
+
if [[ -d "$SCREENSHOT_DIR" ]]; then
|
|
348
|
+
|
|
349
|
+
# 3. Check if ALREADY whitelisted (exact match or parent)
|
|
350
|
+
IS_WHITELISTED=false
|
|
351
|
+
while IFS= read -r ws; do
|
|
352
|
+
# Check if screenshot dir IS a workspace, or IS INSIDE a workspace
|
|
353
|
+
if [[ "$SCREENSHOT_DIR" == "$ws" ]] || [[ "$SCREENSHOT_DIR" == "$ws"/* ]]; then
|
|
354
|
+
IS_WHITELISTED=true
|
|
355
|
+
break
|
|
356
|
+
fi
|
|
357
|
+
done < <(read_workspaces)
|
|
358
|
+
|
|
359
|
+
# 4. Prompt if not whitelisted
|
|
360
|
+
if [[ "$IS_WHITELISTED" == "false" ]]; then
|
|
361
|
+
echo ""
|
|
362
|
+
echo "📸 Screenshot Directory Detected"
|
|
363
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
364
|
+
echo "Location: $SCREENSHOT_DIR"
|
|
365
|
+
echo "Status: Not whitelisted"
|
|
366
|
+
echo ""
|
|
367
|
+
echo "Whitelisting this folder allows you to drag & drop screenshots into AI tools."
|
|
368
|
+
echo ""
|
|
369
|
+
# Use /dev/tty to ensure we read from user even if stdin is redirected
|
|
370
|
+
read -p "Whitelist screenshots folder? [y/N]: " CONFIRM_SS < /dev/tty
|
|
371
|
+
|
|
372
|
+
if [[ "$CONFIRM_SS" =~ ^[Yy]$ ]]; then
|
|
373
|
+
add_workspace "$SCREENSHOT_DIR"
|
|
374
|
+
echo "✅ Added to whitelist."
|
|
375
|
+
else
|
|
376
|
+
echo "❌ Skipped."
|
|
377
|
+
fi
|
|
378
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
379
|
+
fi
|
|
380
|
+
fi
|
|
381
|
+
fi
|
|
382
|
+
|
|
337
383
|
if [[ "$AI_IMAGE_SOURCE" == "registry" ]]; then
|
|
338
384
|
IMAGE="registry.gitlab.com/kokorolee/ai-sandbox-wrapper/ai-${TOOL}:latest"
|
|
339
385
|
else
|
|
@@ -1067,6 +1113,58 @@ else
|
|
|
1067
1113
|
fi
|
|
1068
1114
|
fi
|
|
1069
1115
|
|
|
1116
|
+
# ============================================================================
|
|
1117
|
+
# DISPLAY & CLIPBOARD CONFIGURATION
|
|
1118
|
+
# ============================================================================
|
|
1119
|
+
detect_display_config() {
|
|
1120
|
+
local detected_flags=""
|
|
1121
|
+
local has_display=false
|
|
1122
|
+
|
|
1123
|
+
# 1. X11 Detection
|
|
1124
|
+
if [[ -n "$DISPLAY" ]]; then
|
|
1125
|
+
has_display=true
|
|
1126
|
+
detected_flags="$detected_flags -e DISPLAY=$DISPLAY"
|
|
1127
|
+
|
|
1128
|
+
# Mount X11 socket (common on Linux/macOS with XQuartz)
|
|
1129
|
+
if [[ -d "/tmp/.X11-unix" ]]; then
|
|
1130
|
+
detected_flags="$detected_flags -v /tmp/.X11-unix:/tmp/.X11-unix:rw"
|
|
1131
|
+
fi
|
|
1132
|
+
|
|
1133
|
+
# Handle XAuthority for authentication
|
|
1134
|
+
if [[ -f "$HOME/.Xauthority" ]]; then
|
|
1135
|
+
# Mount read-only for security
|
|
1136
|
+
# Mount to /tmp/.Xauthority to avoid conflict with /home/agent bind mount
|
|
1137
|
+
detected_flags="$detected_flags -e XAUTHORITY=/tmp/.Xauthority -v $HOME/.Xauthority:/tmp/.Xauthority:ro"
|
|
1138
|
+
fi
|
|
1139
|
+
|
|
1140
|
+
# Since we have X11, prefer it over Wayland to avoid clipboard issues in mixed environments
|
|
1141
|
+
# (Many Go apps like atotto/clipboard work better with xclip/X11 than wl-copy/Wayland in Docker)
|
|
1142
|
+
echo "$detected_flags"
|
|
1143
|
+
return
|
|
1144
|
+
fi
|
|
1145
|
+
|
|
1146
|
+
# 2. Wayland Detection
|
|
1147
|
+
if [[ -n "$WAYLAND_DISPLAY" ]]; then
|
|
1148
|
+
has_display=true
|
|
1149
|
+
detected_flags="$detected_flags -e WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
|
|
1150
|
+
|
|
1151
|
+
# Handle XDG_RUNTIME_DIR (needed for Wayland sockets)
|
|
1152
|
+
if [[ -n "$XDG_RUNTIME_DIR" ]]; then
|
|
1153
|
+
# Map host runtime dir to container's /run/user/1001 (agent UID)
|
|
1154
|
+
# ensuring the container can access the socket
|
|
1155
|
+
local container_runtime_dir="/run/user/1001"
|
|
1156
|
+
detected_flags="$detected_flags -e XDG_RUNTIME_DIR=$container_runtime_dir -v $XDG_RUNTIME_DIR:$container_runtime_dir:rw"
|
|
1157
|
+
fi
|
|
1158
|
+
fi
|
|
1159
|
+
|
|
1160
|
+
# Debug log if no display detected (only if debug enabled)
|
|
1161
|
+
if [[ "$has_display" == "false" && "${AI_RUN_DEBUG:-}" == "1" ]]; then
|
|
1162
|
+
echo "🔧 Debug: No display server detected (DISPLAY/WAYLAND_DISPLAY unset). Clipboard integration disabled." >&2
|
|
1163
|
+
fi
|
|
1164
|
+
|
|
1165
|
+
echo "$detected_flags"
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1070
1168
|
# Generate container name based on tool and folder
|
|
1071
1169
|
# Format: {tool}-{sanitized_folder_name}-{random_suffix}
|
|
1072
1170
|
generate_container_name() {
|
|
@@ -1208,6 +1306,9 @@ if [[ "$TOOL" == "opencode" ]]; then
|
|
|
1208
1306
|
CACHE_MOUNTS="-v /home/agent/.npm -v /home/agent/.cache -v /home/agent/.opencode/node_modules"
|
|
1209
1307
|
fi
|
|
1210
1308
|
|
|
1309
|
+
# Detect display configuration (clipboard integration)
|
|
1310
|
+
DISPLAY_FLAGS=$(detect_display_config)
|
|
1311
|
+
|
|
1211
1312
|
docker run $CONTAINER_NAME --rm $TTY_FLAGS \
|
|
1212
1313
|
--init \
|
|
1213
1314
|
--platform "$PLATFORM" \
|
|
@@ -1218,6 +1319,7 @@ docker run $CONTAINER_NAME --rm $TTY_FLAGS \
|
|
|
1218
1319
|
$GIT_MOUNTS \
|
|
1219
1320
|
$NETWORK_OPTIONS \
|
|
1220
1321
|
$CACHE_MOUNTS \
|
|
1322
|
+
$DISPLAY_FLAGS \
|
|
1221
1323
|
$HOST_ACCESS_ARGS \
|
|
1222
1324
|
$PORT_MAPPINGS \
|
|
1223
1325
|
-v "$HOME_DIR":/home/agent \
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
FROM ai-base:latest
|
|
2
|
+
|
|
3
|
+
# Switch to root only for installing bun globally (needed for the system)
|
|
4
|
+
USER root
|
|
5
|
+
RUN npm install -g bun
|
|
6
|
+
USER agent
|
|
7
|
+
|
|
8
|
+
# Install Amp into user directory
|
|
9
|
+
RUN mkdir -p /home/agent/lib/amp && \
|
|
10
|
+
cd /home/agent/lib/amp && \
|
|
11
|
+
bun init -y && \
|
|
12
|
+
bun add @sourcegraph/amp
|
|
13
|
+
|
|
14
|
+
# Add the node_modules .bin to PATH
|
|
15
|
+
ENV PATH="/home/agent/lib/amp/node_modules/.bin:${PATH}"
|
|
16
|
+
|
|
17
|
+
ENTRYPOINT ["amp"]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
FROM node:22-bookworm-slim
|
|
2
|
+
|
|
3
|
+
ARG AGENT_UID=1001
|
|
4
|
+
|
|
5
|
+
# Install common dependencies
|
|
6
|
+
# Note: python3-venv is needed for many tools, unzip for some installers
|
|
7
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git curl ssh ca-certificates jq python3 python3-pip python3-venv python3-dev python3-setuptools build-essential libopenblas-dev pipx unzip xclip wl-clipboard && curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh && rm -rf /var/lib/apt/lists/* && pipx ensurepath
|
|
8
|
+
|
|
9
|
+
# Install pnpm globally using npm (not bun, for stability)
|
|
10
|
+
RUN npm install -g pnpm
|
|
11
|
+
|
|
12
|
+
# Install TypeScript and LSP tools using npm
|
|
13
|
+
RUN npm install -g typescript typescript-language-server
|
|
14
|
+
|
|
15
|
+
# Verify installations
|
|
16
|
+
RUN node --version && npm --version && pnpm --version && tsc --version
|
|
17
|
+
|
|
18
|
+
# Install additional tools (if selected)
|
|
19
|
+
RUN PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin pipx install specify-cli --pip-args="git+https://github.com/github/spec-kit.git" && \
|
|
20
|
+
chmod +x /usr/local/bin/specify && \
|
|
21
|
+
ln -sf /usr/local/bin/specify /usr/local/bin/specify-cli
|
|
22
|
+
RUN mkdir -p /usr/local/lib/uipro-cli && \
|
|
23
|
+
cd /usr/local/lib/uipro-cli && \
|
|
24
|
+
npm init -y && \
|
|
25
|
+
npm install uipro-cli && \
|
|
26
|
+
ln -sf /usr/local/lib/uipro-cli/node_modules/.bin/uipro /usr/local/bin/uipro && \
|
|
27
|
+
ln -sf /usr/local/bin/uipro /usr/local/bin/uipro-cli && \
|
|
28
|
+
chmod -R 755 /usr/local/lib/uipro-cli && \
|
|
29
|
+
chmod +x /usr/local/bin/uipro
|
|
30
|
+
RUN mkdir -p /usr/local/lib/openspec && \
|
|
31
|
+
cd /usr/local/lib/openspec && \
|
|
32
|
+
npm init -y && \
|
|
33
|
+
npm install @fission-ai/openspec && \
|
|
34
|
+
ln -sf /usr/local/lib/openspec/node_modules/.bin/openspec /usr/local/bin/openspec && \
|
|
35
|
+
chmod -R 755 /usr/local/lib/openspec && \
|
|
36
|
+
chmod +x /usr/local/bin/openspec
|
|
37
|
+
|
|
38
|
+
# Create workspace
|
|
39
|
+
WORKDIR /workspace
|
|
40
|
+
|
|
41
|
+
# Non-root user for security
|
|
42
|
+
# Non-root user for security (match host UID)
|
|
43
|
+
RUN useradd -m -u ${AGENT_UID} -d /home/agent agent && \
|
|
44
|
+
mkdir -p /home/agent/.cache /home/agent/.npm /home/agent/.opencode /home/agent/.config && \
|
|
45
|
+
chown -R agent:agent /home/agent/.cache /home/agent/.npm /home/agent/.opencode /home/agent/.config /workspace
|
|
46
|
+
USER agent
|
|
47
|
+
ENV HOME=/home/agent
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
FROM ai-base:latest
|
|
2
|
+
|
|
3
|
+
USER root
|
|
4
|
+
# Install OpenCode using official native installer
|
|
5
|
+
RUN curl -fsSL https://opencode.ai/install | bash && \
|
|
6
|
+
mv /home/agent/.opencode/bin/opencode /usr/local/bin/opencode && \
|
|
7
|
+
rm -rf /home/agent/.opencode
|
|
8
|
+
|
|
9
|
+
USER agent
|
|
10
|
+
ENTRYPOINT ["opencode"]
|
package/lib/install-amp.sh
CHANGED
|
@@ -14,14 +14,21 @@ mkdir -p "$HOME/.ai-sandbox/tools/$TOOL/home"
|
|
|
14
14
|
# Create Dockerfile (extends base image for faster builds)
|
|
15
15
|
cat <<'EOF' > "dockerfiles/$TOOL/Dockerfile"
|
|
16
16
|
FROM ai-base:latest
|
|
17
|
+
|
|
18
|
+
# Switch to root only for installing bun globally (needed for the system)
|
|
17
19
|
USER root
|
|
18
|
-
|
|
19
|
-
RUN mkdir -p /usr/local/lib/amp && \
|
|
20
|
-
cd /usr/local/lib/amp && \
|
|
21
|
-
bun init -y && \
|
|
22
|
-
bun add @sourcegraph/amp && \
|
|
23
|
-
ln -s /usr/local/lib/amp/node_modules/.bin/amp /usr/local/bin/amp
|
|
20
|
+
RUN npm install -g bun
|
|
24
21
|
USER agent
|
|
22
|
+
|
|
23
|
+
# Install Amp into user directory
|
|
24
|
+
RUN mkdir -p /home/agent/lib/amp && \
|
|
25
|
+
cd /home/agent/lib/amp && \
|
|
26
|
+
bun init -y && \
|
|
27
|
+
bun add @sourcegraph/amp
|
|
28
|
+
|
|
29
|
+
# Add the node_modules .bin to PATH
|
|
30
|
+
ENV PATH="/home/agent/lib/amp/node_modules/.bin:${PATH}"
|
|
31
|
+
|
|
25
32
|
ENTRYPOINT ["amp"]
|
|
26
33
|
EOF
|
|
27
34
|
|
package/lib/install-base.sh
CHANGED
|
@@ -126,6 +126,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
126
126
|
libopenblas-dev \
|
|
127
127
|
pipx \
|
|
128
128
|
unzip \
|
|
129
|
+
xclip \
|
|
130
|
+
wl-clipboard \
|
|
129
131
|
&& curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh \
|
|
130
132
|
&& rm -rf /var/lib/apt/lists/* \
|
|
131
133
|
&& pipx ensurepath
|
package/package.json
CHANGED