Antigravity responses without a model field or a Model Selection event (subagents, ACP sessions) were imported as unknown. Recover the model from the native conversations/<id>.db: prefer the tiered model ID (field 21, matching Model Selection and pricing) and fall back to the base model name (field 19). The database is opened read-only, never waits on a writer, and keeps already recovered names when it cannot be read. Co-authored-by: Jason <farion1231@gmail.com>
17 KiB
Antigravity CLI(agy)接入 CC Switch
范围与现状
agy 是独立应用 ID,复用 CCS 的供应商、Skills、MCP、会话和用量页面。它与 Gemini CLI 的数据库标记、供应商选择和文件路径分别管理。此次在已有未完成实现上直接补齐;不迁移或覆盖 Gemini CLI 的配置。
| 功能 | 实现 | 数据来源 / 写入目标 |
|---|---|---|
| 供应商切换 | 官方登录切模型;第三方 Key 经「打开终端」用私有目录启动 | ~/.gemini/antigravity-cli/settings.json、~/.cc-switch/agy/<供应商>/ |
| 模型选择 | 手动填写、第三方 Gemini models API、当前本机 agy models |
config.model.name,兼容 env.GEMINI_MODEL |
| Token 信息 | 输入、输出、缓存读写;会话消息元数据和统一用量面板 | brain/<id>/.system_generated/logs/transcript_full.jsonl |
| MCP | 导入、编辑、独立启用/禁用、删除、重新同步 | ~/.gemini/config/mcp_config.json |
| Skills | 扫描导入、安装、启用/禁用、更新、迁移存储、卸载 | ~/.gemini/config/skills/<name>/ |
| 会话 | 列表、摘要、工作目录、消息预览、Token、恢复命令 | 只读 SQLite 索引和 JSONL 日志 |
本机 CLI 自带文档明确全局定制目录为 ~/.gemini/config/。公开迁移文档存在不同历史路径,因此本次以安装版本的内置文档和隔离 HOME 实测为准。参考:官方 MCP 说明、官方迁移说明。MCP 与 Skills 的全局目录可能被同机其他 Antigravity 产品共享,CCS 页面显示实际写入路径。
供应商、凭据和模型
供应商在 CCS 中继续使用兼容现有 Gemini 表单的数据结构:
{
"env": {
"GEMINI_API_KEY": "your-key",
"GOOGLE_GEMINI_BASE_URL": "https://your-gemini-endpoint"
},
"config": {
"model": { "name": "Gemini 3.1 Pro (High)" }
}
}
这是 CCS 的存储结构,并不原样写入 agy。agy 的 settings.json 里 model 只认显示名(如 Gemini 3.8 Flash (Low)),写模型 ID 会被静默忽略并回落到默认模型,所以两种模式都存显示名。
官方身份由分类或明确的官方预设标记决定;供应商名称含 Google 不会自动删除其 API Key。第三方供应商须兼容 Gemini 协议,不能将任意 OpenAI/Anthropic 端点直接当作 Gemini 使用。
agy 只从进程环境读 Key 和端点,不读取任何文件里的 Key,modelProvider 又是全局开关:写进真实 settings.json 后,没有带 Key 启动的 agy 会直接报错。所以两种卡分开处理:
- 官方登录卡:切换时只改真实
settings.json的model,并去掉modelProvider,主题、受信工作区等其他配置保留。登录凭据由 agy 自己保管(不在~/.gemini里),CCS 不读也不碰。在哪个终端运行agy都生效。 - 第三方 Key 卡:只在卡片「打开终端」启动的 agy 里生效。启动命令是
agy --gemini_dir=<私有目录>,私有目录为~/.cc-switch/agy/<供应商 ID>/:其中antigravity-cli/settings.json写modelProvider: "gemini"和模型(权限0600,不含 Key),config软链回~/.gemini/config(Windows 先试符号链接,失败时用目录联接),MCP、Skills 和提示词照常共享。会话也存在私有目录里,删除供应商不会删掉它。切换到 Key 卡时,真实settings.json只去掉modelProvider,模型不动,直接运行agy仍是官方登录。 - Key 怎么传:macOS / Linux 的启动脚本先读入一个
0600的临时文件,读完立即删除,再经env把 Key 和地址交给这一个 agy 进程;卡上没填地址时用env -u清掉用户 rc 里可能 export 的同名变量,以免被 rc 覆盖或误用。Windows 写进.bat的setlocal段,agy 退出后随endlocal撤掉;含非 ASCII 的路径按 #8034 的办法经环境变量转一手。Key 不出现在命令行参数里,也不写进任何常驻文件。 - 不改 shell 启动文件,也不装包装脚本。 #8268 的测试版装过
~/.gemini/antigravity-cli/bin/agy包装脚本、env文件和 shell PATH 片段,新版启动时会清理:只删带 CCS 标记的脚本、env文件和 PATH 片段(只剩该片段的文件整个删掉),然后按新规则把当前供应商重写一次,让modelProvider回到登录模式。没有标记的同名文件和用户的其他内容原样保留。 - 真实
agy的定位顺序(get_agy_models用):PATH(跳过旧版带标记的包装脚本)、~/.local/bin、/opt/homebrew/bin、/usr/local/bin,最后用登录 shell 执行一次command -v agy(限时 2 秒)。从 Dock / Finder 启动 CCS 时 PATH 只有系统目录,所以后几步不可省。「打开终端」按终端里的 PATH 找 agy,不用这个解析。 - 已经运行的 agy 进程不会热切换。
模型配置和当前供应商指针共用现有 AppWrite 操作日志。写入前验证 JSON;发布中断后使用已有恢复机制补完文件及指针。损坏配置不会按空文件重建;agy 还没写出 settings.json 时切到 Key 卡也不会替它创建空文件。
新增供应商遵循 CCS 原有生命周期,前端不再无条件追加一次切换。原生 settings.json 不存在时返回配置缺失,启动导入不会生成虚构的 default/current。agy 首次启动自己会写出不含供应商信息的 settings.json,这样的配置也不会被导入:只有带模型的配置才会作为 default 导入。全量同步(配置导入、云同步)对没有真实内容的当前供应商不执行任何写入。官方模型按钮读取当前本机 agy 配置;目标供应商尚未启用或尚未登录时仍可手工填入模型。
数据持久化和兼容性
数据库版本从 20 升至 21,为 mcp_servers、skills 分别增加 enabled_agy BOOLEAN NOT NULL DEFAULT 0。新建数据库与升级迁移均覆盖;其他应用的开关和数据不变。旧的导入 JSON 没有 agy 字段时默认关闭。
MCP 支持 stdio 和 Streamable HTTP,兼容导入旧 serverUrl,拒绝 agy 不支持的 SSE。禁用写 disabled: true,保留本地选项;删除仍启用于 agy 的服务器会移除对应原生条目。数据库的关闭标记不记录托管历史,因此删除未启用于 agy 的服务器时保留原生配置,即使同名禁用条目的传输字段完全相同;如需删除保留的禁用条目,应在 agy 中操作。切换传输方式时清理旧传输字段,保留非传输选项和未托管服务器。数据库提交失败会恢复原文件;重新同步不会因为数据库中的默认关闭标记而删掉未托管条目。
Skills 复用既有 SSOT、下载、链接/复制和备份机制,新增独立持久开关。对同名原生目录先核对内容和归属;外部修改不静默覆盖。更新使用暂存副本,数据库失败时恢复旧文件;显式切换也支持回滚。迁移存储时重定向托管链接,卸载前验证选中的原生副本,保留未启用的外部同名目录。
会话和 Token 语义
会话同时扫描 CLI 的 ~/.gemini/antigravity-cli/brain 与 Antigravity IDE 的 ~/.gemini/antigravity/brain(布局相同,各自带同级 conversation_summaries.db);缺失的目录会被忽略,同一会话 ID 只计一次。
会话列表以只读方式打开 SQLite,读取 conversation_summaries 的标题、预览、工作目录和时间。列表优先使用索引,避免每次刷新都解析所有正文;没有索引时回退解析 JSONL。只有二进制记录、没有可读日志的会话仍可展示摘要和恢复命令,不伪造正文。
JSONL 按 step_index 排序,同步骤重复写入取最后一条,容忍尾部未写完的数据。当前已实测 USER_INPUT、PLANNER_RESPONSE,其他步骤保留文本供预览。路径归属经过校验,目录中的链接不能将会话读取引向根目录外。
恢复命令为 agy --conversation=<id>。CCS 不删除 agy 会话,因为正文、二进制存储和摘要索引需由 agy 一起维护;界面和后端均明确要求在原应用中删除。
Token 用量只导入完成的模型响应。实测使用本地模拟 Gemini SSE 响应:输入总量 100、缓存 20、回答 5、思考 7,agy 导出的结果为:
input_tokens = 80:已经排除缓存,数据库明确标为 fresh input。cache_read_tokens = 20:单列展示,不从 80 再扣一次。output_tokens = 12:已经包含思考,不再额外累加 7。
该合成样例保存在 tests/fixtures/sessions/agy.jsonl,不含真实对话或凭据。用量按会话 ID+步骤 ID 去重,去重账本与明细一起事务提交;旧明细被保留策略清理后也不会重复导入。已完成步骤被改写时只更新仍然保留的明细。
用量模型优先取 JSONL 响应中的模型字段或该步骤之前的 Model Selection 事件。两者均缺失时(例如子代理会话),从同一 CLI、IDE 或私有目录下的 conversations/<id>.db 只读查询:通过 steps.metadata 的生成记录编号,读取对应 gen_metadata 中的模型名称:优先取带档位的完整 ID(如 gemini-4-argon-high,与 Model Selection 得到的 ID 一致,计价时剥掉档位;旧版若记的是显示名也按同样规则转换),没有时回退到基础模型名(如 gemini-3.8-flash-n)。Protobuf 仅解析关联和模型字段,不通过对话正文或 flash、pro 档位猜测模型。数据库忙或不可读时继续导入 Token,保留已经恢复的模型名称;后续同步可补全仍保留的 unknown 明细。
无法确定的模型仍记为 unknown。费用沿用现有模型价格表估算,不代表实际账单;查不到价格时为 0;只有基础模型名时,-n、-tiered 等原生后缀也沿用同一价格匹配规则,不按后缀推定价格。用量导入不从当前供应商反推历史模型,也不更改原生登录、订阅额度或计费。
验证
连通性检查对第三方 agy 供应商读取 env.GOOGLE_GEMINI_BASE_URL(沿用 Gemini 的提取规则),未设置时使用 https://generativelanguage.googleapis.com;官方登录供应商不提供检测目标。
新增测试覆盖迁移与新建数据库、独立开关、MCP 格式与失败回滚、Skills 原生文件保护及失败恢复、终端启动的 Key 传递(不进命令行、rc 里的同名变量不覆盖、临时文件读完即删)、Key 卡切换不写凭据也不碰 shell 文件、私有目录与共享 config 的软链、旧版包装脚本和 PATH 片段只删带标记内容、真实 agy 的多位置解析、连通性检查、配置事务中断恢复、会话路径验证、JSONL 重写/残缺尾部、原生 Token 语义和持久去重。
此外使用本机真实 agy,在临时 HOME 中验证 MCP add/disable 的原生格式、models 输出格式及本地模拟 SSE 请求。模拟端点运行在 127.0.0.1,凭据为固定测试值;不连接付费模型,也不修改实际登录状态。
可复查命令:
pnpm typecheck
pnpm test:unit
cargo test --manifest-path src-tauri/Cargo.toml --lib agy -- --test-threads=1
cargo test --manifest-path src-tauri/Cargo.toml --lib -- --test-threads=1
cargo fmt --manifest-path src-tauri/Cargo.toml -- --check
pnpm build:renderer
此次不增加 agy 本地代理、故障转移或 Stack 模式;这些能力要求单独适配数据平面,不能仅通过复用 Gemini UI 宣称可用。
原生联网复核与回归
补充复核发现并修复两处表单问题:
- agy 只有 API Key、未覆盖端点时,模型查询应使用
https://generativelanguage.googleapis.com,不能要求用户额外填写默认地址。 - agy 的模型输入框需要按后端相同的优先级读取
config.model.name,并在编辑时同步写回;否则旧的config.model.name会覆盖刚修改的GEMINI_MODEL。Gemini CLI 保持原有环境变量行为。
新增 src-tauri/src/agy_smoke_tests.rs 原生联网测试,默认 ignore,仅在明确授权调用 API 后手工运行。它要求 CCS_AGY_SMOKE_CONFIG 指向权限受限的临时供应商 JSON,CCS_AGY_SMOKE_BIN 指向真实 agy;测试本身不读取用户数据库。所有切换、文件、Skills 和会话写入均在临时 HOME 和临时工作目录中执行,结束后清理。
已使用真实 Gemini API 完成以下验证:
- 配置投影及当前供应商指针生效;按「打开终端」的方式(私有
--gemini_dir加子进程环境变量)启动的原生 agy 实际请求到配置的模型,CCS 写出的文件里都没有 Key。 - Skill 经 CCS 导入、禁用、重新启用后,被原生 agy 加载并返回预设标记
CCS_AGY_SKILL_OK。 - 原生 agy 识别 CCS 写出的 MCP 配置并完成本地测试服务的
initialize与tools/list;此测试验证连接和工具发现,不覆盖任意第三方 MCP 业务工具的执行。 - CCS 会话预览包含实际回答,导入完成响应的用量明细,重复导入不新增记录。
无界面 --print 模式不会弹出权限确认。Skill 若需要 read_file,必须有对应读取许可,否则 CLI 可能退出为成功、JSON 的 response 却为空并带有 denied_actions。测试仅为临时 Skill 的实际路径及 SSOT 路径授予精确读取许可,保留正常运行时的用户权限决策。
模型 ID 必须精确匹配所用接口。实测 Gemini API 接受 gemini-3.8-flash,而 gemini-3-8-flash 返回 404;不应通过全局替换连字符“修复”任意供应商模型名。原生 agy models 的档位别名与 Google API 模型列表也并不完全相同,表单按登录模式选择对应来源。
深链接导入
统一入口是 ccswitch://v1/import,agy 使用独立的 app=agy / apps=agy:
- 供应商:
resource=provider&app=agy,支持name、apiKey、endpoint、model、config与apiFormat=gemini_native。不支持 OpenAI/Anthropic 协议。确认框关闭「导入后立即切换」时只保存数据库,不创建原生配置;开启时走正常供应商切换。带 Key 的供应商导入后经卡片「打开终端」使用。 - 内联配置:
config是 Base64 编码 JSON,可用上文 CCS 的{env, config:{model:{name}}}结构,或扁平GEMINI_API_KEY、GOOGLE_GEMINI_BASE_URL(兼容GEMINI_BASE_URL)、GEMINI_MODEL。模型优先级为 URL 的model>config.model.name>GEMINI_MODEL。只提取密钥、地址、模型,其他环境变量与原生选项不导入;预览中的密钥打码。远程configUrl仍不支持。 - MCP:
resource=mcp&apps=agy;apps=agy,codex可同时指定多个应用。config为 Base64 编码的{"mcpServers":{...}}。同 ID 已存在时保留数据库中的服务器定义,仅合并应用开关,再走统一 MCP 同步;agy 不支持的 SSE 会报告导入失败。 - Prompt:
resource=prompt&app=agy,content为 Base64 Markdown,确认后保存到 agy 提示词列表;启用时使用既有 Prompt 路径解析和写入逻辑。 - Skills:
resource=skill&repo=owner/name&branch=main只添加所有应用共享的技能仓库,不下载或安装技能,也不会因附带app=agy自动启用。随后在 Skills 页面选择技能并为 agy 启用。
供应商示例(所有凭据都是占位值;链接参数需 URL 编码):
ccswitch://v1/import?resource=provider&app=agy&name=Antigravity&endpoint=https%3A%2F%2Fgenerativelanguage.googleapis.com&apiKey=YOUR_KEY&model=YOUR_MODEL&apiFormat=gemini_native&enabled=false
深链接供应商沿用现有 API Key 导入规则,需要密钥和端点;不通过链接导入或接管 OAuth 登录。会话预览、Token 统计和会话恢复不是导入资源,没有新增对应 resource 类型。
原生登录与 API 凭据
Key 和自定义地址均留空时保留 agy 自身登录;仅修改模型不要求 API Key。填写 Key 时可留空地址以使用 Google 默认端点;自定义地址需要非空 Key。编辑器中的设置只投影 agy 支持的字段,不会改动 Gemini CLI 全局配置。
原生登录模型名称
原生登录模式应使用 agy models 输出第二列的显示名(例如 Gemini 3.8 Flash (Low)),模型列表会填入该值。第一列 CLI 别名适用于命令行 --model;直接把别名保存到原生 settings.json.model 会静默回退默认模型。API Key 模式同样写显示名,而且只能选 agy 内置清单里的 Gemini 模型(如 gemini-2.5-flash 会被拒绝);agy 每次还会附带一个 gemini-3.1-flash-lite-preview 的辅助请求,第三方地址需要支持这些模型。