Skip to content

[Channel RFC] Lark adapter migration (LarkPlatformAdapter → LarkChannelAdapter + group chat + streaming) #261

@eanzhao

Description

@eanzhao

Parent RFC: #254
Implementation PR: #288
Wire-through follow-up: #294

Scope

LarkPlatformAdapter 迁移到 LarkChannelAdapter(新抽象 + 群聊支持 + PR #241 streaming 重接)。本 issue 的终点是 adapter 完整落地 + Lark inbound host path 切到新架构 + Day One 流在新架构下跑通。出站链路的最后一公里 wire-through 转入 follow-up #294,以便聚焦 Day One 体验和 RFC #254 主干推进。

Deliverables (shipped in PR #288)

Package: agents/channels/Aevatar.GAgents.Channel.Lark

Main class: LarkChannelAdapter : IChannelTransport, IChannelOutboundPort

  • 单类同时实现两个 interface(RFC §5.4 硬约束)
  • 迁移自现有 LarkPlatformAdapter
  • lifecycle / inbound stream / update / delete / capabilities / continue conversation / streaming reply 方法全部就绪

Composer: LarkMessageComposer : IMessageComposer<LarkOutboundMessage>

  • 迁移自现有 FeishuCardHumanInteractionPort 的卡片模板
  • intent → Lark Interactive Card JSON(schema 2.0 body-wrapped)

新增能力(相比现状):

  • 群聊支持
    • LarkChannelAdapterchat_type 构造 ConversationReference(DM → lark:dm:{open_id},Group → lark:group:{chat_id}
    • actor 层从 sender-keyed ChannelUserGAgent 换为 canonical-keyed ConversationGAgent(actor id = channel-conversation:{canonical_key},由 ConversationDispatchMiddleware 创建)
  • Streaming reply(复用 PR Stream Lark bot replies progressively as LLM deltas arrive #241 Lark 卡片 stream patch):

Webhook handler 改造 ✅:

  • verify signature + payload encryption(含 5min 时间戳窗口 + 明文 encrypt_key fail-closed)
  • 顺序钉死: verify → redact → commit to durable inbox → 200(对齐 §9.5.2)
  • Durable inbox:LarkConversationInboxRuntime + IStreamProvider,取代原 IMemoryCache 易失 dedup
  • Dedup 权威:ConversationGAgent.State.ProcessedMessageIds(cap 10000,actor 单线程串行)
  • PayloadRedactor.RedactAsync fail-closed(§9.6.1);抛异常返回 503

Credentials 迁移:

Capability declaration ✅:

  • ChannelCapabilities.SupportsEphemeral = false / SupportsModal = false / SupportsThread = true / Streaming = Native

Acceptance

Deferred to #294

重点聚焦 Day One 体验和 RFC #254 主干,以下 wiring 不在本 issue scope 内收尾:

  • LarkConversationTurnRunner 出站切到 IChannelOutboundPort.BeginStreamingReplyAsync
  • Bot tenant_access_token 解析 / 刷新决策(直连 vs Nyx proxy,需 ADR)
  • ConversationGAgent turn continuation 化(LLM 生成从 actor 单线程解耦)
  • 非 text 入站(image / file / sticker / post / rich text):要么类型化接入,要么显式声明不支持
  • Ephemeral disposition capability 如实上报(当前静默降级为 Normal)
  • Region / domain 可配置化(feishu.cnlarksuite.com

Out of scope

References

  • RFC §10.1 Lark (agents/channels/Aevatar.GAgents.Channel.Lark)
  • RFC §5.2b ConversationReference.LarkGroup
  • RFC §5.6 StreamingHandle

Dependencies

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions