dsh-agy-link 0.4.26 → 0.4.28

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.
@@ -0,0 +1,32 @@
1
+ # Headless permissions: diagnose before granting access
2
+
3
+ The Antigravity provider invokes the official `agy` CLI directly. A model-selection label inherited from another provider does not turn this bridge into an API-router call.
4
+
5
+ ## Reproduction
6
+
7
+ With AGY 1.2.2, run from a project directory in `plan` mode and request `list_dir` or `view_file` for a directory outside that workspace that has no read allow-rule. Use a disposable directory containing synthetic files, not private data.
8
+
9
+ ```sh
10
+ agy --model gemini-3.8-flash --effort high --mode plan \
11
+ --output-format stream-json --print-timeout 90s \
12
+ --print 'Use list_dir on /tmp/agy-shared-fixture. Do not modify anything or use alternative tools. If denied, stop.'
13
+ ```
14
+
15
+ In a noninteractive invocation, a request that requires approval can be automatically denied because no interactive permission prompt can be answered. The wording `user denied permission` in a recorded tool error does not establish that a human clicked Deny. Switching from `plan` to `accept-edits` is not an authorization for arbitrary external directories.
16
+
17
+ ## Least-privilege remediation
18
+
19
+ 1. Back up the effective AGY settings privately. In the verified Linux AGY 1.2.2 installation, the CLI reads `~/.gemini/antigravity-cli/settings.json`. Verify the path for the installed version/platform; never copy credential stores into an issue.
20
+ 2. Preserve the entire existing configuration and permission list. Add only the required read rule to `permissions.allow`, for example `read_file(/tmp/agy-shared-fixture)`. This is an individual array entry, not a replacement settings file.
21
+ 3. Test directory listing, a direct child file, a nested child, and a sibling outside the allowed directory. On the verified AGY 1.2.2 installation, this directory rule allowed reads in the subtree and denied the sibling. Revalidate on other versions; this is not a claim about undocumented wildcard or symlink semantics.
22
+ 4. Test the actual required skill path from the actual project working directory. Keep `plan` for this read-only proof. Do not add `command(...)`, write rules or `--dangerously-skip-permissions` to make the check green.
23
+ 5. Read the recorded `step_update` tool outcome. An exit code of zero, a `SUCCESS` process result, or model prose is not enough: the AGY envelope can say success even when an individual tool failed or the final response is empty.
24
+ 6. Verify a fresh DSH turn after deployment. Preserve the original failing session; do not rewrite its history. A newly spawned CLI reads its settings, so a server restart is not automatically required for a permission-list change.
25
+
26
+ A directory read rule is broader than a single file rule. Choose the narrowest paths required by the intended workflow and do not grant the entire home directory. Existing shell permissions are outside the guarantee of this read-tool check: the denied fixture test must not use an alternative command to bypass the failure.
27
+
28
+ ## Separate integration defects
29
+
30
+ PR #15 fixes lifecycle cleanup and continuation detection. A trailing context snapshot can hide a tool result from a last-message-only detector. The follow-up constrains skipping to the declared `snapshot` form; plugin instructions, notices and human messages remain boundaries. Neither fix grants filesystem access.
31
+
32
+ Keep process completion, tool errors and user-visible response completeness separate when reporting readiness. Do not claim the whole turn passed when only a read tool passed.
@@ -15,6 +15,11 @@ Deliberate v1 boundaries and upstream-behavior notes.
15
15
  server (`dsh-tools`) in the workspace `.mcp.json` (merged in, restored on
16
16
  disable). `run_code` and `agy_ask` are never bridged; `mcpToolAllowlist`
17
17
  restricts the set further.
18
+ - **Full tool args / diff cards (v0.4.28+)** - the bridge reads agy's
19
+ conversation SQLite DB via the `sqlite3` CLI to recover arguments that
20
+ `filterToolParameters` strips from stream-json. When `sqlite3` is missing
21
+ or the DB is unreadable, cards fall back to stream-carried metadata only
22
+ (no path traversal: conversation ids are whitelist-validated).
18
23
  - **Structured outputs** - `agy_ask` accepts a `schema` parameter (JSON
19
24
  Schema as a JSON string) enforced via `--json-schema` since v0.2. Wiring
20
25
  schema enforcement into DSH-native tool-call generation remains future
@@ -0,0 +1,67 @@
1
+ # dsh-agy-link — English
2
+
3
+ Integrate Google Antigravity models into DeepSeek Harness (DSH) through the official, unmodified `agy` CLI. The plugin provides streaming, thinking, tool activity, token metering, in-GUI OAuth login, and quota monitoring.
4
+
5
+ ## Requirements
6
+
7
+ | Requirement | Verification |
8
+ | --- | --- |
9
+ | DSH | `dsh --version` |
10
+ | Node.js >= 24 | `node --version` |
11
+ | Google Antigravity CLI | `agy --version` |
12
+ | Google connectivity | proxy/VPN/TUN where required |
13
+
14
+ Where Google is not directly reachable, enable system proxy/TUN mode. If the terminal does not inherit proxy settings, export them before starting DSH:
15
+
16
+ ```bash
17
+ export HTTPS_PROXY=http://127.0.0.1:7890 HTTP_PROXY=http://127.0.0.1:7890 ALL_PROXY=socks5://127.0.0.1:7890
18
+ ```
19
+
20
+ Replace the port with the correct local proxy port. An HTTP(S) or SOCKS proxy can also be configured per account in the DSH Antigravity panel.
21
+
22
+ ## Install and quick start
23
+
24
+ ```bash
25
+ # Install into the web profile
26
+ dsh plugin --profile web add dsh-agy-link
27
+
28
+ # Start DSH Web
29
+ dsh web
30
+ ```
31
+
32
+ In DSH, click the `AGY (n)` badge and choose **Add Account** to complete Google login in the browser. Alternatively run `/agy auth` to start primary-account login. Then choose an Antigravity model from `/model` and start chatting. Use `/agy status` to check status.
33
+
34
+ ## Features
35
+
36
+ - Account pool with isolated HOME environments and credentials.
37
+ - Sequential failover on HTTP 429 or quota exhaustion.
38
+ - Official five-hour and seven-day quota monitoring with reset countdowns.
39
+ - Text, thinking, and tool-activity streaming into native DSH UI cards.
40
+ - DSH sessions bound to native `agy` conversations through `--conversation`.
41
+ - Gemini, Claude, and GPT-OSS models available through the `antigravity` provider.
42
+ - Multimodal images staged locally and authorized to `agy` through `--add-dir`.
43
+ - `agy_ask` for delegating a one-off task to an Antigravity model.
44
+
45
+ ## Configuration
46
+
47
+ | Key | Environment variable | Default | Description |
48
+ | --- | --- | --- | --- |
49
+ | `enabled` | `DSH_AGY_ENABLED` | `true` | Plugin master switch |
50
+ | `agyBin` | `DSH_AGY_BIN` | auto-detected | Path to the `agy` executable |
51
+ | `permissionMode` | `DSH_AGY_MODE` | `skip` | `skip`, `plan`, or `accept-edits` |
52
+ | `defaultModel` | `DSH_AGY_DEFAULT_MODEL` | agy default | Default model slug |
53
+ | `defaultEffort` | `DSH_AGY_DEFAULT_EFFORT` | model default | `low`, `medium`, or `high` |
54
+ | `timeoutMs` | `DSH_AGY_TIMEOUT_MS` | `600000` | Activity watchdog timeout in ms |
55
+ | `workspaceRoot` | `DSH_AGY_WORKSPACE_ROOT` | session cwd | Workspace root |
56
+
57
+ ## `/agy` commands
58
+
59
+ `status`, `auth`, `models`, `mode`, `effort`, `workspace`, `clear`, `doctor`, and `help`.
60
+
61
+ ## Security and terms
62
+
63
+ The plugin invokes only the official, unmodified `agy` binary installed locally. Use it in accordance with Google Antigravity Terms of Service. Preserve commands, variables, model IDs, and paths literally when adapting this documentation.
64
+
65
+ ## License
66
+
67
+ MIT License.
@@ -0,0 +1,67 @@
1
+ # dsh-agy-link — Español
2
+
3
+ Integra modelos de Google Antigravity en DeepSeek Harness (DSH) mediante el CLI oficial y sin modificar `agy`. El plugin ofrece streaming, thinking, actividad de herramientas, uso de tokens, login OAuth desde la interfaz y monitor de cuota.
4
+
5
+ ## Requisitos
6
+
7
+ | Requisito | Verificación |
8
+ | --- | --- |
9
+ | DSH | `dsh --version` |
10
+ | Node.js >= 24 | `node --version` |
11
+ | Google Antigravity CLI | `agy --version` |
12
+ | Conectividad con Google | proxy/VPN/TUN cuando sea necesario |
13
+
14
+ En regiones donde Google no sea accesible directamente, habilite TUN/proxy del sistema. Si la terminal no hereda el proxy, expórtelo antes de iniciar DSH:
15
+
16
+ ```bash
17
+ export HTTPS_PROXY=http://127.0.0.1:7890 HTTP_PROXY=http://127.0.0.1:7890 ALL_PROXY=socks5://127.0.0.1:7890
18
+ ```
19
+
20
+ Sustituya el puerto por el de su proxy local. También puede configurar un proxy HTTP(S) o SOCKS por cuenta desde el panel Antigravity de DSH.
21
+
22
+ ## Instalación e inicio rápido
23
+
24
+ ```bash
25
+ # Instale el plugin en el profile web
26
+ dsh plugin --profile web add dsh-agy-link
27
+
28
+ # Inicie DSH Web
29
+ dsh web
30
+ ```
31
+
32
+ En DSH, haga clic en la insignia `AGY (n)` y seleccione **Add Account** para completar el login Google en el navegador. También puede ejecutar `/agy auth` para iniciar el login de la cuenta principal. Después seleccione un modelo Antigravity en `/model` y empiece a conversar. Use `/agy status` para comprobar el estado.
33
+
34
+ ## Funciones
35
+
36
+ - Pool de cuentas con entornos HOME y credenciales aislados.
37
+ - Failover secuencial cuando una cuenta recibe HTTP 429 o agota su cuota.
38
+ - Cuotas oficiales de 5 horas y 7 días con barras y cuenta regresiva.
39
+ - Streaming de texto, thinking y actividad de herramientas en tarjetas nativas de DSH.
40
+ - Sesiones DSH vinculadas a conversaciones `agy` mediante `--conversation`.
41
+ - Modelos Gemini, Claude y GPT-OSS elegibles desde el provider `antigravity`.
42
+ - Imágenes multimodales guardadas localmente y autorizadas a `agy` con `--add-dir`.
43
+ - Herramienta `agy_ask` para delegar una tarea puntual a un modelo Antigravity.
44
+
45
+ ## Configuración
46
+
47
+ | Clave | Variable de entorno | Predeterminado | Descripción |
48
+ | --- | --- | --- | --- |
49
+ | `enabled` | `DSH_AGY_ENABLED` | `true` | Activa/desactiva el plugin |
50
+ | `agyBin` | `DSH_AGY_BIN` | detección automática | Ruta al ejecutable `agy` |
51
+ | `permissionMode` | `DSH_AGY_MODE` | `skip` | `skip`, `plan` o `accept-edits` |
52
+ | `defaultModel` | `DSH_AGY_DEFAULT_MODEL` | predeterminado de agy | Slug del modelo predeterminado |
53
+ | `defaultEffort` | `DSH_AGY_DEFAULT_EFFORT` | predeterminado del modelo | `low`, `medium` o `high` |
54
+ | `timeoutMs` | `DSH_AGY_TIMEOUT_MS` | `600000` | Timeout del watchdog en ms |
55
+ | `workspaceRoot` | `DSH_AGY_WORKSPACE_ROOT` | cwd de la sesión | Raíz del workspace |
56
+
57
+ ## Comandos `/agy`
58
+
59
+ `status`, `auth`, `models`, `mode`, `effort`, `workspace`, `clear`, `doctor` y `help`.
60
+
61
+ ## Seguridad y términos
62
+
63
+ El plugin invoca solamente el binario `agy` oficial y sin modificar instalado localmente. Úselo conforme a los Términos de Servicio de Google Antigravity. Mantenga literales los comandos, variables, IDs de modelo y rutas al adaptar esta documentación.
64
+
65
+ ## Licencia
66
+
67
+ MIT License.
@@ -0,0 +1,67 @@
1
+ # dsh-agy-link — Português (Brasil)
2
+
3
+ Integre modelos Google Antigravity ao DeepSeek Harness (DSH) por meio do CLI oficial e não modificado `agy`. O plugin oferece streaming, thinking, atividade de ferramentas, medição de tokens, login OAuth pela interface e painel de quota.
4
+
5
+ ## Requisitos
6
+
7
+ | Requisito | Verificação |
8
+ | --- | --- |
9
+ | DSH | `dsh --version` |
10
+ | Node.js >= 24 | `node --version` |
11
+ | Google Antigravity CLI | `agy --version` |
12
+ | Conectividade com Google | proxy/VPN/TUN quando necessário |
13
+
14
+ Em regiões onde o Google não é acessível diretamente, use o modo TUN/proxy do sistema. Se o terminal não herdar o proxy, exporte antes de iniciar o DSH:
15
+
16
+ ```bash
17
+ export HTTPS_PROXY=http://127.0.0.1:7890 HTTP_PROXY=http://127.0.0.1:7890 ALL_PROXY=socks5://127.0.0.1:7890
18
+ ```
19
+
20
+ Substitua a porta pelo proxy local correto. Também é possível configurar um proxy HTTP(S) ou SOCKS por conta no painel Antigravity do DSH.
21
+
22
+ ## Instalação e início rápido
23
+
24
+ ```bash
25
+ # Instale o plugin no profile web
26
+ dsh plugin --profile web add dsh-agy-link
27
+
28
+ # Inicie o DSH Web
29
+ dsh web
30
+ ```
31
+
32
+ No DSH, clique no selo `AGY (n)` e selecione **Add Account** para concluir o login Google no navegador. Como alternativa, execute `/agy auth` para iniciar o login da conta principal. Em seguida, selecione um modelo Antigravity no seletor `/model` e comece a conversar. Use `/agy status` para verificar o estado.
33
+
34
+ ## Recursos
35
+
36
+ - Pool de contas com ambientes HOME e credenciais isolados.
37
+ - Failover sequencial quando uma conta recebe HTTP 429 ou esgota a quota.
38
+ - Quotas oficiais de 5 horas e 7 dias, com barras e contagem regressiva.
39
+ - Streaming de texto, thinking e atividade de ferramentas em componentes nativos do DSH.
40
+ - Conversas DSH vinculadas às conversas do `agy` por `--conversation`.
41
+ - Modelos Gemini, Claude e GPT-OSS selecionáveis no provider `antigravity`.
42
+ - Imagens multimodais armazenadas localmente e autorizadas ao `agy` por `--add-dir`.
43
+ - Ferramenta `agy_ask` para delegar uma tarefa pontual a um modelo Antigravity.
44
+
45
+ ## Configuração
46
+
47
+ | Chave | Variável de ambiente | Padrão | Descrição |
48
+ | --- | --- | --- | --- |
49
+ | `enabled` | `DSH_AGY_ENABLED` | `true` | Liga/desliga o plugin |
50
+ | `agyBin` | `DSH_AGY_BIN` | autodetectado | Caminho do executável `agy` |
51
+ | `permissionMode` | `DSH_AGY_MODE` | `skip` | `skip`, `plan` ou `accept-edits` |
52
+ | `defaultModel` | `DSH_AGY_DEFAULT_MODEL` | padrão do agy | Slug do modelo padrão |
53
+ | `defaultEffort` | `DSH_AGY_DEFAULT_EFFORT` | padrão do modelo | `low`, `medium` ou `high` |
54
+ | `timeoutMs` | `DSH_AGY_TIMEOUT_MS` | `600000` | Timeout do watchdog, em ms |
55
+ | `workspaceRoot` | `DSH_AGY_WORKSPACE_ROOT` | cwd da sessão | Raiz do workspace |
56
+
57
+ ## Comandos `/agy`
58
+
59
+ `status`, `auth`, `models`, `mode`, `effort`, `workspace`, `clear`, `doctor` e `help`.
60
+
61
+ ## Segurança e termos
62
+
63
+ O plugin chama somente o binário `agy` oficial e não modificado instalado localmente. Use-o em conformidade com os Termos de Serviço do Google Antigravity. Preserve literalmente comandos, variáveis, IDs de modelo e caminhos ao adaptar esta documentação.
64
+
65
+ ## Licença
66
+
67
+ MIT License.
@@ -13,9 +13,26 @@ Threat model and boundaries for dsh-agy-link.
13
13
  ## What it can do to your machine
