@kokorolx/ai-sandbox-wrapper 2.7.0 → 3.0.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.
- package/README.md +25 -0
- package/bin/ai-run +623 -308
- package/bin/cli.js +51 -7
- package/dockerfiles/base/Dockerfile +15 -3
- package/dockerfiles/base/skills/rtk/SKILL.md +103 -0
- package/dockerfiles/base/skills/rtk-setup/SKILL.md +118 -0
- package/dockerfiles/sandbox/Dockerfile +133 -0
- package/dockerfiles/sandbox/skills/rtk/SKILL.md +103 -0
- package/dockerfiles/sandbox/skills/rtk-setup/SKILL.md +118 -0
- package/lib/AGENTS.md +14 -0
- package/lib/build-sandbox.sh +89 -0
- package/lib/install-aider.sh +11 -1
- package/lib/install-amp.sh +20 -12
- package/lib/install-auggie.sh +16 -1
- package/lib/install-base.sh +36 -2
- package/lib/install-claude.sh +25 -4
- package/lib/install-codebuddy.sh +16 -1
- package/lib/install-codex.sh +16 -1
- package/lib/install-droid.sh +17 -4
- package/lib/install-gemini.sh +16 -1
- package/lib/install-jules.sh +16 -1
- package/lib/install-kilo.sh +12 -2
- package/lib/install-openclaw.sh +10 -1
- package/lib/install-opencode.sh +17 -4
- package/lib/install-qoder.sh +16 -1
- package/lib/install-qwen.sh +16 -1
- package/lib/install-shai.sh +15 -3
- package/package.json +1 -1
- package/setup.sh +55 -52
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rtk-setup
|
|
3
|
+
description: "One-time setup + ongoing enforcement of RTK (Rust Token Killer) across sessions and subagents. Persists RTK instructions to AGENTS.md and propagates to delegated tasks."
|
|
4
|
+
compatibility: "OpenCode with RTK binary installed"
|
|
5
|
+
metadata:
|
|
6
|
+
author: Sisyphus
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# RTK Setup — Persistent RTK Enforcement
|
|
11
|
+
|
|
12
|
+
This skill performs **setup** (persist RTK instructions) and **ongoing enforcement** (use rtk, propagate to subagents).
|
|
13
|
+
|
|
14
|
+
## Phase 1: Detection (ALWAYS run first)
|
|
15
|
+
|
|
16
|
+
Run these checks before anything else:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
rtk --version
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- If `rtk` is NOT found → **STOP**. Tell the user: "RTK is not installed. Install it first: `cargo install --git https://github.com/rtk-ai/rtk --locked`". Do NOT proceed with setup.
|
|
23
|
+
- If `rtk` IS found → continue.
|
|
24
|
+
|
|
25
|
+
### Check oh-my-opencode
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
ls ~/.config/opencode/oh-my-opencode.json 2>/dev/null
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- If found → omo is installed. Note this for Phase 2.
|
|
32
|
+
- If not found → skip omo-specific steps.
|
|
33
|
+
|
|
34
|
+
## Phase 2: Setup (persist to AGENTS.md)
|
|
35
|
+
|
|
36
|
+
Check BOTH of these files for the RTK managed block:
|
|
37
|
+
|
|
38
|
+
1. **User-level**: `~/.config/opencode/AGENTS.md`
|
|
39
|
+
2. **Project-level**: `./AGENTS.md` (current workspace)
|
|
40
|
+
|
|
41
|
+
For EACH file, check if `<!-- RTK:START -->` exists. If it does NOT exist, **append** the following managed block to the file (create the file if it doesn't exist). NEVER replace existing content — only append.
|
|
42
|
+
|
|
43
|
+
```markdown
|
|
44
|
+
<!-- RTK:START -->
|
|
45
|
+
<!-- Managed block - do not edit manually. Updated by: rtk-setup skill -->
|
|
46
|
+
|
|
47
|
+
## RTK Token Optimizer
|
|
48
|
+
|
|
49
|
+
This project uses **RTK** (Rust Token Killer) to reduce LLM token consumption by 60-90%.
|
|
50
|
+
|
|
51
|
+
### Rules for ALL agents (including subagents)
|
|
52
|
+
|
|
53
|
+
**ALWAYS** prefix these commands with `rtk`:
|
|
54
|
+
|
|
55
|
+
| Command | Use instead |
|
|
56
|
+
|---------|-------------|
|
|
57
|
+
| `git status/diff/log/add/commit/push/pull` | `rtk git ...` |
|
|
58
|
+
| `ls`, `ls -la` | `rtk ls` |
|
|
59
|
+
| `cat file` | `rtk read file` |
|
|
60
|
+
| `grep pattern .` / `rg pattern` | `rtk grep pattern .` |
|
|
61
|
+
| `npm test` / `cargo test` / `pytest` | `rtk test <cmd>` |
|
|
62
|
+
| `npm run build` / `cargo build` | `rtk err <cmd>` |
|
|
63
|
+
| `gh pr list/view` | `rtk gh pr list/view` |
|
|
64
|
+
| `docker ps` | `rtk docker ps` |
|
|
65
|
+
| `eslint` / `tsc` | `rtk lint` / `rtk tsc` |
|
|
66
|
+
|
|
67
|
+
**Do NOT** prefix: `npx`, `npm install`, `pip install`, `node`, `python3`, heredocs, piped commands.
|
|
68
|
+
|
|
69
|
+
<!-- RTK:END -->
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### If oh-my-opencode is installed
|
|
73
|
+
|
|
74
|
+
After updating AGENTS.md files, check if the omo config at `~/.config/opencode/oh-my-opencode.json` has `prompt_append` fields on agents. If it does, inform the user:
|
|
75
|
+
|
|
76
|
+
> "omo is installed. For maximum coverage, you can add RTK instructions to agent `prompt_append` fields in `oh-my-opencode.json`. This ensures subagents always use rtk even when AGENTS.md is not loaded. Want me to do this?"
|
|
77
|
+
|
|
78
|
+
**Only modify `oh-my-opencode.json` if the user explicitly confirms.** If they confirm, append this line to the `prompt_append` of `sisyphus-junior` agent (the primary coder):
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
\n\nRTK: ALWAYS prefix shell commands with `rtk` when available (git, ls, grep, test, build). Example: `rtk git status` not `git status`.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Do NOT modify other agents' prompt_append unless asked.
|
|
85
|
+
|
|
86
|
+
## Phase 3: Ongoing Enforcement (EVERY time this skill is loaded)
|
|
87
|
+
|
|
88
|
+
### For the current agent
|
|
89
|
+
|
|
90
|
+
From this point forward in this session, **you MUST**:
|
|
91
|
+
|
|
92
|
+
1. **Use `rtk` prefix** for all supported shell commands (see table above)
|
|
93
|
+
2. **Verify rtk is available** before first use: `rtk --version`
|
|
94
|
+
3. If rtk is not available in the current environment, fall back to normal commands silently
|
|
95
|
+
|
|
96
|
+
### For subagent delegation
|
|
97
|
+
|
|
98
|
+
When delegating ANY task that involves shell commands (via `task()`, `delegate_task()`, or any delegation mechanism), **ALWAYS** add this to the `MUST DO` section of the delegation prompt:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
- Use `rtk` prefix for shell commands when available (git, ls, grep, test, build). Run `rtk --version` first to check. If not installed, use normal commands. Examples: `rtk git status`, `rtk ls`, `rtk grep pattern .`, `rtk test npm test`.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This is NON-NEGOTIABLE. Subagents do not read AGENTS.md, so RTK instructions MUST be passed explicitly in every delegation prompt.
|
|
105
|
+
|
|
106
|
+
### Quick reference for subagent prompts
|
|
107
|
+
|
|
108
|
+
Copy-paste this one-liner into MUST DO sections:
|
|
109
|
+
|
|
110
|
+
> Use `rtk` prefix for all shell commands (git, ls, grep, test, build, docker). Example: `rtk git status` not `git status`. If `rtk` is not found, use normal commands.
|
|
111
|
+
|
|
112
|
+
## Summary
|
|
113
|
+
|
|
114
|
+
| Phase | When | What |
|
|
115
|
+
|-------|------|------|
|
|
116
|
+
| Detection | Always first | Check rtk installed, check omo |
|
|
117
|
+
| Setup | Once (idempotent) | Append RTK block to AGENTS.md (user + project) |
|
|
118
|
+
| Enforcement | Every session | Use rtk yourself, propagate to all subagents |
|
package/lib/AGENTS.md
CHANGED
|
@@ -49,6 +49,20 @@ lib/
|
|
|
49
49
|
| CodeServer | `install-codeserver.sh` | VSCode browser |
|
|
50
50
|
| VSCode | `install-vscode.sh` | Desktop X11 |
|
|
51
51
|
|
|
52
|
+
## File Writing Rules (MANDATORY)
|
|
53
|
+
|
|
54
|
+
**NEVER write an entire file at once.** Always use chunk-by-chunk editing:
|
|
55
|
+
|
|
56
|
+
1. **Use the Edit tool** (find-and-replace) for all file modifications — insert, update, or delete content in targeted chunks
|
|
57
|
+
2. **Only use the Write tool** for brand-new files that don't exist yet, AND only if the file is small (< 50 lines)
|
|
58
|
+
3. **For new large files (50+ lines):** Write a skeleton first (headers/structure only), then use Edit to fill in each section chunk by chunk
|
|
59
|
+
4. **Why:** Writing entire files at once causes truncation, context window overflow, and silent data loss on large files
|
|
60
|
+
|
|
61
|
+
**Anti-patterns (NEVER do these):**
|
|
62
|
+
- `Write` tool to overwrite an existing file with full content
|
|
63
|
+
- `Write` tool to create a file with 100+ lines in one shot
|
|
64
|
+
- Regenerating an entire file to change a few lines
|
|
65
|
+
|
|
52
66
|
## Conventions
|
|
53
67
|
|
|
54
68
|
- Scripts use `set -e` for fail-fast
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
TOOLS="${TOOLS:-}"
|
|
5
|
+
if [[ -z "$TOOLS" ]]; then
|
|
6
|
+
echo "❌ No tools selected. Set TOOLS=tool1,tool2,..."
|
|
7
|
+
exit 1
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
|
+
cd "$PROJECT_DIR"
|
|
13
|
+
|
|
14
|
+
SANDBOX_DIR="dockerfiles/sandbox"
|
|
15
|
+
mkdir -p "$SANDBOX_DIR"
|
|
16
|
+
|
|
17
|
+
echo "🔄 Generating unified sandbox Dockerfile..."
|
|
18
|
+
echo " Tools: $TOOLS"
|
|
19
|
+
|
|
20
|
+
GENERATE_ONLY=1 INSTALL_RTK="${INSTALL_RTK:-0}" \
|
|
21
|
+
INSTALL_PLAYWRIGHT_MCP="${INSTALL_PLAYWRIGHT_MCP:-0}" \
|
|
22
|
+
INSTALL_CHROME_DEVTOOLS_MCP="${INSTALL_CHROME_DEVTOOLS_MCP:-0}" \
|
|
23
|
+
INSTALL_PLAYWRIGHT="${INSTALL_PLAYWRIGHT:-0}" \
|
|
24
|
+
INSTALL_RUBY="${INSTALL_RUBY:-0}" \
|
|
25
|
+
INSTALL_SPEC_KIT="${INSTALL_SPEC_KIT:-0}" \
|
|
26
|
+
INSTALL_UX_UI_PROMAX="${INSTALL_UX_UI_PROMAX:-0}" \
|
|
27
|
+
INSTALL_OPENSPEC="${INSTALL_OPENSPEC:-0}" \
|
|
28
|
+
bash "$SCRIPT_DIR/install-base.sh"
|
|
29
|
+
|
|
30
|
+
BASE_DOCKERFILE="dockerfiles/base/Dockerfile"
|
|
31
|
+
if [[ ! -f "$BASE_DOCKERFILE" ]]; then
|
|
32
|
+
echo "❌ Base Dockerfile not found at $BASE_DOCKERFILE"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
BASE_CONTENT=$(cat "$BASE_DOCKERFILE")
|
|
37
|
+
BASE_PREAMBLE=$(echo "$BASE_CONTENT" | sed '/^USER agent$/,$d')
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
echo "$BASE_PREAMBLE"
|
|
41
|
+
echo ""
|
|
42
|
+
|
|
43
|
+
IFS=',' read -ra TOOL_ARRAY <<< "$TOOLS"
|
|
44
|
+
for tool in "${TOOL_ARRAY[@]}"; do
|
|
45
|
+
tool=$(echo "$tool" | tr -d ' ')
|
|
46
|
+
INSTALL_SCRIPT="$SCRIPT_DIR/install-${tool}.sh"
|
|
47
|
+
|
|
48
|
+
if [[ ! -f "$INSTALL_SCRIPT" ]]; then
|
|
49
|
+
echo "⚠️ Warning: No install script for '$tool', skipping" >&2
|
|
50
|
+
continue
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "# === $tool ==="
|
|
54
|
+
SNIPPET_MODE=1 source "$INSTALL_SCRIPT"
|
|
55
|
+
dockerfile_snippet
|
|
56
|
+
echo ""
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
echo "USER agent"
|
|
60
|
+
echo "ENV HOME=/home/agent"
|
|
61
|
+
echo "CMD [\"bash\"]"
|
|
62
|
+
} > "$SANDBOX_DIR/Dockerfile"
|
|
63
|
+
|
|
64
|
+
if [[ -d "dockerfiles/base/skills" ]]; then
|
|
65
|
+
cp -r "dockerfiles/base/skills" "$SANDBOX_DIR/"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
echo "✅ Dockerfile generated at $SANDBOX_DIR/Dockerfile"
|
|
69
|
+
|
|
70
|
+
echo "🔨 Building ai-sandbox:latest..."
|
|
71
|
+
HOST_UID=$(id -u)
|
|
72
|
+
docker build ${DOCKER_NO_CACHE:+--no-cache} \
|
|
73
|
+
--build-arg AGENT_UID="${HOST_UID}" \
|
|
74
|
+
-t "ai-sandbox:latest" "$SANDBOX_DIR"
|
|
75
|
+
|
|
76
|
+
echo "✅ ai-sandbox:latest built successfully"
|
|
77
|
+
|
|
78
|
+
SANDBOX_CONFIG="$HOME/.ai-sandbox/config.json"
|
|
79
|
+
if command -v jq &>/dev/null && [[ -f "$SANDBOX_CONFIG" ]]; then
|
|
80
|
+
TOOLS_JSON=$(echo "$TOOLS" | tr ',' '\n' | jq -R . | jq -s .)
|
|
81
|
+
jq --argjson tools "$TOOLS_JSON" '.tools.installed = $tools' "$SANDBOX_CONFIG" > "$SANDBOX_CONFIG.tmp" \
|
|
82
|
+
&& mv "$SANDBOX_CONFIG.tmp" "$SANDBOX_CONFIG"
|
|
83
|
+
chmod 600 "$SANDBOX_CONFIG"
|
|
84
|
+
echo "✅ Saved tools list to $SANDBOX_CONFIG"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo ""
|
|
88
|
+
echo "🎉 Sandbox ready with tools: $TOOLS"
|
|
89
|
+
echo " Run: docker run --rm -it ai-sandbox:latest"
|
package/lib/install-aider.sh
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER agent
|
|
7
|
+
RUN python3 -m pip install --break-system-packages aider-install && aider-install
|
|
8
|
+
SNIPPET
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
12
|
+
return 0 2>/dev/null || exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
5
15
|
TOOL="aider"
|
|
6
16
|
|
|
7
17
|
echo "Installing $TOOL (Python-based AI pair programmer)..."
|
package/lib/install-amp.sh
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /usr/local/lib/amp && \
|
|
8
|
+
cd /usr/local/lib/amp && \
|
|
9
|
+
bun init -y && \
|
|
10
|
+
bun add @sourcegraph/amp && \
|
|
11
|
+
ln -s /usr/local/lib/amp/node_modules/.bin/amp /usr/local/bin/amp
|
|
12
|
+
SNIPPET
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
16
|
+
return 0 2>/dev/null || exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
5
19
|
TOOL="amp"
|
|
6
20
|
|
|
7
21
|
echo "Installing $TOOL (Sourcegraph Amp)..."
|
|
@@ -15,20 +29,14 @@ mkdir -p "$HOME/.ai-sandbox/tools/$TOOL/home"
|
|
|
15
29
|
cat <<'EOF' > "dockerfiles/$TOOL/Dockerfile"
|
|
16
30
|
FROM ai-base:latest
|
|
17
31
|
|
|
18
|
-
# Switch to root only for installing bun globally (needed for the system)
|
|
19
32
|
USER root
|
|
20
|
-
RUN
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Install Amp into user directory
|
|
24
|
-
RUN mkdir -p /home/agent/lib/amp && \
|
|
25
|
-
cd /home/agent/lib/amp && \
|
|
33
|
+
RUN mkdir -p /usr/local/lib/amp && \
|
|
34
|
+
cd /usr/local/lib/amp && \
|
|
26
35
|
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}"
|
|
36
|
+
bun add @sourcegraph/amp && \
|
|
37
|
+
ln -s /usr/local/lib/amp/node_modules/.bin/amp /usr/local/bin/amp
|
|
31
38
|
|
|
39
|
+
USER agent
|
|
32
40
|
ENTRYPOINT ["amp"]
|
|
33
41
|
EOF
|
|
34
42
|
|
package/lib/install-auggie.sh
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /usr/local/lib/auggie && \
|
|
8
|
+
cd /usr/local/lib/auggie && \
|
|
9
|
+
bun init -y && \
|
|
10
|
+
bun add @augmentcode/auggie && \
|
|
11
|
+
ln -s /usr/local/lib/auggie/node_modules/.bin/auggie /usr/local/bin/auggie
|
|
12
|
+
USER agent
|
|
13
|
+
SNIPPET
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
17
|
+
return 0 2>/dev/null || exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
5
20
|
TOOL="auggie"
|
|
6
21
|
|
|
7
22
|
echo "Installing $TOOL (Augment Auggie CLI)..."
|
package/lib/install-base.sh
CHANGED
|
@@ -49,6 +49,22 @@ RUN cargo install --git https://github.com/rtk-ai/rtk --locked
|
|
|
49
49
|
ADDITIONAL_TOOLS_INSTALL+='# Install RTK - token optimizer for AI coding agents (built from source)
|
|
50
50
|
COPY --from=rtk-builder /usr/local/cargo/bin/rtk /usr/local/bin/rtk
|
|
51
51
|
'
|
|
52
|
+
# Copy RTK OpenCode skills into build context so they can be COPY'd into the image
|
|
53
|
+
SCRIPT_BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
54
|
+
RTK_SKILLS_SRC="${SCRIPT_BASE_DIR}/../skills"
|
|
55
|
+
if [[ -d "$RTK_SKILLS_SRC/rtk" && -d "$RTK_SKILLS_SRC/rtk-setup" ]]; then
|
|
56
|
+
mkdir -p "dockerfiles/base/skills/rtk" "dockerfiles/base/skills/rtk-setup"
|
|
57
|
+
cp "$RTK_SKILLS_SRC/rtk/SKILL.md" "dockerfiles/base/skills/rtk/SKILL.md"
|
|
58
|
+
cp "$RTK_SKILLS_SRC/rtk-setup/SKILL.md" "dockerfiles/base/skills/rtk-setup/SKILL.md"
|
|
59
|
+
ADDITIONAL_TOOLS_INSTALL+='# Install RTK OpenCode skills (auto-discovered by OpenCode agents)
|
|
60
|
+
RUN mkdir -p /home/agent/.config/opencode/skills/rtk /home/agent/.config/opencode/skills/rtk-setup
|
|
61
|
+
COPY skills/rtk/SKILL.md /home/agent/.config/opencode/skills/rtk/SKILL.md
|
|
62
|
+
COPY skills/rtk-setup/SKILL.md /home/agent/.config/opencode/skills/rtk-setup/SKILL.md
|
|
63
|
+
'
|
|
64
|
+
echo " ✅ RTK OpenCode skills will be copied into container"
|
|
65
|
+
else
|
|
66
|
+
echo " ⚠️ RTK skills not found at $RTK_SKILLS_SRC — skipping skill installation"
|
|
67
|
+
fi
|
|
52
68
|
fi
|
|
53
69
|
|
|
54
70
|
if [[ "${INSTALL_PLAYWRIGHT:-0}" -eq 1 ]]; then
|
|
@@ -112,7 +128,7 @@ ENV PATH=$RBENV_ROOT/bin:$RBENV_ROOT/shims:$PATH
|
|
|
112
128
|
|
|
113
129
|
RUN rbenv install 3.3.0 && rbenv global 3.3.0 && rbenv rehash
|
|
114
130
|
|
|
115
|
-
RUN gem install rails -v 8.0.2 && gem install bundler && rbenv rehash
|
|
131
|
+
RUN gem install rails -v 8.0.2 && gem install bundler solargraph && rbenv rehash
|
|
116
132
|
'
|
|
117
133
|
fi
|
|
118
134
|
|
|
@@ -201,10 +217,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
201
217
|
xclip \
|
|
202
218
|
wl-clipboard \
|
|
203
219
|
ripgrep \
|
|
220
|
+
tmux \
|
|
221
|
+
fd-find \
|
|
222
|
+
sqlite3 \
|
|
223
|
+
poppler-utils \
|
|
224
|
+
qpdf \
|
|
225
|
+
tesseract-ocr \
|
|
204
226
|
&& curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh \
|
|
205
227
|
&& rm -rf /var/lib/apt/lists/* \
|
|
206
228
|
&& pipx ensurepath
|
|
207
229
|
|
|
230
|
+
# Install Python PDF processing tools for PDF skill
|
|
231
|
+
RUN pip3 install --no-cache-dir --break-system-packages pypdf pdfplumber reportlab pytesseract pdf2image
|
|
232
|
+
|
|
208
233
|
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
209
234
|
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
210
235
|
&& echo "deb [arch=\$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
|
@@ -212,11 +237,14 @@ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | d
|
|
|
212
237
|
&& apt-get install -y gh \
|
|
213
238
|
&& rm -rf /var/lib/apt/lists/*
|
|
214
239
|
|
|
240
|
+
# Install bun (used by most AI tool install scripts)
|
|
241
|
+
RUN npm install -g bun
|
|
242
|
+
|
|
215
243
|
# Install pnpm globally using npm (not bun, for stability)
|
|
216
244
|
RUN npm install -g pnpm
|
|
217
245
|
|
|
218
246
|
# Install TypeScript and LSP tools using npm
|
|
219
|
-
RUN npm install -g typescript typescript-language-server
|
|
247
|
+
RUN npm install -g typescript typescript-language-server pyright vscode-langservers-extracted
|
|
220
248
|
|
|
221
249
|
# Verify installations
|
|
222
250
|
RUN node --version && npm --version && pnpm --version && tsc --version
|
|
@@ -235,6 +263,12 @@ USER agent
|
|
|
235
263
|
ENV HOME=/home/agent
|
|
236
264
|
EOF
|
|
237
265
|
|
|
266
|
+
# GENERATE_ONLY mode: write Dockerfile but don't build
|
|
267
|
+
if [[ "${GENERATE_ONLY:-0}" -eq 1 ]]; then
|
|
268
|
+
echo "✅ Base Dockerfile generated at dockerfiles/base/Dockerfile"
|
|
269
|
+
exit 0
|
|
270
|
+
fi
|
|
271
|
+
|
|
238
272
|
echo "Building base Docker image..."
|
|
239
273
|
HOST_UID=$(id -u)
|
|
240
274
|
docker build ${DOCKER_NO_CACHE:+--no-cache} \
|
package/lib/install-claude.sh
CHANGED
|
@@ -1,7 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN apt-get update && apt-get install -y --no-install-recommends tmux && rm -rf /var/lib/apt/lists/*
|
|
8
|
+
RUN npm install -g @kaitranntt/ccs --ignore-scripts && \
|
|
9
|
+
mkdir -p /home/agent/.ccs && \
|
|
10
|
+
chown -R agent:agent /home/agent/.ccs && \
|
|
11
|
+
which ccs && ccs --version && \
|
|
12
|
+
sed -i 's/fs\.symlinkSync(sourcePath, targetPath, symlinkType)/fs\.symlinkSync(require("path").relative(require("path").dirname(targetPath), sourcePath), targetPath, symlinkType)/g' /usr/local/lib/node_modules/@kaitranntt/ccs/dist/utils/claude-symlink-manager.js
|
|
13
|
+
RUN export HOME=/root && curl -fsSL https://claude.ai/install.sh | bash && \
|
|
14
|
+
mkdir -p /usr/local/share && \
|
|
15
|
+
mv /root/.local/share/claude /usr/local/share/claude && \
|
|
16
|
+
ln -sf /usr/local/share/claude/versions/$(ls /usr/local/share/claude/versions | head -1) /usr/local/bin/claude
|
|
17
|
+
USER agent
|
|
18
|
+
SNIPPET
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
22
|
+
return 0 2>/dev/null || exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
5
25
|
TOOL="claude"
|
|
6
26
|
|
|
7
27
|
echo "Installing $TOOL (Anthropic Claude Code - Native Binary)..."
|
|
@@ -24,12 +44,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends tmux && rm -rf
|
|
|
24
44
|
RUN npm install -g @kaitranntt/ccs --ignore-scripts && \
|
|
25
45
|
mkdir -p /home/agent/.ccs && \
|
|
26
46
|
chown -R agent:agent /home/agent/.ccs && \
|
|
27
|
-
which ccs && ccs --version
|
|
47
|
+
which ccs && ccs --version && \
|
|
48
|
+
sed -i 's/fs\.symlinkSync(sourcePath, targetPath, symlinkType)/fs\.symlinkSync(require("path").relative(require("path").dirname(targetPath), sourcePath), targetPath, symlinkType)/g' /usr/local/lib/node_modules/@kaitranntt/ccs/dist/utils/claude-symlink-manager.js
|
|
28
49
|
|
|
29
50
|
# Install Claude Code using official native installer
|
|
30
|
-
RUN curl -fsSL https://claude.ai/install.sh | bash && \
|
|
51
|
+
RUN export HOME=/root && curl -fsSL https://claude.ai/install.sh | bash && \
|
|
31
52
|
mkdir -p /usr/local/share && \
|
|
32
|
-
mv /
|
|
53
|
+
mv /root/.local/share/claude /usr/local/share/claude && \
|
|
33
54
|
ln -sf /usr/local/share/claude/versions/$(ls /usr/local/share/claude/versions | head -1) /usr/local/bin/claude
|
|
34
55
|
|
|
35
56
|
USER agent
|
package/lib/install-codebuddy.sh
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /usr/local/lib/codebuddy && \
|
|
8
|
+
cd /usr/local/lib/codebuddy && \
|
|
9
|
+
bun init -y && \
|
|
10
|
+
bun add @tencent-ai/codebuddy-code && \
|
|
11
|
+
ln -s /usr/local/lib/codebuddy/node_modules/.bin/codebuddy /usr/local/bin/codebuddy
|
|
12
|
+
USER agent
|
|
13
|
+
SNIPPET
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
17
|
+
return 0 2>/dev/null || exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
5
20
|
TOOL="codebuddy"
|
|
6
21
|
|
|
7
22
|
echo "Installing $TOOL (Tencent CodeBuddy CLI)..."
|
package/lib/install-codex.sh
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /usr/local/lib/codex && \
|
|
8
|
+
cd /usr/local/lib/codex && \
|
|
9
|
+
bun init -y && \
|
|
10
|
+
bun add @openai/codex && \
|
|
11
|
+
ln -s /usr/local/lib/codex/node_modules/.bin/codex /usr/local/bin/codex
|
|
12
|
+
USER agent
|
|
13
|
+
SNIPPET
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
17
|
+
return 0 2>/dev/null || exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
5
20
|
TOOL="codex"
|
|
6
21
|
|
|
7
22
|
echo "Installing $TOOL (OpenAI Codex CLI)..."
|
package/lib/install-droid.sh
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /home/agent/.factory && chown -R agent:agent /home/agent/.factory && \
|
|
8
|
+
export HOME=/root && bash -c "curl -fsSL https://app.factory.ai/cli | sh" && \
|
|
9
|
+
mv /root/.local/bin/droid /usr/local/bin/droid
|
|
10
|
+
USER agent
|
|
11
|
+
SNIPPET
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
15
|
+
return 0 2>/dev/null || exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
4
18
|
echo "Installing droid (Factory CLI)..."
|
|
5
19
|
|
|
6
20
|
# Create directories
|
|
@@ -12,10 +26,9 @@ mkdir -p "$HOME/.ai-sandbox/tools/droid/home"
|
|
|
12
26
|
cat <<'EOF' > "dockerfiles/droid/Dockerfile"
|
|
13
27
|
FROM ai-base:latest
|
|
14
28
|
USER root
|
|
15
|
-
RUN mkdir -p /home/agent/.factory && \
|
|
16
|
-
bash -c "curl -fsSL https://app.factory.ai/cli | sh" && \
|
|
17
|
-
mv /
|
|
18
|
-
chown -R agent:agent /home/agent/.factory
|
|
29
|
+
RUN mkdir -p /home/agent/.factory && chown -R agent:agent /home/agent/.factory && \
|
|
30
|
+
export HOME=/root && bash -c "curl -fsSL https://app.factory.ai/cli | sh" && \
|
|
31
|
+
mv /root/.local/bin/droid /usr/local/bin/droid
|
|
19
32
|
USER agent
|
|
20
33
|
ENTRYPOINT ["bash", "-c", "exec droid \"$@\"", "--"]
|
|
21
34
|
EOF
|
package/lib/install-gemini.sh
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /usr/local/lib/gemini && \
|
|
8
|
+
cd /usr/local/lib/gemini && \
|
|
9
|
+
bun init -y && \
|
|
10
|
+
bun add @google/gemini-cli && \
|
|
11
|
+
ln -s /usr/local/lib/gemini/node_modules/.bin/gemini /usr/local/bin/gemini
|
|
12
|
+
USER agent
|
|
13
|
+
SNIPPET
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
17
|
+
return 0 2>/dev/null || exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
5
20
|
TOOL="gemini"
|
|
6
21
|
|
|
7
22
|
echo "Installing $TOOL (Google Gemini CLI)..."
|
package/lib/install-jules.sh
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN mkdir -p /usr/local/lib/jules && \
|
|
8
|
+
cd /usr/local/lib/jules && \
|
|
9
|
+
bun init -y && \
|
|
10
|
+
bun add @google/jules && \
|
|
11
|
+
ln -s /usr/local/lib/jules/node_modules/.bin/jules /usr/local/bin/jules
|
|
12
|
+
USER agent
|
|
13
|
+
SNIPPET
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
17
|
+
return 0 2>/dev/null || exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
5
20
|
TOOL="jules"
|
|
6
21
|
|
|
7
22
|
echo "Installing $TOOL (Google Jules CLI)..."
|
package/lib/install-kilo.sh
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN npm install -g @kilocode/cli
|
|
8
|
+
USER agent
|
|
9
|
+
SNIPPET
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
13
|
+
return 0 2>/dev/null || exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
6
16
|
TOOL="kilo"
|
|
7
17
|
|
|
8
18
|
echo "Installing $TOOL (Kilo Code CLI)..."
|
package/lib/install-openclaw.sh
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
# openclaw uses docker-compose and is handled separately - no Dockerfile snippet
|
|
7
|
+
SNIPPET
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
11
|
+
return 0 2>/dev/null || exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
5
14
|
TOOL="openclaw"
|
|
6
15
|
|
|
7
16
|
echo "🔄 Installing $TOOL (OpenClaw - Official Docker Compose)..."
|
package/lib/install-opencode.sh
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
+
dockerfile_snippet() {
|
|
5
|
+
cat <<'SNIPPET'
|
|
6
|
+
USER root
|
|
7
|
+
RUN curl -fsSL https://opencode.ai/install | bash && \
|
|
8
|
+
mv /root/.opencode/bin/opencode /usr/local/bin/opencode && \
|
|
9
|
+
rm -rf /root/.opencode
|
|
10
|
+
SNIPPET
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if [[ "${SNIPPET_MODE:-}" == "1" ]]; then
|
|
14
|
+
return 0 2>/dev/null || exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
4
17
|
TOOL="opencode"
|
|
5
18
|
OPENCODE_VERSION="${OPENCODE_VERSION:-}"
|
|
6
19
|
|
|
@@ -20,8 +33,8 @@ FROM ai-base:latest
|
|
|
20
33
|
|
|
21
34
|
USER root
|
|
22
35
|
RUN curl -fsSL https://opencode.ai/install | bash -s -- --version $OPENCODE_VERSION && \\
|
|
23
|
-
mv /
|
|
24
|
-
rm -rf /
|
|
36
|
+
mv /root/.opencode/bin/opencode /usr/local/bin/opencode && \\
|
|
37
|
+
rm -rf /root/.opencode
|
|
25
38
|
|
|
26
39
|
USER agent
|
|
27
40
|
ENTRYPOINT ["opencode"]
|
|
@@ -32,8 +45,8 @@ FROM ai-base:latest
|
|
|
32
45
|
|
|
33
46
|
USER root
|
|
34
47
|
RUN curl -fsSL https://opencode.ai/install | bash && \
|
|
35
|
-
mv /
|
|
36
|
-
rm -rf /
|
|
48
|
+
mv /root/.opencode/bin/opencode /usr/local/bin/opencode && \
|
|
49
|
+
rm -rf /root/.opencode
|
|
37
50
|
|
|
38
51
|
USER agent
|
|
39
52
|
ENTRYPOINT ["opencode"]
|