mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-09 07:16:04 +00:00
196 lines
11 KiB
Markdown
196 lines
11 KiB
Markdown
# EBA Adapter Acceptance Checklist
|
|
|
|
This checklist is the architecture-level acceptance standard for every Event-Based Agents platform adapter. It is not platform-specific. Adapter migration is not complete until the adapter has a written result against this checklist.
|
|
|
|
## Evidence Levels
|
|
|
|
Use these evidence levels consistently in adapter records:
|
|
|
|
| Level | Meaning | Can Mark Complete |
|
|
|-------|---------|-------------------|
|
|
| `plugin-e2e` | Real SDK plugin running through standalone runtime, LangBot core, the migrated adapter, and a real or simulator platform endpoint. | Yes |
|
|
| `adapter-live` | Direct adapter probe connected to a real or simulator platform endpoint, bypassing plugin runtime. | No, auxiliary only |
|
|
| `unit` | Unit/API-shape tests with mocked platform SDK objects or mocked APIs. | No, auxiliary only |
|
|
| `not-supported` | Platform protocol or SDK has no equivalent capability. Must include reason and source. | Yes, as explicitly unsupported |
|
|
| `blocked` | Intended capability could not be verified because of credentials, permissions, endpoint gaps, or simulator gaps. | No |
|
|
|
|
The primary acceptance path must be `plugin-e2e`. `adapter-live` and `unit` tests are useful, but they do not prove the EBA architecture path.
|
|
|
|
## Required Architecture Path
|
|
|
|
Every adapter must prove this full path:
|
|
|
|
```text
|
|
Real platform / simulator UI
|
|
-> platform SDK native event
|
|
-> adapter event converter
|
|
-> unified EBA event/entity/message types
|
|
-> LangBot core event dispatch
|
|
-> standalone SDK runtime
|
|
-> real test plugin listener
|
|
-> plugin calls platform APIs through SDK
|
|
-> LangBot core API dispatch
|
|
-> adapter API implementation
|
|
-> real platform / simulator UI
|
|
```
|
|
|
|
The test plugin must record JSONL evidence containing:
|
|
|
|
- event class and `event.type`
|
|
- adapter name
|
|
- chat type and chat ID
|
|
- sender/user/group IDs with secrets redacted
|
|
- message component list for received messages
|
|
- API action name, input summary, result or error
|
|
- raw unsupported/blocked reason when an item is skipped
|
|
|
|
## Required Message Receive Tests
|
|
|
|
For every adapter, inbound message conversion must be tested through `plugin-e2e` for each component the platform can receive. If the platform cannot create a component from the UI/simulator, record it as `blocked` with the endpoint limitation.
|
|
|
|
| Component | Required Receive Assertion |
|
|
|-----------|----------------------------|
|
|
| `Source` | Message ID and timestamp are present and stable enough for reply/get/delete APIs. |
|
|
| `Plain` | Text is preserved exactly, including spaces and multi-line content. |
|
|
| `At` | Mentioned user ID is converted to common `At.target`. |
|
|
| `AtAll` | Broadcast mention is converted to common `AtAll`, if platform supports it. |
|
|
| `Image` | Image ID, URL, path, or base64 is represented without leaking platform-native segment shape. |
|
|
| `Voice` | Voice/audio component is represented as `Voice` when the platform exposes it. |
|
|
| `File` | File name, ID/URL, and size are represented as `File` when available. |
|
|
| `Quote` | Reply/quote source ID and origin content are represented when the platform exposes it. |
|
|
| `Face` | Native emoji/sticker/dice/rps-like components are represented as `Face` or documented as platform-specific. |
|
|
| `Forward` | Merged/forwarded messages are represented as `Forward` when the platform exposes structured content. |
|
|
| `Unknown` | Unsupported native segments become `Unknown` or `PlatformSpecificEvent` data, not crashes. |
|
|
| Mixed chain | A message containing multiple component types preserves order. |
|
|
|
|
The plugin must subscribe to `MessageReceivedEvent` and assert that `message_chain` contains common `langbot_plugin.api.entities.builtin.platform.message` components, not platform-native SDK objects.
|
|
|
|
## Required Message Send Tests
|
|
|
|
For every adapter, outbound message conversion must be tested through `plugin-e2e` by having the plugin call SDK platform APIs and verifying the platform UI/simulator receives the expected message.
|
|
|
|
| Component | Required Send Assertion |
|
|
|-----------|-------------------------|
|
|
| `Plain` | Text appears exactly on the platform. |
|
|
| `At` | User mention renders as a mention or platform equivalent. |
|
|
| `AtAll` | Broadcast mention renders or is explicitly unsupported. |
|
|
| `Image` | URL, path, or base64 image sends and renders/downloads correctly. |
|
|
| `Voice` | Voice/audio sends when supported. |
|
|
| `File` | File sends with name and content/link when supported. |
|
|
| `Quote` | Quoted reply points to the original message when supported. |
|
|
| `Face` | Native emoji/sticker/dice/rps sends or is explicitly unsupported. |
|
|
| `Forward` | Forward/merged-forward sends when supported; otherwise fallback behavior is documented. |
|
|
| Mixed chain | A mixed chain preserves component order as closely as the platform allows. |
|
|
|
|
If a platform supports a component only in one direction, the adapter record must say so explicitly.
|
|
|
|
## Required Event Tests
|
|
|
|
The plugin must subscribe to every event declared in `manifest.yaml -> spec.supported_events` and record one of `plugin-e2e`, `not-supported`, or `blocked`.
|
|
|
|
| Event | Required Assertion |
|
|
|-------|--------------------|
|
|
| `message.received` | Real message reaches plugin as `MessageReceivedEvent`. |
|
|
| `message.edited` | Edited message reaches plugin with message ID and new content, if declared. |
|
|
| `message.deleted` | Deleted/recalled message reaches plugin with message ID and operator when available, if declared. |
|
|
| `message.reaction` | Reaction add/remove reaches plugin with message ID, user, reaction, and direction, if declared. |
|
|
| `feedback.received` | Feedback payload reaches plugin with feedback type and message/session IDs, if declared. |
|
|
| `group.member_joined` | Join event reaches plugin with group and member. |
|
|
| `group.member_left` | Leave/kick event reaches plugin with group, member, and kick flag. |
|
|
| `group.member_banned` | Mute/ban event reaches plugin with group, member, operator, and duration. |
|
|
| `group.info_updated` | Group metadata update reaches plugin with changed fields, if declared. |
|
|
| `friend.request_received` | Friend request reaches plugin with request ID and message. |
|
|
| `friend.added` | Friend-added event reaches plugin. |
|
|
| `friend.removed` | Friend-removed event reaches plugin, if declared. |
|
|
| `bot.invited_to_group` | Bot invite/join request reaches plugin with group and inviter/request ID. |
|
|
| `bot.removed_from_group` | Bot removal reaches plugin with group and operator when available. |
|
|
| `bot.muted` | Bot mute reaches plugin with duration. |
|
|
| `bot.unmuted` | Bot unmute reaches plugin. |
|
|
| `platform.specific` | At least one unmapped native event is delivered as structured platform-specific data, if declared. |
|
|
|
|
Do not declare an event in the manifest unless there is an implementation path and an acceptance entry.
|
|
|
|
## Required Common API Tests
|
|
|
|
The plugin must call every common API declared in `manifest.yaml -> spec.supported_apis.required` and `optional`. Each call must be recorded with input summary and result.
|
|
|
|
| API | Required Assertion |
|
|
|-----|--------------------|
|
|
| `send_message` | Plugin sends to private and group/channel targets where supported. |
|
|
| `reply_message` | Plugin replies to the triggering message, with quoted mode tested when supported. |
|
|
| `edit_message` | Plugin edits a bot-sent message, if declared. |
|
|
| `delete_message` | Plugin deletes/recalls a bot-sent message, if declared and permissions allow. |
|
|
| `forward_message` | Plugin forwards or emulates forwarding a real message, if declared. |
|
|
| `get_message` | Plugin retrieves a real message and receives common `MessageReceivedEvent` shape. |
|
|
| `get_group_info` | Plugin receives `UserGroup` with ID/name/count where available. |
|
|
| `get_group_list` | Plugin receives joined groups/channels list where supported. |
|
|
| `get_group_member_list` | Plugin receives list of `UserGroupMember` where supported. |
|
|
| `get_group_member_info` | Plugin receives one member with role/display name where available. |
|
|
| `set_group_name` | Plugin changes and restores a disposable group name, if declared. |
|
|
| `mute_member` | Plugin mutes a disposable target, if declared. |
|
|
| `unmute_member` | Plugin unmutes the same target, if declared. |
|
|
| `kick_member` | Plugin kicks a disposable target only in destructive test mode, if declared. |
|
|
| `leave_group` | Plugin leaves only in destructive test mode and only at the end, if declared. |
|
|
| `get_user_info` | Plugin receives common `User` shape. |
|
|
| `get_friend_list` | Plugin receives friend/contact list where supported. |
|
|
| `approve_friend_request` | Plugin accepts/rejects a disposable friend request, if declared. |
|
|
| `approve_group_invite` | Plugin accepts/rejects a disposable group invite, if declared. |
|
|
| `upload_file` | Plugin uploads a real small file, if declared. |
|
|
| `get_file_url` | Plugin resolves a real file ID to a URL, if declared. |
|
|
| `call_platform_api` | Plugin calls every declared platform-specific action with safe parameters. |
|
|
|
|
Destructive APIs must be opt-in and documented with the exact target used.
|
|
|
|
## Platform-Specific API Tests
|
|
|
|
Every action listed in `manifest.yaml -> spec.platform_specific_apis` must have one acceptance entry:
|
|
|
|
- `plugin-e2e`: called by the plugin against the live/simulator endpoint.
|
|
- `not-supported`: removed from manifest or explained if the platform SDK exposes it but this adapter intentionally does not.
|
|
- `blocked`: endpoint did not implement it, permissions missing, or safe fixture unavailable.
|
|
|
|
Do not leave a platform-specific API in the manifest without a corresponding test record.
|
|
|
|
## Required Compatibility Tests
|
|
|
|
Each migrated adapter must also prove:
|
|
|
|
- Manifest supported events match `adapter.get_supported_events()`.
|
|
- Manifest supported APIs match `adapter.get_supported_apis()`.
|
|
- Manifest platform-specific actions match `PLATFORM_API_MAP`.
|
|
- Legacy `FriendMessage` / `GroupMessage` listeners still work when the core registers them.
|
|
- EBA listener dispatch prefers the most specific event class, then `EBAEvent`, then base `Event`.
|
|
- Self-message filtering prevents bot echo loops without dropping edit/delete/moderation events needed for API tests.
|
|
- `source_platform_object` is present for reply/debug but not required by plugins for common behavior.
|
|
|
|
## Required Documentation Per Adapter
|
|
|
|
Each adapter document must include:
|
|
|
|
- adapter directory and manifest name
|
|
- config table
|
|
- supported event table with evidence level per event
|
|
- supported common API table with evidence level per API
|
|
- platform-specific API table with evidence level per action
|
|
- receive component table with evidence level per component
|
|
- send component table with evidence level per component
|
|
- exact test date
|
|
- exact platform endpoint or simulator used
|
|
- standalone runtime command
|
|
- plugin path/name used for testing
|
|
- evidence JSONL path
|
|
- destructive operations performed or explicitly skipped
|
|
- blocked items and reasons
|
|
|
|
## Acceptance Rule
|
|
|
|
An adapter can be marked migrated only when:
|
|
|
|
1. All declared events have `plugin-e2e` or `not-supported` evidence.
|
|
2. All declared APIs have `plugin-e2e` or `not-supported` evidence.
|
|
3. All platform-supported receive/send message components have `plugin-e2e` evidence.
|
|
4. Unit tests cover conversion and API-shape boundaries.
|
|
5. The adapter document lists every blocked or skipped item honestly.
|
|
|
|
If any declared capability is only covered by `adapter-live` or `unit`, the adapter status must remain partial.
|