14
14
 
15
15
  Whatever agy itself may do under the configured permission mode. **skip**
16
- (`--dangerously-skip-permissions`) grants unattended file writes and shell
17
- execution inside agy's workspace — treat it like giving any other agent
18
- skip-permissions. The GUI marks this mode red for a reason.
16
+ (`--dangerously-skip-permissions`) auto-approves ordinary AGY permission
17
+ prompts for unattended file writes and shell execution inside agy's workspace
18
+ — treat it like giving any other agent skip-permissions. It does **not** bypass
19
+ AGY hardcoded system protections. The GUI marks this mode red for a reason.
20
+
21
+ ## Headless permission behavior
22
+
23
+ The bridge forwards the configured `plan` or `accept-edits` mode to the
24
+ official `agy` process; it does not answer permission prompts or bypass them.
25
+ In a headless/print invocation, agy may automatically deny a tool request.
26
+ The bridge preserves that raw tool error in run status. Such an automatic
27
+ denial is **not** evidence that a person approved or denied a prompt.
28
+ Missing-file failures are reported as `missing_file`, not as approval outcomes;
29
+ hardcoded-system-protection failures remain distinct. Raw AGY tool error text
30
+ and its error result are preserved for replay.
31
+
32
+ Do not rely on undocumented wildcard behavior for `plan` or `accept-edits`.
33
+ Use a deliberately scoped workspace and test the exact commands and agy
34
+ version you intend to operate. `skip` remains an explicit unattended-execution
35
+ choice, not a fallback applied by this plugin.
19
36
 
