You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs-src/spectrum-ts/content.mdx.vel
+48-1Lines changed: 48 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ import { TypeTooltip } from "/snippets/type-tooltip.mdx";
8
8
{% set ci = symbol("ts:spectrum-ts#ContentInput") %}
9
9
{% set cb = symbol("ts:spectrum-ts#ContentBuilder") %}
10
10
11
-
Spectrum exposes a family of content builders — `text`, `attachment`, `voice`, `contact`, `richlink`, `poll`, `group`, `custom`, `reaction`, `reply`, `edit`, `typing`, `rename`, and `avatar` — plus a string shortcut that's equivalent to `text()`. Any API that takes a <TypeTooltip name="ContentInput" type={`{{ ci.signature }}`} /> accepts a plain string or a <TypeTooltip name="ContentBuilder" type={`{{ cb.signature }}`} />.
11
+
Spectrum exposes a family of content builders — `text`, `streamText`, `attachment`, `voice`, `contact`, `richlink`, `poll`, `group`, `custom`, `reaction`, `reply`, `edit`, `typing`, `rename`, and `avatar` — plus a string shortcut that's equivalent to `text()`. Any API that takes a <TypeTooltip name="ContentInput" type={`{{ ci.signature }}`} /> accepts a plain string or a <TypeTooltip name="ContentBuilder" type={`{{ cb.signature }}`} />.
Send streaming LLM output as Spectrum content. The `streamText` builder wraps an async stream of text deltas so it can be sent like any other content item. On platforms that support it (iMessage in remote mode), the first chunk is sent immediately as a real message and then edited in place as more text arrives.
27
+
28
+
```ts
29
+
import { streamText } from "spectrum-ts";
30
+
```
31
+
32
+
`streamText` accepts whatever the popular LLM SDKs return — the Vercel AI SDK `streamText()` result, a raw `AsyncIterable` of chunks, or a `ReadableStream`:
33
+
34
+
<Tabs>
35
+
<Tab title="Vercel AI SDK">
36
+
```ts
37
+
import { streamText } from "spectrum-ts";
38
+
import { streamText as aiStreamText } from "ai";
39
+
40
+
const result = aiStreamText({ model, prompt: message.content.text });
41
+
await space.send(streamText(result));
42
+
```
43
+
</Tab>
44
+
<Tab title="AsyncIterable">
45
+
```ts
46
+
import { streamText } from "spectrum-ts";
47
+
48
+
async function* generate() {
49
+
yield "Hello, ";
50
+
yield "world!";
51
+
}
52
+
53
+
await space.send(streamText(generate()));
54
+
```
55
+
</Tab>
56
+
<Tab title="Custom extractor">
57
+
```ts
58
+
import { streamText } from "spectrum-ts";
59
+
60
+
await space.send(
61
+
streamText(customStream, {
62
+
extract: (chunk) => chunk.delta?.text ?? null,
63
+
}),
64
+
);
65
+
```
66
+
</Tab>
67
+
</Tabs>
68
+
69
+
Platforms that cannot stream silently skip the send with a warning.
70
+
24
71
## Attachments
25
72
26
73
Pass a file path or a `Buffer`. MIME types are detected from the file extension; override with `options.mimeType` when you already have the bytes.
Copy file name to clipboardExpand all lines: docs-src/spectrum-ts/custom-events-and-lifecycle.mdx.vel
+12Lines changed: 12 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -34,6 +34,18 @@ for await (const event of im.typing) {
34
34
35
35
Use the flat form on `app` when you want a merged feed across platforms; use the narrowed form when you only care about one.
36
36
37
+
### Fusor custom events
38
+
39
+
Fusor-backed providers can emit non-message events (presence, read receipts, delivery status) into typed event streams using `fusorEvent`. Inside a Fusor `messages` handler, yield a `fusorEvent(name, data)` alongside regular messages to push events into `app.<name>` streams:
Events emitted this way are available as `app.presence` (merged across providers) or `narrowedInstance.presence` (scoped to the emitting provider). The event name and data shape are fully typed based on the provider's event declarations.
When your platform receives inbound messages through webhooks (rather than a persistent connection), use `fusor(...)` as the client in `lifecycle.createClient`. A Fusor client handles webhook signature verification and delivers parsed payloads to your `messages` handler:
181
+
182
+
```ts
183
+
import { definePlatform, fusor, fusorEvent } from "spectrum-ts";
The Fusor overload of `definePlatform` replaces the top-level `messages` async generator with a per-webhook-delivery handler that receives `{ payload, config, respond }`. Call `respond()` to set the HTTP response sent back to the webhook caller.
225
+
178
226
## Registering your platform
179
227
180
228
Exported platforms work like the built-ins — register with `.config()` and use narrowing for the typed surface:
Copy file name to clipboardExpand all lines: docs-src/spectrum-ts/introduction.mdx.vel
+5-2Lines changed: 5 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -23,19 +23,22 @@ A user might message you in iMessage today, WhatsApp tomorrow, and your app next
23
23
24
24
With Spectrum, you run one agent server and add providers for the interfaces you want to support. Each provider connects a native interface to the same Spectrum API, so your agent can feel consistent everywhere.
25
25
26
-
Today, Spectrum supports iMessage, WhatsApp Business, and terminal development. The same model is built for more interfaces over time: Slack, Discord, websites, apps, phone calls, meetings, and hardware like HomePod.
26
+
Today, Spectrum supports iMessage, WhatsApp Business, Telegram, and terminal development. The same model is built for more interfaces over time: Slack, Discord, websites, apps, phone calls, meetings, and hardware like HomePod.
27
27
28
28
## Supported interfaces today
29
29
30
30
Spectrum currently includes official providers for:
Copy file name to clipboardExpand all lines: docs-src/spectrum-ts/platform-narrowing.mdx.vel
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ import { TypeTooltip } from "/snippets/type-tooltip.mdx";
7
7
8
8
{% set pi = symbol("ts:spectrum-ts#PlatformInstance") %}
9
9
10
-
Every platform provider exports a callable — `imessage`, `terminal`, `whatsappBusiness` — that **narrows** generic Spectrum types into platform-specific ones. The same function handles three different inputs.
10
+
Every platform provider exports a callable — `imessage`, `terminal`, `whatsappBusiness`, `telegram` — that **narrows** generic Spectrum types into platform-specific ones. The same function handles three different inputs.
11
11
12
12
## Narrowing the app
13
13
@@ -41,7 +41,7 @@ for await (const [space, message] of app.messages) {
41
41
}
42
42
```
43
43
44
-
Narrowing a space from the wrong platform throws at runtime. Always gate on `message.platform` (or a similar signal) first.
44
+
Narrowing a space from the wrong platform logs a structured warning at runtime. Always gate on `message.platform` (or a similar signal) first to avoid unexpected behavior.
description: "Send and receive messages through the Telegram Bot API"
4
+
---
5
+
6
+
```ts
7
+
import { telegram } from "spectrum-ts/providers/telegram";
8
+
```
9
+
10
+
The Telegram provider connects your agent to the Telegram Bot API. Inbound messages are delivered through Fusor webhooks; outbound messages use the Bot API directly. The provider supports text, media, reactions, replies, typing indicators, edits, and lazy media downloads.
11
+
12
+
## Config
13
+
14
+
```ts
15
+
telegram.config({
16
+
botToken: "your-bot-token",
17
+
});
18
+
```
19
+
20
+
| Option | Description |
21
+
|---|---|
22
+
| `botToken` | Bot token from [@BotFather](https://t.me/BotFather). |
Resolve a user by their Telegram user ID and open a space. You can also pass a `chatId` parameter to target a specific Telegram chat:
51
+
52
+
```ts
53
+
const tg = telegram(app);
54
+
const user = await tg.user("123456789");
55
+
const space = await tg.space(user);
56
+
57
+
await space.send("Hello from Spectrum.");
58
+
```
59
+
60
+
## Webhook registration
61
+
62
+
In cloud mode (when `projectId` and `projectSecret` are provided), the Telegram provider automatically registers its Fusor webhook on startup. In local or direct mode, you need to configure the webhook yourself through the Telegram Bot API.
63
+
64
+
## Supported features
65
+
66
+
| Feature | Support |
67
+
|---|---|
68
+
| Text messages | Send and receive |
69
+
| Media (photos, documents, audio, video) | Send and receive |
70
+
| Reactions | Send and receive |
71
+
| Threaded replies | Send and receive |
72
+
| Typing indicators | Send |
73
+
| Message edits | Send and receive |
74
+
| Custom Bot API calls | Via platform-specific actions |
0 commit comments