Skip to content

fix: Coordinate browser room session lifecycle#10

Open
jiejuncai-ly wants to merge 10 commits into
lex-mainfrom
migrate/adp-session-lifecycle
Open

fix: Coordinate browser room session lifecycle#10
jiejuncai-ly wants to merge 10 commits into
lex-mainfrom
migrate/adp-session-lifecycle

Conversation

@jiejuncai-ly

@jiejuncai-ly jiejuncai-ly commented Jun 11, 2026

Copy link
Copy Markdown

变更概述

本 PR 修复浏览器/raw-media 会话的启动与停止流程:把 participant token 生成和显式 agent dispatch 解耦,增加可取消的 room session 状态,并收紧 dispatch 重试时的 agent participant 匹配逻辑。目标分支是 lex-main

主要改动

1. Session lifecycle API

  • 新增服务端 session registry,让 dispatch、stop、LiveKit room 删除围绕同一个 sessionId 协调。
  • 将显式 agent dispatch 移到 /api/session/dispatch,支持重试、取消、dispatch 清理,以及 stop 抢先完成时的 LiveKit room 清理。
  • 新增 /api/session/stop 和共享 stop helper,让浏览器会话可以先释放本地 UI 状态,再等待较慢的远端清理。

2. 浏览器与 mixed input 客户端流程

  • 更新 room start 逻辑:生成可取消 session id、请求 connection details、dispatch 配置的 agent,并在复用 session 状态前等待 stop barrier。
  • 增加可复用的 stop/dispatch client,以及 browser raw-media session 的 room id 管理。
  • browser source 模式下默认启用浏览器视频媒体控制,同时保留 mixed source 的 role-specific 配置。

3. Dispatch 安全性与项目配置

  • 增加 room id 复用、session registry、stop payload、dispatch cancellation、本地 dispatch 配置和 browser media 默认值覆盖。
  • 收紧 isExpectedAgentParticipant:只有 LiveKit agent 属性匹配配置的 agentName 时才认为目标 agent 已加入,避免把无关的 agent-* identity 误判为目标 agent。
  • 更新 standalone 与 LexVoice integrated 模式的环境说明,并让 .env.example 保持 documentation-only。
  • 对齐 components.json 的 shadcn CSS 入口到 styles/globals.css,并加入项目配置测试防止路径漂移。

影响说明

  • browser source 启动时可以等待浏览器 participant 加入,再重试显式 agent dispatch。
  • stop 会先取消 in-flight dispatch,并在 room-input 清理后删除 LiveKit room,降低 stale room 和重复 agent 的竞态。
  • 更严格的 participant 匹配可能让缺少 lk.agent.name / lk.agent_name 属性的 agent dispatch 重试更久,但能避免无关 agent participant 造成假成功。
  • shadcn CLI 现在能读取当前项目的全局样式入口;.env.example 只作为文档样例,不再被测试要求承载 integrated runtime 配置。

验证

  • pnpm test

    ✅ passed: 37 tests passed

  • pnpm exec tsc --noEmit

    ✅ passed: TypeScript completed successfully

  • pnpm lint

    ✅ passed: ESLint completed successfully

  • pnpm build

    ✅ passed: Next.js production build completed successfully

  • pnpm exec prettier --check .

    ✅ passed: Prettier reported all matched files use the expected style

  • pnpm dlx shadcn@latest info --json

    ✅ passed: reports tailwindCss: "styles/globals.css"

@jiejuncai-ly jiejuncai-ly marked this pull request as ready for review June 12, 2026 11:06
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

Claude finished @jiejuncai-ly's task in 3m 22s —— View job


Code Review

  • 读取仓库配置
  • 分析 PR diff
  • 检查关键文件
  • 输出 review 结论

Review 结论

有条件通过

问题及建议

  • [P1] app-config.ts:140resolveInputDeviceConfigusesServerRoomInput 硬编码为 true,造成 primebot 模式下的 regression。原逻辑为 ['xunfei', 'generic'].includes(inputSource)primebot 原本是 false;现在变为 true,导致 buildDefaultVideoTracks(false, true) 跳过 system_camera_default 分支(lib:181: else if (!usesServerRoomInput)),使 primebotavailableVideoTracks 中丢失系统摄像头入口。建议恢复按 inputSource 判断,或在 resolveInputDeviceConfig 中为 primebot/mixed 保留正确的 usesServerRoomInput 值。Fix this →

  • [P1] app/api/session/session-registry.ts:3-4sessions Map 与 nextGeneration 是进程级内存状态。在 Vercel serverless / 多实例横向扩缩容部署下,/api/session/dispatch/api/session/stop 可能落在不同实例,导致 dispatch cancellation 和 stop barrier 完全失效(dispatchIds 为空、waitForRoomSessionDispatchesToFinish 立即返回)。建议在 README 中明确标注"需要单实例或 sticky-routing 部署",或在路由头部加 export const runtime = 'nodejs' 配合 long-polling 方案。

  • [P2] app/api/session/stop/route.ts:225-229runRemoteSessionCleanupstopRoomInputdeleteLiveKitRoom 串行执行。ROOM_INPUT_STOP_TIMEOUT_MS 默认 12s,若 room-input 服务超时则 LiveKit room 删除最多延迟 12s。两者无依赖关系,建议改为 Promise.allFix this →

  • [P2] app/api/session/session-registry.ts:195-210markRoomSessionStopped 仅将 state 设为 'stopped' 但不从 Map 中删除记录。长时间运行的服务会无限累积历史 session 条目,建议在 markRoomSessionStopped 中调用 sessions.delete(normalizedRoomName),或加一个 TTL 清理。

  • [P2] lib/session-stop-client.ts:170-178registerAgentSessionDispatch 每次都在 pendingStartPromise 上追加 .then() 链,重复开启/停止会线性累积 Promise 层数。可在每次 beginAgentSessionStart 时重置 pendingStartPromise = Promise.resolve() 来截断旧链。

  • [P2] components/app/view-controller.tsx:59-62handleStartCallawait waitForAgentSessionStop(),随即调用 startSession(),而 startSession 内部(useRoom.ts:174)也会再次 await waitForAgentSessionStop(),造成双重等待。逻辑上无害,但冗余;可考虑仅保留 useRoom.ts 侧的调用。


残余风险:serverless 部署下的跨实例 session 状态不共享(见 P1 #2);primebot 模式的视频轨道丢失(见 P1 #1)是两个合并前需确认的点。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant