@spinabot/brigade 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/convex/channels.d.ts +5 -5
- package/convex/schema.d.ts +2 -2
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +27 -4
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/approval-callback-codec.d.ts +107 -0
- package/dist/agents/channels/approval-callback-codec.d.ts.map +1 -0
- package/dist/agents/channels/approval-callback-codec.js +173 -0
- package/dist/agents/channels/approval-callback-codec.js.map +1 -0
- package/dist/agents/channels/approval-router.d.ts +77 -20
- package/dist/agents/channels/approval-router.d.ts.map +1 -1
- package/dist/agents/channels/approval-router.js +163 -37
- package/dist/agents/channels/approval-router.js.map +1 -1
- package/dist/agents/channels/backoff.d.ts +55 -0
- package/dist/agents/channels/backoff.d.ts.map +1 -0
- package/dist/agents/channels/backoff.js +47 -0
- package/dist/agents/channels/backoff.js.map +1 -0
- package/dist/agents/channels/channel-secrets.d.ts +45 -0
- package/dist/agents/channels/channel-secrets.d.ts.map +1 -0
- package/dist/agents/channels/channel-secrets.js +69 -0
- package/dist/agents/channels/channel-secrets.js.map +1 -0
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +67 -3
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/channels/last-sent-message.d.ts +46 -0
- package/dist/agents/channels/last-sent-message.d.ts.map +1 -0
- package/dist/agents/channels/last-sent-message.js +55 -0
- package/dist/agents/channels/last-sent-message.js.map +1 -0
- package/dist/agents/channels/manager.d.ts +52 -0
- package/dist/agents/channels/manager.d.ts.map +1 -1
- package/dist/agents/channels/manager.js +141 -31
- package/dist/agents/channels/manager.js.map +1 -1
- package/dist/agents/channels/plugin-channel-manager-facade.d.ts +13 -2
- package/dist/agents/channels/plugin-channel-manager-facade.d.ts.map +1 -1
- package/dist/agents/channels/plugin-channel-manager-facade.js +21 -0
- package/dist/agents/channels/plugin-channel-manager-facade.js.map +1 -1
- package/dist/agents/channels/sdk.d.ts +426 -0
- package/dist/agents/channels/sdk.d.ts.map +1 -0
- package/dist/agents/channels/sdk.js +274 -0
- package/dist/agents/channels/sdk.js.map +1 -0
- package/dist/agents/channels/telegram/account-config.d.ts +92 -0
- package/dist/agents/channels/telegram/account-config.d.ts.map +1 -0
- package/dist/agents/channels/telegram/account-config.js +192 -0
- package/dist/agents/channels/telegram/account-config.js.map +1 -0
- package/dist/agents/channels/telegram/adapter.d.ts +79 -0
- package/dist/agents/channels/telegram/adapter.d.ts.map +1 -0
- package/dist/agents/channels/telegram/adapter.js +475 -0
- package/dist/agents/channels/telegram/adapter.js.map +1 -0
- package/dist/agents/channels/telegram/allowed-updates.d.ts +44 -0
- package/dist/agents/channels/telegram/allowed-updates.d.ts.map +1 -0
- package/dist/agents/channels/telegram/allowed-updates.js +52 -0
- package/dist/agents/channels/telegram/allowed-updates.js.map +1 -0
- package/dist/agents/channels/telegram/approval-authorize.d.ts +41 -0
- package/dist/agents/channels/telegram/approval-authorize.d.ts.map +1 -0
- package/dist/agents/channels/telegram/approval-authorize.js +69 -0
- package/dist/agents/channels/telegram/approval-authorize.js.map +1 -0
- package/dist/agents/channels/telegram/approval-native.d.ts +68 -0
- package/dist/agents/channels/telegram/approval-native.d.ts.map +1 -0
- package/dist/agents/channels/telegram/approval-native.js +94 -0
- package/dist/agents/channels/telegram/approval-native.js.map +1 -0
- package/dist/agents/channels/telegram/command-menu.d.ts +35 -0
- package/dist/agents/channels/telegram/command-menu.d.ts.map +1 -0
- package/dist/agents/channels/telegram/command-menu.js +59 -0
- package/dist/agents/channels/telegram/command-menu.js.map +1 -0
- package/dist/agents/channels/telegram/connection.d.ts +359 -0
- package/dist/agents/channels/telegram/connection.d.ts.map +1 -0
- package/dist/agents/channels/telegram/connection.js +865 -0
- package/dist/agents/channels/telegram/connection.js.map +1 -0
- package/dist/agents/channels/telegram/format.d.ts +48 -0
- package/dist/agents/channels/telegram/format.d.ts.map +1 -0
- package/dist/agents/channels/telegram/format.js +256 -0
- package/dist/agents/channels/telegram/format.js.map +1 -0
- package/dist/agents/channels/telegram/inbound-extras.d.ts +73 -0
- package/dist/agents/channels/telegram/inbound-extras.d.ts.map +1 -0
- package/dist/agents/channels/telegram/inbound-extras.js +231 -0
- package/dist/agents/channels/telegram/inbound-extras.js.map +1 -0
- package/dist/agents/channels/telegram/index.d.ts +14 -0
- package/dist/agents/channels/telegram/index.d.ts.map +1 -0
- package/dist/agents/channels/telegram/index.js +14 -0
- package/dist/agents/channels/telegram/index.js.map +1 -0
- package/dist/agents/channels/telegram/media.d.ts +68 -0
- package/dist/agents/channels/telegram/media.d.ts.map +1 -0
- package/dist/agents/channels/telegram/media.js +143 -0
- package/dist/agents/channels/telegram/media.js.map +1 -0
- package/dist/agents/channels/telegram/module.d.ts +15 -0
- package/dist/agents/channels/telegram/module.d.ts.map +1 -0
- package/dist/agents/channels/telegram/module.js +36 -0
- package/dist/agents/channels/telegram/module.js.map +1 -0
- package/dist/agents/channels/telegram/plugin.d.ts +76 -0
- package/dist/agents/channels/telegram/plugin.d.ts.map +1 -0
- package/dist/agents/channels/telegram/plugin.js +314 -0
- package/dist/agents/channels/telegram/plugin.js.map +1 -0
- package/dist/agents/channels/telegram/probe.d.ts +54 -0
- package/dist/agents/channels/telegram/probe.d.ts.map +1 -0
- package/dist/agents/channels/telegram/probe.js +95 -0
- package/dist/agents/channels/telegram/probe.js.map +1 -0
- package/dist/agents/channels/telegram/webhook.d.ts +55 -0
- package/dist/agents/channels/telegram/webhook.d.ts.map +1 -0
- package/dist/agents/channels/telegram/webhook.js +141 -0
- package/dist/agents/channels/telegram/webhook.js.map +1 -0
- package/dist/agents/extensions/modules/index.d.ts.map +1 -1
- package/dist/agents/extensions/modules/index.js +4 -0
- package/dist/agents/extensions/modules/index.js.map +1 -1
- package/dist/agents/extensions/types.d.ts +72 -2
- package/dist/agents/extensions/types.d.ts.map +1 -1
- package/dist/agents/extensions/types.js.map +1 -1
- package/dist/agents/tools/connect-channel-tool.d.ts +86 -0
- package/dist/agents/tools/connect-channel-tool.d.ts.map +1 -0
- package/dist/agents/tools/connect-channel-tool.js +398 -0
- package/dist/agents/tools/connect-channel-tool.js.map +1 -0
- package/dist/agents/tools/message-action-tool.d.ts +67 -0
- package/dist/agents/tools/message-action-tool.d.ts.map +1 -0
- package/dist/agents/tools/message-action-tool.js +216 -0
- package/dist/agents/tools/message-action-tool.js.map +1 -0
- package/dist/agents/tools/registry.d.ts.map +1 -1
- package/dist/agents/tools/registry.js +19 -0
- package/dist/agents/tools/registry.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/channels.d.ts.map +1 -1
- package/dist/cli/commands/channels.js +27 -2
- package/dist/cli/commands/channels.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +77 -27
- package/dist/core/server.js.map +1 -1
- package/dist/cron/service/state.d.ts +10 -0
- package/dist/cron/service/state.d.ts.map +1 -1
- package/dist/cron/service/state.js.map +1 -1
- package/dist/cron/service/timer.d.ts.map +1 -1
- package/dist/cron/service/timer.js +43 -14
- package/dist/cron/service/timer.js.map +1 -1
- package/dist/cron/session-reaper.d.ts +27 -0
- package/dist/cron/session-reaper.d.ts.map +1 -1
- package/dist/cron/session-reaper.js +81 -0
- package/dist/cron/session-reaper.js.map +1 -1
- package/dist/system-prompt/assembler.d.ts +14 -0
- package/dist/system-prompt/assembler.d.ts.map +1 -1
- package/dist/system-prompt/assembler.js +36 -14
- package/dist/system-prompt/assembler.js.map +1 -1
- package/package.json +16 -3
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ════════════════════════════════════════════════════════════════════════════
|
|
3
|
+
* Brigade Channel SDK — the COMPLETE surface for authoring a channel
|
|
4
|
+
* ════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
*
|
|
6
|
+
* One import for everything a new channel adapter (Slack, Discord, iMessage, …)
|
|
7
|
+
* needs: the CONTRACT it implements (BOTH the single-account `ChannelAdapter`
|
|
8
|
+
* AND the multi-account `ChannelPlugin`), the SHARED HELPERS every channel
|
|
9
|
+
* reuses (the inbound pipeline, the approval router, the last-channel pin), and
|
|
10
|
+
* the central capabilities (inline-button approvals, message actions, the
|
|
11
|
+
* durable token seal, the webhook HTTP route). The goal is that the NEXT channel
|
|
12
|
+
* — including a multi-account + webhook + native-commands channel like Discord —
|
|
13
|
+
* is built ENTIRELY on this barrel: no reaching across into `whatsapp/`,
|
|
14
|
+
* `../types.*`, `../inbound-pipeline`, `../approval-router`, `../manager`, or
|
|
15
|
+
* `../../extensions/` for a stray type or helper.
|
|
16
|
+
*
|
|
17
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
18
|
+
* TWO AUTHORING PATHS
|
|
19
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* A. SINGLE-ACCOUNT adapter (`ChannelAdapter`) — one live connection per
|
|
22
|
+
* gateway, started by the legacy `startChannels` manager. Simplest path;
|
|
23
|
+
* implement `start/stop/sendText/…` and register via `b.channel(adapter)`.
|
|
24
|
+
*
|
|
25
|
+
* B. MULTI-ACCOUNT plugin (`ChannelPlugin`) — run N accounts of the same
|
|
26
|
+
* channel at once (`channels.<id>.accounts: [{ id, … }, …]`). You implement
|
|
27
|
+
* the sub-adapters (`config`/`gateway`/`outbound`/`security`/`status`/
|
|
28
|
+
* `actions`/`secrets`/`approvalCapability`), partition per-account runtime
|
|
29
|
+
* state in a `Map<accountId, …>`, and drive each account's inbound through
|
|
30
|
+
* the SHARED `runChannelInboundPipeline` so every account carries the
|
|
31
|
+
* identical ACL + debounce + abort + approval surface. Telegram's
|
|
32
|
+
* `plugin.ts` is the reference; mirror it.
|
|
33
|
+
*
|
|
34
|
+
* Most real channels ship BOTH: the `ChannelAdapter` is the per-connection
|
|
35
|
+
* worker, and the `ChannelPlugin` wraps `createXAdapter()` once per account.
|
|
36
|
+
*
|
|
37
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
38
|
+
* HOW TO AUTHOR A CHANNEL — the 8-file skeleton
|
|
39
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
40
|
+
*
|
|
41
|
+
* Mirror the `telegram/` layout (the reference token-based channel):
|
|
42
|
+
*
|
|
43
|
+
* channels/<id>/
|
|
44
|
+
* ├─ module.ts register: `defineModule({ id, register(b){ b.channel(createXAdapter()) } })`
|
|
45
|
+
* ├─ adapter.ts implement `ChannelAdapter` (id/label/start/stop/sendText/…)
|
|
46
|
+
* ├─ plugin.ts implement `ChannelPlugin` (multi-account: config/gateway/outbound/…)
|
|
47
|
+
* ├─ connection.ts the live transport (lazy-import the heavy SDK here)
|
|
48
|
+
* ├─ account-config.ts resolve per-account config + token (see secret seal below)
|
|
49
|
+
* ├─ format.ts markdown → the channel's native markup
|
|
50
|
+
* ├─ inbound-extras.ts normalize provider payloads → `InboundMessage` fields
|
|
51
|
+
* ├─ command-menu.ts map `buildBundledCommands(adapter)` → native `/`-menu (optional)
|
|
52
|
+
* ├─ webhook.ts build the inbound `HttpRoute` for push transport (optional)
|
|
53
|
+
* ├─ media.ts in/out media (run `validateOutboundMediaPath` on send)
|
|
54
|
+
* └─ index.ts re-export the public surface
|
|
55
|
+
*
|
|
56
|
+
* plus tests alongside each (`*.test.ts`).
|
|
57
|
+
*
|
|
58
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
59
|
+
* REGISTRATION
|
|
60
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
61
|
+
*
|
|
62
|
+
* 1. `module.ts` calls `b.channel(createXAdapter())` inside `defineModule`.
|
|
63
|
+
* 2. Add the module to the bundled module list (`extensions/modules/index.ts`).
|
|
64
|
+
* 3. Account config lives under `~/.brigade/channels/<id>/<accountId>/`.
|
|
65
|
+
* 4. Lazy-import the heavy transport SDK inside `connection.ts` (Baileys /
|
|
66
|
+
* grammY style) so a non-X boot never pays for it.
|
|
67
|
+
* 5. Implement reconnect with `nextBackoffDelay({ attempt, initialMs, maxMs,
|
|
68
|
+
* factor, jitter })` (do NOT hand-roll the curve) + a capped attempt count.
|
|
69
|
+
* 6. Run inbound through dedupe (`createDedupeCache`) and outbound media
|
|
70
|
+
* through `validateOutboundMediaPath` before uploading bytes.
|
|
71
|
+
*
|
|
72
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
73
|
+
* MULTI-ACCOUNT PLUGIN PATH (`ChannelPlugin`)
|
|
74
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
75
|
+
*
|
|
76
|
+
* 1. Declare `id` / `meta` / `capabilities` / `config` (required) plus the
|
|
77
|
+
* sub-adapters you support (`gateway`/`outbound`/`security`/`status`/
|
|
78
|
+
* `actions`/`secrets`/`approvalCapability`). Omit a slot to opt out; the
|
|
79
|
+
* manager pre-checks `capabilities.<flag>` before calling an adapter.
|
|
80
|
+
* 2. `config.listAccountIds(cfg)` + `config.resolveAccount(cfg, id)` drive
|
|
81
|
+
* multi-account discovery. Make the legacy single-account `ChannelAdapter`
|
|
82
|
+
* STEP ASIDE when >1 account is configured (its `isConfigured` returns
|
|
83
|
+
* false for the default account) so the two paths never double-start.
|
|
84
|
+
* 3. In `gateway.startAccount`, build a per-account pipeline with
|
|
85
|
+
* `createInboundPipelineContext({ adapter, config, agentId, runTurn,
|
|
86
|
+
* commandMap, parentAbort })` and feed each inbound through
|
|
87
|
+
* `runChannelInboundPipeline(pipeline, msg)` (stamp `msg.accountId`).
|
|
88
|
+
* Build the command map from `buildBundledCommands(adapter)`.
|
|
89
|
+
* 4. Register a PER-ACCOUNT approval dispatcher with
|
|
90
|
+
* `registerChannelApprovalDispatcher(channelId, accountId, dispatcher)` on
|
|
91
|
+
* start and `removeChannelApprovalDispatcher(channelId, accountId)` on stop,
|
|
92
|
+
* so an exec-gate prompt raised by a turn on (channel, accountId) replies on
|
|
93
|
+
* that same account — not the channel default.
|
|
94
|
+
* 5. Take `runTurn` from the gateway via `StartChannelsArgs["runTurn"]`.
|
|
95
|
+
*
|
|
96
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
97
|
+
* WEBHOOK / PUSH TRANSPORT (`HttpRoute`)
|
|
98
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
99
|
+
*
|
|
100
|
+
* For channels that receive updates via an inbound POST (Telegram webhook
|
|
101
|
+
* mode, Slack Events API, …) instead of long-polling:
|
|
102
|
+
* • Build an `HttpRoute` (the `HttpRoute` type is re-exported here) whose
|
|
103
|
+
* handler verifies the provider's signature / secret header FIRST (before
|
|
104
|
+
* parsing the body), then feeds the parsed update into the started
|
|
105
|
+
* adapter's normalize+dedupe+dispatch path.
|
|
106
|
+
* • Register it from `module.ts` via `b.httpRoute(route)`, gated on config so
|
|
107
|
+
* a default polling install exposes NO inbound HTTP surface.
|
|
108
|
+
* • Set `auth: "none"` ONLY when the provider authenticates via a signed
|
|
109
|
+
* payload the handler verifies itself (the gateway can't present operator-
|
|
110
|
+
* auth to a third-party webhook); otherwise use `auth: "operator"`.
|
|
111
|
+
*
|
|
112
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
113
|
+
* NATIVE COMMAND MENU
|
|
114
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
115
|
+
*
|
|
116
|
+
* Brigade owns the channel command set centrally (`buildBundledCommands(adapter)`
|
|
117
|
+
* → `/help`, `/status`, `/allowlist`, `/agent`, `/agents`, `/whoami`, `/org`,
|
|
118
|
+
* plus module-registered `ChannelCommand`s). A channel with a native `/`-menu
|
|
119
|
+
* (Telegram `setMyCommands`, Discord application commands) maps that set onto
|
|
120
|
+
* the provider's shape on connect — see `telegram/command-menu.ts`. Advertise
|
|
121
|
+
* `capabilities.nativeCommands: true`.
|
|
122
|
+
*
|
|
123
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
124
|
+
* OPTING INTO CENTRAL CAPABILITIES
|
|
125
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
126
|
+
*
|
|
127
|
+
* • Inline-button approvals: set `adapter.approvalCapability.sendApprovalPrompt`
|
|
128
|
+
* (render `buildApprovalCallbackButtons(approvalId)` as native buttons whose
|
|
129
|
+
* `callback_data` is each button's `.data`). Deliver the press back as
|
|
130
|
+
* `InboundMessage.callbackQuery` — the central pipeline decodes + resolves
|
|
131
|
+
* it. Add `authorizeApprover` to refuse non-operator pressers.
|
|
132
|
+
* • Message actions (edit / delete / react / pin): implement
|
|
133
|
+
* `adapter.handleAction(...)` and advertise the matching `capabilities`
|
|
134
|
+
* flags (`edit` / `unsend` / `reactions` / `reply`). The central
|
|
135
|
+
* `message_action` tool pre-checks the flag before calling you.
|
|
136
|
+
* • Outbound id: return `{ messageId }` from `sendText`/`sendMedia` so the
|
|
137
|
+
* agent can reference "my last message" via `message_action`.
|
|
138
|
+
* • Durable token: `connect_channel` seals tokens via `sealChannelToken`;
|
|
139
|
+
* read yours back at start with `readSealedChannelToken("<id>")` as a token
|
|
140
|
+
* source (survives a gateway reboot when the live env is gone).
|
|
141
|
+
*
|
|
142
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
143
|
+
* ENUMERATION TESTS TO UPDATE when you add a channel-related agent tool
|
|
144
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
145
|
+
*
|
|
146
|
+
* • `agents/tools/registry.test.ts` — the sorted tool-name list + count
|
|
147
|
+
* • `agents/session-wiring.test.ts` — the brigade-tool list + counts
|
|
148
|
+
* • `agents/tools/owner-only.test.ts` — the customTools count + name list
|
|
149
|
+
*
|
|
150
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
151
|
+
* DESIGN NOTE — RE-EXPORT, never RELOCATE
|
|
152
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
153
|
+
*
|
|
154
|
+
* Helpers like `chunkText` physically live where they were first written
|
|
155
|
+
* (`whatsapp/chunk.js`) and WhatsApp imports them directly. Moving a file would
|
|
156
|
+
* change WhatsApp's import and risk the one channel that works perfectly, so
|
|
157
|
+
* this barrel RE-EXPORTS from where things already are — it has zero runtime
|
|
158
|
+
* behaviour of its own. The codec + the durable-seal + the backoff helper DO
|
|
159
|
+
* live in `channels/` (they are channel-neutral by design) and are re-exported
|
|
160
|
+
* here as the canonical author-facing surface.
|
|
161
|
+
*/
|
|
162
|
+
export {
|
|
163
|
+
/** Register a channel through the extension seam: `defineModule({ id, register(b){ b.channel(adapter) } })`. */
|
|
164
|
+
defineModule, } from "../extensions/types.js";
|
|
165
|
+
export type {
|
|
166
|
+
/** The channel contract every adapter implements (start/stop/sendText/handleAction/…). */
|
|
167
|
+
ChannelAdapter,
|
|
168
|
+
/** A normalized inbound message handed to `ChannelStartContext.onInbound`. */
|
|
169
|
+
InboundMessage,
|
|
170
|
+
/** Inbound media attachment saved to disk (image / voice / document / …). */
|
|
171
|
+
InboundMediaAttachment,
|
|
172
|
+
/** Quoted-reply context an inbound carries when it replies to a prior message. */
|
|
173
|
+
InboundReplyContext,
|
|
174
|
+
/** What the manager passes to `adapter.start(ctx)` — onInbound, log, signal, pairing hooks. */
|
|
175
|
+
ChannelStartContext,
|
|
176
|
+
/** Synchronous health verdict an adapter exposes via `health()`. */
|
|
177
|
+
ChannelHealth,
|
|
178
|
+
/** A `/command` handler a channel can register. */
|
|
179
|
+
ChannelCommand,
|
|
180
|
+
/** Context handed to a channel `/command` handler. */
|
|
181
|
+
ChannelCommandContext,
|
|
182
|
+
/** Per-channel pairing customization (idLabel, allow-entry normalize, approve notify). */
|
|
183
|
+
ChannelPairingAdapter,
|
|
184
|
+
/** Declarative setup wizard (`brigade channels add`) credential prompts. */
|
|
185
|
+
ChannelSetupAdapter,
|
|
186
|
+
/** One credential key the setup wizard prompts for. */
|
|
187
|
+
ChannelSetupCredentialKey,
|
|
188
|
+
/** Outbound media descriptor for `adapter.sendMedia(...)`. */
|
|
189
|
+
OutboundMedia,
|
|
190
|
+
/** Per-send options (threadId, accountId) for `adapter.sendText(...)`. */
|
|
191
|
+
OutboundSendOptions,
|
|
192
|
+
/** The module shape `defineModule` returns / consumes. */
|
|
193
|
+
BrigadeModule, } from "../extensions/types.js";
|
|
194
|
+
export type {
|
|
195
|
+
/** Static capability flags a channel advertises (`reactions`/`edit`/`unsend`/`reply`/`media`/…). */
|
|
196
|
+
ChannelCapabilities, } from "./types.core.js";
|
|
197
|
+
export type {
|
|
198
|
+
/** The action union the agent can take on a message (reply/react/edit/delete/pin/unpin). */
|
|
199
|
+
ChannelMessageAction,
|
|
200
|
+
/** Result of a message action ({ ok, messageId?, error? }). */
|
|
201
|
+
ChannelMessageActionResult,
|
|
202
|
+
/** The native inline-button approval capability an adapter opts into. */
|
|
203
|
+
ChannelApprovalCapability,
|
|
204
|
+
/** Approval prompt params handed to `sendApprovalPrompt`. */
|
|
205
|
+
ChannelApprovalPromptParams,
|
|
206
|
+
/** Approval kind discriminator ("exec" | "plugin"). */
|
|
207
|
+
ChannelApprovalKind,
|
|
208
|
+
/** Decision kinds an approval button can encode. */
|
|
209
|
+
ChannelApprovalDecisionKind,
|
|
210
|
+
/** Outcome params for `formatApprovalOutcome`. */
|
|
211
|
+
ChannelApprovalOutcomeParams,
|
|
212
|
+
/** A config-path entry declaring a secret-ref target for the secrets system. */
|
|
213
|
+
SecretTargetRegistryEntry, } from "./types.adapters.js";
|
|
214
|
+
export {
|
|
215
|
+
/**
|
|
216
|
+
* Split a long outbound message into provider-safe chunks WITHOUT shredding
|
|
217
|
+
* code fences / paragraphs. Lives under `whatsapp/` for history; it is
|
|
218
|
+
* channel-agnostic (Telegram reuses it with `{ limit: 4096 }`). Re-exported
|
|
219
|
+
* here so new channels don't reach across into the WhatsApp folder.
|
|
220
|
+
*/
|
|
221
|
+
chunkText, } from "./whatsapp/chunk.js";
|
|
222
|
+
export {
|
|
223
|
+
/** Build a per-channel inbound dedupe cache (claim-once, LRU + TTL). */
|
|
224
|
+
createDedupeCache, } from "./dedupe.js";
|
|
225
|
+
export type { DedupeCache, DedupeOptions } from "./dedupe.js";
|
|
226
|
+
export {
|
|
227
|
+
/**
|
|
228
|
+
* Refuse to ATTACH a local secret / system file on outbound media — the
|
|
229
|
+
* content-exfil guard every `sendMedia` path must run before uploading
|
|
230
|
+
* a local path's bytes to a conversation.
|
|
231
|
+
*/
|
|
232
|
+
validateOutboundMediaPath, } from "../../security/media-path-guard.js";
|
|
233
|
+
export type { MediaPathVerdict } from "../../security/media-path-guard.js";
|
|
234
|
+
export {
|
|
235
|
+
/** Named JSON subsystem logger — `createSubsystemLogger("channels/<id>")`. */
|
|
236
|
+
createSubsystemLogger, } from "../../logging/subsystem-logger.js";
|
|
237
|
+
export type { SubsystemLogger } from "../../logging/subsystem-logger.js";
|
|
238
|
+
export {
|
|
239
|
+
/**
|
|
240
|
+
* Jittered exponential reconnect-delay helper shared by every channel.
|
|
241
|
+
* Pass the schedule ({ attempt, initialMs, maxMs, factor, jitter }); the
|
|
242
|
+
* arithmetic is WhatsApp's proven curve. WhatsApp + Telegram both delegate
|
|
243
|
+
* to it; a new channel should too instead of hand-rolling its own.
|
|
244
|
+
*/
|
|
245
|
+
nextBackoffDelay, } from "./backoff.js";
|
|
246
|
+
export type { BackoffSchedule } from "./backoff.js";
|
|
247
|
+
export {
|
|
248
|
+
/** Encode `{ approvalId, decision }` into a <=64-byte callback payload (undefined if oversized). */
|
|
249
|
+
encodeApprovalCallback,
|
|
250
|
+
/** Decode a callback payload back to `{ approvalId, decision }` (null if not ours / malformed). */
|
|
251
|
+
decodeApprovalCallback,
|
|
252
|
+
/** True iff a string fits the universal 64-byte callback-data budget. */
|
|
253
|
+
fitsApprovalCallback,
|
|
254
|
+
/** Build the standard Allow once / Allow always / Deny buttons (label + encoded payload). */
|
|
255
|
+
buildApprovalCallbackButtons,
|
|
256
|
+
/** The universal callback-data byte ceiling (Telegram's 64). */
|
|
257
|
+
APPROVAL_CALLBACK_MAX_BYTES, } from "./approval-callback-codec.js";
|
|
258
|
+
export type {
|
|
259
|
+
/** Decisions an inline approval button can encode. */
|
|
260
|
+
ApprovalCallbackDecision,
|
|
261
|
+
/** One inline approval button: label + decision + encoded payload. */
|
|
262
|
+
ApprovalCallbackButton, } from "./approval-callback-codec.js";
|
|
263
|
+
export {
|
|
264
|
+
/** Durably seal a channel's token into the encrypted credential store (survives reboot). */
|
|
265
|
+
sealChannelToken,
|
|
266
|
+
/** Read a channel's durably-sealed token (""→ none) at start time, no agent context needed. */
|
|
267
|
+
readSealedChannelToken,
|
|
268
|
+
/** Provider key a channel's token is sealed under (`channel:<id>`). */
|
|
269
|
+
channelSecretProvider, } from "./channel-secrets.js";
|
|
270
|
+
export type {
|
|
271
|
+
/**
|
|
272
|
+
* The MULTI-ACCOUNT channel contract. Wrap your `createXAdapter()` once per
|
|
273
|
+
* configured account; declare `id`/`meta`/`capabilities`/`config` (required)
|
|
274
|
+
* plus the sub-adapter slots you support. Generic over the channel's resolved
|
|
275
|
+
* per-account state (and optional probe/audit payload shapes).
|
|
276
|
+
*/
|
|
277
|
+
ChannelPlugin, } from "./types.plugin.js";
|
|
278
|
+
export type {
|
|
279
|
+
/** Canonical kebab-case plugin id (also the `cfg.channels.<id>` key + dir name). */
|
|
280
|
+
ChannelId,
|
|
281
|
+
/** User-facing display metadata (labels, blurb, docs path, ordering, exposure). */
|
|
282
|
+
ChannelMeta,
|
|
283
|
+
/** Exposure tier controlling which setup surfaces list the channel. */
|
|
284
|
+
ChannelExposure,
|
|
285
|
+
/** Per-account lifecycle state surfaced by `brigade status`. */
|
|
286
|
+
ChannelAccountState,
|
|
287
|
+
/** Open-shaped per-account snapshot row returned by `status.buildAccountSnapshot`. */
|
|
288
|
+
ChannelAccountSnapshot,
|
|
289
|
+
/** A single status row for `status.collectStatusIssues`. */
|
|
290
|
+
ChannelStatusIssue,
|
|
291
|
+
/** One diagnostic line emitted by `status.formatCapabilitiesProbe`. */
|
|
292
|
+
ChannelCapabilitiesDisplayLine,
|
|
293
|
+
/** Diagnostics block emitted by `status.buildCapabilitiesDiagnostics`. */
|
|
294
|
+
ChannelCapabilitiesDiagnostics,
|
|
295
|
+
/** Cross-cutting runtime context (logger + abort signal) handed to side-effect adapters. */
|
|
296
|
+
RuntimeEnv, } from "./types.core.js";
|
|
297
|
+
export type {
|
|
298
|
+
/** Adapter 1 — account discovery + enable/disable/resolve (always required). */
|
|
299
|
+
ChannelConfigAdapter,
|
|
300
|
+
/** Adapter 2 — per-account inbound listener lifecycle (start/stop/logout) + webhook auth-bypass paths. */
|
|
301
|
+
ChannelGatewayAdapter,
|
|
302
|
+
/** Per-account context handed to `gateway.startAccount` / `stopAccount`. */
|
|
303
|
+
ChannelGatewayContext,
|
|
304
|
+
/** Per-account context handed to `gateway.logoutAccount` (carries `purge`). */
|
|
305
|
+
ChannelLogoutContext,
|
|
306
|
+
/** Result of `gateway.logoutAccount`. */
|
|
307
|
+
ChannelLogoutResult,
|
|
308
|
+
/** Adapter 3 — outbound dispatch (sendText / sendMedia / sendReaction). */
|
|
309
|
+
ChannelOutboundAdapter,
|
|
310
|
+
/** Reusable outbound address shape ({ channel, to, accountId?, threadId? }). */
|
|
311
|
+
ChannelOutboundTarget,
|
|
312
|
+
/** Adapter 4 — DM-policy decisions + doctor warnings + audit findings. */
|
|
313
|
+
ChannelSecurityAdapter,
|
|
314
|
+
/** Per-call context for the security adapter's check methods. */
|
|
315
|
+
ChannelSecurityContext,
|
|
316
|
+
/** DM policy verdict ("owner" | "allow-from" | "all"). */
|
|
317
|
+
ChannelSecurityDmPolicy,
|
|
318
|
+
/** A single structured finding from `security.collectAuditFindings`. */
|
|
319
|
+
ChannelSecurityAuditFinding,
|
|
320
|
+
/** Adapter 5 — config-change / removal / startup-maintenance hooks. */
|
|
321
|
+
ChannelLifecycleAdapter,
|
|
322
|
+
/** Adapter 6 — probe + snapshot + diagnostics for `brigade status`. */
|
|
323
|
+
ChannelStatusAdapter,
|
|
324
|
+
/** Adapter 7 — tool-driven message actions (reply/react/edit/delete dispatch). */
|
|
325
|
+
ChannelMessageActionAdapter,
|
|
326
|
+
/** Adapter 8 — secret-target registry entries for the secrets system. */
|
|
327
|
+
ChannelSecretsAdapter,
|
|
328
|
+
/**
|
|
329
|
+
* Bivariance box for adapter callbacks that need a narrower `account` type at
|
|
330
|
+
* the call site than the manager's generic (lets the rename through, no `as`).
|
|
331
|
+
*/
|
|
332
|
+
BivariantCallback, } from "./types.adapters.js";
|
|
333
|
+
export {
|
|
334
|
+
/**
|
|
335
|
+
* Run ONE inbound message end-to-end through the shared pipeline (media + reply
|
|
336
|
+
* note synthesis → access gate → mark-read → approval-callback + approval-reply
|
|
337
|
+
* intercept → abort triggers → channel command → 8-tier route → last-channel pin
|
|
338
|
+
* → optional debounce → dispatchTurn → reply). Never throws. Both the legacy
|
|
339
|
+
* manager and every multi-account plugin call THIS so the safety surface is
|
|
340
|
+
* identical on every channel.
|
|
341
|
+
*/
|
|
342
|
+
runChannelInboundPipeline,
|
|
343
|
+
/** Build a fresh per-channel-instance pipeline context (per account on the plugin path). */
|
|
344
|
+
createInboundPipelineContext,
|
|
345
|
+
/**
|
|
346
|
+
* Build the bundled built-in channel commands (`/help`, `/status`, `/allowlist`,
|
|
347
|
+
* `/agent`, `/agents`, `/whoami`, `/org`) an operator can DM to admin the bot.
|
|
348
|
+
* Feed the result into your `commandMap` AND into a native command menu.
|
|
349
|
+
*/
|
|
350
|
+
buildBundledCommands,
|
|
351
|
+
/** Disambiguating lane key for inflight + pending maps ((adapter, account, conversation, thread)). */
|
|
352
|
+
laneKey, } from "./inbound-pipeline.js";
|
|
353
|
+
export type {
|
|
354
|
+
/** Per-channel-instance pipeline context — captures every dispatch-time dep. */
|
|
355
|
+
InboundPipelineContext,
|
|
356
|
+
/** runTurn signature shared by the legacy manager and the plugin path. */
|
|
357
|
+
RunChannelTurnFn,
|
|
358
|
+
/** Result of one channel turn — only the reply text matters. */
|
|
359
|
+
ChannelTurnResult,
|
|
360
|
+
/** A pending debounce slot — accumulated text waiting to dispatch. */
|
|
361
|
+
PendingDispatch, } from "./inbound-pipeline.js";
|
|
362
|
+
export {
|
|
363
|
+
/**
|
|
364
|
+
* Register a (per-account) dispatcher so an exec-gate approval prompt raised by
|
|
365
|
+
* a channel-routed turn lands IN that conversation. Pass `(channelId, accountId,
|
|
366
|
+
* dispatcher)` on the multi-account path so each account routes to itself.
|
|
367
|
+
*/
|
|
368
|
+
registerChannelApprovalDispatcher,
|
|
369
|
+
/** Drop a channel's (per-account) dispatcher + deny its in-flight prompts on stop. */
|
|
370
|
+
removeChannelApprovalDispatcher,
|
|
371
|
+
/** Send an approval prompt via the channel + register the pending entry (called by the bridge). */
|
|
372
|
+
dispatchChannelApproval,
|
|
373
|
+
/** Intercept a yes/no TEXT reply as the answer to a pending approval for this peer. */
|
|
374
|
+
tryConsumeChannelApprovalReply,
|
|
375
|
+
/** Intercept an inline-BUTTON press (callback_query) as the answer to a pending approval. */
|
|
376
|
+
tryConsumeChannelApprovalCallback,
|
|
377
|
+
/** Cancel a pending approval by request id (e.g. on session abort). */
|
|
378
|
+
cancelChannelApprovalById,
|
|
379
|
+
/** Diagnostic — list registered dispatcher keys. */
|
|
380
|
+
listChannelApprovalDispatchers,
|
|
381
|
+
/** Diagnostic — snapshot of pending channel approvals. */
|
|
382
|
+
listPendingChannelApprovals, } from "./approval-router.js";
|
|
383
|
+
export type {
|
|
384
|
+
/** The route a channel-routed turn carries so its approval prompt comes back to the same peer. */
|
|
385
|
+
ChannelApprovalRoute,
|
|
386
|
+
/** Per-(account) dispatcher capability surface the router needs to ask the operator. */
|
|
387
|
+
ChannelApprovalDispatcher, } from "./approval-router.js";
|
|
388
|
+
export type {
|
|
389
|
+
/**
|
|
390
|
+
* The args the gateway hands `startChannels` at boot. A multi-account plugin
|
|
391
|
+
* takes its serialized turn executor as `StartChannelsArgs["runTurn"]` — the
|
|
392
|
+
* gateway funnels every channel turn through one queue so they never overlap.
|
|
393
|
+
* (`startChannels` itself is framework-internal: the gateway boots it, a
|
|
394
|
+
* channel never calls it.)
|
|
395
|
+
*/
|
|
396
|
+
StartChannelsArgs,
|
|
397
|
+
/** The live channel-manager handle the gateway owns (started ids, stop, adapter lookup, live start/stop). */
|
|
398
|
+
ChannelManager,
|
|
399
|
+
/** Outcome of a runtime single-channel start attempt. */
|
|
400
|
+
StartChannelResult,
|
|
401
|
+
/** Outcome of a runtime single-channel stop attempt. */
|
|
402
|
+
StopChannelResult, } from "./manager.js";
|
|
403
|
+
export {
|
|
404
|
+
/**
|
|
405
|
+
* Pin THIS channel as the agent's most-recently-active (called by the pipeline
|
|
406
|
+
* on every admitted inbound). A cron's announce-delivery reads it as the
|
|
407
|
+
* last-resort target when no explicit channel was set. The pipeline already
|
|
408
|
+
* calls this for you; a channel only calls it directly for a bespoke surface.
|
|
409
|
+
*/
|
|
410
|
+
recordLastChannelForAgent,
|
|
411
|
+
/** Read the agent's last-recorded channel (undefined when no channel activity yet). */
|
|
412
|
+
getLastChannelForAgent, } from "./last-channel.js";
|
|
413
|
+
export type {
|
|
414
|
+
/** One operator's most recently active channel + peer + thread record. */
|
|
415
|
+
LastChannelRecord, } from "./last-channel.js";
|
|
416
|
+
export type {
|
|
417
|
+
/**
|
|
418
|
+
* A module-registered HTTP route on the gateway's server. A push-transport
|
|
419
|
+
* channel (Telegram webhook, Slack Events API) builds one of these — verify the
|
|
420
|
+
* provider signature/secret in the handler, then feed the update into the
|
|
421
|
+
* adapter — and registers it via `b.httpRoute(route)` from `module.ts`.
|
|
422
|
+
*/
|
|
423
|
+
HttpRoute,
|
|
424
|
+
/** The handler signature an `HttpRoute` carries: `(req, res) => void | Promise<void>`. */
|
|
425
|
+
HttpRouteHandler, } from "../extensions/types.js";
|
|
426
|
+
//# sourceMappingURL=sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/agents/channels/sdk.ts"],"names":[],"mappings":"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"}
|