返回 CodeWhale
README.md
根目录 / scripts / remote-smoke / README.md
1 # Remote-workbench smoke lab (EXPERIMENTAL)
2
3 Status: experimental smoke-lab scripts for the US-first remote-workbench lane
4 (issue #1990). Not part of the supported install paths until the smoke passes
5 and this graduates into a documented setup.
6
7 This concretizes `docs/REMOTE_VM_US.md`: a cheap US VPS running the Codewhale
8 runtime on `127.0.0.1` plus the Telegram long-polling bridge, reusing the
9 provider-agnostic Ubuntu scripts under `scripts/tencent-lighthouse/` (audited:
10 nothing in them is Tencent-specific).
11
12 ## Layout
13
14 - `setup-vm.sh` — provider-agnostic. Run on any fresh Ubuntu 24.04 VM:
15 bootstrap + prebuilt release binaries (sha256-verified, no Rust
16 build) + `gh` CLI + 4G swapfile + Telegram bridge services + secrets +
17 validator + doctor.
18 - `digitalocean/provision.sh`, `digitalocean/teardown.sh` — active lane.
19 Chosen over AWS Lightsail for auth simplicity: one API token vs IAM
20 credential setup (#1990 allows "a clearly documented better alternative").
21 - `aws-lightsail/provision.sh`, `aws-lightsail/teardown.sh` — kept as the
22 AWS alternative; same flow, needs `aws configure` first.
23 - `agent-session.sh` — sourceable helper for interactive/tmux agent sessions
24 as the `codewhale` user. Sources `/etc/codewhale/runtime.env` so the
25 provider key is available outside of systemd.
26
27 Both provisioners print the API-reported monthly price and require a typed
28 `yes` before creating anything billable, and both teardowns end with a
29 leftover-billable-resources check.
30
31 ## Who this lane is for (China note)
32
33 Telegram is blocked in mainland China and DigitalOcean has no China
34 datacenters (cross-border routes are slow; DO IP ranges are frequently
35 GFW-affected). Mainland-based users should prefer a regional host and chat
36 bridge approved by their organization. This lane is for users outside mainland
37 China.
38
39 ## Security model
40
41 - Runtime API binds `127.0.0.1:7878` only; the only inbound port anywhere is
42 SSH (cloud firewall + ufw, both default to caller-IP /32 where supported).
43 - Telegram uses outbound long polling — no webhook, no public ingress.
44 - Telegram chats are allowlisted (`TELEGRAM_CHAT_ALLOWLIST`); unlisted chats
45 are refused. `TELEGRAM_ALLOW_UNLISTED=true` only for first pairing.
46 - Secrets travel as a chmod-600 file over scp, land in `/etc/codewhale/*.env`
47 (0640 root:codewhale), and the transfer file is shredded. Never in argv,
48 shell history, or logs.
49
50 ## Run order — DigitalOcean (from the laptop)
51
52 ```bash
53 # 0. once: create an API token (Web UI -> API -> Generate New Token, write
54 # scope), then in a real terminal: doctl auth init (paste token)
55
56 # 1. provision (asks before billing starts)
57 bash scripts/remote-smoke/digitalocean/provision.sh
58 # defaults: sfo3, s-1vcpu-2gb (~$12/mo), ubuntu-24-04-x64, ~/.ssh/id_ed25519.pub
59
60 # 2. secrets file (never commit; values from BotFather / provider console)
61 umask 077 && cat > /tmp/cw-secrets.env <<'EOF'
62 TELEGRAM_BOT_TOKEN=...
63 CODEWHALE_PROVIDER=deepseek
64 PROVIDER_KEY_NAME=DEEPSEEK_API_KEY
65 PROVIDER_KEY_VALUE=...
66 TELEGRAM_CHAT_ALLOWLIST=... # optional; empty enables first-pairing mode
67 EOF
68
69 # 3. push secrets + installer, run it (DO Ubuntu images log in as root)
70 scp /tmp/cw-secrets.env scripts/remote-smoke/setup-vm.sh root@<IP>:/tmp/
71 rm /tmp/cw-secrets.env
72 ssh root@<IP> 'SECRETS_FILE=/tmp/cw-secrets.env bash /tmp/setup-vm.sh'
73
74 # 4. phone smoke per docs/REMOTE_VM_US.md "First Smoke Test"
75
76 # 5. teardown when done (stops billing)
77 bash scripts/remote-smoke/digitalocean/teardown.sh
78 ```
79
80 For AWS Lightsail substitute step 0 with `aws configure`, step 1/5 with the
81 `aws-lightsail/` scripts, and ssh as `ubuntu@<IP>` with `sudo` in step 3.
82
83 ## Cost
84
85 Billed hourly until destroyed. DO `s-1vcpu-2gb` ≈ $12/mo (~$0.018/h);
86 1 vCPU / 2 GB is enough because the VM downloads release binaries instead of
87 compiling Rust. A same-day smoke costs well under $1. Bigger options for a
88 longer-lived host: `s-2vcpu-2gb` (~$18/mo), `s-2vcpu-4gb` (~$24/mo, the
89 docs/REMOTE_VM_US.md default spec).
90
91 ## Known sharp edges (from the 2026-06-09 audit)
92
93 - The Rust binary reads only `DEEPSEEK_RUNTIME_TOKEN`/`--auth-token` and
94 `--port`; the `CODEWHALE_RUNTIME_*` names in `/etc/codewhale/runtime.env`
95 work because the systemd unit expands them into flags. Don't start
96 `codewhale serve` by hand and expect the env file to apply.
97 - `codewhale-runtime.service` hard-fails activation if
98 `/home/codewhale/.codewhale` or `/home/codewhale/.deepseek` don't exist
99 (`ReadWritePaths`); `setup-vm.sh` pre-creates them.
100 - Both binaries are required (`codewhale` delegates to `codewhale-tui`).
101 - Exactly one bridge process per bot token — a second poller causes endless
102 Telegram 409s. Stop any local bridge before starting the VM one.
103 - `/interrupt` is queued behind an active streaming turn (known limitation,
104 documented in `docs/REMOTE_SETUP_DESIGN.md` hardening table).
105
106 ## Autonomous agent loop (#3022)
107
108 Once the droplet is provisioned and `gh` is authenticated with a
109 fine-grained PAT (scoped to Hmbown/CodeWhale: Contents RW, Issues RW,
110 PRs RW, Metadata R), an agent can work the full pick→PR loop headless.
111
112 One-time git wiring after `gh auth login` so pushes use the PAT and
113 commits have a stable identity:
114
115 ```bash
116 gh auth setup-git
117 git config --global user.name "whalebro-agent"
118 git config --global user.email "whalebro-agent@users.noreply.github.com"
119 ```
120
121 ```bash
122 # 1. Pick an agent-ready issue
123 gh issue list --repo Hmbown/CodeWhale --label agent-ready --state open --json number,title,url
124
125 # 2. Claim it
126 gh issue edit <N> --add-label agent-in-progress --remove-label agent-ready
127
128 # 3. Isolate in a worktree
129 git -C /opt/whalebro/codewhale fetch origin
130 git -C /opt/whalebro/codewhale worktree add \
131 /opt/whalebro/worktrees/issue-<N> -b agent/<N>-<slug> origin/main
132 cd /opt/whalebro/worktrees/issue-<N>
133
134 # 4. Execute (run inside a tmux session for SSH-disconnect safety)
135 . /opt/whalebro/codewhale/scripts/remote-smoke/agent-session.sh
136 gh issue view <N> --json body -q .body | \
137 codewhale exec --auto --output-format stream-json "$(cat)"
138
139 # 5. Verify (run the issue's Verification block verbatim)
140 # 6. Deliver
141 gh pr create --repo Hmbown/CodeWhale --base main \
142 --title "<title>" --body "Closes #<N>"
143
144 # 7. On blockage: swap label to needs-human + comment
145 gh issue edit <N> --add-label needs-human --remove-label agent-in-progress
146 ```
147
148 Keep the same safety rules for any automated agent lane: PR-only delivery, no
149 force-push, secrets never in argv/history/logs, and one worktree per issue.
150
150 lines MARKDOWN