20
37
  ## What it never touches
21
38
 
@@ -0,0 +1,239 @@
1
+ # Spec:GitHub Issue / PR Triage(2026-09-15)
2
+
3
+ 基线:`main` @ `8b14fc0`(v0.4.27)。本文件记录 open issues / PRs 的对应关系、修复方案、可合并性评估,以及提示词注入与安全审查结论。
4
+
5
+ ## 1. 审查方法与威胁模型
6
+
7
+ ### 1.1 方法
8
+
9
+ - 对 7 个 open issues、5 个 open PRs 拉取完整正文、diff、文件清单。
10
+ - 在临时目录独立 checkout 每个 PR head,执行 `npm run check` → `npm run build` → `npm test`(不信任 PR 正文自述的“N tests passed”)。
11
+ - 对照当前 `src/` 源码验证 issue 中的根因描述是否属实(而不是照抄 issue 里的补丁片段)。
12
+ - 检查 merge-base / conflict / 祖先关系,判断 PR 之间是否互相覆盖。
13
+
14
+ ### 1.2 提示词注入与不可信内容
15
+
16
+ Issue / PR 正文、评论、补丁建议均按**不可信数据**处理,遵循以下规则:
17
+
18
+ | 规则 | 说明 |
19
+ | --- | --- |
20
+ | 不执行正文中的指令 | 正文里出现的“请合并 / 请改权限 / 请跑某命令”一律不作为操作依据 |
21
+ | 补丁片段需对照源码与官方 API | 例如 issue #13 给出的 `windowsHide: true` 需对照 Node `child_process` 文档与本仓库实际 spawn 点 |
22
+ | 自述测试结果需复验 | 已在临时克隆中全部复验(见 §3) |
23
+ | PR 注入进 prompt 的文本需审查 | 见 PR #20 的 Recovery boundary(§3.3) |
24
+ | 文档/README 改动需防嵌套指令 | PR #17 为纯文档,已抽查命令与标识符未改语义 |
25
+
26
+ ## 2. 主分支基线
27
+
28
+ | 检查 | 结果 |
29
+ | --- | --- |
30
+ | `npm run check` | 通过 |
31
+ | `npm test` | 152/152 通过 |
32
+ | 分支保护 | 无(`main` 未设 protection) |
33
+ | CI | `.github/workflows/ci.yml` 在 `pull_request` 上跑 check/build/test;fork PR 首次常需 maintainer 批准,故多数 PR 显示 “no checks reported / UNSTABLE” |
34
+
35
+ `mergeStateStatus: UNSTABLE` 在本仓库**不等于**代码失败,而是 CI 未在 fork 分支上跑起来。可合并性以本地复验为准。
36
+
37
+ ## 3. Issue 对应关系与修复方案
38
+
39
+ ### 3.1 总览
40
+
41
+ | Issue | 类型 | 对应 PR | 状态 | 处置 |
42
+ | --- | --- | --- | --- | --- |
43
+ | #11 stdin 传输(32KB cmdline) | enhancement | 无 | 未修 | 与 #14 同根因,合并成一项 stdin 方案 |
44
+ | #12 `mcpBridge` 好用不 | question/enh | 无 | 功能已存在 | 文档答疑 + 可选稳定性增强 |
45
+ | #13 Windows CMD 窗口闪烁 | bug | 无 | 未修 | 小补丁,可快速合入 |
46
+ | #14 `spawn ENAMETOOLONG` | bug | 无 | 未修 | 高优先级;与 #11 一并做 stdin |
47
+ | #16 多语言文档 | docs | **#17** | PR 可合 | 合 #17 即可 close |
48
+ | #18 headless 权限拒绝 / replay 生命周期 | bug | **#20**(覆盖并优于 #15) | PR 可合 | 合 #20,close #15 |
49
+ | #19 插件 UI i18n | feat | **#21** | PR 可合 | 依赖新 peer,需审 |
50
+
51
+ ### 3.2 Issue #13 — Windows 控制台闪窗(可立即修)
52
+
53
+ **根因核验(属实)**:
54
+
55
+ 1. `src/host/oauth.ts:316-320` — `openBrowser` 的 `execFile('cmd.exe', …)` **未传** `windowsHide: true`。
56
+ 2. `src/index.ts:519` 与 `:545` — `pool/add`、`pool/open-terminal` 拉起 `cmd.exe /c start cmd.exe /k …` **未传** `windowsHide: true`。
57
+ 3. `runner.ts` 的 `startAgyProcess` / `killTree` **已有** `windowsHide: true`(v0.4.x 已修主路径);`mirror-tool.ts` 的 `execFileSync` 也有。issue 里第 3、4 点(agy 子进程 / git shim)在 bridge 侧已基本覆盖,残余在 agy 上游。
58
+
59
+ **修复方案(bridge 侧,低风险)**:
60
+
61
+ ```ts
62
+ // oauth.ts openBrowser — win32 分支
63
+ { windowsVerbatimArguments: true, windowsHide: true }
64
+
65
+ // index.ts pool/add 与 pool/open-terminal — win32 分支
66
+ execFile('cmd.exe', ['/c', 'start', 'cmd.exe', '/k', `set "HOME=${acc.dir}" && set "USERPROFILE=${acc.dir}" && agy`],
67
+ { windowsHide: true }, () => {})
68
+ ```
69
+
70
+ 注意:`open-terminal` 的**内层**可见终端仍会弹出(这是产品意图);要隐藏的是**外层**包装 CMD 的闪窗。
71
+
72
+ **验收**:Windows 上触发 openBrowser / pool/open-terminal,无额外一闪而过的黑框;内层交互终端仍可用。补 `windowsHide` 选项的单元断言(若现有测试有 spawn 包装点)。
73
+
74
+ ### 3.3 Issue #14 / #11 — `ENAMETOOLONG` 与 stdin 传输(高优先级)
75
+
76
+ **根因核验(属实)**:
77
+
78
+ - `src/host/adapter.ts:286`:`args.push('-p', opts.prompt)` 把整段 prompt(含 digest)塞进 argv。
79
+ - `src/host/oneshot.ts:120`:同样 `args.push('-p', prompt)`。
80
+ - Windows `CreateProcess` 命令行上限 ~32767 字符;走 `cmd.exe` 包装时(`runner.ts:214`,cmd-shim)还会再吃一层长度。
81
+ - issue #11 提出改 stdin,与 #14 同源。
82
+
83
+ **修复方案(建议一次做完)**:
84
+
85
+ 1. **探测 agy 是否支持 prompt-from-stdin**(`-p -` / `--stdin` / 管道写入;以当前 agy 1.2.x 文档与 `--help` 为准,实现前先探测,不要假设 flag 名)。
86
+ 2. **阈值策略**(稳健、可回退):
87
+ - argv 总长度 < 某阈值(建议 ~24KB,给 env/cwd/引号留余量):维持现状 `-p <prompt>`。
88
+ - 超过阈值且 CLI 支持 stdin:改为 `stdio: ['pipe','pipe','pipe']` + 写入 prompt 后 `stdin.end()`。
89
+ - 超过阈值且 CLI **不**支持 stdin:明确报错(带长度与建议),避免静默截断。
90
+ 3. **Windows cmd-shim 路径**:`viaCmd` 时拼接进 `/c` 的字符串同样受限;stdin 方案可绕过。若仍走 argv,应优先 `spawn(bin, args)` 直启(已有非 cmd 路径)并仅在必要时回退 cmd。
91
+ 4. **注意 `keepStdin` 语义**(`runner.ts:175`):当前非 keepStdin 会立刻 `stdin.end()`,因为 agy 在 pipe stdin 下会挂住(见注释)。引入 stdin-prompt 时必须区分“prompt 管道”与“挂着不用的 stdin”,避免复现挂死。
92
+ 5. **测试**:构造 >32KB prompt 的 fake-agy,断言 spawn 成功、prompt 内容完整到达;Windows 条件下跑 cmd-shim 路径。
93
+
94
+ **不建议**:仅加大 `digestMaxChars` 来规避——多轮对话仍会超限,且会丢上下文。
95
+
96
+ ### 3.4 Issue #12 — `mcpBridge` 现状答疑
97
+
98
+ **事实**:功能自 v0.2 起存在,默认 `mcpBridge: false`(`src/common/types.ts:105`)。实现见 `src/host/mcp-bridge.ts` + `src/host/bridge.mjs`;`docs/KNOWN-GAPS.md:12-17` 标注为 experimental。本地 E2E(`test/v02.test.ts`)覆盖 loopback endpoint、allowlist、stdio JSON-RPC。
99
+
100
+ **答复建议**(可直接回 issue):
101
+
102
+ - 可用,但是实验特性:loopback + token 守卫,向 workspace `.mcp.json` 注册 `dsh-tools`,禁用 `run_code`/`agy_ask`,可用 `mcpToolAllowlist` 收窄。
103
+ - 开启:配置 `mcpBridge: true` 或 `DSH_AGY_MCP_BRIDGE=1`。
104
+ - PR #20 还修了 dispose 期间 bridge 启动竞态与 `server.unref()`,合入后更稳。
105
+ - 若仍有问题,请附 `/agy doctor` 与 agy 版本。
106
+
107
+ ## 4. PR 可合并性评估
108
+
109
+ 本地复验结果(临时克隆,`check + build + test`):
110
+
111
+ | PR | 标题 | +/− | 本地结果 | 冲突 | 与 main 关系 | 结论 |
112
+ | --- | --- | --- | --- | --- | --- | --- |
113
+ | #15 | skip trailing snapshots + unref | +34/−15 | 152/152 | 无 | 落后 main 若干 release | **不要合**;被 #20 取代 |
114
+ | #17 | docs pt-BR/es/en | +205/−1 | 152/152 | 无 | 干净 | **可合** |
115
+ | #20 | headless denial + lifecycle + config | +418/−28 | 163/163 | 无 | 含 #15 的改进版 | **可合(带 review 意见)** |
116
+ | #21 | UI i18n zh/en/pt-BR/es | +511/−109 | 158/158 | 无 | 干净 | **可合(先审依赖)** |
117
+ | #22 | native toolview + agy-db | +1330/−7 | 173/173 | 无 | 干净 | **可合(带 review 意见)** |
118
+
119
+ ### 4.1 PR #15 — 建议 Close(被 #20 取代)
120
+
121
+ - 改动:`detectContinuation` 回跳时跳过**所有** `source.kind === 'plugin'` 消息 + unref timers/bridge。
122
+ - 问题:跳过任意 plugin 消息过宽——plugin 非 snapshot 形态可能携带指令/通知,误判 continuation 会复放错误 run。
123
+ - #20 已包含 unref 修复,并把 continuation 收窄为 **仅跳过 `source.form === 'snapshot'`**,语义更安全。
124
+ - 祖先关系:PR #15 **不是** #20 的 git 祖先(#20 重做/摘取而非 merge #15 分支)。
125
+ - **处置**:合并 #20 后评论并关闭 #15,致谢作者;不要两边都合。
126
+
127
+ ### 4.2 PR #17 — 可合并
128
+
129
+ - 纯文档:`README` 链接 + `docs/README.{en,es,pt-BR}.md`。
130
+ - 无运行时/依赖变更;命令与标识符保持字面量(抽查通过)。
131
+ - 对应 close #16。
132
+
133
+ ### 4.3 PR #20 — 可合并(优先 review 意见)
134
+
135
+ 关闭 #18。关键变更:
136
+
137
+ 1. **continuation**:仅跳过 `plugin + form==='snapshot'`;human / 外部 tool result / 未知形态仍为边界。
138
+ 2. **status 诚实性**:`onRun` 从 `{ok, code}` 改为 `{processOk, processCode, toolErrors[]}`,进程成功与工具失败分离。
139
+ 3. **config 优先级**:`resolveConfig` 层序 `[entry, overrides]` → `[overrides, entry]`,env 仍在最后最高优先(与注释 “Env wins last / ADR-13” 一致)。修的是 runtime 选择覆盖 Cordis entry 默认。
140
+ 4. **MCP lifecycle**:dispose 期间关闭启动中的 bridge;unref 后台 handle。
141
+ 5. **文档**:新增 `docs/HEADLESS-PERMISSIONS.md`,扩展 SECURITY-NOTES。
142
+
143
+ **Review 意见(合并前建议处理或明确接受)**:
144
+
145
+ | 级别 | 意见 |
146
+ | --- | --- |
147
+ | 应改/应确认 | `adapter.ts` 中 **Recovery boundary**:当 `binding !== undefined` **或** prompt 匹配 `/\b(missing\|not found\|enoent)\b/i` 时,向 prompt 追加一段英文系统指令。这是插件侧的**关键词驱动 prompt 注入**——“missing the bus”“TODO not found”都会触发;resumed turn 无条件追加也可能污染短回复。建议:仅在上一轮存在 `missing_file` 类 tool error(`classifyToolError` 已提供)时追加,且做成可配置/默认关闭;文案去掉 “global brain” 这类环境特定措辞。 |
148
+ | 应改 | `classifyToolError` 用英文正则分类,对 agy 本地化/改文案的错误字符串很脆。保留 raw error 已做对;分类仅用于 status 展示时要在 UI 标明 “heuristic”。 |
149
+ | 可选 | `HEADLESS-PERMISSIONS.md` 中的复现命令较长,确认不含真实私有路径(当前为 `/tmp/agy-shared-fixture`,OK)。 |
150
+ | API 变更 | `onRun` 形状变更会破坏任何外部依赖旧字段的消费者;本仓库内已改齐,CHANGELOG 需标注。 |
151
+
152
+ ### 4.4 PR #21 — 可合并(先审依赖)
153
+
154
+ 关闭 #19。关键变更:
155
+
156
+ - 新增 `src/client/locales.ts`(zh/en/pt-BR/es 字典 + placeholder 对齐测试)。
157
+ - `inject` 增加 `locale`;`package.json` 增加 **必选** peer `@deepseek-ai/dsh-client-locale`(`optional: false`)。
158
+ - `permission.skip` 文案改为“自动批准;AGY 内部保护仍生效”,与 #20 的安全叙事一致。
159
+
160
+ **Review 意见**:
161
+
162
+ | 级别 | 意见 |
163
+ | --- | --- |
164
+ | 应确认 | 将 `@deepseek-ai/dsh-client-locale` 设为 **非 optional peer**:旧版 DSH 宿主若无该包,安装/运行可能失败。建议 `optional: true` + 运行时探测,或文档写明最低 DSH 版本。 |
165
+ | 应确认 | 正文提到 “pre-existing LOCAL dsh-sound patch” 等本机环境补丁——与上游无关,勿带入。当前 diff 未包含,OK。 |
166
+ | 可选 | 字典为硬编码 `as const` 对象,无远程加载,无注入面。保持即可。 |
167
+
168
+ ### 4.5 PR #22 — 可合并(带 review 意见)
169
+
170
+ 大功能:原生 `agy_tool` 工具卡片 + 从 agy SQLite 恢复被 `filterToolParameters` 剥掉的完整参数。
171
+
172
+ **亮点**:mapper 在 `state === 'DONE'/'ERROR'` 时也 cut span,修无 output 丢卡片;toolview 纯 React + 主题 CSS 变量;版本 bump 0.4.28 + CHANGELOG。
173
+
174
+ **Review 意见(安全相关优先)**:
175
+
176
+ | 级别 | 意见 |
177
+ | --- | --- |
178
+ | 应改 | `agy-db.ts`:`join(AGY_DB_DIR, \`${conversationId}.db\`)` **未校验** `conversationId`。若上游事件被污染为 `../../.ssh/id_rsa` 等,存在路径穿越读文件风险。合并前应加白名单:`/^[A-Za-z0-9_-]{1,64}$/`(或同等严格规则),否则直接返回 null。 |
179
+ | 应改 | 依赖外部 `sqlite3` CLI:Windows 官方安装常无此命令。已有 graceful fallback,但应在 README/KNOWN-GAPS 写明“无 sqlite3 时 diff 降级”。 |
180
+ | 应确认 | 复制 DB + `-wal`/`-shm` 到 `tmpdir` 的并发与磁盘占用;`maxBuffer: 10MB` 是否足够大会话;失败时是否绝不抛到用户 turn。 |
181
+ | 可选 | protobuf “亚毫秒扫描器”是启发式字节扫描,非标准解码;对上游 payload 布局变更敏感。建议加注释与回归 fixture(已有部分测试)。 |
182
+ | 版本 | PR 自带 version 0.4.28 + CHANGELOG,合并策略与 #17/#20/#21 的版本节奏对齐(谁最后合谁负责 bump,或全部由 maintainer 统一 bump)。 |
183
+
184
+ ## 5. 建议合并顺序
185
+
186
+ ```text
187
+ 1. PR #17 (docs) — 无依赖,先合
188
+ 2. PR #20 (runtime fix) — 关 #18;close #15
189
+ 3. PR #22 (toolview) — 修 path 校验后合;或先合再开 follow-up 修
190
+ 4. PR #21 (UI i18n) — 确认 peer optional / 版本门槛后合
191
+ 5. 本地再合 Windows 小修 (#13) 与 ENAMETOOLONG/stdin (#14/#11)
192
+ ```
193
+
194
+ 冲突面:五个 PR 的 `merge-tree` 目前均无冲突标记,但 #20/#21/#22 都碰 `src/index.ts` / `src/host/adapter.ts` / `package.json`,**必须按序合并并在每步后跑 check+build+test**,不要并行 merge。
195
+
196
+ ## 6. 合并后仍待实现的修复(建议 issue/PR 跟踪)
197
+
198
+ 1. **#13 闪窗**:3 处 `windowsHide: true`(见 §3.2),半天内可完成。
199
+ 2. **#14/#11 stdin**:按 §3.3 做阈值 + stdin + Windows 直启;这是当前**最影响可用性**的 bug。
200
+ 3. **PR #20 Recovery boundary 收窄**(§4.3)。
201
+ 4. **PR #22 conversationId 白名单**(§4.5)。
202
+ 5. 可选:为 fork PR 启用 CI(`pull_request_target` 谨慎使用,或要求 first-time contributor approve),避免 UNSTABLE 误导。
203
+
204
+ ## 7. 明确不做的事
205
+
206
+ - 不因 issue 正文建议而放宽 `permissionMode`、不默认 `--dangerously-skip-permissions`。
207
+ - 不把 PR/issue 文档中的命令自动 copy 进仓库脚本。
208
+ - 不在未复验的情况下采信 “independent review PASS / N tests passed”。
209
+ - 不发布 npm / 不打 tag(遵循 AGENTS.md:必须 maintainer 明示)。
210
+
211
+ ## 8. 复验记录(摘要)
212
+
213
+ | 分支 | check | build | test |
214
+ | --- | --- | --- | --- |
215
+ | main | pass | (已有 dist) | 152/152 |
216
+ | pr-15 | pass | pass | 152/152 |
217
+ | pr-17 | pass | pass | 152/152 |
218
+ | pr-20 | pass | pass | 163/163 |
219
+ | pr-21 | pass | pass | 158/158 |
220
+ | pr-22 | pass | pass | 173/173 |
221
+
222
+ 复验环境:macOS,Node 由本机提供;PR #21/#22 因 `package.json` 变更使用 `npm ci`。fork CI 未跑不作为否决依据。
223
+
224
+ ## 9. 执行记录(2026-09-15 已完成)
225
+
226
+ | 步骤 | 结果 |
227
+ | --- | --- |
228
+ | Fork PR CI | 全部 `action_required` run 已 approve;CI 全绿。流程写入 `AGENTS.md`(GitHub 无公开 API 可关闭首次批准门) |
229
+ | PR #17 | 已合并 |
230
+ | PR #20 | 已合并;随后移除 Recovery boundary 关键词注入 |
231
+ | PR #15 | 已关闭(被 #20 取代) |
232
+ | PR #22 | 与 #20 冲突解决后合并;conversationId 白名单已加 |
233
+ | PR #21 | 与 #22 冲突解决后合并;locale peer 改为 optional + 运行时回退 zh |
234
+ | Issue #13 | 已修并关闭(`windowsHide: true`) |
235
+ | Issue #14 / #11 | 已实现 stdin stream-json 传输并关闭 |
236
+ | Issue #12 / #16 / #18 / #19 | 已关闭 |
237
+ | 最终验证 | `check` + `build` + **197/197 tests**;main CI success |
238
+
239
+ **未做(遵守 AGENTS.md)**:未 `npm publish`、未打 tag / GitHub Release。版本号为 `0.4.28`(含上述全部变更),等 maintainer 明示后再发。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-agy-link",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "description": "Google Antigravity (agy CLI) models for DeepSeek Harness — stream Gemini/Claude/GPT-OSS subscriptions into DSH with thinking, tool activity, token usage and in-GUI Google OAuth login.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  "peerDependencies": {
30
30
  "@deepseek-ai/cordis": "*",
31
31
  "@deepseek-ai/dsh-commands": "*",
32
+ "@deepseek-ai/dsh-client-locale": "*",
32
33
  "@deepseek-ai/dsh-llm": "*",
33
34
  "@deepseek-ai/dsh-tools": "*",
34
35
  "react": "^18.0.0"
@@ -40,6 +41,9 @@
40
41
  "@deepseek-ai/cordis": {
41
42
  "optional": true
42
43
  },
44
+ "@deepseek-ai/dsh-client-locale": {
45
+ "optional": true
46
+ },
43
47
  "@deepseek-ai/dsh-commands": {
44
48
  "optional": true
45
49
  },
@@ -52,6 +56,7 @@
52
56
  },
53
57
  "devDependencies": {
54
58
  "@deepseek-ai/cordis": "^4.0.1",
59
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
55
60
  "@deepseek-ai/dsh-commands": "0.1.2-rc.1",
56
61
  "@deepseek-ai/dsh-llm": "0.1.2-rc.1",
57
62
  "@deepseek-ai/dsh-tools": "0.1.2-rc.1",
@@ -67,7 +72,8 @@
67
72
  },
68
73
  "client": {
69
74
  "inject": [
70
- "slots"
75
+ "slots",
76
+ "locale"
71
77
  ],
72
78
  "platform": "web"
73
79
  }