Skip to content

[Bug] chat_with_agent 调用链路无条件启动 FloatingChatService(悬浮窗+常驻通知);create_chat 的前置服务检查并非必需 #1208

Description

@hongyijiashen666

环境

  • Operit 1.12.1(源码 main @ fea1daa,2026-09-16)
  • 设备:小米 marble / MIUI V14(Android 13)
  • 场景:主 Agent 通过内置包 extended_chat 的 chat_with_agent 工具,让另一张角色卡(子代理)在独立会话中处理任务

现象

FloatingChatService 未运行时,AI 调用 chat_with_agent 会启动 FloatingChatService:

  1. 屏幕左上角出现 WINDOW 模式悬浮小窗(显示当前会话内容);
  2. 通知栏出现前台服务常驻通知「AI助手悬浮窗 / AI助手正在后台运行」;
  3. 用户关闭小窗后服务进程随窗销毁(onDestroy),下次调用 chat_with_agent 重复以上过程。

复现步骤

  1. 关闭悬浮窗(或等待系统回收后台),使 FloatingChatService 未运行;
  2. 对 AI 说「用子代理查一下 XX」,使其调用 chat_with_agent(不传 chat_id,触发新建会话路径);
  3. 观察:左上角弹出 WINDOW 小窗 + 常驻通知;日志中 FloatingChatService onCreate、模式 WINDOW。

根因分析(源码已全部定位,附 main 分支链接)

① chat_with_agent_impl 无条件启动服务(弹窗直接调用点)

app/src/main/assets/packages/extended_chat.js 约 L377:

await Tools.Chat.startService();   // 每次工具调用无条件执行

② 真正需要服务的只有 create_chat 工具的前置检查,而该检查并非必需

StandardChatManagerTool.kt 约 L1354-1362(createNewChat):

if (!ensureServiceConnected()) {
    return ToolResult(..., error = "Service not connected")
}

但检查通过后实际执行的是 core.createNewChat()——core 来自 ChatServiceCore(纯 Kotlin 核心,与悬浮窗服务无绑定)。UI 路径(主界面手动新建对话)直接调用同一 core,没有此检查,服务未运行时也能正常创建,可见该前置检查并非技术必需。

③ 发送消息链路完全不依赖 FloatingChatService

同文件 sendMessageToAIStream 约 L1721-1736:

val core = chatRuntimeHolder.getCore(runtimeSlot ?: ChatRuntimeSlot.FLOATING)
...
// 后台发送到指定对话,不切换 UI
core.sendUserMessage(...)

ChatRuntimeHolder(api/chat/ChatRuntimeHolder.kt)的 core 独立于服务运行。实测验证:FloatingChatService 已销毁(onDestroy)后向既有会话发送消息,消息仍正常送达并得到子代理完整回复。

④ 服务一旦启动必然可见(无 headless 模式)

因此工具链路中任何一次 startService 都必然造成可见的 UI/通知。

完整因果链

chat_with_agent(不传 chat_id)→ ① 插件无条件 startService(弹窗根源)。即便移除 ①,新建会话仍会被 ② 的前置检查拒绝——这就是插件被迫无条件启动服务的原因。但 ③ 证明消息收发无需服务,② 的检查又是非必需的:整条工具链路完全可以不触碰 FloatingChatService。

期望行为

工具路径(chat_with_agent / create_chat / send_message_to_ai)在服务未运行时也能完成「新建会话 + 发送消息 + 等待回复」全流程,不启动 FloatingChatService、不产生任何可见 UI/通知(与 UI 路径行为对齐)。

修复建议(任一即可,组合更佳)

  1. create_chat 工具移除 ensureServiceConnected() 前置检查,改用 chatRuntimeHolder.getCore(...) 获取 core(与 UI 路径一致);
  2. 修复 1 落地后,chat_with_agent_impl 可安全移除无条件 startService();
  3. 可选:为 FloatingChatService 提供 headless 启动参数(如 INITIAL_MODE=NONE),供程序化调用使用。

附:验证日志(2026-09-17,本机)

  • 06:23:32 调用 chat_with_agent → FloatingChatService onCreate,以 WINDOW 模式启动;
  • 06:31:58 手动关闭小窗 → WakeLock released → onDestroy(服务销毁);
  • 服务销毁后,同会话的子代理回复照常完成(证明 ③:发送链路不依赖服务)。

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions