makecindy / makecindy/cindy

[Feature] 灵动岛:主窗口聚焦且正在查看会话时,会话完成不播提示音,与开始提示音行为不对称

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

Description

### 现象

主窗口聚焦、且当前正在查看某个会话时:

- 该会话**开始运行**:灵动岛播放开始提示音 ✅
- 该会话**完成**:灵动岛**不播放**完成提示音 ❌

用户感知为「完成音时好时坏」,实际是聚焦 + 正在查看时被固定抑制。

### 复现步骤

1. 启用灵动岛及其声音(Settings → Agent Island,声音总开关开启,complete 事件配置了音效)。
2. 保持主窗口聚焦,停留在某会话页面。
3. 在该会话发送一条消息让 agent 运行 → 能听到开始音。
4. 保持聚焦并停留在该会话,等待其完成 → 听不到完成音。
5. 对照组:切到其它会话或让窗口失焦后再等完成 → 完成音正常播放。

### 源码定位

声音决策:`apps/desktop/src/main/agent-island/service.ts` 的 `getAgentIslandSoundEventForTransition()`(L1603-1633):

```ts
for (const session of next.sessions) {
if (!session.attention || session.phase !== 'completed') continue; // ← 完成音要求 attention
...
if (prev?.phase !== 'completed') return 'complete';
}
for (const session of next.sessions) {
if (session.phase !== 'running') continue; // ← 开始音不看 attention / 焦点
...
if (!prev || prev.phase !== 'running') return 'start';
}
```

完成时 `attention` 来自 `unread`,`unread` 由 smart suppress 决定:`apps/desktop/src/main/agent-island/state.ts` L1415-1418:

```ts
function shouldSmartSuppressSession(state, session) {
if (isPermissionApprovalSession(session)) return false;
return state.appFocused && state.visibleSessionIds.has(session.sessionId);
}
```

链路:会话完成 → `completeAgentIslandSession`(state.ts L1154-1184)→ 聚焦且正在查看该会话时 `shouldSmartSuppressSession` 返回 true → `unread=false` → display state 中 `attention=false` → `'complete'` 分支的 `if (!session.attention) continue` 直接跳过 → 完成音被抑制。

- `appFocused` 来源:`bootstrap-electron.ts` `syncAppFocusState()` → `service.ts setAppFocused`;
- `visibleSessionIds` 来源:renderer 上报当前查看的会话(`MainLayout.tsx` / `OrcaSplitView.tsx` / `WorkdirBrowseRoute.tsx`)。

例外:error 结束走 `forceUnread: true`(state.ts L598 附近),所以聚焦时错误音仍会响。

### 为什么归为体验优化而非 Bug

完成音的抑制是 smart suppress 的**有意设计**(用户正盯着该会话,完成状态已经看见,不额外打扰;同一机制也抑制灵动岛的自动展开)。但存在两点体验问题:

1. **不对称**:四类音中 attention / error / complete 三类都以 `attention` 为门槛,唯独 start 完全豁免且无注释说明——同一个正在查看的会话,「开跑」响、「跑完」不响,直觉相反(完成通常比开始更值得声音反馈)。
2. **不透明**:设置页配置了 complete 音效后没有任何提示说明「聚焦查看时不响」,用户容易误判为声音功能故障。

### 可选改进方向(供讨论)

- **方向 A(声音与 attention 解耦)**:聚焦查看时仍播完成音,仅保留对 reveal / 未读标记的抑制——smart suppress 只管「不打扰视觉」,不管声音。满足「听到任务跑完了」的即时反馈诉求。
- **方向 B(补齐对称)**:给 `'start'` 分支补上与 `shouldSmartSuppressSession` 等价的判断,聚焦查看该会话时开始音也不响,行为统一为「正看着的会话不出声」。
- **方向 C(可配置)**:在 Agent Island 声音设置中加「聚焦查看时是否静音」高级选项(需按 `docs/configuration-design-principles.md` 评估可见性层级)。

任一方向改动落点:`service.ts` 的 `getAgentIslandSoundEventForTransition` / `playSoundForDisplayTransition`,以及 smart suppress 与声音判定的解耦;改动为纯主进程逻辑,按仓规需同步补单测。

Contributor guide

Open the contributing guide

Research direction

Read getAgentIslandSoundEventForTransition() in apps/desktop/src/main/agent-island/service.ts together with shouldSmartSuppressSession() and completeAgentIslandSession() in state.ts. First resolve which sound behavior is intended among the proposed directions, then add the corresponding main-process tests and verify completion and start sounds for focused and visible sessions, including the error exception.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, typescript
Domain
desktop
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.