chat 4.18.0 → 4.20.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.
Files changed (44) hide show
  1. package/README.md +2 -0
  2. package/dist/{chunk-WAB7KMH4.js → chunk-JW7GYSMH.js} +3 -3
  3. package/dist/chunk-JW7GYSMH.js.map +1 -0
  4. package/dist/index.d.ts +220 -13
  5. package/dist/index.js +274 -56
  6. package/dist/index.js.map +1 -1
  7. package/dist/jsx-runtime.d.ts +1 -1
  8. package/dist/jsx-runtime.js +1 -1
  9. package/docs/adapters/whatsapp.mdx +222 -0
  10. package/docs/{adapters/index.mdx → adapters.mdx} +46 -65
  11. package/docs/api/channel.mdx +15 -0
  12. package/docs/api/index.mdx +1 -0
  13. package/docs/api/thread.mdx +50 -0
  14. package/docs/contributing/building.mdx +1 -0
  15. package/docs/error-handling.mdx +2 -2
  16. package/docs/getting-started.mdx +2 -0
  17. package/docs/guides/code-review-hono.mdx +3 -3
  18. package/docs/guides/discord-nuxt.mdx +3 -2
  19. package/docs/guides/durable-chat-sessions-nextjs.mdx +331 -0
  20. package/docs/guides/meta.json +7 -1
  21. package/docs/guides/scheduled-posts-neon.mdx +447 -0
  22. package/docs/guides/slack-nextjs.mdx +3 -2
  23. package/docs/index.mdx +3 -1
  24. package/docs/meta.json +3 -4
  25. package/docs/slash-commands.mdx +4 -4
  26. package/docs/{state/index.mdx → state.mdx} +24 -12
  27. package/docs/threads-messages-channels.mdx +17 -0
  28. package/docs/usage.mdx +5 -0
  29. package/package.json +1 -1
  30. package/dist/chunk-WAB7KMH4.js.map +0 -1
  31. package/docs/adapters/discord.mdx +0 -217
  32. package/docs/adapters/gchat.mdx +0 -237
  33. package/docs/adapters/github.mdx +0 -222
  34. package/docs/adapters/linear.mdx +0 -206
  35. package/docs/adapters/meta.json +0 -13
  36. package/docs/adapters/slack.mdx +0 -314
  37. package/docs/adapters/teams.mdx +0 -287
  38. package/docs/adapters/telegram.mdx +0 -161
  39. package/docs/state/ioredis.mdx +0 -81
  40. package/docs/state/memory.mdx +0 -52
  41. package/docs/state/meta.json +0 -4
  42. package/docs/state/postgres.mdx +0 -98
  43. package/docs/state/redis.mdx +0 -100
  44. package/dist/{jsx-runtime-BYavlUk9.d.ts → jsx-runtime-C2ATKxHQ.d.ts} +95 -95
