makecindy / makecindy/cindy

[Bug] 运行时 manifest 获取失败时,已安装运行时仍无法离线启动

Open
#3,042 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
2.7k
Forks
401
Avg merge
21h 48m
Merged PRs (30d)
776

Description

## 问题描述

macOS arm64 正式版 Cindy 在启动阶段获取运行时 manifest 失败时,即使本机已经安装并通过校验 Claude Code、Codex、Pi 和内置 ripgrep,仍会停留在 Splash 页面,只显示“环境初始化失败”和“重试”,无法进入应用。

这会把“启动时暂时无法访问 CDN / 代理隧道失败”和“本地运行时确实损坏”混成同一个阻断错误。

## 环境

- Cindy 版本:0.1.38(本地正式打包版本)
- 平台:macOS 26.5.1,Apple Silicon(arm64)
- 当前线上 manifest 的运行时版本:
- Claude Code 2.1.219
- Codex 0.145.0
- Pi 0.83.0
- 安装方式:macOS 正式打包版本

## 复现步骤

1. 保留已经安装好的运行时二进制,确保对应目录中存在 `.verified` 标记。
2. 让 Cindy 启动时无法通过 Electron 网络层获取 `manifest-darwin-arm64.json`,例如代理隧道失败或临时断网。
3. 启动 Cindy。
4. 观察 Splash 页面。

## 实际结果

页面停留在:

> 环境初始化失败

只有“重试”按钮,没有失败组件、错误码、manifest 状态或离线启动选项。重试会重复进入相同流程。

本次日志中的关键记录:

```
[clientEndpoints] fetch failed (ERR_TUNNEL_CONNECTION_FAILED | net::ERR_TUNNEL_CONNECTION_FAILED) for https://hotfix.cindy.app/cindy/endpoint.json
[clientEndpoints] starting with cached endpoint manifest automatically after network failure
[updateService] Manifest fetch failed, falling back to local patch
```

本机检查确认以下运行时文件存在、具有可执行权限,并且可以直接执行版本检查:

- Claude Code 2.1.219
- Codex 0.145.0
- Pi 0.83.0
- 内置 ripgrep 15.1.0

因此这次不是“运行时文件不存在”或“二进制无法执行”,而是启动链把在线 manifest 获取失败升级成了环境初始化失败。

## 期望结果

1. 如果本地已有通过 `.verified` 校验的运行时,启动时应允许离线进入应用,manifest 更新放到后台重试。
2. 如果确实必须在线获取 manifest,应明确显示:
- 是 manifest 获取失败还是二进制准备失败;
- 失败的 agent / 组件;
- 错误码和网络原因;
- 可执行的恢复方式。
3. Pi 是可选运行时,Pi 准备失败不应阻断 Claude/Codex 主流程。

## 初步源码定位

当前实现存在两个问题:

1. `apps/desktop/src/main/agent-binaries/factory.ts` 的 `prepare()` 在本地没有内存 manifest 时直接调用 `fetchManifest()`;获取失败就返回 `manifest_failed`,不会先根据本地已验证版本启动。
2. `apps/desktop/src/renderer/contexts/EnvCheckContext.tsx` / `hooks/useSplash.ts` 将 `allPassed === false` 统一映射为 `splash_failed`,而 `SplashScreen.tsx` 对该状态只渲染通用标题和“重试”按钮,没有展示 `EnvCheckResult` 中已有的错误详情。

相关代码:

- https://github.com/makecindy/cindy/blob/main/apps/desktop/src/main/agent-binaries/factory.ts
- https://github.com/makecindy/cindy/blob/main/apps/desktop/src/main/bootstrap-electron.ts
- https://github.com/makecindy/cindy/blob/main/apps/desktop/src/renderer/contexts/EnvCheckContext.tsx
- https://github.com/makecindy/cindy/blob/main/apps/desktop/src/renderer/hooks/useSplash.ts
- https://github.com/makecindy/cindy/blob/main/apps/desktop/src/renderer/components/splash/SplashScreen.tsx

## 建议验收标准

- [ ] 已验证的本地 Claude/Codex 运行时在 manifest 暂时不可用时仍可启动。
- [ ] manifest 不可用时不覆盖或删除现有可用运行时。
- [ ] 环境检查失败页显示具体组件、错误码和恢复建议。
- [ ] 网络失败、manifest 缺字段、下载失败、二进制损坏分别显示不同状态。
- [ ] Pi 失败继续保持非阻断降级。
- [ ] 增加断网 / 代理隧道失败场景的启动测试。

Contributor guide

Open the contributing guide

Research direction

Start with prepare() in apps/desktop/src/main/agent-binaries/factory.ts, then trace the result through bootstrap-electron.ts, EnvCheckContext.tsx, useSplash.ts, and SplashScreen.tsx. Check how manifest failures and allPassed are represented before running or adding startup tests for offline and tunnel-failure cases. Done means verified local runtimes can start offline, failure details are shown distinctly, existing runtimes remain intact, and Pi remains non-blocking.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, typescript
Domain
desktop, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.