@owlmeans/bot 0.0.0-stage → 0.1.18-rc.2

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.
Files changed (99) hide show
  1. package/README.md +85 -2
  2. package/agent-meta/manifest.json +16 -0
  3. package/agent-meta/skills/bot/SKILL.md +187 -0
  4. package/build/consts.d.ts +132 -0
  5. package/build/consts.d.ts.map +1 -0
  6. package/build/consts.js +197 -0
  7. package/build/consts.js.map +1 -0
  8. package/build/consts.local.d.ts +13 -0
  9. package/build/consts.local.d.ts.map +1 -0
  10. package/build/consts.local.js +13 -0
  11. package/build/consts.local.js.map +1 -0
  12. package/build/errors.d.ts +43 -0
  13. package/build/errors.d.ts.map +1 -0
  14. package/build/errors.js +66 -0
  15. package/build/errors.js.map +1 -0
  16. package/build/helpers/command/types.d.ts +14 -0
  17. package/build/helpers/command/types.d.ts.map +1 -0
  18. package/build/helpers/command/types.js +2 -0
  19. package/build/helpers/command/types.js.map +1 -0
  20. package/build/helpers/command.d.ts +4 -0
  21. package/build/helpers/command.d.ts.map +1 -0
  22. package/build/helpers/command.js +21 -0
  23. package/build/helpers/command.js.map +1 -0
  24. package/build/helpers/index.d.ts +7 -0
  25. package/build/helpers/index.d.ts.map +1 -0
  26. package/build/helpers/index.js +4 -0
  27. package/build/helpers/index.js.map +1 -0
  28. package/build/helpers/platform/types.d.ts +12 -0
  29. package/build/helpers/platform/types.d.ts.map +1 -0
  30. package/build/helpers/platform/types.js +2 -0
  31. package/build/helpers/platform/types.js.map +1 -0
  32. package/build/helpers/platform.d.ts +4 -0
  33. package/build/helpers/platform.d.ts.map +1 -0
  34. package/build/helpers/platform.js +17 -0
  35. package/build/helpers/platform.js.map +1 -0
  36. package/build/helpers/rule/types.d.ts +26 -0
  37. package/build/helpers/rule/types.d.ts.map +1 -0
  38. package/build/helpers/rule/types.js +2 -0
  39. package/build/helpers/rule/types.js.map +1 -0
  40. package/build/helpers/rule.d.ts +4 -0
  41. package/build/helpers/rule.d.ts.map +1 -0
  42. package/build/helpers/rule.js +71 -0
  43. package/build/helpers/rule.js.map +1 -0
  44. package/build/index.d.ts +8 -0
  45. package/build/index.d.ts.map +1 -0
  46. package/build/index.js +6 -0
  47. package/build/index.js.map +1 -0
  48. package/build/protocols/types.d.ts +115 -0
  49. package/build/protocols/types.d.ts.map +1 -0
  50. package/build/protocols/types.js +2 -0
  51. package/build/protocols/types.js.map +1 -0
  52. package/build/protocols.d.ts +21 -0
  53. package/build/protocols.d.ts.map +1 -0
  54. package/build/protocols.js +70 -0
  55. package/build/protocols.js.map +1 -0
  56. package/build/schemas.d.ts +17 -0
  57. package/build/schemas.d.ts.map +1 -0
  58. package/build/schemas.js +140 -0
  59. package/build/schemas.js.map +1 -0
  60. package/build/types.d.ts +215 -0
  61. package/build/types.d.ts.map +1 -0
  62. package/build/types.js +2 -0
  63. package/build/types.js.map +1 -0
  64. package/build/utils/aliases/types.d.ts +30 -0
  65. package/build/utils/aliases/types.d.ts.map +1 -0
  66. package/build/utils/aliases/types.js +2 -0
  67. package/build/utils/aliases/types.js.map +1 -0
  68. package/build/utils/aliases.d.ts +4 -0
  69. package/build/utils/aliases.d.ts.map +1 -0
  70. package/build/utils/aliases.js +26 -0
  71. package/build/utils/aliases.js.map +1 -0
  72. package/package.json +42 -4
  73. package/src/consts.local.ts +14 -0
  74. package/src/consts.ts +214 -0
  75. package/src/errors.ts +78 -0
  76. package/src/helpers/command/types.ts +14 -0
  77. package/src/helpers/command.ts +26 -0
  78. package/src/helpers/index.ts +6 -0
  79. package/src/helpers/platform/types.ts +12 -0
  80. package/src/helpers/platform.ts +23 -0
  81. package/src/helpers/rule/types.ts +26 -0
  82. package/src/helpers/rule.ts +89 -0
  83. package/src/index.ts +7 -0
  84. package/src/protocols/types.ts +107 -0
  85. package/src/protocols.ts +121 -0
  86. package/src/schemas.ts +159 -0
  87. package/src/types.ts +228 -0
  88. package/src/utils/aliases/types.ts +25 -0
  89. package/src/utils/aliases.ts +30 -0
  90. package/tests/command.spec.ts +23 -0
  91. package/tests/context.ts +13 -0
  92. package/tests/errors.spec.ts +41 -0
  93. package/tests/platforms.spec.ts +60 -0
  94. package/tests/protocols.spec.ts +80 -0
  95. package/tests/rule.spec.ts +129 -0
  96. package/tests/schemas.spec.ts +102 -0
  97. package/tests/tsconfig.json +12 -0
  98. package/tests/update.spec.ts +38 -0
  99. package/tsconfig.json +8 -0
