feat(desktop): install and configure Antigravity ACP - #5164
Conversation
Reuse RuntimePolicy, Host setup operations and OAuth presentation for local macOS arm64 connection checks and Google sign-in. Add process cleanup, setup safeguards and branded Settings UI. Record the official account eligibility blocker for successful-login acceptance. Generated-by: Codex
Record successful official authentication, restart, retry and process cleanup. Update the local-only operation exclusion assertion and remove an unused public type export found by full repository checks. Generated-by: Codex
Preserve upstream protocol changes and assign Antigravity setup compatibility epoch 142. Record merged-tree validation and the independent successful Runtime rerun. Generated-by: Codex
Add pinned verified downloads through the existing setup lifecycle and proxy configuration. Save managed paths through Settings, retain native selection for existing installs, and simplify the setup layout. Cover download integrity, cancellation, cached reuse and stale configuration; record real installation acceptance. Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Queue projection may arrive before the previous send releases admission. Wait for the exact Send control before follow-up and steering keyboard actions. Generated-by: Codex
Keep setup browser presentation available across initialization and authentication while preserving regular OAuth timing. Record remaining continuous acceptance separately from implementation and CI. Generated-by: Codex
Record the user-approved reuse of the verified official program, successful authentication, cancellation of a live process and successful retry. Keep prior installation evidence separate. Generated-by: Codex
Keep installation and existing-program selection visible in the Program section. Show path confirmation only after selection, remove the redundant advanced foldout, and refresh current UI screenshots. Generated-by: Codex
Generated-by: Codex
The queue projection can render before the previous send releases admission, so an immediate Enter is ignored. Wait for the exact Send control before keyboard submissions.\n\nGenerated-by: Codex
Resolve the Host compatibility epoch at 144 to distinguish the combined Antigravity setup and Skill query protocol. Regenerate the Astryx surface inventory and refresh compatibility documentation. Generated-by: Codex
Astro-Han
left a comment
There was a problem hiding this comment.
Architecture: right seam. Installer, ACP child spawn/teardown, attempt admission and residency all live in Runtime Host (HostExternalAgentSetupCoordinator → withAcpConnection, acquireResidency('external-agent-setup'), beginDrain/close/releaseConnection, terminateProcessTree). The managed copy is a Host-owned directory under the Host state root; Desktop only sees the path through the setup projection and saves it via the existing set_external_agents mutation. Desktop main is limited to IPC, the oauth_presentation gate and the native picker. Proxy transport, RuntimePolicy revisioning, open_external presentation and process-tree termination are all reused, and nothing pre-commits a shape PR2 must fight: no backend/session/model types, and withAcpConnection (spawn → op → kill) can be split into open/close later without touching the coordinator. Solution is sound; the gaps below are all on failure/recovery paths.
P2 — A tampered or corrupted managed copy is unrecoverable from the UI
Reachability ②. installAntigravity treats an existing <state>/external-agents/antigravity/1.1.1 as immutable: packages/runtime-host/src/server/acp/antigravity-install.ts:65-71 rethrows integrity_failed on any mismatch, and antigravity-install.test.ts:90-95 pins it. Once one byte of agy_acp_server.par or the helper changes (disk error, a helper rewriting itself, a half-applied manual edit), both Install and Reinstall return integrity_failed forever; the only recovery is rm -rf on a directory the UI never names. The archive is hash-pinned, so replacing a mismatched copy with a freshly verified one cannot install anything unverified. Fix: when verifyInstallation(destination) fails, remove or rename the directory aside and fall through to the staged install; keep the reuse fast path for the match case. If the copy must stay immutable, add a distinct managed_copy_modified failure whose copy names the directory.
P3 — "Late results cannot replace changed configuration" holds only in the renderer
Reachability ②, narrow window. The Host compares expectedExecutable only at admission (external-agent-setup-coordinator.ts:102-104); the post-install save goes through applyHostPatchWithoutLane → updateRuntimePolicy (runtime-host-settings-ipc-main.ts:384-386), which is optimistic-retry and overwrites the current revision. The only guard is object identity on props.settings in external-agent-settings/page.tsx:188-196. Fine for PR1, but the PR body states it as a Host property. Either soften the claim, or let the install attempt capture the RuntimePolicy revision at admission and commit set_external_agents itself with that expectedRevision.
P3 — cleanup_failed drains the whole Host
Reachability ④, noted for blast radius only. onCleanupFailure calls retainUntilProcessExit() + requestDrain() (execution-composition.ts:1430-1433), so one leaked child from a Settings-page check takes every running session on the Host down. Marking setup unavailable for the process lifetime and logging the pid bounds the damage to the feature that caused it.
WorkHub E2E change
Test-only, not masking a product bug: packages/ui/src/composer.tsx:1267-1273 deliberately ignores Enter while sendPendingRef.current is set, and the click path already auto-waits; workhub-layout.spec.ts:354,372 gives the keyboard path the same wait. Unrelated to Antigravity, so give it its own commit.
Complexity
The six-module move into application/contracts/settings-presentation/ plus shims (~470 lines) is forced by the renderer-architecture check. Two things can go: docs/antigravity-acp-settings.md:49-67 and the login screenshot are PR evidence committed as docs (user docs are PR3 in #5103), and expectedStateHint in runtime-host-oauth-presentation.ts:94 is defensive only since the single-slot expectation already serialises attempts. Existing-program selection saving without validation is per #5103; the Host still validates at spawn (checkedFile), same trust level as shell.executable.
Tests: Host 66 / storage 71 / CLI 7 / Desktop 39 passed; the admission guard, per-file hash verification and the six-minute window each go red with their fix reverted. Compatibility epoch on the head is 144 over main's 142; the PR body's 143/141 is stale.
中文
架构:接缝正确。 安装器、ACP 子进程启动/回收、attempt 准入和 residency 都在 Runtime Host(HostExternalAgentSetupCoordinator → withAcpConnection、acquireResidency('external-agent-setup')、beginDrain/close/releaseConnection、terminateProcessTree)。托管副本是 Host state root 下 Host 自有的目录;Desktop 只通过 setup projection 拿到路径,再经现有 set_external_agents mutation 保存。Desktop main 只做 IPC、oauth_presentation 门禁和原生文件选择。代理传输、RuntimePolicy revision、open_external 展示、进程树终止全部复用,也没有预设会与 PR2 冲突的形状:没有 backend/session/model 类型,withAcpConnection(spawn → op → kill)以后可拆成 open/close 而不动 coordinator。方案成立;下面的缺口都在失败/恢复路径上。
P2 — 托管副本被篡改或损坏后 UI 无法恢复
可达 ②。installAntigravity 把已存在的 <state>/external-agents/antigravity/1.1.1 视为不可变:antigravity-install.ts:65-71 任何不匹配都抛 integrity_failed,antigravity-install.test.ts:90-95 还固定了这一行为。一旦 agy_acp_server.par 或 helper 变了一个字节(磁盘错误、helper 自改写、手工改到一半),Install 和 Reinstall 都永远返回 integrity_failed;唯一恢复办法是手动 rm -rf 一个 UI 从不显示的目录。归档是 hash 固定的,用新验证的副本替换不匹配的副本不会装进任何未验证内容。修法:verifyInstallation(destination) 失败时删除或改名挪开该目录,然后走 staged 安装;匹配时保留复用快路径。若坚持不可变,则新增 managed_copy_modified 失败码并在文案里指出目录。
P3 — “迟到结果不能覆盖已变更配置”只在 renderer 层成立
可达 ②,窗口很窄。Host 只在准入时比较 expectedExecutable(external-agent-setup-coordinator.ts:102-104);安装后的保存走 applyHostPatchWithoutLane → updateRuntimePolicy(runtime-host-settings-ipc-main.ts:384-386),乐观重试会覆盖当前 revision。唯一守卫是 external-agent-settings/page.tsx:188-196 对 props.settings 的对象同一性判断。PR1 可接受,但 PR 正文把它表述成 Host 属性。要么弱化表述,要么让安装 attempt 在准入时记录 RuntimePolicy revision,自己用该 expectedRevision 提交 set_external_agents。
P3 — cleanup_failed 会 drain 整个 Host
可达 ④,只因影响面记一笔。onCleanupFailure 调用 retainUntilProcessExit() + requestDrain()(execution-composition.ts:1430-1433),Settings 页一次检查泄漏一个子进程就会让该 Host 上所有会话退出。改成本进程生命周期内标记 setup 不可用并记录 pid,可把损害限定在引发它的功能内。
WorkHub E2E 改动
仅测试层面,没有掩盖产品 bug:packages/ui/src/composer.tsx:1267-1273 在 sendPendingRef.current 期间有意忽略 Enter,点击路径本来就会自动等待;workhub-layout.spec.ts:354,372 只是让键盘路径等同样的就绪。与 Antigravity 无关,请单独一个 commit。
复杂度
六个模块搬到 application/contracts/settings-presentation/ 加 shim(约 470 行)是 renderer-architecture 检查强制的。可去掉两处:docs/antigravity-acp-settings.md:49-67 和登录截图是当作文档提交的 PR 证据(用户文档按 #5103 属于 PR3);runtime-host-oauth-presentation.ts:94 的 expectedStateHint 纯属防御,单槽 expectation 已经串行化了 attempt。选择已有程序不验证即保存符合 #5103;Host 启动时仍会校验(checkedFile),信任等级与 shell.executable 相同。
测试:Host 66 / storage 71 / CLI 7 / Desktop 39 通过;准入守卫、逐文件 hash 校验、六分钟窗口三处在回退修复后各自变红。head 的兼容 epoch 是 144(main 为 142);PR 正文写的 143/141 已过期。
| // interoperability. Mismatches are rejected before domain commands are admitted. | ||
| export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 142 as const; | ||
| // 142: Invocable Skill queries expose missing and archived Session refusals explicitly. | ||
| export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 144 as const; |
There was a problem hiding this comment.
Head is 144 over main's 142, but the log now lists 142 twice and a 143 that never shipped. Collapse to 143 with one line ("Antigravity setup: RuntimePolicy externalAgents, external_agents.setup.* operations, managed install progress") and update the PR body, which still says 143/141.
(epoch 只需大于 main 的 142;合成一行 143,PR 正文同步。)
There was a problem hiding this comment.
Push back on lowering the epoch to 143, while accepting the history correction. The branch had already advertised 143 before it incorporated main epoch 142, whose Skill-query refusal contract is incompatible with those builds. Reusing 143 would therefore let different protocols claim compatibility, and the repository guard states that epochs never decrease. Commit 1c83548 keeps 144, corrects the 142/143 history, and adds a comment-only compatible-change declaration. The PR body now states 144 over main 142. (由 Codex 代为更新)
| if (!pending || !stateHint) { | ||
| throw new Error('Desktop has no matching OAuth presentation request'); | ||
| } | ||
| if (pending.expectedStateHint !== undefined && pending.expectedStateHint !== stateHint) { |
There was a problem hiding this comment.
expectedStateHint is defensive only: the single #pending slot already refuses a second expectation, so no other attempt can present into this one. Drop the parameter and the field; setup can rely on the existing attempt-scoped slot like model OAuth does.
(单槽已保证不串号,expectedStateHint 可删。)
There was a problem hiding this comment.
Push back: keep expectedStateHint. A single slot serializes current expectations but does not bind a late producer to the current generation. Attempt A can expire or cancel, attempt B can occupy the slot, and then a delayed URL from A can arrive; without the state check it would consume B and open the wrong URL. The rolling-lease regression in 1c83548 proves that an expired A cannot present into B. (由 Codex 代为更新)
|
Reworked from the reviewed Accepted and fixed:
Push back:
The WorkHub readiness fix remains isolated in test-only commit Validation: full build and typecheck; Biome lint/format; Desktop/UI Knip; renderer architecture; Astryx and Windows inventories; staged epoch guard; complete Core, Runtime Host, and Desktop compiled test suites; focused setup regression suites. All passed. Real Google/download acceptance was not repeated. (由 Codex 代为更新) |
Repair damaged managed installs through verified crash-recoverable replacement, clean interrupted staging, classify proxy credential failures, renew active OAuth presentation leases, and guard the post-install Settings write against concurrent configuration changes. Keep acceptance evidence in the PR and correct compatibility history without reusing epoch 143. Generated-by: Codex
91cad6d to
1c83548
Compare
|
Reworked the review follow-up from |
Summary
Refs #5103 — PR1.
Add Settings → External Agents for local macOS arm64 users to install the pinned official Antigravity ACP 1.1.1 distribution or choose an existing executable, check the connection, sign in with Google, cancel, and retry.
Managed installation uses the configured proxy, verifies the archive size/SHA-256 and both executable hashes, publishes under the Runtime Host state root, reuses a verified cache, repairs damaged copies only after verifying a replacement, recovers an interrupted directory exchange, and removes abandoned staging. A successful install is checked through ACP before its path is saved through Settings.
The post-install Settings mutation is conditional on the executable still matching the attempt's admission basis, so optimistic revision retries cannot overwrite a newer selection. Browser presentation uses the normal 30-second lease and is renewed only by polling for the same live setup attempt; terminal results, cancellation, presentation, or abandonment release the slot. Attempt/state matching rejects a late URL from an older attempt.
RuntimePolicy schema 4 migrates schemas 2/3. Compatibility epoch remains 144 over main's 142: branch builds already advertised 143 before they contained main's epoch-142 Skill-query refusal contract, so reusing 143 would falsely claim compatibility.
Scope stays limited to PR1 Settings setup. No task execution, session creation/restoration, model catalog, disk/PATH discovery, automatic upgrade, remote Host flow, or additional workspace package is added.
Review resolution
expectedStateHint: a late URL from expired attempt A must not consume attempt B's replacement slot.cleanup_failed: TERM/KILL have both failed and PR1 has no retained orphan supervisor that can safely own the surviving process.07af97634.Verification
The controlled review follow-up did not repeat the real Google login or full production download. Historical acceptance remains evidence for the earlier UI/build and is not presented as a new run.
UI evidence
Historical real Google login success
AI use
Tool(s) and scope: Codex implemented configuration, installation, setup lifecycle, Desktop UI, tests, review follow-up, and verification. Retain the
Generated-by: Codextrailers when squashing.Checklist