makecindy / makecindy/cindy

[Bug] iOS 错过模型可见性变更后继续展示 Mac 已隐藏模型

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

Description

## 问题描述

在 Cindy `v0.1.22` 中,Mac 端「设置 → 模型供应商」修改模型显示状态后,iOS 新建会话的模型列表可能没有同步最新可见性。用户反馈的复现现象是:Mac 端已将 CindyAI 的模型全部隐藏,tapsvx 仅显示 10 个模型,但 iOS 新建会话仍出现 Mac 端未显示的模型。

## 环境

- Cindy 版本:`v0.1.22`
- 控制端:iOS 新建会话
- 被控端:Mac,已通过 device-link 连接
- Mac 模型供应商设置:CindyAI 全部隐藏;tapsvx 显示 10 个模型

## 复现步骤

1. 在 Mac 端进入「设置 → 模型供应商」。
2. 将 CindyAI 的模型全部设置为隐藏,并确认 tapsvx 仅显示 10 个模型。
3. 让 iOS 在后台、弱网或断线期间错过供应商变更推送(`maker:provider:changed`),再回到前台或重新进入新建会话。
4. 打开 iOS 新建会话的模型选择器,观察模型列表。

## 实际行为

iOS 仍展示 Mac 端已经隐藏的模型,并且这些模型可能可以被继续选中创建会话。列表与 Mac 端的当前可见性设置不一致。

## 期望行为

iOS 新建会话应始终基于被控 Mac 的最新模型可见性快照;即使错过实时推送,在重新连接、回到前台或打开模型选择器时也应通过主动刷新或 revision 校验收敛,隐藏模型不应继续出现在可选列表中。

## 源码分析

当前源码的相关链路如下:

- `apps/mobile/src/device-link/deviceProvidersCache.ts:55-60` 命中 `deviceId` 缓存后直接返回,没有 TTL、revision 校验或强制刷新入口。
- `apps/mobile/src/device-link/useDeviceProviders.ts:60-68` 命中缓存后直接结束 effect,不会重新调用 `maker:listProviders`。
- `apps/mobile/src/device-link/DeviceLinkContext.tsx:663-678` 只有收到 `maker:provider:changed` 推送时才驱逐缓存并重拉供应商目录。
- `DeviceLinkContext` 的前台/重连 rehydrate 主要补齐会话、能力等快照,没有对供应商目录做同等的主动刷新;因此 iOS 在推送断档期间保留旧缓存时,重新进入选择器仍会读取旧的 `modelVisibilityOverrides`。
- `apps/mobile/src/session/providerModelSections.ts:6-10,116-133` 会按 `modelVisibilityOverrides` 过滤列表,但该快照一旦过期,过滤逻辑会稳定地产生错误结果。

这说明问题不在 Mac 端隐藏操作本身,而在 iOS 对供应商目录变更通知的缓存一致性依赖过强。

## 截图

Mac 端模型供应商设置:

![Mac 端模型供应商设置](https://github.com/user-attachments/assets/0fba9e29-043d-4085-892f-f250bf103e4a)

iOS 新建会话模型列表:

![iOS 新建会话模型列表](https://github.com/user-attachments/assets/0777c3ad-14ae-4b0c-94b1-177e4f729cee)

## 与现有 Issue 的边界

自定义供应商把 `transcribe`、`image`、`embedding`、`elevenlabs`、`voyage` 等非 chat 模型导入模型列表的问题已由 [#101](https://github.com/makecindy/cindy/issues/101) 跟踪。本 Issue 只跟踪「Mac 已隐藏模型在 iOS 因缓存未刷新而重新出现」的跨端可见性一致性问题,不重复 #101 的能力护栏议题。

## 验收标准

- Mac 端修改模型可见性后,iOS 在线且收到推送时,模型选择器及时移除已隐藏模型。
- iOS 在后台、断线或弱网期间错过推送后,重新连接、回到前台或打开新建会话时能主动刷新或校验 revision,不再展示过期模型。
- 供应商目录刷新仍保持按 `deviceId` 隔离、inflight 去重和旧版本被控端兼容,不引入跨设备或跨账号缓存串用。
- 为上述推送命中、推送丢失后恢复、缓存过期/刷新及模型过滤补充自动化测试。

Contributor guide

Open the contributing guide

Research direction

Start with apps/mobile/src/device-link/deviceProvidersCache.ts and useDeviceProviders.ts, then trace DeviceLinkContext.tsx rehydration and provider-change handling. Check providerModelSections.ts to understand how stale modelVisibilityOverrides affect filtering. Done means missed provider-change events converge after reconnect, foregrounding, or opening the selector, with automated coverage for refresh, deduplication, device isolation, and filtering.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, react-native, typescript
Domain
mobile, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.