From 72a48c49920b783087269595ffb3fc1d0ad18dc4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 13 Jan 2026 06:51:20 +0000 Subject: [PATCH] docs: align channels naming --- README.md | 36 +++--- docs/automation/cron-jobs.md | 6 +- docs/automation/poll.md | 18 +-- docs/automation/webhook.md | 12 +- docs/channels/msteams.md | 2 +- docs/channels/telegram.md | 2 +- docs/cli/index.md | 6 +- docs/cli/message.md | 26 ++--- docs/docs.json | 8 ++ docs/install/docker.md | 10 +- .../{provider-plugin.md => channel-plugin.md} | 103 +++++++++--------- docs/tools/agent-send.md | 8 +- 12 files changed, 123 insertions(+), 114 deletions(-) rename docs/refactor/{provider-plugin.md => channel-plugin.md} (51%) diff --git a/README.md b/README.md index 11d42c690..c7046da96 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ Details: [Tailscale guide](https://docs.clawd.bot/gateway/tailscale) · [Web sur It’s perfectly fine to run the Gateway on a small Linux instance. Clients (macOS app, CLI, WebChat) can connect over **Tailscale Serve/Funnel** or **SSH tunnels**, and you can still pair device nodes (macOS/iOS/Android) to execute device‑local actions when needed. -- **Gateway host** runs the exec tool and provider connections by default. +- **Gateway host** runs the exec tool and channel connections by default. - **Device nodes** run device‑local actions (`system.run`, camera, screen recording, notifications) via `node.invoke`. In short: exec runs where the Gateway lives; device actions run where the device lives. @@ -317,50 +317,54 @@ Details: [Security guide](https://docs.clawd.bot/gateway/security) · [Docker + ### [WhatsApp](https://docs.clawd.bot/channels/whatsapp) -- Link the device: `pnpm clawdbot providers login` (stores creds in `~/.clawdbot/credentials`). -- Allowlist who can talk to the assistant via `whatsapp.allowFrom`. -- If `whatsapp.groups` is set, it becomes a group allowlist; include `"*"` to allow all. +- Link the device: `pnpm clawdbot channels login` (stores creds in `~/.clawdbot/credentials`). +- Allowlist who can talk to the assistant via `channels.whatsapp.allowFrom`. +- If `channels.whatsapp.groups` is set, it becomes a group allowlist; include `"*"` to allow all. ### [Telegram](https://docs.clawd.bot/channels/telegram) -- Set `TELEGRAM_BOT_TOKEN` or `telegram.botToken` (env wins). -- Optional: set `telegram.groups` (with `telegram.groups."*".requireMention`); when set, it is a group allowlist (include `"*"` to allow all). Also `telegram.allowFrom` or `telegram.webhookUrl` as needed. +- Set `TELEGRAM_BOT_TOKEN` or `channels.telegram.botToken` (env wins). +- Optional: set `channels.telegram.groups` (with `channels.telegram.groups."*".requireMention`); when set, it is a group allowlist (include `"*"` to allow all). Also `channels.telegram.allowFrom` or `channels.telegram.webhookUrl` as needed. ```json5 { - telegram: { - botToken: "123456:ABCDEF" + channels: { + telegram: { + botToken: "123456:ABCDEF" + } } } ``` ### [Slack](https://docs.clawd.bot/channels/slack) -- Set `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN` (or `slack.botToken` + `slack.appToken`). +- Set `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN` (or `channels.slack.botToken` + `channels.slack.appToken`). ### [Discord](https://docs.clawd.bot/channels/discord) -- Set `DISCORD_BOT_TOKEN` or `discord.token` (env wins). -- Optional: set `commands.native`, `commands.text`, or `commands.useAccessGroups`, plus `discord.dm.allowFrom`, `discord.guilds`, or `discord.mediaMaxMb` as needed. +- Set `DISCORD_BOT_TOKEN` or `channels.discord.token` (env wins). +- Optional: set `commands.native`, `commands.text`, or `commands.useAccessGroups`, plus `channels.discord.dm.allowFrom`, `channels.discord.guilds`, or `channels.discord.mediaMaxMb` as needed. ```json5 { - discord: { - token: "1234abcd" + channels: { + discord: { + token: "1234abcd" + } } } ``` ### [Signal](https://docs.clawd.bot/channels/signal) -- Requires `signal-cli` and a `signal` config section. +- Requires `signal-cli` and a `channels.signal` config section. ### [iMessage](https://docs.clawd.bot/channels/imessage) - macOS only; Messages must be signed in. -- If `imessage.groups` is set, it becomes a group allowlist; include `"*"` to allow all. +- If `channels.imessage.groups` is set, it becomes a group allowlist; include `"*"` to allow all. -### [Microsoft Teams](https://docs.clawd.bot/providers/msteams) +### [Microsoft Teams](https://docs.clawd.bot/channels/msteams) - Configure a Teams app + Bot Framework, then add a `msteams` config section. - Allowlist who can talk via `msteams.allowFrom`; group access via `msteams.groupAllowFrom` or `msteams.groupPolicy: "open"`. diff --git a/docs/automation/cron-jobs.md b/docs/automation/cron-jobs.md index 6bacb5f30..e56d2b5a7 100644 --- a/docs/automation/cron-jobs.md +++ b/docs/automation/cron-jobs.md @@ -192,7 +192,7 @@ clawdbot cron add \ --session isolated \ --message "Summarize inbox + calendar for today." \ --deliver \ - --provider whatsapp \ + --channel whatsapp \ --to "+15551234567" ``` @@ -205,7 +205,7 @@ clawdbot cron add \ --session isolated \ --message "Summarize today; send to the nightly topic." \ --deliver \ - --provider telegram \ + --channel telegram \ --to "-1001234567890:topic:123" ``` @@ -220,7 +220,7 @@ clawdbot cron add \ --model "opus" \ --thinking high \ --deliver \ - --provider whatsapp \ + --channel whatsapp \ --to "+15551234567" Agent selection (multi-agent setups): diff --git a/docs/automation/poll.md b/docs/automation/poll.md index 4860ae269..d22de2eec 100644 --- a/docs/automation/poll.md +++ b/docs/automation/poll.md @@ -7,8 +7,8 @@ read_when: # Polls -## Supported providers -- WhatsApp (web provider) +## Supported channels +- WhatsApp (web channel) - Discord - MS Teams (Adaptive Cards) @@ -22,18 +22,18 @@ clawdbot message poll --to 123456789@g.us \ --poll-question "Meeting time?" --poll-option "10am" --poll-option "2pm" --poll-option "4pm" --poll-multi # Discord -clawdbot message poll --provider discord --to channel:123456789 \ +clawdbot message poll --channel discord --to channel:123456789 \ --poll-question "Snack?" --poll-option "Pizza" --poll-option "Sushi" -clawdbot message poll --provider discord --to channel:123456789 \ +clawdbot message poll --channel discord --to channel:123456789 \ --poll-question "Plan?" --poll-option "A" --poll-option "B" --poll-duration-hours 48 # MS Teams -clawdbot message poll --provider msteams --to conversation:19:abc@thread.tacv2 \ +clawdbot message poll --channel msteams --to conversation:19:abc@thread.tacv2 \ --poll-question "Lunch?" --poll-option "Pizza" --poll-option "Sushi" ``` Options: -- `--provider`: `whatsapp` (default), `discord`, or `msteams` +- `--channel`: `whatsapp` (default), `discord`, or `msteams` - `--poll-multi`: allow selecting multiple options - `--poll-duration-hours`: Discord-only (defaults to 24 when omitted) @@ -47,16 +47,16 @@ Params: - `options` (string[], required) - `maxSelections` (number, optional) - `durationHours` (number, optional) -- `provider` (string, optional, default: `whatsapp`) +- `channel` (string, optional, default: `whatsapp`) - `idempotencyKey` (string, required) -## Provider differences +## Channel differences - WhatsApp: 2-12 options, `maxSelections` must be within option count, ignores `durationHours`. - Discord: 2-10 options, `durationHours` clamped to 1-768 hours (default 24). `maxSelections > 1` enables multi-select; Discord does not support a strict selection count. - MS Teams: Adaptive Card polls (Clawdbot-managed). No native poll API; `durationHours` is ignored. ## Agent tool (Message) -Use the `message` tool with `poll` action (`to`, `pollQuestion`, `pollOption`, optional `pollMulti`, `pollDurationHours`, `provider`). +Use the `message` tool with `poll` action (`to`, `pollQuestion`, `pollOption`, optional `pollMulti`, `pollDurationHours`, `channel`). Note: Discord has no “pick exactly N” mode; `pollMulti` maps to multi-select. Teams polls are rendered as Adaptive Cards and require the gateway to stay online diff --git a/docs/automation/webhook.md b/docs/automation/webhook.md index b3ec0d65e..00734f0d0 100644 --- a/docs/automation/webhook.md +++ b/docs/automation/webhook.md @@ -58,7 +58,7 @@ Payload: "sessionKey": "hook:email:msg-123", "wakeMode": "now", "deliver": true, - "provider": "last", + "channel": "last", "to": "+15551234567", "model": "openai/gpt-5.2-mini", "thinking": "low", @@ -70,9 +70,9 @@ Payload: - `name` optional (string): Human-readable name for the hook (e.g., "GitHub"), used as a prefix in session summaries. - `sessionKey` optional (string): The key used to identify the agent's session. Defaults to a random `hook:`. Using a consistent key allows for a multi-turn conversation within the hook context. - `wakeMode` optional (`now` | `next-heartbeat`): Whether to trigger an immediate heartbeat (default `now`) or wait for the next periodic check. -- `deliver` optional (boolean): If `true`, the agent's response will be sent to the messaging provider. Defaults to `true`. Responses that are only heartbeat acknowledgments are automatically skipped. -- `provider` optional (string): The messaging service for delivery. One of: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `msteams`. Defaults to `last`. -- `to` optional (string): The recipient identifier for the provider (e.g., phone number for WhatsApp/Signal, chat ID for Telegram, channel ID for Discord/Slack, conversation ID for MS Teams). Defaults to the last recipient in the main session. +- `deliver` optional (boolean): If `true`, the agent's response will be sent to the messaging channel. Defaults to `true`. Responses that are only heartbeat acknowledgments are automatically skipped. +- `channel` optional (string): The messaging channel for delivery. One of: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `msteams`. Defaults to `last`. +- `to` optional (string): The recipient identifier for the channel (e.g., phone number for WhatsApp/Signal, chat ID for Telegram, channel ID for Discord/Slack, conversation ID for MS Teams). Defaults to the last recipient in the main session. - `model` optional (string): Model override (e.g., `anthropic/claude-3-5-sonnet` or an alias). Must be in the allowed model list if restricted. - `thinking` optional (string): Thinking level override (e.g., `low`, `medium`, `high`). - `timeoutSeconds` optional (number): Maximum duration for the agent run in seconds. @@ -94,8 +94,8 @@ Mapping options (summary): - `hooks.transformsDir` + `transform.module` loads a JS/TS module for custom logic. - Use `match.source` to keep a generic ingest endpoint (payload-driven routing). - TS transforms require a TS loader (e.g. `bun` or `tsx`) or precompiled `.js` at runtime. -- Set `deliver: true` + `provider`/`to` on mappings to route replies to a chat surface - (`provider` defaults to `last` and falls back to WhatsApp). +- Set `deliver: true` + `channel`/`to` on mappings to route replies to a chat surface + (`channel` defaults to `last` and falls back to WhatsApp). - `clawdbot hooks gmail setup` writes `hooks.gmail` config for `clawdbot hooks gmail run`. See [Gmail Pub/Sub](/automation/gmail-pubsub) for the full Gmail watch flow. diff --git a/docs/channels/msteams.md b/docs/channels/msteams.md index 534d261ae..223f3ef82 100644 --- a/docs/channels/msteams.md +++ b/docs/channels/msteams.md @@ -408,7 +408,7 @@ By default, Clawdbot only downloads media from Microsoft/Teams hostnames. Overri ## Polls (Adaptive Cards) Clawdbot sends Teams polls as Adaptive Cards (there is no native Teams poll API). -- CLI: `clawdbot message poll --provider msteams --to conversation: ...` +- CLI: `clawdbot message poll --channel msteams --to conversation: ...` - Votes are recorded by the gateway in `~/.clawdbot/msteams-polls.json`. - The gateway must stay online to record votes. - Polls do not auto-post result summaries yet (inspect the store file if needed). diff --git a/docs/channels/telegram.md b/docs/channels/telegram.md index dd83a3ba4..2c787f9a4 100644 --- a/docs/channels/telegram.md +++ b/docs/channels/telegram.md @@ -266,7 +266,7 @@ Outbound Telegram API calls retry on transient network/429 errors with exponenti ## Delivery targets (CLI/cron) - Use a chat id (`123456789`) or a username (`@name`) as the target. -- Example: `clawdbot message send --provider telegram --to 123456789 --message "hi"`. +- Example: `clawdbot message send --channel telegram --to 123456789 --message "hi"`. ## Troubleshooting diff --git a/docs/cli/index.md b/docs/cli/index.md index 63c92bc4b..474361de7 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -387,7 +387,7 @@ Subcommands: Examples: - `clawdbot message send --to +15555550123 --message "Hi"` -- `clawdbot message poll --provider discord --to channel:123 --poll-question "Snack?" --poll-option Pizza --poll-option Sushi` +- `clawdbot message poll --channel discord --to channel:123 --poll-question "Snack?" --poll-option Pizza --poll-option Sushi` ### `agent` Run one agent turn via the Gateway (or `--local` embedded). @@ -400,7 +400,7 @@ Options: - `--session-id ` - `--thinking ` (GPT-5.2 + Codex models only) - `--verbose ` -- `--provider ` +- `--channel ` - `--local` - `--deliver` - `--json` @@ -443,7 +443,7 @@ Options: - `--json` - `--all` (full diagnosis; read-only, pasteable) - `--deep` (probe channels) -- `--usage` (show provider usage/quota) +- `--usage` (show model provider usage/quota) - `--timeout ` - `--verbose` - `--debug` (alias for `--verbose`) diff --git a/docs/cli/message.md b/docs/cli/message.md index d60ea9729..52da57732 100644 --- a/docs/cli/message.md +++ b/docs/cli/message.md @@ -1,13 +1,13 @@ --- -summary: "CLI reference for `clawdbot message` (send + provider actions)" +summary: "CLI reference for `clawdbot message` (send + channel actions)" read_when: - Adding or modifying message CLI actions - - Changing outbound provider behavior + - Changing outbound channel behavior --- # `clawdbot message` -Single outbound command for sending messages and provider actions +Single outbound command for sending messages and channel actions (Discord/Slack/Telegram/WhatsApp/Signal/iMessage/MS Teams). ## Usage @@ -16,9 +16,9 @@ Single outbound command for sending messages and provider actions clawdbot message [flags] ``` -Provider selection: -- `--provider` required if more than one provider is configured. -- If exactly one provider is configured, it becomes the default. +Channel selection: +- `--channel` required if more than one channel is configured. +- If exactly one channel is configured, it becomes the default. - Values: `whatsapp|telegram|discord|slack|signal|imessage|msteams` Target formats (`--to`): @@ -32,7 +32,7 @@ Target formats (`--to`): ## Common flags -- `--provider ` +- `--channel ` - `--account ` - `--json` - `--dry-run` @@ -170,13 +170,13 @@ Target formats (`--to`): Send a Discord reply: ``` -clawdbot message send --provider discord \ +clawdbot message send --channel discord \ --to channel:123 --message "hi" --reply-to 456 ``` Create a Discord poll: ``` -clawdbot message poll --provider discord \ +clawdbot message poll --channel discord \ --to channel:123 \ --poll-question "Snack?" \ --poll-option Pizza --poll-option Sushi \ @@ -185,13 +185,13 @@ clawdbot message poll --provider discord \ Send a Teams proactive message: ``` -clawdbot message send --provider msteams \ +clawdbot message send --channel msteams \ --to conversation:19:abc@thread.tacv2 --message "hi" ``` Create a Teams poll: ``` -clawdbot message poll --provider msteams \ +clawdbot message poll --channel msteams \ --to conversation:19:abc@thread.tacv2 \ --poll-question "Lunch?" \ --poll-option Pizza --poll-option Sushi @@ -199,12 +199,12 @@ clawdbot message poll --provider msteams \ React in Slack: ``` -clawdbot message react --provider slack \ +clawdbot message react --channel slack \ --to C123 --message-id 456 --emoji "✅" ``` Send Telegram inline buttons: ``` -clawdbot message send --provider telegram --to @mychat --message "Choose:" \ +clawdbot message send --channel telegram --to @mychat --message "Choose:" \ --buttons '[ [{"text":"Yes","callback_data":"cmd:yes"}], [{"text":"No","callback_data":"cmd:no"}] ]' ``` diff --git a/docs/docs.json b/docs/docs.json index bbdd07ade..0cf1606da 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -541,6 +541,14 @@ "source": "/concepts/provider-routing/", "destination": "/concepts/channel-routing" }, + { + "source": "/refactor/provider-plugin", + "destination": "/refactor/channel-plugin" + }, + { + "source": "/refactor/provider-plugin/", + "destination": "/refactor/channel-plugin" + }, { "source": "/queue", "destination": "/concepts/queue" diff --git a/docs/install/docker.md b/docs/install/docker.md index e4257d92a..59c791dc9 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -167,23 +167,23 @@ ENV NODE_ENV=production CMD ["node","dist/index.js"] ``` -### Provider setup (optional) +### Channel setup (optional) -Use the CLI container to configure providers, then restart the gateway if needed. +Use the CLI container to configure channels, then restart the gateway if needed. WhatsApp (QR): ```bash -docker compose run --rm clawdbot-cli providers login +docker compose run --rm clawdbot-cli channels login ``` Telegram (bot token): ```bash -docker compose run --rm clawdbot-cli providers add --provider telegram --token "" +docker compose run --rm clawdbot-cli channels add --channel telegram --token "" ``` Discord (bot token): ```bash -docker compose run --rm clawdbot-cli providers add --provider discord --token "" +docker compose run --rm clawdbot-cli channels add --channel discord --token "" ``` Docs: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord) diff --git a/docs/refactor/provider-plugin.md b/docs/refactor/channel-plugin.md similarity index 51% rename from docs/refactor/provider-plugin.md rename to docs/refactor/channel-plugin.md index d792e444f..955226e1a 100644 --- a/docs/refactor/provider-plugin.md +++ b/docs/refactor/channel-plugin.md @@ -1,83 +1,80 @@ --- -summary: "Provider plugin refactor implementation notes (registry, status, gateway/runtime)" +summary: "Channel plugin refactor implementation notes (registry, status, gateway/runtime)" read_when: - - Adding or refactoring provider plugin wiring - - Moving provider-specific behavior into plugin hooks + - Adding or refactoring channel plugin wiring + - Moving channel-specific behavior into plugin hooks --- -# Provider Plugin Refactor — Implementation Notes +# Channel Plugins — Implementation Notes -Goal: make providers (iMessage, Discord, etc.) pluggable with minimal wiring and shared UX/state paths. +Goal: make chat channels (iMessage, Discord, etc.) pluggable with minimal wiring and shared UX/state paths. ## Architecture Overview -- Registry: `src/providers/plugins/index.ts` owns the plugin list. -- Provider dock: `src/providers/dock.ts` owns lightweight provider metadata used by shared flows (reply, command auth, block streaming) without importing full plugins. -- IDs/aliases: `src/providers/registry.ts` owns stable provider ids + input aliases. -- Shape: `src/providers/plugins/types.ts` defines the plugin contract. -- Gateway: `src/gateway/server-providers.ts` drives start/stop + runtime snapshots via plugins. +- Registry: `src/channels/plugins/index.ts` owns the plugin list. +- Channel dock: `src/channels/dock.ts` owns lightweight channel metadata used by shared flows (reply, command auth, block streaming) without importing full plugins. +- IDs/aliases: `src/channels/registry.ts` owns stable channel ids + input aliases. +- Shape: `src/channels/plugins/types.ts` defines the plugin contract. +- Gateway: `src/gateway/server-channels.ts` drives start/stop + runtime snapshots via plugins. - Outbound: `src/infra/outbound/deliver.ts` routes through plugin outbound when present. -- Outbound delivery loads **outbound adapters** on-demand via `src/providers/plugins/outbound/load.ts` (avoid importing heavy provider plugins on hot paths). +- Outbound delivery loads **outbound adapters** on-demand via `src/channels/plugins/outbound/load.ts` (avoid importing heavy channel plugins on hot paths). - Reload: `src/gateway/config-reload.ts` uses plugin `reload.configPrefixes` lazily (avoid init cycles). -- CLI: `src/commands/providers/*` uses plugin list for add/remove/status/list. -- Protocol: `src/gateway/protocol/schema.ts` (v3) makes provider-shaped responses container-generic (maps keyed by provider id). +- CLI: `src/commands/channels/*` uses plugin list for add/remove/status/list. +- Protocol: `src/gateway/protocol/schema.ts` keeps `channels.status` schema-light (maps keyed by channel id). ## Plugin Contract (high-level) -Each `ProviderPlugin` bundles: +Each `ChannelPlugin` bundles: - `meta`: id/labels/docs/sort order. - `capabilities`: chatTypes + optional features (polls, media, nativeCommands, etc.). - `config`: list/resolve/default/isConfigured/describeAccount + isEnabled + (un)configured reasons + `resolveAllowFrom` + `formatAllowFrom`. - `outbound`: deliveryMode + chunker + resolveTarget (mode-aware) + sendText/sendMedia/sendPoll + pollMaxOptions. -- `status`: defaultRuntime + probe/audit/buildAccountSnapshot + buildProviderSummary + logSelfId + collectStatusIssues. +- `status`: defaultRuntime + probe/audit/buildAccountSnapshot + buildChannelSummary + logSelfId + collectStatusIssues. - `gateway`: startAccount/stopAccount with runtime context (`getStatus`/`setStatus`), plus optional `loginWithQrStart/loginWithQrWait` for gateway-owned QR login flows. - `security`: dmPolicy + allowFrom hints used by `doctor security`. - `heartbeat`: optional readiness checks + heartbeat recipient resolution when providers own targeting. - `auth`: optional login hook used by `clawdbot channels login`. - `reload`: `configPrefixes` that map to hot restarts. -- `onboarding`: optional CLI onboarding adapter (wizard UI hooks per provider). -- `agentTools`: optional provider-owned agent tools (ex: QR login). +- `onboarding`: optional CLI onboarding adapter (wizard UI hooks per channel). +- `agentTools`: optional channel-owned agent tools (ex: QR login). ## Key Integration Notes -- `listProviderPlugins()` is the runtime source of truth for provider UX and wiring. -- Avoid importing `src/providers/plugins/index.ts` from shared modules (reply flow, command auth, sandbox explain). It’s intentionally “heavy” (providers may pull web login / monitor code). Use `getProviderDock()` + `normalizeProviderId()` for cheap metadata, and only `getProviderPlugin()` at execution boundaries (ex: `src/auto-reply/reply/route-reply.ts`). +- `listChannelPlugins()` is the runtime source of truth for channel UX and wiring. +- Avoid importing `src/channels/plugins/index.ts` from shared modules (reply flow, command auth, sandbox explain). It’s intentionally “heavy” (channels may pull web login / monitor code). Use `getChannelDock()` + `normalizeChannelId()` (from `src/channels/registry.ts`) for cheap metadata, and only `getChannelPlugin()` at execution boundaries (ex: `src/auto-reply/reply/route-reply.ts`). - WhatsApp plugin keeps Baileys-heavy login bits behind lazy imports; cheap auth file checks live in `src/web/auth-store.ts` (so outbound routing doesn’t pay Baileys import cost). -- `routeReply` delegates sending to plugin `outbound` adapters via a lazy import of `src/infra/outbound/deliver.ts` (so adding a provider is “just implement outbound adapter”, no router switches). -- Avoid static imports of provider monitors inside plugin modules. Monitors typically import the reply pipeline, which can create ESM cycles (and break Vite/Vitest SSR with TDZ errors). Prefer lazy imports inside `gateway.startAccount`. -- Debug cycle leaks quickly with: `npx -y madge --circular src/providers/plugins/index.ts`. -- Gateway protocol schema keeps provider selection as an open-ended string (no provider enum / static list) to avoid init cycles and so new plugins don’t require protocol changes. -- Protocol v3: no more per-provider fields in `providers.status`; consumers must read map entries by provider id. -- `DEFAULT_CHAT_PROVIDER` lives in `src/providers/registry.ts` and is used anywhere we need a fallback delivery surface. -- Provider reload rules are computed lazily to avoid static init cycles in tests. -- Signal/iMessage media size limits are now resolved inside their plugins. -- `normalizeProviderId()` handles aliases (ex: `imsg`, `teams`) so CLI and API inputs stay stable. -- `ProviderId` is `ChatProviderId` (no extra special-cased provider IDs in shared code). -- Gateway runtime defaults (`status.defaultRuntime`) replace the old per-provider runtime map. -- Gateway runtime snapshot (`getRuntimeSnapshot`) is map-based: `{ providers, providerAccounts }` (no `${id}Accounts` keys). -- `providers.status` response keys (v3): - - `providerOrder: string[]` - - `providerLabels: Record` - - `providers: Record` (provider summary objects, plugin-defined) - - `providerAccounts: Record` - - `providerDefaultAccountId: Record` -- `providers.status` summary objects come from `status.buildProviderSummary` (no per-provider branching in the handler). -- `providers.status` warnings now flow through `status.collectStatusIssues` per plugin. +- `routeReply` delegates sending to plugin `outbound` adapters via a lazy import of `src/infra/outbound/deliver.ts` (so adding a channel is “just implement outbound adapter”, no router switches). +- Avoid static imports of channel monitors inside plugin modules. Monitors typically import the reply pipeline, which can create ESM cycles (and break Vite/Vitest SSR with TDZ errors). Prefer lazy imports inside `gateway.startAccount`. +- Debug cycle leaks quickly with: `npx -y madge --circular src/channels/plugins/index.ts`. +- Protocol v3: `channels.status` is map-based and schema-light so new channels can ship without protocol updates. +- `DEFAULT_CHAT_CHANNEL` lives in `src/channels/registry.ts` and is used anywhere we need a fallback delivery surface. +- Channel reload rules are computed lazily to avoid static init cycles in tests. +- Signal/iMessage media size limits are resolved inside their plugins. +- `normalizeChannelId()` handles aliases (ex: `imsg`, `teams`) so CLI and API inputs stay stable. +- Gateway runtime snapshot (`getRuntimeSnapshot`) is map-based: `{ channels, channelAccounts }` (no `${id}Accounts` keys). +- `channels.status` response keys (v3): + - `channelOrder: string[]` + - `channelLabels: Record` + - `channels: Record` (channel summary objects, plugin-defined) + - `channelAccounts: Record` + - `channelDefaultAccountId: Record` +- `channels.status` summary objects come from `status.buildChannelSummary` (no per-channel branching in the handler). +- `channels.status` warnings flow through `status.collectStatusIssues` per plugin. - CLI list uses `meta.showConfigured` to decide whether to show configured state. - CLI provider options and prompt provider lists are generated from `listProviderPlugins()` (avoid hardcoded arrays). -- Provider selection (`resolveMessageProviderSelection`) now inspects `config.isEnabled` + `config.isConfigured` per plugin instead of hardcoded provider checks. -- Pairing flows (CLI + store) now use `plugin.pairing` (`idLabel`, `normalizeAllowEntry`, `notifyApproval`) via `src/providers/plugins/pairing.ts`. -- CLI provider remove/disable delegates to `config.setAccountEnabled` + `config.deleteAccount` per plugin. -- CLI provider add now delegates to `plugin.setup` for account validation, naming, and config writes (no hardcoded provider checks). -- Agent provider status entries are now built from plugin config/status (`status.resolveAccountState` for custom state labels). -- Agent binding defaults use `meta.forceAccountBinding` to avoid hardcoded provider checks. -- Onboarding quickstart allowlist uses `meta.quickstartAllowFrom` to avoid hardcoded provider lists. -- `resolveProviderDefaultAccountId()` is the shared helper for picking default accounts from `accountIds` + plugin config. -- `routeReply` uses plugin outbound senders; `ProviderOutboundContext` supports `replyToId` + `threadId` and outbound delivery supports `abortSignal` for cooperative cancellation. -- Outbound target resolution (`resolveOutboundTarget`) now delegates to `plugin.outbound.resolveTarget` (mode-aware, uses config allowlists when present). -- Outbound delivery results accept `meta` for provider-specific fields to avoid core type churn in new plugins. +- Channel selection (`resolveMessageChannelSelection`) inspects `config.isEnabled` + `config.isConfigured` per plugin instead of hardcoded checks. +- Pairing flows (CLI + store) use `plugin.pairing` (`idLabel`, `normalizeAllowEntry`, `notifyApproval`) via `src/channels/plugins/pairing.ts`. +- CLI channel remove/disable delegates to `config.setAccountEnabled` + `config.deleteAccount` per plugin. +- CLI channel add delegates to `plugin.setup` for account validation, naming, and config writes (no hardcoded checks). +- Agent channel status entries are built from plugin config/status (`status.resolveAccountState` for custom state labels). +- Agent binding defaults use `meta.forceAccountBinding` to avoid hardcoded checks. +- Onboarding quickstart allowlist uses `meta.quickstartAllowFrom` to avoid hardcoded channel lists. +- `resolveChannelDefaultAccountId()` is the shared helper for picking default accounts from `accountIds` + plugin config. +- `routeReply` uses plugin outbound senders; `ChannelOutboundContext` supports `replyToId` + `threadId` and outbound delivery supports `abortSignal` for cooperative cancellation. +- Outbound target resolution (`resolveOutboundTarget`) delegates to `plugin.outbound.resolveTarget` (mode-aware, uses config allowlists when present). +- Outbound delivery results accept `meta` for channel-specific fields to avoid core type churn in new plugins. - Agent gateway routing sets `deliveryTargetMode` and uses `resolveOutboundTarget` for implicit fallback targets when `to` is missing. -- Elevated tool allowlists (`tools.elevated.allowFrom`) are a record keyed by provider id (no schema update needed when adding providers). +- Elevated tool allowlists (`tools.elevated.allowFrom`) are a record keyed by channel id (no schema update needed when adding channels). - Block streaming defaults live on the plugin (`capabilities.blockStreaming`, `streaming.blockStreamingCoalesceDefaults`) instead of hardcoded provider checks. -- Provider logout now routes through `providers.logout` using `gateway.logoutAccount` on each plugin (clients should call the generic method). -- Gateway message-provider normalization uses `src/providers/registry.ts` for cheap validation/normalization without plugin init cycles. +- Channel logout routes through `channels.logout` using `gateway.logoutAccount` on each plugin (clients should call the generic method). +- Gateway message-channel normalization uses `src/channels/registry.ts` for cheap validation/normalization without plugin init cycles. - Group mention gating now flows through `plugin.groups.resolveRequireMention` (Discord/Slack/Telegram/WhatsApp/iMessage) instead of branching in reply handlers. - Command authorization uses `config.resolveAllowFrom` + `config.formatAllowFrom`, with `commands.enforceOwnerForCommands` and `commands.skipWhenConfigEmpty` driving provider-specific behavior. - Security warnings (`doctor security`) use `plugin.security.resolveDmPolicy` + `plugin.security.collectWarnings`; supply `policyPath` + `allowFromPath` for accurate config hints. diff --git a/docs/tools/agent-send.md b/docs/tools/agent-send.md index dd85740b5..c5b8eaa59 100644 --- a/docs/tools/agent-send.md +++ b/docs/tools/agent-send.md @@ -20,7 +20,7 @@ runtime on the current machine. - Output: - default: prints reply text (plus `MEDIA:` lines) - `--json`: prints structured payload + metadata -- Optional delivery back to a provider with `--deliver` + `--provider` (target formats match `clawdbot message --to`). +- Optional delivery back to a channel with `--deliver` + `--channel` (target formats match `clawdbot message --to`). If the Gateway is unreachable, the CLI **falls back** to the embedded local run. @@ -35,9 +35,9 @@ clawdbot agent --to +15555550123 --message "Summon reply" --deliver ## Flags -- `--local`: run locally (requires provider keys in your shell) -- `--deliver`: send the reply to the chosen provider (requires `--to`) -- `--provider`: `whatsapp|telegram|discord|slack|signal|imessage` (default: `whatsapp`) +- `--local`: run locally (requires model provider API keys in your shell) +- `--deliver`: send the reply to the chosen channel (requires `--to`) +- `--channel`: `whatsapp|telegram|discord|slack|signal|imessage` (default: `whatsapp`) - `--thinking `: persist thinking level (GPT-5.2 + Codex models only) - `--verbose `: persist verbose level - `--timeout `: override agent timeout