@@ -1,161 +0,0 @@
1
- ---
2
- title: Telegram
3
- description: Configure the Telegram adapter for bot webhooks and messaging.
4
- type: integration
5
- prerequisites:
6
- - /docs/getting-started
7
- ---
8
-
9
- ## Installation
10
-
11
- ```sh title="Terminal"
12
- pnpm add @chat-adapter/telegram
13
- ```
14
-
15
- ## Usage
16
-
17
- The adapter auto-detects `TELEGRAM_BOT_TOKEN`, `TELEGRAM_WEBHOOK_SECRET_TOKEN`, `TELEGRAM_BOT_USERNAME`, and `TELEGRAM_API_BASE_URL` from environment variables:
18
-
19
- ```typescript title="lib/bot.ts" lineNumbers
20
- import { Chat } from "chat";
21
- import { createTelegramAdapter } from "@chat-adapter/telegram";
22
-
23
- const bot = new Chat({
24
- userName: "mybot",
25
- adapters: {
26
- telegram: createTelegramAdapter(),
27
- },
28
- });
29
-
30
- bot.onNewMention(async (thread, message) => {
31
- await thread.post(`You said: ${message.text}`);
32
- });
33
- ```
34
-
35
- ## Webhook route
36
-
37
- ```typescript title="app/api/webhooks/telegram/route.ts" lineNumbers
38
- import { bot } from "@/lib/bot";
39
-
40
- export async function POST(request: Request): Promise<Response> {
41
- return bot.webhooks.telegram(request);
42
- }
43
- ```
44
-
45
- Configure this URL as your bot webhook in BotFather / Telegram API:
46
-
47
- ```sh title="Terminal"
48
- curl -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \
49
- -H "Content-Type: application/json" \
50
- -d '{
51
- "url": "https://your-domain.com/api/webhooks/telegram",
52
- "secret_token": "your-secret-token"
53
- }'
54
- ```
55
-
56
- ## Polling (local development)
57
-
58
- When developing locally you typically can't expose a public URL for Telegram to deliver webhooks to. Polling mode uses `getUpdates` to fetch messages directly from Telegram instead — no public endpoint needed.
59
-
60
- The `longPolling` option is entirely optional. Sensible defaults are applied when omitted.
61
-
62
- ```typescript title="lib/bot.ts" lineNumbers
63
- import { Chat } from "chat";
64
- import { createTelegramAdapter } from "@chat-adapter/telegram";
65
- import { createMemoryState } from "@chat-adapter/state-memory";
66
-
67
- const telegram = createTelegramAdapter({
68
- mode: "polling",
69
- // Optional — fine-tune polling behavior:
70
- // longPolling: { timeout: 30, dropPendingUpdates: false },
71
- });
72
-
73
- const bot = new Chat({
74
- userName: "mybot",
75
- adapters: { telegram },
76
- state: createMemoryState(),
77
- });
78
-
79
- // Optional manual lifecycle control:
80
- // await telegram.resetWebhook();
81
- // await telegram.startPolling();
82
- // await telegram.stopPolling();
83
- ```
84
-
85
- ### Auto mode
86
-
87
- With `mode: "auto"` (the default), the adapter picks the right strategy for you. When deployed to a serverless environment like Vercel it uses webhooks; everywhere else (e.g. local dev) it falls back to polling automatically.
88
-
89
- ```typescript title="lib/bot.ts" lineNumbers
90
- import { Chat } from "chat";
91
- import { createTelegramAdapter } from "@chat-adapter/telegram";
92
- import { createMemoryState } from "@chat-adapter/state-memory";
93
-
94
- const telegram = createTelegramAdapter({
95
- mode: "auto", // default
96
- });
97
-
98
- export const bot = new Chat({
99
- userName: "mybot",
100
- adapters: { telegram },
101
- state: createMemoryState(),
102
- });
103
-
104
- // Call initialize() so polling can start in long-running local processes:
105
- void bot.initialize();
106
-
107
- console.log(telegram.runtimeMode); // "webhook" | "polling"
108
- ```
109
-
110
- ## Configuration
111
-
112
- All options are auto-detected from environment variables when not provided.
113
-
114
- | Option | Required | Description |
115
- |--------|----------|-------------|
116
- | `botToken` | No* | Telegram bot token. Auto-detected from `TELEGRAM_BOT_TOKEN` |
117
- | `secretToken` | No | Optional webhook secret token. Auto-detected from `TELEGRAM_WEBHOOK_SECRET_TOKEN` |
118
- | `mode` | No | Adapter mode: `auto` (default), `webhook`, or `polling` |
119
- | `longPolling` | No | Optional long polling config for `getUpdates` (`timeout`, `limit`, `allowedUpdates`, `deleteWebhook`, `dropPendingUpdates`, `retryDelayMs`) |
120
- | `userName` | No | Bot username used for mention detection. Auto-detected from `TELEGRAM_BOT_USERNAME` or `getMe` |
121
- | `apiBaseUrl` | No | Telegram API base URL. Auto-detected from `TELEGRAM_API_BASE_URL` |
122
- | `logger` | No | Logger instance (defaults to `ConsoleLogger("info")`) |
123
-
124
- *`botToken` is required — either via config or env vars.
125
-
126
- ## Environment variables
127
-
128
- ```bash title=".env.local"
129
- TELEGRAM_BOT_TOKEN=123456:ABCDEF...
130
- TELEGRAM_WEBHOOK_SECRET_TOKEN=your-webhook-secret
131
- TELEGRAM_BOT_USERNAME=mybot
132
- # Optional (self-hosted API gateway)
133
- TELEGRAM_API_BASE_URL=https://api.telegram.org
134
- ```
135
-
136
- ## Features
137
-
138
- | Feature | Supported |
139
- |---------|-----------|
140
- | Mentions | Yes |
141
- | Reactions (add/remove) | Yes |
142
- | Cards | Text fallback + inline keyboard buttons/link buttons |
143
- | Modals | No |
144
- | Streaming | Post+Edit fallback |
145
- | DMs | Yes |
146
- | Ephemeral messages | No |
147
- | File uploads | Single file (`sendDocument`) |
148
- | Typing indicator | Yes |
149
- | Message history | Cached messages seen/sent by the adapter |
150
-
151
- ## Notes
152
-
153
- - Telegram does not expose full historical message APIs to bots. `fetchMessages` / `fetchChannelMessages` return adapter-cached messages from the current process.
154
- - `listThreads` is not available for Telegram chats.
155
- - Polling and webhooks are mutually exclusive in Telegram.
156
- - `mode: "polling"` deletes webhook by default before calling `getUpdates`.
157
- - `mode: "auto"` checks `getWebhookInfo`: if a webhook URL exists it uses webhook mode; if it is empty it falls back to polling on non-serverless runtimes without deleting webhook.
158
- - If `getWebhookInfo` fails in `mode: "auto"`, the adapter stays in webhook mode (safe fallback).
159
- - `Button` and `LinkButton` in card `Actions` render as inline keyboard buttons.
160
- - Telegram callback data is limited to 64 bytes. Keep button `id`/`value` payloads short.
161
- - Other rich card elements (images/select menus/radios) render as fallback text only.
@@ -1,81 +0,0 @@
1
- ---
2
- title: ioredis
3
- description: Alternative Redis state adapter using ioredis with Cluster and Sentinel support.
4
- type: reference
5
- prerequisites:
6
- - /docs/getting-started
7
- ---
8
-
9
- An alternative Redis state adapter using [ioredis](https://www.npmjs.com/package/ioredis). Use this if you already have ioredis in your project or need Redis Cluster/Sentinel support.
10
-
11
- ## Installation
12
-
13
- ```sh title="Terminal"
14
- pnpm add @chat-adapter/state-ioredis
15
- ```
16
-
17
- ## Usage
18
-
19
- ```typescript title="lib/bot.ts" lineNumbers
20
- import { Chat } from "chat";
21
- import { createIORedisState } from "@chat-adapter/state-ioredis";
22
-
23
- const bot = new Chat({
24
- userName: "mybot",
25
- adapters: { /* ... */ },
26
- state: createIORedisState({
27
- url: process.env.REDIS_URL!,
28
- }),
29
- });
30
- ```
31
-
32
- ### Using an existing client
33
-
34
- ```typescript title="lib/bot.ts" lineNumbers
35
- import Redis from "ioredis";
36
-
37
- const client = new Redis("redis://localhost:6379");
38
-
39
- const state = createIORedisState({ client });
40
- ```
41
-
42
- ## Configuration
43
-
44
- | Option | Required | Description |
45
- |--------|----------|-------------|
46
- | `url` | Yes* | Redis connection URL |
47
- | `client` | No | Existing `ioredis` client instance |
48
- | `keyPrefix` | No | Prefix for all keys (default: `"chat-sdk"`) |
49
-
50
- *Either `url` or `client` is required.
51
-
52
- ## When to use ioredis vs redis
53
-
54
- **Use `@chat-adapter/state-ioredis` when:**
55
-
56
- - You already use ioredis in your project
57
- - You need Redis Cluster support
58
- - You need Redis Sentinel support
59
- - You prefer the ioredis API
60
-
61
- **Use `@chat-adapter/state-redis` when:**
62
-
63
- - You want the official Redis client
64
- - You're starting a new project
65
- - You don't need Cluster or Sentinel
66
-
67
- ## Key structure
68
-
69
- ```
70
- {keyPrefix}:subscriptions - SET of subscribed thread IDs
71
- {keyPrefix}:lock:{threadId} - Lock key with TTL
72
- ```
73
-
74
- ## Features
75
-
76
- - Persistent subscriptions across restarts
77
- - Distributed locking across multiple instances
78
- - Automatic reconnection
79
- - Redis Cluster support
80
- - Redis Sentinel support
81
- - Key prefix namespacing
@@ -1,52 +0,0 @@
1
- ---
2
- title: Memory
3
- description: In-memory state adapter for local development and testing.
4
- type: reference
5
- prerequisites:
6
- - /docs/getting-started
7
- ---
8
-
9
- An in-memory state adapter for development and testing. Zero configuration required.
10
-
11
- <Callout type="warn">
12
- Only use the memory adapter for local development and testing. State is lost on restart and locks don't work across multiple instances. For production, use [Redis](/docs/state/redis), [ioredis](/docs/state/ioredis), or [PostgreSQL](/docs/state/postgres).
13
- </Callout>
14
-
15
- ## Installation
16
-
17
- ```sh title="Terminal"
18
- pnpm add @chat-adapter/state-memory
19
- ```
20
-
21
- ## Usage
22
-
23
- ```typescript title="lib/bot.ts" lineNumbers
24
- import { Chat } from "chat";
25
- import { createMemoryState } from "@chat-adapter/state-memory";
26
-
27
- const bot = new Chat({
28
- userName: "mybot",
29
- adapters: { /* ... */ },
30
- state: createMemoryState(),
31
- });
32
- ```
33
-
34
- No configuration options are needed.
35
-
36
- ## Features
37
-
38
- - Thread subscriptions (in-memory)
39
- - Locking (single-process only)
40
- - Zero configuration
41
-
42
- ## Limitations
43
-
44
- - **Not suitable for production** — state is lost on restart
45
- - **Single process only** — locks don't work across multiple instances
46
- - **No persistence** — subscriptions reset when the process restarts
47
-
48
- ## When to use
49
-
50
- - Local development
51
- - Unit testing
52
- - Quick prototyping
@@ -1,4 +0,0 @@
1
- {
2
- "title": "State",
3
- "pages": ["index", "redis", "ioredis", "postgres", "memory"]
4
- }
@@ -1,98 +0,0 @@
1
- ---
2
- title: PostgreSQL
3
- description: Production state adapter using pg (node-postgres).
4
- type: reference
5
- prerequisites:
6
- - /docs/getting-started
7
- ---
8
-
9
- Production PostgreSQL state adapter built with [pg](https://www.npmjs.com/package/pg) (node-postgres). Use this when PostgreSQL is your primary datastore and you want state persistence without a separate Redis dependency.
10
-
11
- ## Installation
12
-
13
- ```sh title="Terminal"
14
- pnpm add @chat-adapter/state-pg
15
- ```
16
-
17
- ## Usage
18
-
19
- `createPostgresState()` auto-detects `POSTGRES_URL` (or `DATABASE_URL`) so you can call it with no arguments:
20
-
21
- ```typescript title="lib/bot.ts" lineNumbers
22
- import { Chat } from "chat";
23
- import { createPostgresState } from "@chat-adapter/state-pg";
24
-
25
- const bot = new Chat({
26
- userName: "mybot",
27
- adapters: { /* ... */ },
28
- state: createPostgresState(),
29
- });
30
- ```
31
-
32
- To provide a URL explicitly:
33
-
34
- ```typescript title="lib/bot.ts"
35
- const state = createPostgresState({
36
- url: "postgres://postgres:postgres@localhost:5432/chat",
37
- });
38
- ```
39
-
40
- ### Using an existing client
41
-
42
- ```typescript title="lib/bot.ts" lineNumbers
43
- import pg from "pg";
44
-
45
- const client = new pg.Pool({ connectionString: process.env.POSTGRES_URL! });
46
- const state = createPostgresState({ client });
47
- ```
48
-
49
- ## Configuration
50
-
51
- | Option | Required | Description |
52
- |--------|----------|-------------|
53
- | `url` | No* | Postgres connection URL |
54
- | `client` | No | Existing `pg.Pool` instance |
55
- | `keyPrefix` | No | Prefix for all state rows (default: `"chat-sdk"`) |
56
- | `logger` | No | Logger instance (defaults to `ConsoleLogger("info").child("postgres")`) |
57
-
58
- *Either `url`, `POSTGRES_URL`/`DATABASE_URL`, or `client` is required.
59
-
60
- ## Environment variables
61
-
62
- ```bash title=".env.local"
63
- POSTGRES_URL=postgres://postgres:postgres@localhost:5432/chat
64
- ```
65
-
66
- ## Data model
67
-
68
- The adapter creates these tables automatically on `connect()`:
69
-
70
- ```sql
71
- chat_state_subscriptions
72
- chat_state_locks
73
- chat_state_cache
74
- ```
75
-
76
- All rows are namespaced by `key_prefix`.
77
-
78
- ## Features
79
-
80
- - Persistent subscriptions across restarts
81
- - Distributed locking across multiple instances
82
- - Key-value caching with TTL
83
- - Automatic table creation on first connect
84
-
85
- ## Locking considerations
86
-
87
- The Redis state adapters use atomic `SET NX PX` for lock acquisition, which is a single atomic operation. The PostgreSQL adapter uses `INSERT ... ON CONFLICT DO UPDATE WHERE expires_at <= now()`, which relies on Postgres row-level locking. This is safe for most workloads but under extreme contention (many processes competing for the same lock simultaneously) may behave slightly differently than Redis. For high-contention distributed locking, prefer the Redis adapter.
88
-
89
- ## Expired row cleanup
90
-
91
- Unlike Redis (which handles TTL expiry natively), PostgreSQL does not automatically delete expired rows. The adapter performs opportunistic cleanup — expired locks are overwritten on the next `acquireLock()` call, and expired cache entries are deleted on the next `get()` call for that key.
92
-
93
- For high-throughput deployments, you may want to run a periodic cleanup job:
94
-
95
- ```sql
96
- DELETE FROM chat_state_locks WHERE expires_at <= now();
97
- DELETE FROM chat_state_cache WHERE expires_at <= now();
98
- ```
@@ -1,100 +0,0 @@
1
- ---
2
- title: Redis
3
- description: Production state adapter using the official redis package.
4
- type: reference
5
- prerequisites:
6
- - /docs/getting-started
7
- ---
8
-
9
- The recommended state adapter for production. Uses the official [redis](https://www.npmjs.com/package/redis) package.
10
-
11
- ## Installation
12
-
13
- ```sh title="Terminal"
14
- pnpm add @chat-adapter/state-redis
15
- ```
16
-
17
- ## Usage
18
-
19
- `createRedisState()` auto-detects the `REDIS_URL` environment variable, so you can call it with no arguments:
20
-
21
- ```typescript title="lib/bot.ts" lineNumbers
22
- import { Chat } from "chat";
23
- import { createRedisState } from "@chat-adapter/state-redis";
24
-
25
- const bot = new Chat({
26
- userName: "mybot",
27
- adapters: { /* ... */ },
28
- state: createRedisState(),
29
- });
30
- ```
31
-
32
- To provide a URL explicitly:
33
-
34
- ```typescript title="lib/bot.ts"
35
- const state = createRedisState({ url: "redis://localhost:6379" });
36
- ```
37
-
38
- ### Using an existing client
39
-
40
- If you already have a connected Redis client, pass it directly:
41
-
42
- ```typescript title="lib/bot.ts" lineNumbers
43
- import { createClient } from "redis";
44
-
45
- const client = createClient({ url: "redis://localhost:6379" });
46
- await client.connect();
47
-
48
- const state = createRedisState({ client });
49
- ```
50
-
51
- ### Key prefix
52
-
53
- All keys are namespaced under a configurable prefix (default: `"chat-sdk"`):
54
-
55
- ```typescript title="lib/bot.ts" lineNumbers
56
- const state = createRedisState({
57
- url: process.env.REDIS_URL!,
58
- keyPrefix: "my-bot",
59
- });
60
- ```
61
-
62
- ## Configuration
63
-
64
- | Option | Required | Description |
65
- |--------|----------|-------------|
66
- | `url` | No* | Redis connection URL (auto-detected from `REDIS_URL`) |
67
- | `client` | No | Existing `redis` client instance |
68
- | `keyPrefix` | No | Prefix for all keys (default: `"chat-sdk"`) |
69
- | `logger` | No | Logger instance (defaults to `ConsoleLogger("info")`) |
70
-
71
- *Either `url`, `REDIS_URL` env var, or `client` is required.
72
-
73
- ## Environment variables
74
-
75
- ```bash title=".env.local"
76
- REDIS_URL=redis://localhost:6379
77
- ```
78
-
79
- For serverless deployments (Vercel, AWS Lambda), use a serverless-compatible Redis provider like [Upstash](https://upstash.com).
80
-
81
- ## Key structure
82
-
83
- ```
84
- {keyPrefix}:subscriptions - SET of subscribed thread IDs
85
- {keyPrefix}:lock:{threadId} - Lock key with TTL
86
- ```
87
-
88
- ## Production recommendations
89
-
90
- - Use Redis 6.0+ for best performance
91
- - Enable Redis persistence (RDB or AOF)
92
- - Use Redis Cluster for high availability
93
- - Set appropriate memory limits
94
-
95
- ## Features
96
-
97
- - Persistent subscriptions across restarts
98
- - Distributed locking across multiple instances
99
- - Automatic reconnection
100
- - Key prefix namespacing
@@ -1,98 +1,3 @@
1
- /**
2
- * Modal elements for form dialogs.
3
- */
4
-
5
- type ModalChild = TextInputElement | SelectElement | RadioSelectElement | TextElement | FieldsElement;
6
- interface ModalElement {
7
- callbackId: string;
8
- children: ModalChild[];
9
- closeLabel?: string;
10
- notifyOnClose?: boolean;
11
- /** Arbitrary string passed through the modal lifecycle (e.g., JSON context). */
12
- privateMetadata?: string;
13
- submitLabel?: string;
14
- title: string;
15
- type: "modal";
16
- }
17
- interface TextInputElement {
18
- id: string;
19
- initialValue?: string;
20
- label: string;
21
- maxLength?: number;
22
- multiline?: boolean;
23
- optional?: boolean;
24
- placeholder?: string;
25
- type: "text_input";
26
- }
27
- interface SelectElement {
28
- id: string;
29
- initialOption?: string;
30
- label: string;
31
- optional?: boolean;
32
- options: SelectOptionElement[];
33
- placeholder?: string;
34
- type: "select";
35
- }
36
- interface SelectOptionElement {
37
- description?: string;
38
- label: string;
39
- value: string;
40
- }
41
- interface RadioSelectElement {
42
- id: string;
43
- initialOption?: string;
44
- label: string;
45
- optional?: boolean;
46
- options: SelectOptionElement[];
47
- type: "radio_select";
48
- }
49
- declare function isModalElement(value: unknown): value is ModalElement;
50
- interface ModalOptions {
51
- callbackId: string;
52
- children?: ModalChild[];
53
- closeLabel?: string;
54
- notifyOnClose?: boolean;
55
- /** Arbitrary string passed through the modal lifecycle (e.g., JSON context). */
56
- privateMetadata?: string;
57
- submitLabel?: string;
58
- title: string;
59
- }
60
- declare function Modal(options: ModalOptions): ModalElement;
61
- interface TextInputOptions {
62
- id: string;
63
- initialValue?: string;
64
- label: string;
65
- maxLength?: number;
66
- multiline?: boolean;
67
- optional?: boolean;
68
- placeholder?: string;
69
- }
70
- declare function TextInput(options: TextInputOptions): TextInputElement;
71
- interface SelectOptions {
72
- id: string;
73
- initialOption?: string;
74
- label: string;
75
- optional?: boolean;
76
- options: SelectOptionElement[];
77
- placeholder?: string;
78
- }
79
- declare function Select(options: SelectOptions): SelectElement;
80
- declare function SelectOption(options: {
81
- label: string;
82
- value: string;
83
- description?: string;
84
- }): SelectOptionElement;
85
- interface RadioSelectOptions {
86
- id: string;
87
- initialOption?: string;
88
- label: string;
89
- optional?: boolean;
90
- options: SelectOptionElement[];
91
- }
92
- declare function RadioSelect(options: RadioSelectOptions): RadioSelectElement;
93
- type AnyModalElement = ModalElement | ModalChild | SelectOptionElement;
94
- declare function fromReactModalElement(element: unknown): AnyModalElement | null;
95
-
96
1
  /**
97
2
  * Card elements for cross-platform rich messaging.
98
3
  *
@@ -458,6 +363,101 @@ declare function fromReactElement(element: unknown): AnyCardElement | null;
458
363
  */
459
364
  declare function cardChildToFallbackText(child: CardChild): string | null;
460
365
 
366
+ /**
367
+ * Modal elements for form dialogs.
368
+ */
369
+
370
+ type ModalChild = TextInputElement | SelectElement | RadioSelectElement | TextElement | FieldsElement;
371
+ interface ModalElement {
372
+ callbackId: string;
373
+ children: ModalChild[];
374
+ closeLabel?: string;
375
+ notifyOnClose?: boolean;
376
+ /** Arbitrary string passed through the modal lifecycle (e.g., JSON context). */
377
+ privateMetadata?: string;
378
+ submitLabel?: string;
379
+ title: string;
380
+ type: "modal";
381
+ }
382
+ interface TextInputElement {
383
+ id: string;
384
+ initialValue?: string;
385
+ label: string;
386
+ maxLength?: number;
387
+ multiline?: boolean;
388
+ optional?: boolean;
389
+ placeholder?: string;
390
+ type: "text_input";
391
+ }
392
+ interface SelectElement {
393
+ id: string;
394
+ initialOption?: string;
395
+ label: string;
396
+ optional?: boolean;
397
+ options: SelectOptionElement[];
398
+ placeholder?: string;
399
+ type: "select";
400
+ }
401
+ interface SelectOptionElement {
402
+ description?: string;
403
+ label: string;
404
+ value: string;
405
+ }
406
+ interface RadioSelectElement {
407
+ id: string;
408
+ initialOption?: string;
409
+ label: string;
410
+ optional?: boolean;
411
+ options: SelectOptionElement[];
412
+ type: "radio_select";
413
+ }
414
+ declare function isModalElement(value: unknown): value is ModalElement;
415
+ interface ModalOptions {
416
+ callbackId: string;
417
+ children?: ModalChild[];
418
+ closeLabel?: string;
419
+ notifyOnClose?: boolean;
420
+ /** Arbitrary string passed through the modal lifecycle (e.g., JSON context). */
421
+ privateMetadata?: string;
422
+ submitLabel?: string;
423
+ title: string;
424
+ }
425
+ declare function Modal(options: ModalOptions): ModalElement;
426
+ interface TextInputOptions {
427
+ id: string;
428
+ initialValue?: string;
429
+ label: string;
430
+ maxLength?: number;
431
+ multiline?: boolean;
432
+ optional?: boolean;
433
+ placeholder?: string;
434
+ }
435
+ declare function TextInput(options: TextInputOptions): TextInputElement;
436
+ interface SelectOptions {
437
+ id: string;
438
+ initialOption?: string;
439
+ label: string;
440
+ optional?: boolean;
441
+ options: SelectOptionElement[];
442
+ placeholder?: string;
443
+ }
444
+ declare function Select(options: SelectOptions): SelectElement;
445
+ declare function SelectOption(options: {
446
+ label: string;
447
+ value: string;
448
+ description?: string;
449
+ }): SelectOptionElement;
450
+ interface RadioSelectOptions {
451
+ id: string;
452
+ initialOption?: string;
453
+ label: string;
454
+ optional?: boolean;
455
+ options: SelectOptionElement[];
456
+ }
457
+ declare function RadioSelect(options: RadioSelectOptions): RadioSelectElement;
458
+ type AnyModalElement = ModalElement | ModalChild | SelectOptionElement;
459
+ declare function fromReactModalElement(element: unknown): AnyModalElement | null;
460
+
461
461
  /**
462
462
  * Custom JSX runtime for chat cards.
463
463
  *