feat: implement channel runtime connectors
This commit is contained in:
@ -13,19 +13,19 @@ ChannelConnector
|
||||
-> install / auth / QR / OAuth / credential validation / login state
|
||||
-> ChannelConnectionStore
|
||||
-> ChannelRuntime
|
||||
-> ChannelAdapter
|
||||
-> ChannelAdapter or ExternalConnectorChannel
|
||||
-> MessageBus
|
||||
-> AgentService
|
||||
```
|
||||
|
||||
The existing `ChannelRuntime`, `MessageBus`, `ChannelManager`, and `ChannelAdapter` contracts remain the message routing core. The new connector layer owns user-visible setup and connection lifecycle.
|
||||
The existing `ChannelRuntime`, `MessageBus`, `ChannelManager`, and `ChannelAdapter` contracts remain the message routing core. The new connector layer owns user-visible setup and connection lifecycle. For platforms backed by predeclared sidecar services, Beaver should expose the sidecar to the runtime as an `ExternalConnectorChannel` rather than a Beaver-owned platform protocol adapter.
|
||||
|
||||
## Why This Is Required
|
||||
|
||||
The current channel design assumes a channel is already configured before the backend starts. That is enough for local development and simple webhook/token channels, but it does not match real platform onboarding:
|
||||
|
||||
- Feishu/Lark now has a Channel SDK pattern that packages bot channel setup, WebSocket or webhook transport, event handling, and replies around an installed app identity.
|
||||
- Weixin/OpenClaw-style setup uses a local plugin installer plus QR login and persistent login state.
|
||||
- Weixin personal-account setup uses a docker-compose predeclared sidecar connector plus QR login and persistent login state.
|
||||
- Terminal devices need pairing or device registration; a raw `peer_id` connect frame is not enough for a real deployment.
|
||||
- Even simple token platforms such as Telegram need a UI flow for token entry, validation, status, revoke, and restart.
|
||||
|
||||
@ -44,11 +44,13 @@ So Beaver needs a connection lifecycle layer. Adapters should not be responsible
|
||||
|
||||
`ChannelConnection` is the user-visible connection instance. Examples: "Weixin personal account", "Lark workspace bot", "Telegram main bot", "Desk terminal".
|
||||
|
||||
`ChannelConnector` is the setup and lifecycle controller for one platform family. It starts pairing sessions, validates credentials, launches connector processes, handles reconnects, and emits runtime channel config.
|
||||
`ChannelConnector` is the setup and lifecycle controller for one platform family. It starts pairing sessions, validates credentials, checks preconfigured connector endpoints when needed, handles reconnects, and emits runtime channel config.
|
||||
|
||||
`ChannelAdapter` is the message transport adapter used by `ChannelRuntime`. It receives normalized inbound messages and sends outbound replies. It does not own onboarding.
|
||||
|
||||
`ExternalConnectorProcess` is an optional local process for platforms whose SDK or login behavior is better isolated outside the Python backend. It talks to Beaver through a narrow control and message protocol.
|
||||
`ExternalConnectorChannel` is the runtime channel object used when a platform protocol lives outside the Python backend. It implements the same `start()`, `stop()`, and `send()` contract as an adapter, but its `send()` method calls an external connector HTTP API and inbound messages enter Beaver through a connector bridge endpoint.
|
||||
|
||||
`ExternalConnectorProcess` is an optional preconfigured service for platforms whose SDK or login behavior is better isolated outside the Python backend. For Weixin, this process is a docker-compose predeclared sidecar service. Beaver must not dynamically create containers or require Docker socket access.
|
||||
|
||||
## Data Model
|
||||
|
||||
@ -171,7 +173,7 @@ Some channels should run through an external process:
|
||||
ExternalConnectorProcess
|
||||
-> Beaver connector control API
|
||||
-> local Unix/TCP/WebSocket bridge
|
||||
-> ChannelRuntime external adapter
|
||||
-> ChannelRuntime ExternalConnectorChannel
|
||||
```
|
||||
|
||||
The external process must not receive permanent backend admin credentials through QR codes or copied commands. It should receive a short-lived pairing token with a narrow scope:
|
||||
@ -183,7 +185,7 @@ expires_in: 10 minutes
|
||||
one_time: true
|
||||
```
|
||||
|
||||
After pairing, Beaver stores the resulting connection credentials and gives the connector a renewable connection token scoped to that connection only.
|
||||
After pairing, Beaver stores the resulting connection credentials and gives the connector a renewable connection token scoped to that connection only. For docker-compose sidecars, that token is passed through the connector HTTP API or service configuration agreed for that sidecar; Beaver does not create or restart the sidecar container.
|
||||
|
||||
## Per-Channel Assessment
|
||||
|
||||
@ -211,23 +213,41 @@ The connector should expose both "manual app credential setup" and future "insta
|
||||
|
||||
### Weixin
|
||||
|
||||
Weixin should use an external connector process.
|
||||
Weixin should use a docker-compose predeclared sidecar connector.
|
||||
|
||||
Recommended first implementation:
|
||||
|
||||
- connector kind: `weixin`
|
||||
- setup mode: local plugin command plus QR login.
|
||||
- external process: required.
|
||||
- runtime adapter: external bridge adapter that receives normalized events from the connector.
|
||||
- setup mode: Beaver calls the sidecar HTTP API to start QR login and poll pairing state.
|
||||
- external process: required, predeclared in docker-compose, and never dynamically created by Beaver.
|
||||
- runtime channel: `ExternalConnectorChannel`.
|
||||
|
||||
Required setup checks:
|
||||
|
||||
- local connector installed.
|
||||
- sidecar base URL is configured.
|
||||
- sidecar health endpoint responds.
|
||||
- connector version is compatible with Beaver.
|
||||
- QR session is pending, scanned, confirmed, expired, or failed.
|
||||
- login state is stored behind `credentials_ref`.
|
||||
- connector heartbeat is visible.
|
||||
|
||||
The sidecar owns Weixin protocol handling, QR login, inbound receive, outbound send, and login-state persistence. Beaver owns connector setup state, bridge API validation, message normalization boundaries, runtime dedupe, and outbound HTTP calls to the sidecar `/send` API.
|
||||
|
||||
The agreed runtime flow is:
|
||||
|
||||
```text
|
||||
Weixin sidecar connector
|
||||
-> Beaver connector bridge endpoint
|
||||
-> ChannelRuntime.accept_inbound()
|
||||
-> MessageBus
|
||||
-> AgentService
|
||||
|
||||
AgentService
|
||||
-> MessageBus outbound
|
||||
-> ExternalConnectorChannel.send()
|
||||
-> Weixin sidecar connector /send
|
||||
```
|
||||
|
||||
Group delivery remains best-effort. The connector must surface group capability separately from direct message capability.
|
||||
|
||||
### Telegram
|
||||
|
||||
Reference in New Issue
Block a user