package/README.md CHANGED
@@ -1,3 +1,86 @@
1
- # Temporary Holding Version
1
+ # @owlmeans/bot
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The runtime-free, browser-safe contract of OwlMeans chat bots on Telegram, WhatsApp, Discord and
4
+ Slack: what each platform needs and can do, connections, keyword rules (groups) and the one
5
+ Unicode-aware matcher, the `/command` parser, normalized updates and activity, the managing and hook
6
+ protocol trees with their AJV schemas, and the bot error family. A shared package imports it to
7
+ declare the bot routes; a server, a store, the panels and an agent's tools build on it. It stores,
8
+ receives and sends nothing — that is `@owlmeans/server-bot`.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ bun add @owlmeans/bot@^0.1.18-rc.2
14
+ ```
15
+
16
+ ## Concepts
17
+
18
+ - **Connection** — one bot account on one platform, owned by a scope (an organization or the
19
+ application). Clients see `BotConnection`, never a credential; `credentialsSet` names the keys set.
20
+ - **Rule** — a keyword group: keywords, a match mode (`word` / `contains`) and what to do
21
+ (`BotRuleAction`). `connection: null` applies to every connection of the scope.
22
+ - **Update** — an inbound message normalized across platforms (`BotUpdate`), with the rules it
23
+ matched already in `matches`.
24
+ - **Activity** — one thing the bot did or tried (`BotActivity`), recorded with `ok` / `error`.
25
+ - **Descriptor** — `BOT_PLATFORMS[platform]`: credentials, receive modes, platform actions, setup.
26
+
27
+ ## Usage
28
+
29
+ ```typescript
30
+ import { DEFAULT_GUARD } from '@owlmeans/auth-common'
31
+ import { botCommandHelper, botRuleHelper, makeBotHookProtocols, makeBotProtocols } from '@owlmeans/bot'
32
+
33
+ export const botProtocols = Object.freeze({
34
+ operator: makeBotProtocols({ base: { alias: 'api:bot:operator', path: '/bot/operator' }, guards: DEFAULT_GUARD }),
35
+ hook: makeBotHookProtocols({ base: { alias: 'api:bot:hook', path: '/bot/hook' } }),
36
+ })
37
+
38
+ const matches = botRuleHelper.match('Free money at the CASINO!', rules) // enabled rules, by order
39
+ const command = botCommandHelper.parse('/report@MyBot spam', 'MyBot') // { name: 'report', args: 'spam' }
40
+ ```
41
+
42
+ ## API
43
+
44
+ - Enums: `BotPlatform`, `BotReceiveMode`, `BotTransport`, `BotConnectionStatus`, `BotActionKind`,
45
+ `BotRuleAction`, `BotMatchMode`, `BotUpdateKind`, `BotChatKind`
46
+ - Constants: `BOT_PLATFORMS`, `BOT_*` limits (`BOT_KEYWORDS_MAX`, `BOT_KEYWORD_MAX`,
47
+ `BOT_ACTIVITY_LIMIT_MAX`, `BOT_ID_PATTERN`, …)
48
+ - Helpers: `botRuleHelper` (`match`, `normalizeKeywords`, `appliesTo`), `botCommandHelper`
49
+ (`parse`), `botPlatformHelper` (`actionsOf`, `supports`)
50
+ - Protocols: `makeBotProtocols`, `makeBotHookProtocols` and their types (`BotProtocols`,
51
+ `BotHookProtocols`, `BotProtocolOptions`, `BotHookProtocolOptions`, …)
52
+ - Schemas: `BotConnectionInputSchema`, `BotRuleInputSchema`, `BotSimulateInputSchema`,
53
+ `BotIdParamsSchema`, `BotRuleListQuerySchema`, `BotActivityQuerySchema`, `BotHookParamsSchema`,
54
+ `BotChallengeQuerySchema`
55
+ - Errors: `BotError`, `BotConnectionNotFound` (404), `BotCredentialsRejected` (422),
56
+ `BotSignatureRejected` (401), `BotTransportMismatch` (409), `BotUnsupportedAction` (422)
57
+
58
+ ## Common pitfalls
59
+
60
+ - Never put a guard in front of the hook tree: the platform signs the raw body.
61
+ - Ask `botPlatformHelper.supports(...)` before an action — WhatsApp cannot delete, mute or ban;
62
+ Slack deletes only with the admin `userToken`.
63
+ - Use `contains` for scripts written without spaces; `word` matches whole words and phrases.
64
+
65
+ The `bot` skill covers matching, the protocols and how a generated target mounts them.
66
+
67
+ ## Related packages
68
+
69
+ - [`@owlmeans/entrypoint`](../entrypoint) — protocol declarations
70
+ - [`@owlmeans/planning`](../planning) — the same per-mount protocol-factory shape
71
+
72
+ <!-- owlmeans:agent-guidance:start -->
73
+ ## Agent guidance
74
+
75
+ This package ships embedded agent skills under `agent-meta/`. After installing your
76
+ `@owlmeans/*` packages, run the OwlMeans agent-skills installer to place them into
77
+ your project's skill store (`.agents/skills/`):
78
+
79
+ ```sh
80
+ npx @owlmeans/agent-skills@^0.1.18-rc.59
81
+ ```
82
+
83
+ The embedded files are version-matched to this package release. Do not edit them
84
+ directly — they are regenerated on each publish. To contribute guidance edits,
85
+ open a PR against the source monorepo.
86
+ <!-- owlmeans:agent-guidance:end -->
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 3,
3
+ "package": "@owlmeans/bot",
4
+ "version": "0.1.18-rc.2",
5
+ "generatedAt": "2026-10-26T22:23:53.842Z",
6
+ "canonicalRepo": "https://github.com/owlmeans/common",
7
+ "entries": [
8
+ {
9
+ "kind": "skill",
10
+ "name": "bot",
11
+ "category": "package-specific",
12
+ "file": "skills/bot/SKILL.md",
13
+ "canonicalPath": ".agents/skills/bot/SKILL.md"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: bot
3
+ description: How to use @owlmeans/bot — the runtime-free, browser-safe contract of OwlMeans chat bots on Telegram, WhatsApp, Discord and Slack. Covers the platform descriptors (credentials, receive modes, supported actions), connections, keyword rules (groups) and the Unicode-aware matcher, the /command parser, normalized updates and activity, the managing and hook protocol trees with their AJV schemas, the bot error family, and how a generated target mounts the operator, member and hook trees. Auto-invoked when importing from @owlmeans/bot, declaring bot routes, matching a message against keyword groups, or deciding what a platform can do.
4
+ user-invocable: false
5
+ ---
6
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
7
+
8
+ # @owlmeans/bot
9
+
10
+ **Layer:** Cross-cutting domain (contracts only)
11
+ **Install:** `"@owlmeans/bot": "^0.1.18-rc.2"` in `dependencies`
12
+ **Runtime-free:** no network, no storage, no logging — enums, descriptors, interfaces, AJV schemas
13
+ (plain objects), two pure helpers, protocol factories and registered errors. Safe in a browser.
14
+
15
+ A bot connection is ONE bot account on one platform, owned by a **scope** (the organization — or the
16
+ application itself — that runs it). Its **rules** are keyword groups: keywords + what to do with a
17
+ matching message. The server half (`@owlmeans/server-bot`) stores, verifies, receives, matches and
18
+ acts; `@owlmeans/bot-postgres` persists; `@owlmeans/web-bot` draws the panels; `@owlmeans/bot-agent`
19
+ gives an agent the actions as tools. Every one of them speaks the vocabulary declared here.
20
+
21
+ ## Key Exports
22
+
23
+ | Export | What it is |
24
+ |---|---|
25
+ | `BotPlatform` | `telegram` · `whatsapp` · `discord` · `slack` |
26
+ | `BotReceiveMode` / `BotTransport` / `BotConnectionStatus` | `webhook`·`poll`·`gateway` / `live`·`mock` / `pending`·`connected`·`failed`·`disabled` |
27
+ | `BotActionKind` | platform calls: `reply` `send` `delete` `mute` `ban` `react`, plus `note` (activity only) |
28
+ | `BotRuleAction` | what a group tells the bot: `delete` `warn` `mute` `ban` `reply` `record` `agent` |
29
+ | `BotMatchMode` / `BotUpdateKind` / `BotChatKind` | `word`·`contains` / `message`·`edited`·`command`·`member` / `private`·`group`·`channel` |
30
+ | `BOT_PLATFORMS` | `Record<BotPlatform, BotPlatformDescriptor>` — credentials, receive modes, actions, setup, docs |
31
+ | `BotConnection` / `BotConnectionInput` | the client view (never a credential) / the write (credentials write-only) |
32
+ | `BotRule` / `BotRuleInput` / `BotMatch` | a keyword group / its write / a matched group with its matched keywords |
33
+ | `BotUpdate`, `BotMessage`, `BotMessageRef`, `BotChatRef`, `BotSenderRef`, `BotCommand` | the normalized inbound update a handler receives |
34
+ | `BotActivity`, `BotSimulateInput`, `BotSimulateResult` | one recorded action (a failure carries `error`, a sentence, and `code`, its `bot:<marker>:` marker); the simulator's input and answer `{ update, duplicate? }` |
35
+ | `botRuleHelper` | `match(text, rules)`, `normalizeKeywords(list)`, `appliesTo(rule, connection)` |
36
+ | `botCommandHelper` | `parse(text, botUsername?) → BotCommand \| null` |
37
+ | `botPlatformHelper` | `actionsOf(platform, credentialsSet?)`, `supports(platform, kind, credentialsSet?)` |
38
+ | `makeBotProtocols(opts)` → `BotProtocols` | the managing tree (connections, rules, activity) |
39
+ | `makeBotHookProtocols(opts)` → `BotHookProtocols` | the platforms' inbound tree (`receive`, `challenge`) |
40
+ | `Bot*Schema` | `BotConnectionInputSchema`, `BotRuleInputSchema`, `BotSimulateInputSchema`, `BotIdParamsSchema`, `BotRuleListQuerySchema`, `BotActivityQuerySchema`, `BotHookParamsSchema`, `BotChallengeQuerySchema` |
41
+ | `BotError` family | `BotConnectionNotFound` 404, `BotCredentialsRejected` 422, `BotSignatureRejected` 401, `BotTransportMismatch` 409, `BotUnsupportedAction` 422 |
42
+ | `BOT_*` limits | `BOT_KEYWORDS_MAX` 200, `BOT_KEYWORD_MAX` 100, `BOT_ACTIVITY_LIMIT_MAX` 200 / `_DEFAULT` 50, `BOT_ID_PATTERN` … |
43
+ | `BOT_MANAGE_PERMISSION` | `'bot--manage'` — the permission the member mount's gate requires (organization owners hold it by default where users work in organizations; otherwise granted explicitly) |
44
+
45
+ ## Platforms
46
+
47
+ | Platform | Credentials | Receive | Actions | Setup |
48
+ |---|---|---|---|---|
49
+ | telegram | `token` | webhook, poll | reply send delete mute ban react | auto (`setWebhook` + secret token) |
50
+ | whatsapp | `accessToken`, `phoneNumberId`, `appSecret`, `verifyToken` (generated) | webhook | reply send react | manual (callback URL + verify token) |
51
+ | discord | `token`, `applicationId` | gateway | reply send delete mute (timeout) ban react | auto (gateway; invite URL) |
52
+ | slack | `botToken`, `signingSecret`, optional admin `userToken` | webhook (Events API) | reply send react; `delete` only with `userToken` | manual (Request URL) |
53
+
54
+ - Ask `botPlatformHelper.supports(platform, kind, connection.credentialsSet)` — never a local table.
55
+ It adds what an optional credential `enables` and always answers `note` true.
56
+ - A moderation kit on a platform that cannot delete (WhatsApp; Slack without `userToken`) falls back
57
+ to `warn` (a reply). WhatsApp cannot delete, mute or ban at all.
58
+ - A `generated` credential (WhatsApp `verifyToken`) is created by the server and shown in the
59
+ connection's `setup` steps; nobody types it.
60
+
61
+ ## Matching rules
62
+
63
+ `botRuleHelper.match(text, rules)` is the ONE matcher — the server's dispatch, the panels and the
64
+ tests call it, so a group means the same thing everywhere.
65
+
66
+ - Both sides fold: NFKC, then a case fold (`ß` ≡ `ss`, `Ё` ≡ `ё`, full-width ≡ ASCII). Accents are
67
+ kept: `cafe` does not match `café`.
68
+ - `word`: tokens are runs of letters, combining marks, digits and `_`; punctuation splits. A
69
+ multi-word keyword is a PHRASE — consecutive tokens (`free money` matches `FREE, money!`, not
70
+ `money for free`). A keyword with no letters or digits never matches a word.
71
+ - `contains`: a substring of the folded text, whitespace runs collapsed — also the mode for scripts
72
+ written without spaces (Chinese, Japanese, Thai), where a word is the whole run.
73
+ - Disabled rules never match; results are sorted by `order` (ties keep the given order); each
74
+ `BotMatch.keywords` lists the rule's keywords, as stored, that matched.
75
+ - Which rules apply to a connection is `appliesTo`: its own, or a scope-wide one (`connection`
76
+ `null`/absent). The runtime filters with it before matching.
77
+ - `normalizeKeywords(list)` is what a store keeps: trimmed, inner whitespace collapsed, ≤
78
+ `BOT_KEYWORD_MAX` code points, empties and folded duplicates dropped (first spelling kept), ≤
79
+ `BOT_KEYWORDS_MAX` items.
80
+
81
+ `botCommandHelper.parse('/report@MyBot some args', 'MyBot')` → `{ name: 'report', args: 'some args' }`.
82
+ The name is lower-cased and must end at whitespace or the end (`/usr/bin` is no command); a command
83
+ addressed to another bot answers `null`; with no `botUsername`, any address is accepted.
84
+
85
+ ## Protocols
86
+
87
+ ```ts
88
+ makeBotProtocols({ base: { alias, path, parent?, service? }, guards?, gates? }): BotProtocols
89
+ // base (carries the guards and the ONE gate)
90
+ // connection.list GET /connections → BotConnection[]
91
+ // connection.save POST /connections BotConnectionInput → BotConnection
92
+ // connection.verify POST /connections/:id/verify → BotConnection
93
+ // connection.remove DELETE /connections/:id → { id }
94
+ // connection.simulate POST /connections/:id/simulate BotSimulateInput → BotSimulateResult (mock only)
95
+ // rule.list GET /rules?connection= → BotRule[]
96
+ // rule.save POST /rules BotRuleInput → BotRule
97
+ // rule.remove DELETE /rules/:id → { id }
98
+ // activity.list GET /activity?connection=&limit= → BotActivity[] (newest first, limit ≤ 200)
99
+ makeBotHookProtocols({ base: { alias, path, parent?, service? } }): BotHookProtocols
100
+ // receive POST /:platform/:connection (native payload, no body schema)
101
+ // challenge GET /:platform/:connection (WhatsApp hub.* handshake → the challenge string)
102
+ ```
103
+
104
+ - Aliases derive from the base: `<alias>:connection:list`, `<alias>:rule:save`, `<alias>:receive` …
105
+ Two mounts are two base aliases.
106
+ - `gates` is the gate the base carries (`{ alias, params? }` — a protocol has exactly one gate).
107
+ - **The hook tree carries no guard and no gate, on purpose: the platform signs.** Telegram's secret
108
+ token, WhatsApp's app-secret HMAC and Slack's signing secret are verified by the server against the
109
+ connection's credentials over the RAW body — never put an auth guard in front of it, never add a
110
+ body schema.
111
+ - List queries are required on the client: `rule.list.call({ query: {} })`.
112
+
113
+ ## Rules for consumers
114
+
115
+ - **Actions never throw.** Every `BotActions` call of `@owlmeans/server-bot` answers
116
+ `{ ok, error?, code? }` and records a `BotActivity` with both; a handler checks `ok`, never wraps in
117
+ try/catch to "handle" a platform refusal, and asks `supports(kind)` before an action its platform
118
+ may lack. `error` is one sentence for a person or a model; `code` is the marker code compares.
119
+ - A handler reacts to `update.matches` (already filtered and ordered) — it never re-matches text
120
+ and never calls a platform API by hand.
121
+ - `BotConnection` never carries a credential; `credentialsSet` says which keys hold a value. In a
122
+ `BotConnectionInput`, an omitted credential key keeps its stored value; `''` is spellable (clear).
123
+ - `simulate` exists only for `transport: 'mock'`; on a live connection it is `BotTransportMismatch`.
124
+ The server hands the platform's native payload straight to normalization and the inbox — no hook.
125
+ `BotSimulateResult.duplicate: true` means the payload was already in the inbox: `update` is the
126
+ existing row and nothing new is dispatched — a caller waiting for a reaction stops there.
127
+ - Chat members are not application users: nothing of theirs is a guest endpoint; their messages
128
+ arrive only through the hook or the worker's receivers.
129
+ - `scope` is decided by the server from the acting organization (`makeEntityScope` / the target's
130
+ actor) — it is never read from the wire.
131
+ - `BotMessageRef` alone addresses a message: it carries `space` (Discord guild / Slack team) where
132
+ the platform needs it.
133
+ - Error messages are `bot:<marker>:<detail>`; the UI copy ships with `web-bot` as
134
+ `lib : bot.errors.<key>` (`botErrorHelper.keyOf` reads the class, then `@owlmeans/server-bot`'s type
135
+ names, then the marker — an activity's `code`, a connection's `lastError`).
136
+
137
+ ## Target wiring
138
+
139
+ A generated target (`bot` / `ai-bot` case seed) declares three trees in
140
+ `sources/common/src/bot-protocols.ts` and spreads them into its case protocol surface:
141
+
142
+ ```ts
143
+ import { DEFAULT_GUARD } from '@owlmeans/auth-common'
144
+ import { BOT_MANAGE_PERMISSION, makeBotHookProtocols, makeBotProtocols } from '@owlmeans/bot'
145
+ import { OIDC_GATE } from '@owlmeans/oidc'
146
+ import { OPERATOR_PERMISSION } from './consts.js'
147
+
148
+ export const botProtocols = Object.freeze({
149
+ // tenancy none / operators: the operator area runs the bot (/backoffice)
150
+ operator: makeBotProtocols({
151
+ base: { alias: 'api:bot:operator', path: '/bot/operator' },
152
+ guards: DEFAULT_GUARD, gates: { alias: OIDC_GATE, params: [OPERATOR_PERMISSION] },
153
+ }),
154
+ // tenancy users: each customer organization runs its own bot (/frontoffice)
155
+ member: makeBotProtocols({
156
+ base: { alias: 'api:bot:member', path: '/bot/member' },
157
+ guards: DEFAULT_GUARD, gates: { alias: OIDC_GATE, params: [BOT_MANAGE_PERMISSION] },
158
+ }),
159
+ // the platforms: unguarded, signed
160
+ hook: makeBotHookProtocols({ base: { alias: 'api:bot:hook', path: '/bot/hook' } }),
161
+ })
162
+ ```
163
+
164
+ - The member mount's gate requires `BOT_MANAGE_PERMISSION` (`'bot--manage'`) — import it, never
165
+ respell it: the platform and the target seed read the same constant. Where users work in
166
+ organizations, an organization's owners hold it by default; otherwise it is only granted explicitly.
167
+ - The api binds each managing tree with `serveBotEntrypoints(tree, { scope })` (`@owlmeans/server-bot`),
168
+ `scope` from the target's actor — the application's own organization for `operator` without
169
+ tenancy, the acting organization otherwise — and the hook tree with `serveBotHookEntrypoints`.
170
+ - Hook URL: `https://<host>/api/bot/hook/<platform>/<connection>` — the host of the request that
171
+ saved or verified the connection, so preview, production and custom domains all work.
172
+ - The web screens host `BotConnectionsPanel` / `BotRulesPanel` / `BotActivityPanel` with
173
+ `surface = appProtocols.api.bot.operator` (or `.member`); handlers live in
174
+ `sources/backend/src/bot/handlers/` and run in the worker (`bot.runtime(handlers)`).
175
+
176
+ ## Depends On
177
+
178
+ - `@owlmeans/entrypoint`, `@owlmeans/route` — the protocol trees
179
+ - `@owlmeans/error` — the `BotError` family
180
+ - `@owlmeans/context`
181
+ - `ajv` (peer, types only) — the `JSONSchemaType` of the schemas
182
+
183
+ ## Related
184
+
185
+ - [[entrypoint]] — immutable protocols, `bind` / `bindAll`
186
+ - [[planning]] — the same per-mount protocol-factory shape (`makePlanningProtocols`)
187
+ - [[viable-common]] — `BlueprintCase.Bot` / `AiBot`, `BotKit`, the card's `botPlatforms` / `botKit`
@@ -0,0 +1,132 @@
1
+ import type { BotPlatformDescriptor } from './types.js';
2
+ /** The messaging platforms a bot connection can live on. */
3
+ export declare enum BotPlatform {
4
+ Telegram = "telegram",
5
+ WhatsApp = "whatsapp",
6
+ Discord = "discord",
7
+ Slack = "slack"
8
+ }
9
+ /** How a connection's updates reach the application. */
10
+ export declare enum BotReceiveMode {
11
+ /** The platform POSTs every update to the connection's hook URL. */
12
+ Webhook = "webhook",
13
+ /** The worker asks the platform for updates (Telegram long polling). */
14
+ Poll = "poll",
15
+ /** The worker holds a socket the platform pushes over (the Discord gateway). */
16
+ Gateway = "gateway"
17
+ }
18
+ /**
19
+ * Who answers a connection's platform calls.
20
+ *
21
+ * `mock` is the platform's API faithfully faked — no network, every call recorded as activity — so a
22
+ * preview, a test or an end-to-end run exercises the exact live path without a real bot.
23
+ */
24
+ export declare enum BotTransport {
25
+ Live = "live",
26
+ Mock = "mock"
27
+ }
28
+ export declare enum BotConnectionStatus {
29
+ /** Saved, not verified yet. */
30
+ Pending = "pending",
31
+ /** The platform accepted the credentials and the receiver is (or can be) running. */
32
+ Connected = "connected",
33
+ /** The last verification or receive failed — `lastError` says why. */
34
+ Failed = "failed",
35
+ /** Switched off by its owner; nothing is received or sent. */
36
+ Disabled = "disabled"
37
+ }
38
+ /**
39
+ * What a bot can DO — the platform calls a handler makes, each recorded as one activity.
40
+ *
41
+ * `note` is the exception: it records an activity and makes no platform call, so every connection
42
+ * supports it and no platform descriptor lists it.
43
+ */
44
+ export declare enum BotActionKind {
45
+ Reply = "reply",
46
+ Send = "send",
47
+ Delete = "delete",
48
+ Mute = "mute",
49
+ Ban = "ban",
50
+ React = "react",
51
+ Note = "note"
52
+ }
53
+ /**
54
+ * What a keyword group (a rule) tells the bot to do with a message it matches.
55
+ *
56
+ * A product vocabulary, not a platform one: `warn` is a reply, `record` is a request record of the
57
+ * product, `agent` hands the message to the product's own agent.
58
+ */
59
+ export declare enum BotRuleAction {
60
+ Delete = "delete",
61
+ Warn = "warn",
62
+ Mute = "mute",
63
+ Ban = "ban",
64
+ Reply = "reply",
65
+ Record = "record",
66
+ Agent = "agent"
67
+ }
68
+ /** How a rule's keywords are compared with a message. */
69
+ export declare enum BotMatchMode {
70
+ /** Whole words and whole phrases (consecutive words), Unicode-aware and case-insensitive. */
71
+ Word = "word",
72
+ /** A case-insensitive substring — also the mode for scripts written without spaces. */
73
+ Contains = "contains"
74
+ }
75
+ export declare enum BotUpdateKind {
76
+ Message = "message",
77
+ Edited = "edited",
78
+ Command = "command",
79
+ Member = "member"
80
+ }
81
+ export declare enum BotChatKind {
82
+ Private = "private",
83
+ Group = "group",
84
+ Channel = "channel"
85
+ }
86
+ /** The longest identifier (connection, rule, activity, update) the wire accepts. */
87
+ export declare const BOT_ID_MAX = 128;
88
+ /** What an identifier on the wire may look like — it is also a path segment of the hook URL. */
89
+ export declare const BOT_ID_PATTERN = "^[A-Za-z0-9][A-Za-z0-9_.:-]*$";
90
+ /** The longest connection label. */
91
+ export declare const BOT_LABEL_MAX = 120;
92
+ /** The longest rule (keyword group) name. */
93
+ export declare const BOT_RULE_NAME_MAX = 120;
94
+ /** How many keywords one rule keeps. */
95
+ export declare const BOT_KEYWORDS_MAX = 200;
96
+ /** The longest keyword or phrase, in code points. */
97
+ export declare const BOT_KEYWORD_MAX = 100;
98
+ /** The longest fixed reply text of a rule. */
99
+ export declare const BOT_REPLY_MAX = 4096;
100
+ /** The longest instruction a rule hands to the product's agent. */
101
+ export declare const BOT_INSTRUCTION_MAX = 4000;
102
+ /** The longest message text the simulator accepts. */
103
+ export declare const BOT_TEXT_MAX = 4096;
104
+ /** The longest single credential value. */
105
+ export declare const BOT_CREDENTIAL_MAX = 4096;
106
+ /** How many credential keys one connection input may carry. */
107
+ export declare const BOT_CREDENTIALS_MAX = 16;
108
+ /** What a credential key may look like. */
109
+ export declare const BOT_CREDENTIAL_KEY_PATTERN = "^[A-Za-z][A-Za-z0-9]{0,63}$";
110
+ /** The longest free-text field of a simulated chat or sender (title, name, username). */
111
+ export declare const BOT_NAME_MAX = 256;
112
+ /** The most activity rows one read returns. */
113
+ export declare const BOT_ACTIVITY_LIMIT_MAX = 200;
114
+ /** The activity rows a read returns when it names no limit. */
115
+ export declare const BOT_ACTIVITY_LIMIT_DEFAULT = 50;
116
+ /**
117
+ * The permission the MEMBER mount's gate requires (`gates: { alias: OIDC_GATE, params:
118
+ * [BOT_MANAGE_PERMISSION] }`) — who may connect an organization's bots, edit its keyword groups and
119
+ * read its bot activity. In a product whose users work in organizations, an organization's owners hold
120
+ * it by default; otherwise it is only ever granted explicitly.
121
+ */
122
+ export declare const BOT_MANAGE_PERMISSION = "bot--manage";
123
+ /**
124
+ * What each platform needs and can do — the one table every layer reads: the panel draws the
125
+ * credential inputs from it, the server verifies and acts by it, generation picks actions from it.
126
+ *
127
+ * `actions` lists the platform CALLS a connection can make with its required credentials; an
128
+ * optional credential's `enables` adds more (Slack's admin `userToken` adds `delete`). `note` is never
129
+ * listed — it makes no platform call (`botPlatformHelper.actionsOf` answers the full set).
130
+ */
131
+ export declare const BOT_PLATFORMS: Record<BotPlatform, BotPlatformDescriptor>;
132
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,4DAA4D;AAC5D,oBAAY,WAAW;IACrB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,wDAAwD;AACxD,oBAAY,cAAc;IACxB,oEAAoE;IACpE,OAAO,YAAY;IACnB,wEAAwE;IACxE,IAAI,SAAS;IACb,gFAAgF;IAChF,OAAO,YAAY;CACpB;AAED;;;;;GAKG;AACH,oBAAY,YAAY;IACtB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,oBAAY,mBAAmB;IAC7B,+BAA+B;IAC/B,OAAO,YAAY;IACnB,qFAAqF;IACrF,SAAS,cAAc;IACvB,sEAAsE;IACtE,MAAM,WAAW;IACjB,8DAA8D;IAC9D,QAAQ,aAAa;CACtB;AAED;;;;;GAKG;AACH,oBAAY,aAAa;IACvB,KAAK,UAAU;IACf,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,KAAK,UAAU;IACf,IAAI,SAAS;CACd;AAED;;;;;GAKG;AACH,oBAAY,aAAa;IACvB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,yDAAyD;AACzD,oBAAY,YAAY;IACtB,6FAA6F;IAC7F,IAAI,SAAS;IACb,uFAAuF;IACvF,QAAQ,aAAa;CACtB;AAED,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,MAAM,WAAW;CAClB;AAED,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED,oFAAoF;AACpF,eAAO,MAAM,UAAU,MAAM,CAAA;AAE7B,gGAAgG;AAChG,eAAO,MAAM,cAAc,kCAAkC,CAAA;AAE7D,oCAAoC;AACpC,eAAO,MAAM,aAAa,MAAM,CAAA;AAEhC,6CAA6C;AAC7C,eAAO,MAAM,iBAAiB,MAAM,CAAA;AAEpC,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAEnC,qDAAqD;AACrD,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC,8CAA8C;AAC9C,eAAO,MAAM,aAAa,OAAO,CAAA;AAEjC,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,sDAAsD;AACtD,eAAO,MAAM,YAAY,OAAO,CAAA;AAEhC,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,2CAA2C;AAC3C,eAAO,MAAM,0BAA0B,gCAAgC,CAAA;AAEvE,yFAAyF;AACzF,eAAO,MAAM,YAAY,MAAM,CAAA;AAE/B,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,MAAM,CAAA;AAEzC,+DAA+D;AAC/D,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,gBAAgB,CAAA;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,qBAAqB,CAyDrB,CAAA"}
@@ -0,0 +1,197 @@
1
+ /** The messaging platforms a bot connection can live on. */
2
+ export var BotPlatform;
3
+ (function (BotPlatform) {
4
+ BotPlatform["Telegram"] = "telegram";
5
+ BotPlatform["WhatsApp"] = "whatsapp";
6
+ BotPlatform["Discord"] = "discord";
7
+ BotPlatform["Slack"] = "slack";
8
+ })(BotPlatform || (BotPlatform = {}));
9
+ /** How a connection's updates reach the application. */
10
+ export var BotReceiveMode;
11
+ (function (BotReceiveMode) {
12
+ /** The platform POSTs every update to the connection's hook URL. */
13
+ BotReceiveMode["Webhook"] = "webhook";
14
+ /** The worker asks the platform for updates (Telegram long polling). */
15
+ BotReceiveMode["Poll"] = "poll";
16
+ /** The worker holds a socket the platform pushes over (the Discord gateway). */
17
+ BotReceiveMode["Gateway"] = "gateway";
18
+ })(BotReceiveMode || (BotReceiveMode = {}));
19
+ /**
20
+ * Who answers a connection's platform calls.
21
+ *
22
+ * `mock` is the platform's API faithfully faked — no network, every call recorded as activity — so a
23
+ * preview, a test or an end-to-end run exercises the exact live path without a real bot.
24
+ */
25
+ export var BotTransport;
26
+ (function (BotTransport) {
27
+ BotTransport["Live"] = "live";
28
+ BotTransport["Mock"] = "mock";
29
+ })(BotTransport || (BotTransport = {}));
30
+ export var BotConnectionStatus;
31
+ (function (BotConnectionStatus) {
32
+ /** Saved, not verified yet. */
33
+ BotConnectionStatus["Pending"] = "pending";
34
+ /** The platform accepted the credentials and the receiver is (or can be) running. */
35
+ BotConnectionStatus["Connected"] = "connected";
36
+ /** The last verification or receive failed — `lastError` says why. */
37
+ BotConnectionStatus["Failed"] = "failed";
38
+ /** Switched off by its owner; nothing is received or sent. */
39
+ BotConnectionStatus["Disabled"] = "disabled";
40
+ })(BotConnectionStatus || (BotConnectionStatus = {}));
41
+ /**
42
+ * What a bot can DO — the platform calls a handler makes, each recorded as one activity.
43
+ *
44
+ * `note` is the exception: it records an activity and makes no platform call, so every connection
45
+ * supports it and no platform descriptor lists it.
46
+ */
47
+ export var BotActionKind;
48
+ (function (BotActionKind) {
49
+ BotActionKind["Reply"] = "reply";
50
+ BotActionKind["Send"] = "send";
51
+ BotActionKind["Delete"] = "delete";
52
+ BotActionKind["Mute"] = "mute";
53
+ BotActionKind["Ban"] = "ban";
54
+ BotActionKind["React"] = "react";
55
+ BotActionKind["Note"] = "note";
56
+ })(BotActionKind || (BotActionKind = {}));
57
+ /**
58
+ * What a keyword group (a rule) tells the bot to do with a message it matches.
59
+ *
60
+ * A product vocabulary, not a platform one: `warn` is a reply, `record` is a request record of the
61
+ * product, `agent` hands the message to the product's own agent.
62
+ */
63
+ export var BotRuleAction;
64
+ (function (BotRuleAction) {
65
+ BotRuleAction["Delete"] = "delete";
66
+ BotRuleAction["Warn"] = "warn";
67
+ BotRuleAction["Mute"] = "mute";
68
+ BotRuleAction["Ban"] = "ban";
69
+ BotRuleAction["Reply"] = "reply";
70
+ BotRuleAction["Record"] = "record";
71
+ BotRuleAction["Agent"] = "agent";
72
+ })(BotRuleAction || (BotRuleAction = {}));
73
+ /** How a rule's keywords are compared with a message. */
74
+ export var BotMatchMode;
75
+ (function (BotMatchMode) {
76
+ /** Whole words and whole phrases (consecutive words), Unicode-aware and case-insensitive. */
77
+ BotMatchMode["Word"] = "word";
78
+ /** A case-insensitive substring — also the mode for scripts written without spaces. */
79
+ BotMatchMode["Contains"] = "contains";
80
+ })(BotMatchMode || (BotMatchMode = {}));
81
+ export var BotUpdateKind;
82
+ (function (BotUpdateKind) {
83
+ BotUpdateKind["Message"] = "message";
84
+ BotUpdateKind["Edited"] = "edited";
85
+ BotUpdateKind["Command"] = "command";
86
+ BotUpdateKind["Member"] = "member";
87
+ })(BotUpdateKind || (BotUpdateKind = {}));
88
+ export var BotChatKind;
89
+ (function (BotChatKind) {
90
+ BotChatKind["Private"] = "private";
91
+ BotChatKind["Group"] = "group";
92
+ BotChatKind["Channel"] = "channel";
93
+ })(BotChatKind || (BotChatKind = {}));
94
+ /** The longest identifier (connection, rule, activity, update) the wire accepts. */
95
+ export const BOT_ID_MAX = 128;
96
+ /** What an identifier on the wire may look like — it is also a path segment of the hook URL. */
97
+ export const BOT_ID_PATTERN = '^[A-Za-z0-9][A-Za-z0-9_.:-]*$';
98
+ /** The longest connection label. */
99
+ export const BOT_LABEL_MAX = 120;
100
+ /** The longest rule (keyword group) name. */
101
+ export const BOT_RULE_NAME_MAX = 120;
102
+ /** How many keywords one rule keeps. */
103
+ export const BOT_KEYWORDS_MAX = 200;
104
+ /** The longest keyword or phrase, in code points. */
105
+ export const BOT_KEYWORD_MAX = 100;
106
+ /** The longest fixed reply text of a rule. */
107
+ export const BOT_REPLY_MAX = 4096;
108
+ /** The longest instruction a rule hands to the product's agent. */
109
+ export const BOT_INSTRUCTION_MAX = 4000;
110
+ /** The longest message text the simulator accepts. */
111
+ export const BOT_TEXT_MAX = 4096;
112
+ /** The longest single credential value. */
113
+ export const BOT_CREDENTIAL_MAX = 4096;
114
+ /** How many credential keys one connection input may carry. */
115
+ export const BOT_CREDENTIALS_MAX = 16;
116
+ /** What a credential key may look like. */
117
+ export const BOT_CREDENTIAL_KEY_PATTERN = '^[A-Za-z][A-Za-z0-9]{0,63}$';
118
+ /** The longest free-text field of a simulated chat or sender (title, name, username). */
119
+ export const BOT_NAME_MAX = 256;
120
+ /** The most activity rows one read returns. */
121
+ export const BOT_ACTIVITY_LIMIT_MAX = 200;
122
+ /** The activity rows a read returns when it names no limit. */
123
+ export const BOT_ACTIVITY_LIMIT_DEFAULT = 50;
124
+ /**
125
+ * The permission the MEMBER mount's gate requires (`gates: { alias: OIDC_GATE, params:
126
+ * [BOT_MANAGE_PERMISSION] }`) — who may connect an organization's bots, edit its keyword groups and
127
+ * read its bot activity. In a product whose users work in organizations, an organization's owners hold
128
+ * it by default; otherwise it is only ever granted explicitly.
129
+ */
130
+ export const BOT_MANAGE_PERMISSION = 'bot--manage';
131
+ /**
132
+ * What each platform needs and can do — the one table every layer reads: the panel draws the
133
+ * credential inputs from it, the server verifies and acts by it, generation picks actions from it.
134
+ *
135
+ * `actions` lists the platform CALLS a connection can make with its required credentials; an
136
+ * optional credential's `enables` adds more (Slack's admin `userToken` adds `delete`). `note` is never
137
+ * listed — it makes no platform call (`botPlatformHelper.actionsOf` answers the full set).
138
+ */
139
+ export const BOT_PLATFORMS = Object.freeze({
140
+ [BotPlatform.Telegram]: Object.freeze({
141
+ platform: BotPlatform.Telegram,
142
+ title: 'Telegram',
143
+ credentials: Object.freeze([
144
+ Object.freeze({ key: 'token', secret: true, required: true }),
145
+ ]),
146
+ receive: Object.freeze([BotReceiveMode.Webhook, BotReceiveMode.Poll]),
147
+ actions: Object.freeze([
148
+ BotActionKind.Reply, BotActionKind.Send, BotActionKind.Delete, BotActionKind.Mute, BotActionKind.Ban,
149
+ BotActionKind.React,
150
+ ]),
151
+ setup: 'auto',
152
+ docs: 'https://core.telegram.org/bots/tutorial#obtain-your-bot-token',
153
+ }),
154
+ [BotPlatform.WhatsApp]: Object.freeze({
155
+ platform: BotPlatform.WhatsApp,
156
+ title: 'WhatsApp',
157
+ credentials: Object.freeze([
158
+ Object.freeze({ key: 'accessToken', secret: true, required: true }),
159
+ Object.freeze({ key: 'phoneNumberId', secret: false, required: true }),
160
+ Object.freeze({ key: 'appSecret', secret: true, required: true }),
161
+ Object.freeze({ key: 'verifyToken', secret: true, required: true, generated: true }),
162
+ ]),
163
+ receive: Object.freeze([BotReceiveMode.Webhook]),
164
+ actions: Object.freeze([BotActionKind.Reply, BotActionKind.Send, BotActionKind.React]),
165
+ setup: 'manual',
166
+ docs: 'https://developers.facebook.com/docs/whatsapp/cloud-api/get-started',
167
+ }),
168
+ [BotPlatform.Discord]: Object.freeze({
169
+ platform: BotPlatform.Discord,
170
+ title: 'Discord',
171
+ credentials: Object.freeze([
172
+ Object.freeze({ key: 'token', secret: true, required: true }),
173
+ Object.freeze({ key: 'applicationId', secret: false, required: true }),
174
+ ]),
175
+ receive: Object.freeze([BotReceiveMode.Gateway]),
176
+ actions: Object.freeze([
177
+ BotActionKind.Reply, BotActionKind.Send, BotActionKind.Delete, BotActionKind.Mute, BotActionKind.Ban,
178
+ BotActionKind.React,
179
+ ]),
180
+ setup: 'auto',
181
+ docs: 'https://discord.com/developers/docs/quick-start/getting-started',
182
+ }),
183
+ [BotPlatform.Slack]: Object.freeze({
184
+ platform: BotPlatform.Slack,
185
+ title: 'Slack',
186
+ credentials: Object.freeze([
187
+ Object.freeze({ key: 'botToken', secret: true, required: true }),
188
+ Object.freeze({ key: 'signingSecret', secret: true, required: true }),
189
+ Object.freeze({ key: 'userToken', secret: true, required: false, enables: Object.freeze([BotActionKind.Delete]) }),
190
+ ]),
191
+ receive: Object.freeze([BotReceiveMode.Webhook]),
192
+ actions: Object.freeze([BotActionKind.Reply, BotActionKind.Send, BotActionKind.React]),
193
+ setup: 'manual',
194
+ docs: 'https://api.slack.com/apis/events-api',
195
+ }),
196
+ });
197
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * One token of `word` matching: letters, combining marks, digits and `_`. Marks are part of the word
3
+ * (Devanagari vowel signs, a decomposed accent left after folding), so a word never splits on one.
4
+ */
5
+ export declare const BOT_TOKEN_PATTERN: RegExp;
6
+ /** Any whitespace run — collapsed to one space before a `contains` comparison and in a stored keyword. */
7
+ export declare const BOT_SPACE_PATTERN: RegExp;
8
+ /**
9
+ * A `/command`, optionally addressed `@ToBot`, ending at whitespace or at the end of the text, then
10
+ * its arguments.
11
+ */
12
+ export declare const BOT_COMMAND_PATTERN: RegExp;
13
+ //# sourceMappingURL=consts.local.d.ts.map