Skip to content

feat(messaging): 实现 Worker Stdio Session Control(用户指令透传) #21

@hrygo

Description

@hrygo

实现 Worker Stdio Session Control(用户指令透传)

概述

实现 Worker-Session-Control-Spec.md 中定义的 10 个 worker stdio 命令,
让用户通过 Slack/飞书平台使用 /compact/context/clear 等原地操作指令,
无需杀进程重启。

Spec: docs/specs/Worker-Session-Control-Spec.md
验证脚本: scripts/test_cc_context.py(10/10 命令已在 CC 协议层验证通过)

动机

现状 问题
/reset = 杀进程 + 新建 延迟 5-10s 冷启动,丢失 session 连续性
无 context 可见性 用户无法感知 token 消耗,直到 API 报错
无法原地压缩 对话变长后只能全量 reset,浪费已有上下文

架构

现有 Control Command(进程级):
  Messaging → ParseControlCommand → SM.Transition() → Worker.Terminate()
  特征:改变 session 状态,进程重启/终止

Worker Stdio Command(协议级):
  Messaging → ParseWorkerCommand → handleWorkerCommand → Worker.Input/SendControlRequest
  特征:session 状态不变,stdin/stdout 原地交互

实施阶段

Phase 1: 类型定义(无外部依赖)

  • pkg/events/events.go
    • 新增 ContextUsage / MCPStatus / WorkerCommand EventType
    • 新增 WorkerStdioCommand 类型(10 个常量:StdioContextUsage, StdioMCPStatus, StdioSetModel, StdioSetPermMode, StdioCompact, StdioClear, StdioModel, StdioEffort, StdioRewind, StdioCommit
    • 新增 IsPassthrough() 方法
    • 新增 WorkerCommandData / ContextUsageData / MCPStatusData struct
    • 新增 ContextCategory / ContextSkillInfo struct

Phase 2: Messaging 层命令解析(无外部依赖)

  • internal/messaging/control_command.go
    • 新增 WorkerCommandResult struct
    • 新增 workerSlashMap(10 项 slash 命令映射)
    • 新增 workerNLMap(14 项自然语言触发映射)
    • 新增 ParseWorkerCommand() 函数
    • ParseControlCommand 优先于 ParseWorkerCommand

Phase 3: Claude Code Worker — ControlRequester

  • internal/worker/claudecode/control.go

    • 新增 pendingRequests map(map[string]chan map[string]any
    • 新增 SendControlRequest() — 发送 control_request 到 CC stdin,等待 control_response
    • 新增 DeliverResponse() — 路由 control_response 到 pending channel
    • readOutput 中新增 control_response case,调用 DeliverResponse
  • internal/worker/claudecode/worker.go

    • 新增 SendControlRequest() 方法(委托到 control.SendControlRequest
  • internal/worker/claudecode/mapper.go

    • 新增 mapContextUsageResponse() — CC JSON → ContextUsageData
    • 新增 mapMCPStatusResponse() — CC JSON → MCPStatusData

Phase 4: Gateway Handler 集成

  • internal/gateway/handler.go
    • 新增 handleWorkerCommand() 方法
    • 支持路径 A(Passthrough):6 项命令 → worker.Input("/compact", nil)
    • 支持路径 B(Control Request):4 项命令 → SendControlRequest() + broadcast response
    • Handle() 中新增 WorkerCommand event type 分发

Phase 5: OpenCode Server Worker(可与 Phase 4 并行)

  • 新增 internal/worker/opencodeserver/commands.go

    • ServerCommander 结构体(嵌入 HTTP client)
    • 实现 ControlRequester 接口:SendControlRequest() 委托到 HTTP REST
    • 实现 WorkerCommander 接口:Compact() / Clear() / Rewind()
    • queryContextUsage() — 聚合 message tokens
    • setModel() / setPermissionMode()
  • internal/worker/opencodeserver/worker.go

    • 嵌入 ServerCommander
    • 实现 ControlRequester / WorkerCommander 接口

Phase 6: Messaging 平台渲染

  • internal/messaging/feishu/adapter.go

    • context_usage 事件渲染为 CardKit 互动卡片
    • mcp_status 事件渲染为 CardKit 互动卡片
  • internal/messaging/slack/adapter.go

    • context_usage 事件渲染为 Block Kit
    • mcp_status 事件渲染为 Block Kit

测试

  • control_command_test.go:新增 ParseWorkerCommand 测试(10 项 slash + 14 项 NL + 优先级验证)
  • claudecode/control_test.goSendControlRequest + DeliverResponse 路由测试
  • claudecode/mapper_test.gomapContextUsageResponse + mapMCPStatusResponse 测试
  • gateway/handler_test.gohandleWorkerCommand passthrough + control_request 测试
  • opencodeserver/commands_test.go:HTTP mock 测试(若可行)

能力矩阵

命令 分类 CC OpenCode Server
/context Control Request 4/4 3/4(mcp_status 间接)
/mcp Control Request ⚠️ 间接
/model <name> Control Request + Passthrough ✅(per-message)
/perm <mode> Control Request
/compact Passthrough
/clear Passthrough ✅(session 重建)
/effort <level> Passthrough ❌ 不支持
/rewind Passthrough ✅(更强,含文件回退)
/commit Passthrough
自然语言 NL 触发

风险

风险 概率 影响 缓解
CC idle 时 get_context_usage 不响应 挂起 30s ctx 超时兜底
OpenCode clear 重建 session ID 变化 连接断开 clear 后需通知 Gateway 更新 session 映射
/commit 在自动化上下文误触发 git 污染 仅对授权用户开放
pendingRequests map 内存泄漏 内存泄漏 ctx cancel 时清理;response 后 delete
/rewind CC 只回退对话不回退文件 用户困惑 渲染时明确提示范围

参考资料

  • Spec: docs/specs/Worker-Session-Control-Spec.md
  • 验证脚本: scripts/test_cc_context.py
  • 相关已实现: internal/messaging/control_command.go(现有 ParseControlCommand

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementFeature: new capabilities or improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions