wechatbridge-cli 1.4.9__tar.gz → 1.5.0__tar.gz
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.
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/PKG-INFO +29 -13
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/README.md +28 -12
- wechatbridge_cli-1.5.0/tests/test_dsh.py +657 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/tests/test_hardening.py +177 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/__init__.py +1 -1
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/config.py +45 -2
- wechatbridge_cli-1.5.0/wechatbridge/dsh.py +478 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/main.py +22 -4
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/runner_common.py +48 -26
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge_cli.egg-info/PKG-INFO +29 -13
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge_cli.egg-info/SOURCES.txt +2 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/LICENSE +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/pyproject.toml +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/setup.cfg +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/tests/test_codex.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/tests/test_codex_auth.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/tests/test_grok_auth.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/__main__.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/agy.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/codex.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/grok.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/ilink.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge/update_check.py +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge_cli.egg-info/dependency_links.txt +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge_cli.egg-info/entry_points.txt +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge_cli.egg-info/requires.txt +0 -0
- {wechatbridge_cli-1.4.9 → wechatbridge_cli-1.5.0}/wechatbridge_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wechatbridge-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Bridge WeChat messages to agy, Grok Build, or Codex CLIs — text/image/file/voice in, CLI replies and generated files back.
|
|
5
5
|
Author: WeChatBridge contributors
|
|
6
6
|
License: MIT
|
|
@@ -36,21 +36,21 @@ Dynamic: license-file
|
|
|
36
36
|

|
|
37
37
|

|
|
38
38
|
|
|
39
|
-
WeChatBridge connects a WeChat bot to agentic coding CLIs (Google's agy / Antigravity, xAI's Grok Build,
|
|
39
|
+
WeChatBridge connects a WeChat bot to agentic coding CLIs (Google's agy / Antigravity, xAI's Grok Build, OpenAI's Codex, or DeepSeek Harness' dsh). From WeChat you can send text, images, files, and voice-as-text to the active CLI, get replies back, and receive certain generated files over the WeChat CDN. Switch backends per user with `/backend` — no restart.
|
|
40
40
|
|
|
41
41
|
```
|
|
42
|
-
WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok / codex CLI
|
|
42
|
+
WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok / codex / dsh CLI
|
|
43
43
|
(this project) (runs tools)
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
The bridge process stays up and long-polls iLink. For prompts that go to a CLI, it spawns one `agy`
|
|
46
|
+
The bridge process stays up and long-polls iLink. For prompts that go to a CLI, it spawns one `agy` / `grok` / `codex` / `dsh` child (single-turn) and exits that child when done — the child does not stay resident. Many slash commands (`/help`, `/backend`, `/persona`, …) are handled inside the bridge and never start a CLI. Only artifacts the bridge can detect under the user's allowed session paths are pushed back via CDN.
|
|
47
47
|
|
|
48
48
|
## Features
|
|
49
49
|
|
|
50
|
-
- Text, image, file, and voice (WeChat server-side transcription only) go to the **active** backend (`agy`, `grok`, or `
|
|
50
|
+
- Text, image, file, and voice (WeChat server-side transcription only) go to the **active** backend (`agy`, `grok`, `codex`, or `dsh`)
|
|
51
51
|
- Detected CLI artifacts under the per-user allowed tree can be sent back (size-capped); not every file the CLI touches
|
|
52
52
|
- Each WeChat user gets an isolated workspace; model / effort / mode are remembered **per backend**
|
|
53
|
-
- Runtime backend switch: `/backend agy`, `/backend grok`, or `/backend
|
|
53
|
+
- Runtime backend switch: `/backend agy`, `/backend grok`, `/backend codex`, or `/backend dsh` (clears that backend's continuation state — the agy/grok continuation flag and the codex `thread_id`/resume state — so the next CLI turn starts a fresh session; history files on disk are not wiped immediately)
|
|
54
54
|
- Slash commands for model, session reset, persona, and more (see below)
|
|
55
55
|
- Dangerous-prompt gate: a **keyword list** of concrete destructive patterns asks for confirmation before run
|
|
56
56
|
- Sender whitelist (`WECHATBRIDGE_ALLOWED_SENDERS`; empty = allow all)
|
|
@@ -72,8 +72,17 @@ Default data paths expand from `~` (e.g. `~/.local/share/wechatbridge/<instance>
|
|
|
72
72
|
- **agy** (default) — Google Antigravity CLI
|
|
73
73
|
- **grok** — xAI Grok Build CLI
|
|
74
74
|
- **codex** — OpenAI Codex CLI
|
|
75
|
+
- **dsh** — DeepSeek Harness CLI (one-shot `headless` profile)
|
|
75
76
|
|
|
76
|
-
Per-user switch: `/backend agy`, `/backend grok`, or `/backend
|
|
77
|
+
Per-user switch: `/backend agy`, `/backend grok`, `/backend codex`, or `/backend dsh`. Each backend keeps its own model / effort / mode memory and persona file layout. Global default is `WECHATBRIDGE_BACKEND`.
|
|
78
|
+
|
|
79
|
+
### dsh backend notes
|
|
80
|
+
|
|
81
|
+
- **Single-turn:** the `headless` profile always creates a fresh session per invocation (`session-<uuid>`), so every WeChat message starts a new dsh session. `/clear` / `/new` are accepted but are no-ops, and `/model`, `/fast`, `/planning`, `/persona`, `/add-dir` are not wired yet (they return a short "not supported" notice).
|
|
82
|
+
- Runs `dsh --profile headless -- <prompt>` with `cwd` = the per-user session directory (per-user workspace; model-created files land there and can be sent back via CDN).
|
|
83
|
+
- Image and file attachments are merged into the prompt text as `@/absolute/path` mentions. Verified in dsh v0.1.1-rc.2: `headless` passes the prompt text directly to the model without pre-reading or inlining mentions; the model receives system guidance on @-paths and may invoke file tools (e.g. `read`) if needed. The bridge only filters out-of-bounds mentions starting with absolute paths, `~`, or `file://` (`@/abs`, `@~/x`, `@file://`, replaced with `[blocked-path]`), which is best-effort prompt text filtering rather than a sandbox boundary.
|
|
84
|
+
- Auth / profiles are **machine-wide** (`~/.dsh`, same model as grok's machine-wide login): the child's `HOME` points at the per-user session dir, so the bridge always passes `DSH_HOME` explicitly. Set `WECHATBRIDGE_DSH_HOME` to configure a dedicated service home with automatic session retention cleanup; when unset, it reuses the host `~/.dsh` without automatic session cleanup (managed by the operator). `DSH_BIN_PATH`, `DSH_PROFILE`, and `DSH_TIMEOUT` are configurable.
|
|
85
|
+
- Status: implemented from the published `dsh` CLI contract (headless bundle source) plus a fake CLI in the test suite; final acceptance depends on a real `dsh login` + headless run.
|
|
77
86
|
|
|
78
87
|
### Grok backend notes
|
|
79
88
|
|
|
@@ -93,7 +102,8 @@ Per-user switch: `/backend agy`, `/backend grok`, or `/backend codex`. Each back
|
|
|
93
102
|
- **agy** on `PATH`, or set `AGY_BIN_PATH`
|
|
94
103
|
- **and/or grok** on `PATH`, or set `GROK_BIN_PATH`
|
|
95
104
|
- **and/or codex** on `PATH`, or set `CODEX_BIN_PATH`
|
|
96
|
-
-
|
|
105
|
+
- **and/or dsh** on `PATH`, or set `DSH_BIN_PATH` (DeepSeek Harness, `dsh login` required)
|
|
106
|
+
- Antigravity is Google's terminal agentic coding CLI (successor to Gemini CLI). Grok Build is xAI's counterpart; Codex is OpenAI's terminal agentic coding CLI; dsh is DeepSeek Harness' CLI.
|
|
97
107
|
- A WeChat account with a [ClawBot / iLink](https://ilinkai.weixin.qq.com) bot (QR bind on first run)
|
|
98
108
|
- Python 3.10+
|
|
99
109
|
|
|
@@ -164,10 +174,14 @@ Key variables (all have defaults):
|
|
|
164
174
|
| `AGY_BIN_PATH` | `agy` | path to the agy binary |
|
|
165
175
|
| `GROK_BIN_PATH` | `grok` | path to the grok binary |
|
|
166
176
|
| `CODEX_BIN_PATH` | `codex` | path to the codex binary |
|
|
167
|
-
| `
|
|
177
|
+
| `DSH_BIN_PATH` | `dsh` | path to the dsh binary |
|
|
178
|
+
| `DSH_PROFILE` | `headless` | dsh profile booted for one-shot tasks |
|
|
179
|
+
| `DSH_TIMEOUT` | `600` | dsh CLI run timeout in seconds |
|
|
180
|
+
| `WECHATBRIDGE_DSH_HOME` | _empty_ | explicit `DSH_HOME` passed to the dsh child. Explicitly set = dedicated home + auto session cleanup; unset = reuse host `~/.dsh` without auto cleanup |
|
|
181
|
+
| `WECHATBRIDGE_BACKEND` | `agy` | global default backend (`agy` / `grok` / `codex` / `dsh`; overridable per user via `/backend`) |
|
|
168
182
|
| `WECHATBRIDGE_INSTANCE` | `default` | instance name; state / session / QR paths derive from it |
|
|
169
183
|
| `WECHATBRIDGE_ALLOWED_SENDERS` | _empty_ | comma-separated WeChat IDs (empty = allow all) |
|
|
170
|
-
| `AGY_TIMEOUT` | `600` | CLI run timeout in seconds (
|
|
184
|
+
| `AGY_TIMEOUT` | `600` | CLI run timeout in seconds (agy / grok / codex backends) |
|
|
171
185
|
| `WECHATBRIDGE_MAX_OUTBOUND_BYTES` | `104857600` | max file size sent back to WeChat (100 MB) |
|
|
172
186
|
| `WECHATBRIDGE_MAX_INBOUND_BYTES` | `20971520` | max inbound image/file after download (20 MB) |
|
|
173
187
|
| `WECHATBRIDGE_MAX_CONCURRENT` | `4` | global concurrent process slots; same user serial (queue does not hold a slot); extras get a busy reply |
|
|
@@ -253,7 +267,7 @@ See [`deploy/wechatbridge-windows.md`](deploy/wechatbridge-windows.md).
|
|
|
253
267
|
| Command | Action |
|
|
254
268
|
|---|---|
|
|
255
269
|
| `/help` | list supported commands for the active backend |
|
|
256
|
-
| `/backend <agy\|grok\|codex>` | switch CLI backend for this WeChat user (on real change: clears that backend's continuation state — agy/grok flag and codex `thread_id`/resume — so the next turn starts a fresh session; history files may remain until retention cleanup) |
|
|
270
|
+
| `/backend <agy\|grok\|codex\|dsh>` | switch CLI backend for this WeChat user (on real change: clears that backend's continuation state — agy/grok flag and codex `thread_id`/resume — so the next turn starts a fresh session; history files may remain until retention cleanup) |
|
|
257
271
|
| `/clear` or `/new` | drop continue flag so the next CLI turn is a new conversation (does not instantly delete history files) |
|
|
258
272
|
| `/model <name>` | set model (all backends validate against a live list: agy/grok via CLI `models`; codex via `codex debug models` [then `--bundled`]; unknown name or list-fetch failure refuse and do not write prefs; see `/models`) |
|
|
259
273
|
| `/models` | list models — agy/grok/codex all query the live CLI (codex: `debug models`; falls back to a built-in reference note only if the live list cannot be fetched) |
|
|
@@ -273,7 +287,7 @@ Other `/…` commands are either rejected (e.g. `/exit`), reported as unsupporte
|
|
|
273
287
|
## Ops & security (what the bridge actually enforces)
|
|
274
288
|
|
|
275
289
|
- **Whitelist first.** Empty `WECHATBRIDGE_ALLOWED_SENDERS` means anyone who can message the bot can use it.
|
|
276
|
-
- **Auto-approve CLIs.** agy runs with `--dangerously-skip-permissions`; grok with `--always-approve` (unless planning mode). Treat this as trusted-user tooling, not a multi-tenant sandbox.
|
|
290
|
+
- **Auto-approve CLIs.** agy runs with `--dangerously-skip-permissions`; grok with `--always-approve` (unless planning mode); dsh tools run without host path restrictions. Treat this as trusted-user tooling, not a multi-tenant sandbox.
|
|
277
291
|
- **Danger gate is keyword-based**, not full intent understanding. Defaults target concrete patterns (`rm -rf /`, pipe-to-shell, `mkfs`, `format c:`, a few heavy Chinese phrases, …). Everyday wording like bare “delete” is **not** gated. Override list via `WECHATBRIDGE_CONFIRM_KEYWORDS`; approve with `WECHATBRIDGE_CONFIRM_TOKEN` (default `y`), TTL `WECHATBRIDGE_PENDING_TTL`.
|
|
278
292
|
- **Inbound media** is size-capped (default 20 MB), streamed, and CDN hosts are allowlisted. Missing `aes_key` returns a clear error.
|
|
279
293
|
- **Outbound artifacts** only leave the allowed per-user tree (agy: session scratch; grok: under session dir), after `realpath` checks, and only if under `WECHATBRIDGE_MAX_OUTBOUND_BYTES`.
|
|
@@ -285,8 +299,10 @@ Other `/…` commands are either rejected (e.g. `/exit`), reported as unsupporte
|
|
|
285
299
|
|
|
286
300
|
## Limitations
|
|
287
301
|
|
|
288
|
-
- Not a standalone agent — requires agy and/or grok and/or codex.
|
|
302
|
+
- Not a standalone agent — requires agy and/or grok and/or codex and/or dsh.
|
|
289
303
|
- The **codex** backend is not yet verified against a real Codex subscription/CLI; it is validated by source research, a JSONL fixture, and a fake CLI in tests. Treat it as community-tested until a real user confirms.
|
|
304
|
+
- The **dsh** backend is single-turn only (the `headless` profile always starts a fresh session) and has not yet been verified against a real `dsh login` + headless run; it is validated against the published headless bundle contract and a fake CLI in tests.
|
|
305
|
+
- dsh model/effort/mode/persona slash commands are not wired yet; `/model`, `/fast`, `/planning`, `/persona`, `/add-dir` return a "not supported" notice on the dsh backend.
|
|
290
306
|
- Voice is WeChat speech-to-text only; no local ASR; empty transcript → “type instead”.
|
|
291
307
|
- No video send/receive; no native WeChat voice-bubble replies (no silk encode).
|
|
292
308
|
- One WeChat binding per process; multiple accounts need multiple instances (`WECHATBRIDGE_INSTANCE`).
|
|
@@ -5,21 +5,21 @@
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
WeChatBridge connects a WeChat bot to agentic coding CLIs (Google's agy / Antigravity, xAI's Grok Build,
|
|
8
|
+
WeChatBridge connects a WeChat bot to agentic coding CLIs (Google's agy / Antigravity, xAI's Grok Build, OpenAI's Codex, or DeepSeek Harness' dsh). From WeChat you can send text, images, files, and voice-as-text to the active CLI, get replies back, and receive certain generated files over the WeChat CDN. Switch backends per user with `/backend` — no restart.
|
|
9
9
|
|
|
10
10
|
```
|
|
11
|
-
WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok / codex CLI
|
|
11
|
+
WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok / codex / dsh CLI
|
|
12
12
|
(this project) (runs tools)
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
The bridge process stays up and long-polls iLink. For prompts that go to a CLI, it spawns one `agy`
|
|
15
|
+
The bridge process stays up and long-polls iLink. For prompts that go to a CLI, it spawns one `agy` / `grok` / `codex` / `dsh` child (single-turn) and exits that child when done — the child does not stay resident. Many slash commands (`/help`, `/backend`, `/persona`, …) are handled inside the bridge and never start a CLI. Only artifacts the bridge can detect under the user's allowed session paths are pushed back via CDN.
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
19
|
-
- Text, image, file, and voice (WeChat server-side transcription only) go to the **active** backend (`agy`, `grok`, or `
|
|
19
|
+
- Text, image, file, and voice (WeChat server-side transcription only) go to the **active** backend (`agy`, `grok`, `codex`, or `dsh`)
|
|
20
20
|
- Detected CLI artifacts under the per-user allowed tree can be sent back (size-capped); not every file the CLI touches
|
|
21
21
|
- Each WeChat user gets an isolated workspace; model / effort / mode are remembered **per backend**
|
|
22
|
-
- Runtime backend switch: `/backend agy`, `/backend grok`, or `/backend
|
|
22
|
+
- Runtime backend switch: `/backend agy`, `/backend grok`, `/backend codex`, or `/backend dsh` (clears that backend's continuation state — the agy/grok continuation flag and the codex `thread_id`/resume state — so the next CLI turn starts a fresh session; history files on disk are not wiped immediately)
|
|
23
23
|
- Slash commands for model, session reset, persona, and more (see below)
|
|
24
24
|
- Dangerous-prompt gate: a **keyword list** of concrete destructive patterns asks for confirmation before run
|
|
25
25
|
- Sender whitelist (`WECHATBRIDGE_ALLOWED_SENDERS`; empty = allow all)
|
|
@@ -41,8 +41,17 @@ Default data paths expand from `~` (e.g. `~/.local/share/wechatbridge/<instance>
|
|
|
41
41
|
- **agy** (default) — Google Antigravity CLI
|
|
42
42
|
- **grok** — xAI Grok Build CLI
|
|
43
43
|
- **codex** — OpenAI Codex CLI
|
|
44
|
+
- **dsh** — DeepSeek Harness CLI (one-shot `headless` profile)
|
|
44
45
|
|
|
45
|
-
Per-user switch: `/backend agy`, `/backend grok`, or `/backend
|
|
46
|
+
Per-user switch: `/backend agy`, `/backend grok`, `/backend codex`, or `/backend dsh`. Each backend keeps its own model / effort / mode memory and persona file layout. Global default is `WECHATBRIDGE_BACKEND`.
|
|
47
|
+
|
|
48
|
+
### dsh backend notes
|
|
49
|
+
|
|
50
|
+
- **Single-turn:** the `headless` profile always creates a fresh session per invocation (`session-<uuid>`), so every WeChat message starts a new dsh session. `/clear` / `/new` are accepted but are no-ops, and `/model`, `/fast`, `/planning`, `/persona`, `/add-dir` are not wired yet (they return a short "not supported" notice).
|
|
51
|
+
- Runs `dsh --profile headless -- <prompt>` with `cwd` = the per-user session directory (per-user workspace; model-created files land there and can be sent back via CDN).
|
|
52
|
+
- Image and file attachments are merged into the prompt text as `@/absolute/path` mentions. Verified in dsh v0.1.1-rc.2: `headless` passes the prompt text directly to the model without pre-reading or inlining mentions; the model receives system guidance on @-paths and may invoke file tools (e.g. `read`) if needed. The bridge only filters out-of-bounds mentions starting with absolute paths, `~`, or `file://` (`@/abs`, `@~/x`, `@file://`, replaced with `[blocked-path]`), which is best-effort prompt text filtering rather than a sandbox boundary.
|
|
53
|
+
- Auth / profiles are **machine-wide** (`~/.dsh`, same model as grok's machine-wide login): the child's `HOME` points at the per-user session dir, so the bridge always passes `DSH_HOME` explicitly. Set `WECHATBRIDGE_DSH_HOME` to configure a dedicated service home with automatic session retention cleanup; when unset, it reuses the host `~/.dsh` without automatic session cleanup (managed by the operator). `DSH_BIN_PATH`, `DSH_PROFILE`, and `DSH_TIMEOUT` are configurable.
|
|
54
|
+
- Status: implemented from the published `dsh` CLI contract (headless bundle source) plus a fake CLI in the test suite; final acceptance depends on a real `dsh login` + headless run.
|
|
46
55
|
|
|
47
56
|
### Grok backend notes
|
|
48
57
|
|
|
@@ -62,7 +71,8 @@ Per-user switch: `/backend agy`, `/backend grok`, or `/backend codex`. Each back
|
|
|
62
71
|
- **agy** on `PATH`, or set `AGY_BIN_PATH`
|
|
63
72
|
- **and/or grok** on `PATH`, or set `GROK_BIN_PATH`
|
|
64
73
|
- **and/or codex** on `PATH`, or set `CODEX_BIN_PATH`
|
|
65
|
-
-
|
|
74
|
+
- **and/or dsh** on `PATH`, or set `DSH_BIN_PATH` (DeepSeek Harness, `dsh login` required)
|
|
75
|
+
- Antigravity is Google's terminal agentic coding CLI (successor to Gemini CLI). Grok Build is xAI's counterpart; Codex is OpenAI's terminal agentic coding CLI; dsh is DeepSeek Harness' CLI.
|
|
66
76
|
- A WeChat account with a [ClawBot / iLink](https://ilinkai.weixin.qq.com) bot (QR bind on first run)
|
|
67
77
|
- Python 3.10+
|
|
68
78
|
|
|
@@ -133,10 +143,14 @@ Key variables (all have defaults):
|
|
|
133
143
|
| `AGY_BIN_PATH` | `agy` | path to the agy binary |
|
|
134
144
|
| `GROK_BIN_PATH` | `grok` | path to the grok binary |
|
|
135
145
|
| `CODEX_BIN_PATH` | `codex` | path to the codex binary |
|
|
136
|
-
| `
|
|
146
|
+
| `DSH_BIN_PATH` | `dsh` | path to the dsh binary |
|
|
147
|
+
| `DSH_PROFILE` | `headless` | dsh profile booted for one-shot tasks |
|
|
148
|
+
| `DSH_TIMEOUT` | `600` | dsh CLI run timeout in seconds |
|
|
149
|
+
| `WECHATBRIDGE_DSH_HOME` | _empty_ | explicit `DSH_HOME` passed to the dsh child. Explicitly set = dedicated home + auto session cleanup; unset = reuse host `~/.dsh` without auto cleanup |
|
|
150
|
+
| `WECHATBRIDGE_BACKEND` | `agy` | global default backend (`agy` / `grok` / `codex` / `dsh`; overridable per user via `/backend`) |
|
|
137
151
|
| `WECHATBRIDGE_INSTANCE` | `default` | instance name; state / session / QR paths derive from it |
|
|
138
152
|
| `WECHATBRIDGE_ALLOWED_SENDERS` | _empty_ | comma-separated WeChat IDs (empty = allow all) |
|
|
139
|
-
| `AGY_TIMEOUT` | `600` | CLI run timeout in seconds (
|
|
153
|
+
| `AGY_TIMEOUT` | `600` | CLI run timeout in seconds (agy / grok / codex backends) |
|
|
140
154
|
| `WECHATBRIDGE_MAX_OUTBOUND_BYTES` | `104857600` | max file size sent back to WeChat (100 MB) |
|
|
141
155
|
| `WECHATBRIDGE_MAX_INBOUND_BYTES` | `20971520` | max inbound image/file after download (20 MB) |
|
|
142
156
|
| `WECHATBRIDGE_MAX_CONCURRENT` | `4` | global concurrent process slots; same user serial (queue does not hold a slot); extras get a busy reply |
|
|
@@ -222,7 +236,7 @@ See [`deploy/wechatbridge-windows.md`](deploy/wechatbridge-windows.md).
|
|
|
222
236
|
| Command | Action |
|
|
223
237
|
|---|---|
|
|
224
238
|
| `/help` | list supported commands for the active backend |
|
|
225
|
-
| `/backend <agy\|grok\|codex>` | switch CLI backend for this WeChat user (on real change: clears that backend's continuation state — agy/grok flag and codex `thread_id`/resume — so the next turn starts a fresh session; history files may remain until retention cleanup) |
|
|
239
|
+
| `/backend <agy\|grok\|codex\|dsh>` | switch CLI backend for this WeChat user (on real change: clears that backend's continuation state — agy/grok flag and codex `thread_id`/resume — so the next turn starts a fresh session; history files may remain until retention cleanup) |
|
|
226
240
|
| `/clear` or `/new` | drop continue flag so the next CLI turn is a new conversation (does not instantly delete history files) |
|
|
227
241
|
| `/model <name>` | set model (all backends validate against a live list: agy/grok via CLI `models`; codex via `codex debug models` [then `--bundled`]; unknown name or list-fetch failure refuse and do not write prefs; see `/models`) |
|
|
228
242
|
| `/models` | list models — agy/grok/codex all query the live CLI (codex: `debug models`; falls back to a built-in reference note only if the live list cannot be fetched) |
|
|
@@ -242,7 +256,7 @@ Other `/…` commands are either rejected (e.g. `/exit`), reported as unsupporte
|
|
|
242
256
|
## Ops & security (what the bridge actually enforces)
|
|
243
257
|
|
|
244
258
|
- **Whitelist first.** Empty `WECHATBRIDGE_ALLOWED_SENDERS` means anyone who can message the bot can use it.
|
|
245
|
-
- **Auto-approve CLIs.** agy runs with `--dangerously-skip-permissions`; grok with `--always-approve` (unless planning mode). Treat this as trusted-user tooling, not a multi-tenant sandbox.
|
|
259
|
+
- **Auto-approve CLIs.** agy runs with `--dangerously-skip-permissions`; grok with `--always-approve` (unless planning mode); dsh tools run without host path restrictions. Treat this as trusted-user tooling, not a multi-tenant sandbox.
|
|
246
260
|
- **Danger gate is keyword-based**, not full intent understanding. Defaults target concrete patterns (`rm -rf /`, pipe-to-shell, `mkfs`, `format c:`, a few heavy Chinese phrases, …). Everyday wording like bare “delete” is **not** gated. Override list via `WECHATBRIDGE_CONFIRM_KEYWORDS`; approve with `WECHATBRIDGE_CONFIRM_TOKEN` (default `y`), TTL `WECHATBRIDGE_PENDING_TTL`.
|
|
247
261
|
- **Inbound media** is size-capped (default 20 MB), streamed, and CDN hosts are allowlisted. Missing `aes_key` returns a clear error.
|
|
248
262
|
- **Outbound artifacts** only leave the allowed per-user tree (agy: session scratch; grok: under session dir), after `realpath` checks, and only if under `WECHATBRIDGE_MAX_OUTBOUND_BYTES`.
|
|
@@ -254,8 +268,10 @@ Other `/…` commands are either rejected (e.g. `/exit`), reported as unsupporte
|
|
|
254
268
|
|
|
255
269
|
## Limitations
|
|
256
270
|
|
|
257
|
-
- Not a standalone agent — requires agy and/or grok and/or codex.
|
|
271
|
+
- Not a standalone agent — requires agy and/or grok and/or codex and/or dsh.
|
|
258
272
|
- The **codex** backend is not yet verified against a real Codex subscription/CLI; it is validated by source research, a JSONL fixture, and a fake CLI in tests. Treat it as community-tested until a real user confirms.
|
|
273
|
+
- The **dsh** backend is single-turn only (the `headless` profile always starts a fresh session) and has not yet been verified against a real `dsh login` + headless run; it is validated against the published headless bundle contract and a fake CLI in tests.
|
|
274
|
+
- dsh model/effort/mode/persona slash commands are not wired yet; `/model`, `/fast`, `/planning`, `/persona`, `/add-dir` return a "not supported" notice on the dsh backend.
|
|
259
275
|
- Voice is WeChat speech-to-text only; no local ASR; empty transcript → “type instead”.
|
|
260
276
|
- No video send/receive; no native WeChat voice-bubble replies (no silk encode).
|
|
261
277
|
- One WeChat binding per process; multiple accounts need multiple instances (`WECHATBRIDGE_INSTANCE`).
|