state — 流式状态和工具栏状态#
源码:src/cclark/state.py
每个频道的流式状态和工具栏状态的模块级全局注册表。 不跨重启持久化(仅内存)。
VerboseChannelState#
追踪一个飞书频道的活跃流式卡片和回合进度:
@dataclass
class VerboseChannelState:
streaming_card_id: str | None # 实时卡片的 message_id
last_flush_ms: float # 上次刷新的单调时间戳
turn_states: dict[str, VerboseTurnState] # 按 user_id 为键
``VerboseTurnState``(嵌套)#
@dataclass
class VerboseTurnState:
last_turn_index: int # 用户已看到的最大 turn_index
pending_text: str # 自上次刷新以来积累的文本
ToolbarState#
@dataclass
class ToolbarState:
toolbar_card_id: str | None # 显示中的工具栏的 message_id
toolbar_window_id: str | None # 工具栏所附着的窗口
全局注册表访问器#
_verbose_states: dict[str, VerboseChannelState] # 按 channel_id 为键
_toolbar_states: dict[str, ToolbarState] # 按 channel_id 为键
get_verbose_state(channel_id) → VerboseChannelState
get_toolbar_state(channel_id) → ToolbarState
reset_channel_state(channel_id) # 取消绑定时清除两者
持久化#
此模块**不持久化**。流式状态和工具栏状态在重启后从网关事件重建。
cards/streaming.py 中的 VerboseCardStreamer 是主要消费者。
VerboseCardStreamer 使用 get_verbose_state 来:
检查流式卡片是否已存在(
streaming_card_id)在后续刷新时 patch 它而非创建新卡片
存储上次刷新时间戳用于防抖计算
调用栈#
流式卡片 — 首次刷新(新卡片)#
VerboseCardStreamer.push("hello", turn_index=0)
→ turn_index 变化? → _flush()
→ _pending = ["hello"]
→ _pending_chars = 5
→ self._state.last_flush_ms = now
→ _build_card("hello") → card_json
→ client.send_interactive_card(channel_id, card_json)
→ POST /im/v1/messages → message_id = "om_xxx"
→ self._state.streaming_card_id = "om_xxx"
流式卡片 — 第二次刷新(patch)#
VerboseCardStreamer.push(" world", turn_index=0)
→ _pending = ["hello", " world"], _pending_chars += 6
→ 定时触发 _flush()
→ text = "hello world"
→ _state.streaming_card_id 已设置
→ client.patch_message("om_xxx", card_json)
→ PATCH /im/v1/messages/om_xxx → 更新卡片
新回合 — 新的流式卡片#
VerboseCardStreamer.push("next turn", turn_index=1)
→ turn_index 变化(0 → 1)
→ _flush() → 发送回合 0 的卡片,设置 streaming_card_id = None
→ self._turn_index = 1
→ push 添加到新 _pending
→ 下次刷新 → 新卡片通过 send_interactive_card() 发送