mirror of
https://github.com/vercel/chat.git
synced 2026-09-14 18:32:29 +08:00
create-chat-sdk@0.2.0
470 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b1940d2374 |
chore(release): version packages (#660)
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @chat-adapter/github@4.33.0 ### Minor Changes - |
||
|
|
ef2542c5fd |
feat(x): add X (Twitter) adapter (#682)
## summary
new `@chat-adapter/x` adapter for X (Twitter), built on the X API v2 and
the X Activity API. write bot logic once and reply to mentions, hold DM
conversations, post from the account, and like posts, like the other
Chat SDK adapters
what it supports:
- reply to public mentions (`post.mention.create`) and top-level posts
via `channel.post`
- send and receive direct messages (`dm.received` / `dm.sent`)
- edit and delete owned posts, delete own DM events
- likes as the only reaction (`emoji.heart` or `"like"`)
- buffered streaming: accumulates an LLM stream and posts once instead
of post+edit churn on a public timeline
- OAuth 2.0 user context with managed token refresh (rotating refresh
token persisted in the state adapter, optional AES-256-GCM encryption)
- webhook CRC and `x-twitter-webhooks-signature` verification
key design decisions:
- DMs are threaded by the other participant's user id (`x:dm:{userId}`)
because X DM webhooks carry no conversation id, only participants
- OAuth 2.0 only at runtime: DM send and read are verified to work on
OAuth 2.0 user tokens, so no OAuth 1.0a in the adapter (subscription and
webhook setup is one-time and handled in the X developer console)
- parsers were written against real captured payloads: mentions use the
v2 shape (author hydrated in `includes.users`), DMs use the legacy
Account Activity shape (`direct_message_events`,
`message_create.message_data`, a `users` map, and no conversation id)
also includes the `chat/adapters` catalog entry, docs page, CLI scaffold
spec, and `sample-messages.md` with real captured payloads
<details><summary>usage</summary>
```typescript
import { Chat } from "chat";
import { createXAdapter } from "@chat-adapter/x";
const bot = new Chat({
userName: "mybot",
adapters: { x: createXAdapter() },
});
bot.onNewMention(async (thread, message) => {
await thread.post(`hi @${message.author.userName}!`);
});
bot.onDirectMessage(async (thread) => {
await thread.post("hello from X");
});
```
</details>
## test plan
- adapter unit tests pass against the real captured payload shapes, with
regression tests for author-from-`includes` (mentions) and the legacy
`direct_message_events` shape (DMs)
- real captured `post.mention.create` and `dm.received` payloads
verified end-to-end through `handleWebhook`: signature verification,
routing, author resolution, and participant threading, plus
bad-signature rejection returns 401
- every write and read path fired live against the X API through the
adapter: top-level post, reply to a mention, like and unlike, edit,
delete, DM send, DM read, DM delete
- OAuth 2.0 managed token refresh exercised live (access and refresh
token rotation)
---------
Signed-off-by: dancer <josh@afterima.ge>
|
||
|
|
6de45723ef |
fix(discord): Implement rehydrateAttachment (#679)
## Summary The Discord adapter never implemented `rehydrateAttachment`, so consumers couldn't rebuild an attachment's `fetchData` after a message was serialized and restored, and inbound Discord attachments couldn't be downloaded once rehydrated. Every other URL/media adapter implements it. Discord attachment URLs are directly fetchable and survive serialization, so `fetchData` is rebuilt to fetch the URL (signed params preserved, no auth header — the links are pre-signed), reading `fetchMetadata?.url ?? attachment.url` like the other URL-based adapters. Returns the attachment unchanged when there's no URL. Adds unit tests and a changeset. ## Test plan - `pnpm --filter @chat-adapter/discord test` — 248 passing - `pnpm validate` Signed-off-by: marsxiang5902 <marsxiang5902@gmail.com> |
||
|
|
e7a396ae70 |
feat(tests): add threadId + self-message contracts and adopt across adapters (#675)
## @chat-adapter/tests Adds two shared behavioral contracts (self-tested against fakes, exported, with a minor changeset): - `threadIdContract` — verifies a thread-id codec round-trips (`decode(encode(x))`), prefixes ids with the adapter name, matches pinned encoded strings, and optionally distinguishes DM from non-DM. - `selfMessageContract` — verifies an adapter dispatches inbound messages from other users but ignores messages the bot authored itself (uses the shared matchers). ## Adoption - `threadIdContract` adopted across 10 adapters (github, linear, gchat, teams, discord, slack, telegram, whatsapp, twilio, messenger), replacing bespoke encode/decode/round-trip/isDM blocks while keeping error/edge cases. - `selfMessageContract` adopted where it cleanly applies (github, messenger). Deliberately skipped where adapters dispatch-then-flag `isMe` (linear, slack, gchat) or lack a network-free webhook self test (teams, whatsapp, etc.). Net ~−290 more lines. Stacked on #674. --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
ac5a54ee1d |
test(adapters): adopt shared @chat-adapter/tests factories and matchers (#674)
Wires `@chat-adapter/tests` as a devDependency and registers its matchers via `setupFiles: ["@chat-adapter/tests/setup"]` across all 11 platform adapters, then replaces bespoke local `mockLogger`/`createMockState`/`createMockChatInstance` with the shared factories and adopts `toHaveDispatched`/`not.toHaveDispatched` where clean. - 10 adapters migrated (gchat, messenger, teams, whatsapp, telegram, discord, twilio, linear, github, slack). Positional `createMockChatInstance(...)` call sites converted to the options API (slack 100, linear 35). - `web` left as-is — its suite uses the real `Chat`/`createMemoryState` for e2e, so the shared factories don't apply. - Platform SDK mocks (Octokit, WebClient, socket-mode, `@linear/sdk`, `fetch`) and the Phase 1 `connectWebhookContract` descriptors are left intact. Net ~−540 lines of duplicated test scaffolding. Stacked on #673. Tests-only, no changeset. --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
840c0d16e9 |
test(adapters): migrate Vercel Connect webhook tests to connectWebhookContract (#673)
Adopts the shared `connectWebhookContract` from `@chat-adapter/tests` in the Slack, GitHub, and Linear suites, replacing the bespoke `webhookVerifier` blocks (verifier pass → 200, throw/falsy → 401, invoked with request + raw body, precedence over a native secret). Adapter-specific Connect tests are kept (token resolvers, GitHub bot-id capture, type-level mutual exclusivity, 400-on-invalid-JSON, Linear identity/`withInstallation`). Each descriptor keeps `initialize()` network-free (GitHub `botUserId`, Slack `_botUserId` to skip `auth.test`, Linear stubs `resolveConnectIdentity`). Twilio is intentionally not included — it has a single generic `webhookVerifier` usage with no 200/401 gating suite to migrate. First of three stacked test-generalization PRs. Tests-only, no changeset. Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
eb466e526f |
docs: add chat-adapter-zaileys community adapter (#677)
## Summary Adds **chat-adapter-zaileys** to the community adapters catalog — a WhatsApp adapter powered by [Zaileys](https://github.com/zeative/zaileys), a batteries-included TypeScript wrapper around the unofficial WhatsApp Web API. - npm: https://www.npmjs.com/package/chat-adapter-zaileys - Repo: https://github.com/zeative/chat-adapter-zaileys - Docs: https://zeative.github.io/chat-adapter-zaileys/ ## What it adds vs the existing Baileys community adapter - Real `thread.fetchMessages` history backed by a pluggable message store (memory/SQLite/Postgres/Redis/Convex), with cursor pagination and `rehydrateAttachment` for queue/debounce strategies - Cards render as **native WhatsApp buttons** with `chat.onAction` round-trips - Poll votes decrypted natively — no `messageSecret` bookkeeping, works across restarts - `scheduleMessage` support (persisted scheduler) - Opt-in slash-command routing to `chat.onSlashCommand` - QR/pairing auth, reconnection, and session persistence handled by the underlying client ## Files changed (per `.agents/skills/add-adapter`) - `apps/docs/content/adapters/community/zaileys.mdx` — docs page with feature matrix - `apps/docs/content/adapters/community/meta.json` — slug added to Platforms - `apps/docs/adapters.json` — registry entry - `packages/integration-tests/src/documentation-test-utils.ts` — `chat-adapter-zaileys` + `zaileys` in `VALID_DOC_PACKAGES` ## Validation - `pnpm --filter chat build` ✓ - `pnpm --filter @chat-adapter/integration-tests test` → 914/914 ✓ - `pnpm --filter chat typecheck` ✓ - `pnpm check` + `pnpm konsistent` ✓ Signed-off-by: zeative <zaadevofc@gmail.com> |
||
|
|
0c761f1bdd |
docs(adapters): add Dial as vendor-official adapter (#676)
Adds Dial as a vendor-official adapter — SMS, MMS, iMessage, and inbound voice-call transcripts for Chat SDK. - `vendor-official/dial.mdx` adapter page (following the Photon / Linq / Sendblue format) - catalog entry in `packages/chat/src/adapters/index.ts` with `DIAL_API_KEY` / `DIAL_FROM_NUMBER_ID` / `DIAL_WEBHOOK_SECRET` - `create-chat-sdk` scaffold spec entry - registry entry in `adapters.json` + `dial` added to vendor-official `meta.json` - integration-test doc lists + changeset Repo: https://github.com/GetDial-AI/chat-sdk-adapter · npm: `@getdial/chat-sdk-adapter` · Dial docs: https://docs.getdial.ai/integrations/agent-clients/vercel-chat-sdk The adapter maps a phone conversation to a Chat SDK thread (identified by the pair of phone numbers — Dial-owned and peer), an SMS/MMS/iMessage to a message with optional media attachments, and a completed voice call's transcript to a message on the caller's thread. Outbound sends and transcript fetches go through the official `@getdial/sdk`; inbound webhooks are HMAC-SHA256 verified against a per-subscription signing secret with constant-time compare. ### Validation - `pnpm --filter chat build` — clean - `pnpm --filter chat typecheck` — clean - `pnpm --filter create-chat-sdk typecheck` — clean - `pnpm --filter @chat-adapter/integration-tests exec vitest run src/docs-adapters.test.ts` — 361/361 passed - `pnpm check` (ultracite) — clean - `pnpm konsistent` — 34 files, no violations |
||
|
|
d4c52cade3 |
refactor(shared): share the bare-mention scanner across Discord, Teams, and Slack (#652)
The Discord adapter (fixed in #651) converts bare `@mentions` with a regex. A single-character lookbehind can't tell whether an `@` sits inside a URL, a code span, or an email host, so it still mangles cases the regex can't see. The Slack adapter already had a robust character-scanning resolver — `replaceBareMentions` — that handles exactly those cases, but it lived inside `adapter-slack`. This lifts that scanner into `@chat-adapter/shared` and points every adapter that does bare-mention conversion at it: Slack (dedup, no behavior change), Discord, and Teams — which had the identical `/@(\w+)/g` → `<at>$1</at>` bug in two places. ## What changed - **`@chat-adapter/shared`** — new `replaceBareMentions` (+ `MentionReplacer` type), moved verbatim from Slack. It skips inline/fenced code, scheme + schemeless URLs, and existing `<…>` tokens before handing each real `@name` to a platform-specific replacer. Adds a dedicated test file (the scanner had no direct tests before). - **Slack** — sources `replaceBareMentions` from `@chat-adapter/shared`; local `mentions.ts` deleted. Behavior unchanged. - **Discord** — regex → scanner in both conversion sites. - **Teams** — same fix for `<at>…</at>` mention tags. ## What this fixes (Discord + Teams) Across both the `{markdown}`/AST and `{raw}`/plain-string paths: | input | before | after | |---|---|---| | `https://github.com/@vercel` | `https://github.com/<@vercel>` | preserved | | `twitter.com/@jack` | `twitter.com/<@jack>` | preserved | | `` `ping @here` `` | `` `ping <@here>` `` | preserved | | `<@123>` (Discord, raw) | `<<@123>>` | preserved | Emails (`user@example.com`), period-prefixed mentions (`docs.@everyone`), and existing tokens keep working. ## Notes - `.changeset/config.json` uses `fixed: [["chat", "@chat-adapter/*"]]`, so the `@chat-adapter/shared` **minor** bump carries the whole family to a minor release; the `discord` / `teams` `patch` changesets exist for their changelog text. Slack has no behavioral change, so it gets no changeset. - Rebased on top of #651. That PR's `discord-email-mentions.md` changeset stays; this PR's scanner supersedes its regex implementation, so the two Discord changelog entries read as a progression. Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
0b63791b66 |
fix(slack): process Socket Mode retry envelopes instead of dropping them (#667)
Fixes #666 ## Summary Both `slack_event` handlers (`startSocketMode` and `runSocketModeListener`) ack and discard every envelope with `retry_num > 0`. Slack retries an event (immediately, +1 min, +5 min) when a prior delivery wasn't acked — including events that arrived while the app had **no open socket** (restart, deploy, or Slack's routine connection refreshes). For those, the retry is the only delivery the app ever sees, so dropping it permanently loses the event (production incident details in #666). - **`@chat-adapter/slack`**: route retry envelopes through `routeSocketEvent` like first deliveries (it acks per envelope type, preserving the 3s ack window), and log them at info with `retry_num` / `retry_reason` so redelivery is observable. Duplicate protection is unchanged and sufficient: `Chat.processMessage` dedupes on `message.id` (the Slack event `ts`, identical on a retry) via `state.setIfNotExists`. - **`chat`**: raise the default `DEDUPE_TTL_MS` from 5 to 10 minutes. Slack's final retry fires ~5 minutes after the original delivery — exactly at the old TTL boundary, where the dedupe entry from the first processing could expire just before the retry arrives and cause a double-process. `dedupeTtlMs` config still overrides. Behavior note for review: apps that relied on retries being invisible will now see redelivered events flow through — deduped when already handled, processed when not. That is the intended semantic: at-least-once delivery from Slack, exactly-once handling via the SDK's dedupe. ## Test plan - Replaced the `"skips retries"` test with `"processes retries like first deliveries (dedupe drops true duplicates)"` — asserts a `retry_num: 1` envelope is acked and reaches `processMessage`. - Updated the default-TTL test to 10 minutes; the custom-`dedupeTtlMs` test is unchanged. - `pnpm validate` passes end to end (knip, check, typecheck, test, build); `pnpm --filter chat --filter @chat-adapter/slack test` = 1028 + 506 passing. Signed-off-by: tdietert <thomasd@mercury.com> |
||
|
|
3abdc69103 |
docs(adapters): add Cloudflare Agents as vendor-official state adapter (#669)
Adds Cloudflare Agents as a vendor-official **state** adapter — `agents/chat-sdk`'s `createChatSdkState()`, a Chat SDK `StateAdapter` that stores subscriptions, locks, queues, dedupe keys, thread/channel state, transcripts, and history in Durable Object SQLite via `ChatSdkStateAgent` sub-agents. - `vendor-official/cloudflare-agents.mdx` state-adapter page (Agent setup, wrangler DO migration, sharding, config, storage/cleanup) - catalog entry in `packages/chat/src/adapters/index.ts` (`group: vendor-official`, `type: state`) - registry entry in `adapters.json` + `cloudflare-agents` in vendor-official `meta.json` - integration-test doc lists + changeset Repo: https://github.com/cloudflare/agents · package `agents` (`agents/chat-sdk`) · [docs](https://developers.cloudflare.com/agents/runtime/communication/chat-sdk/) ### Not wired into the create-chat-sdk CLI This adapter runs inside a Cloudflare Worker with Durable Objects, not the generated Next.js runtime, so it is intentionally kept out of the scaffold: - added to `CLI_INCOMPATIBLE_ADAPTERS` (rejected via `--adapter`, hidden from the platform picker and e2e run, like `lark`/`matrix`) - new `listCliStateAdapters()` filters the interactive **state** picker and the `--help` adapter list (the state picker previously used raw `listStateAdapters()` and would have offered it, then thrown on selection) ### Tests - `catalog/display.test.ts` — `listCliStateAdapters`: returns only state adapters, includes `memory`/`redis`, and excludes `cloudflare-agents` while asserting it *is* in the raw catalog - `catalog/selection.test.ts` — `resolveAdapterValue("cloudflare-agents")` throws "not supported" - `cli/program.test.ts` — `buildAdapterList()` help text omits `cloudflare-agents` - existing `CLI_SCAFFOLD_SPEC covers every catalog adapter` + docs-adapters/docs-content suites cover the catalog entry, registry parity, and MDX imports ### Validation - create-chat-sdk: **178 passed**, typecheck clean - integration docs suites pass; Biome + knip clean --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
24a04d5653 |
docs(adapters): add Photon as vendor-official adapter (#668)
Adds Photon as a vendor-official adapter — iMessage for Chat SDK. - `vendor-official/photon.mdx` adapter page (following the Linq / Sendblue / Kapso format) - catalog entry in `packages/chat/src/adapters/index.ts` with cloud/self-host credential modes - `create-chat-sdk` scaffold spec entry - registry entry in `adapters.json` + `photon` added to vendor-official `meta.json` - integration-test doc lists + changeset Repo: https://github.com/photon-hq/vercel-chat-adapter-imessage · npm: `@photon-ai/chat-adapter-imessage` · built on [spectrum-ts](https://github.com/photon-hq/spectrum-ts) The adapter runs in three modes — **Cloud** ([Spectrum Cloud](https://app.photon.codes)), **self-hosted** (gRPC), and **local** (on-device, macOS) — auto-detected from environment variables. Cloud mode delivers inbound messages via HMAC-signed webhooks; DMs can be replied to cold from a webhook delivery. ### Notes - Catalog slug is `photon`; docs code examples use `imessage` as the adapter key to match the upstream README. - Feature flags encode the README's remote-only caveats (reactions / editing / typing / modals as `partial`, mentions as DMs-only; no history, thread info, or reaction removal). ### Validation - `docs-adapters` integration tests — 1237 passed (catalog↔registry parity, peerDeps↔PackageInstall alignment) - `create-chat-sdk` e2e scaffold — 175 passed (scaffolds every catalog adapter, incl. photon) - `chat` + `create-chat-sdk` typecheck, Biome check, and konsistent — clean Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
ba375ce16c |
feat(create-chat-sdk): add Vercel Connect mode (#655)
Adds an opt-in Vercel Connect authentication mode to the scaffolder for the Slack, GitHub, and Linear adapters, via a `--connect` flag and a new interactive auth-mode prompt (shown only when a Connect-capable adapter is selected). When enabled, the generated project: - spreads the matching helper from `@vercel/connect/chat` into the adapter factory in `src/lib/bot.ts` (non-Connect adapters keep their native factory calls) - adds `@vercel/connect` to dependencies - lists each connector UID (for example `SLACK_CONNECTOR`) plus the recommended `GITHUB_BOT_USER_ID`, in place of native provider secrets, in `.env.example` - documents `vercel link` / `vercel env pull` and the deployed-URL webhook caveat in the README and post-install next steps Connect policy lives in the existing `scaffold-spec.ts` (per-adapter `connect` field), so `chat/adapters` stays the single source of adapter metadata. Stacked on #647 (base `vercel-connect/base`). ## Companion `@vercel/connect/chat` subpath: vercel/vercel#16826. --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
a7fb1bcfa1 |
feat(tests): add Vercel Connect webhook contract helper (#654)
Adds `connectWebhookContract` to `@chat-adapter/tests`: a shared Vitest suite that verifies a Connect-capable adapter's webhook verification. Given a small per-adapter descriptor, it asserts the behavior every Connect adapter shares — a `webhookVerifier` replaces the native signature/secret check and gates inbound requests (`200` on a truthy result, `401` on a thrown error or falsy result) and is invoked with the request and raw body. The helper depends only on `chat` types and is self-tested against a fake adapter, so it lives entirely under `packages/tests`. Stacked on #647 (base `vercel-connect/base`). ## Follow-up The Slack, GitHub, and Linear adapters don't consume this helper yet — they still have their own inline `webhookVerifier` tests. Migrating those to `connectWebhookContract` will happen as part of the ongoing effort to port adapter tests over to `@chat-adapter/tests`, which is where the helper becomes real shared coverage. ## Companion `@vercel/connect/chat` subpath: vercel/vercel#16826. --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
6750d59e72 |
feat(github): add Vercel Connect support (#650)
Adds Vercel Connect support to the GitHub adapter: - A new `installationToken` config option (string or resolver) supplies installation access tokens directly, skipping the GitHub App private-key JWT exchange. - A new optional `webhookVerifier` verifies inbound webhooks (Connect trigger-forwarded requests via a Vercel OIDC token) in place of the GitHub webhook secret. Pair with `connectGitHubAdapter()` from `@vercel/connect/chat`. Includes a changeset (`@chat-adapter/github` minor). Stacked on #647 (base `vercel-connect/base`). ## Companion `@vercel/connect/chat` subpath: vercel/vercel#16826. <img width="933" height="755" alt="CleanShot 2026-06-30 at 12 02 18" src="https://github.com/user-attachments/assets/cc834560-0486-4f09-b8d5-8264be360544" /> --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
4115c9431e |
feat(linear): add Vercel Connect support (#649)
Adds Vercel Connect support to the Linear adapter: - `accessToken` now accepts a `() => string | Promise<string>` resolver in addition to a string, so tokens can be sourced from Vercel Connect at runtime. - A new optional `webhookVerifier` verifies inbound webhooks (Connect trigger-forwarded requests via a Vercel OIDC token) in place of the Linear webhook secret. - Connect-mode outbound calls outside webhook handling are supported via `withInstallation(organizationId, fn)`. Pair with `connectLinearAdapter()` from `@vercel/connect/chat`. Includes a changeset (`@chat-adapter/linear` minor). Stacked on #647 (base `vercel-connect/base`). ## Companion `@vercel/connect/chat` subpath: vercel/vercel#16826. <img width="929" height="664" alt="CleanShot 2026-06-30 at 12 35 30" src="https://github.com/user-attachments/assets/c5861cb9-d66b-42c6-b838-5b4983f48646" /> --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
ba687cb13c |
docs(slack): document Vercel Connect support (#648)
Documents authenticating the Slack adapter with Vercel Connect via `connectSlackAdapter()` from `@vercel/connect/chat`. The Slack adapter already supports a `botToken` resolver and a `webhookVerifier`, so this is a documentation-only change (no changeset). Stacked on #647 (base `vercel-connect/base`). ## Companion `@vercel/connect/chat` subpath: vercel/vercel#16826. <img width="824" height="527" alt="CleanShot 2026-06-30 at 12 03 26" src="https://github.com/user-attachments/assets/cbced069-8913-4848-9cf1-df0e5f614353" /> --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
ab0e1806c8 |
feat(chat): Vercel Connect (#647)
Adds a Vercel Connect guide to the docs under **Usage** (`chat-sdk.dev/docs/vercel-connect`), covering connector setup, trigger forwarding, the per-platform `connect*Adapter` helpers from `@vercel/connect/chat`, custom OIDC webhook verification and its trust boundary, and limitations. Also adds a "Vercel Connect Guide" card to the docs homepage. This is the base of a stack; the adapter, tests, and CLI PRs below build on it. Docs-only, so no changeset. ## Stack - #647 — feat(chat): Vercel Connect (this PR, base → `main`) - #648 — docs(slack): document Vercel Connect support - #649 — feat(linear): add Vercel Connect support - #650 — feat(github): add Vercel Connect support - #654 — feat(tests): add Vercel Connect webhook contract helper - #655 — feat(create-chat-sdk): add Vercel Connect mode All of the above are stacked on this branch (`vercel-connect/base`). ## Companion The helpers this documents ship in the `@vercel/connect/chat` subpath: vercel/vercel#16826. --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
076fe5dc43 |
fix(chat): preserve skipped mention routing (#659)
## summary fixes skipped mention routing for collapsed concurrency messages queue and burst already passed skipped message context, but mention routing could still swallow message pattern handlers when no `onNewMention` handler was registered this also makes debounce preserve skipped context so an earlier debounced bot mention can still route to `onNewMention` when the latest message does not mention the bot |
||
|
|
6f18930cf3 |
chore(release): version packages (#623)
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @chat-adapter/discord@4.32.0 ### Minor Changes - |
||
|
|
219625724c |
fix(discord): sort imports (#657)
## summary sorts the Discord adapter type imports so main lint passes again ## test plan - `pnpm exec ultracite check packages/adapter-discord/src/index.ts` - `git diff --check` |
||
|
|
2e4735118e |
fix: let Plan tasks run in parallel without implicit auto-completion (#632)
## Summary Plan’s task list API always marked existing in-progress steps as complete whenever a new step was added. That made sense for simple sequential bots, but it blocked parallel work — even though the docs already showed a parallel pattern and per-task updates by ID were added earlier. This PR adds an optional flag on task creation so callers can keep multiple steps in progress at once, while leaving the old sequential behavior as the default. **Opt-out flag, default on**. We considered removing auto-completion entirely. That would’ve been cleaner for parallel use but would’ve broken existing sequential bots that rely on implicit “move to next step” behavior. Defaulting to the current behavior keeps upgrades safe; parallel callers pass the flag off. **No broader API redesign**. Task completion stays explicit via status updates and the existing “complete plan” flow. The change is scoped to when a new task is appended. closes #630 |
||
|
|
022a502726 |
feat(discord): add ephemeral slash command responses (#514)
## summary resolves #515 adds Discord slash-command interaction response flags so selected commands can defer as ephemeral Discord locks ephemerality on the initial `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE` response, so the adapter now exposes `interactionFlags` on `createDiscordAdapter` for that initial acknowledgement ```ts import { createDiscordAdapter, DiscordInteractionResponseFlag, } from "@chat-adapter/discord"; const discord = createDiscordAdapter({ interactionFlags: ({ command }) => { if (command === "/admin") { return DiscordInteractionResponseFlag.Ephemeral; } }, }); ``` handlers still use the normal `event.channel.post(...)` flow, and `event.channel.postEphemeral(...)` keeps the normal Chat SDK fallback behavior outside Discord's slash-command interaction response path Co-authored-by: dancer <josh@afterima.ge> |
||
|
|
eccc6b91bf |
fix(chat): detect mentions in skipped queued messages (#656)
## summary fixes #613 detects bot mentions across queued and burst skipped messages before routing handlers this makes `onNewMention` fire when an earlier skipped message mentions the bot and the latest collapsed message does not, while preserving `message.isMention` on the latest message adds regression coverage for both `queue` and `burst` |
||
|
|
4ee187ac3c |
fix(telegram): start typing before message processing (#612)
## Summary Send Telegram typing actions immediately for private incoming message and slash command updates before handing the message to Chat SDK processing. This lets Telegram clients show the native `...` indicator during early processing instead of waiting for downstream handler code to call `thread.startTyping()`. The change is scoped to private, non-bot Telegram messages and adds regression coverage for normal messages and slash commands plus a patch changeset. Closes #611 ## Test plan - [x] `pnpm validate` - [x] `pnpm --filter @chat-adapter/telegram test` - [x] `pnpm --filter @chat-adapter/telegram typecheck` - [x] `pnpm --filter @chat-adapter/telegram build` ## Checklist - [x] All commits are signed and verified - [x] `pnpm validate` passes - [x] Changeset added (or N/A — see [CONTRIBUTING.md](./CONTRIBUTING.md)) - [x] Documentation updated (or N/A) --------- Signed-off-by: dancer <josh@afterima.ge> Co-authored-by: dancer <josh@afterima.ge> |
||
|
|
fc7df9c4cf |
fix(github): remove raw webhook payload logging (#500)
- Remove raw GitHub webhook body previews from adapter debug/error logs - Prevents webhook payload content from being copied into application logs when debug logging is enabled - No webhook routing or response behavior change; only log fields change ## Context The GitHub adapter logged a preview of incoming webhook request bodies while handling webhooks. Raw webhook payloads can contain repository metadata, user-authored issue or pull request text, URLs, installation details, and other provider-controlled content. Even at debug level, SDK logging should avoid copying raw provider payloads into application logs by default. ## Problem Debug logging should provide useful operational context without changing the privacy boundary of webhook data. The previous log emitted a raw body preview before signature verification. That meant an application with debug logging enabled could record payload content from both valid GitHub webhook events and invalid requests that were later rejected. This is unnecessary for normal webhook troubleshooting. Derived request metadata is enough to understand routing and parsing failures without retaining payload text. ## Changes The GitHub adapter no longer logs raw webhook bodies or body previews. Webhook logs now use bounded request-shape metadata: - `bodyBytes` - `contentType` - `eventType` - `signaturePresent` - `jsonParseStatus` for invalid JSON The change preserves signature verification, ping handling, JSON parsing, and event routing behavior. Regression tests cover invalid signature, invalid JSON, and valid webhook paths with token-shaped and customer-slug sentinel strings in the payload. The tests assert those sentinels, the full raw body, the old raw-body log message, and `bodyPreview` do not appear in logger calls. A patch changeset is included for `@chat-adapter/github`. ## Verification - `pnpm turbo build --filter @chat-adapter/github` - `pnpm --filter @chat-adapter/github test` - `pnpm --filter @chat-adapter/github typecheck` - `pnpm check` - `git diff --check` |
||
|
|
0d4e3ee490 |
fix(discord): render bare URLs as bare links, not masked links. (#567)
## Summary Discord only renders masked links `[text](url)` inside embeds. In a normal message, a bare URL converted to `[url](url)` shows up as literal text rather than a clickable link. In nodeToDiscordMarkdown's link branch, return the bare URL when the link's label equals its target (the bare-URL / autolink case); labeled links are unchanged. Adds regression tests for both bare URLs and <autolinks>. Fixes #565. |
||
|
|
490fa00e87 |
fix(discord): don't mangle email addresses into mentions (#651)
## Bug The Discord adapter converts `@mentions` with `/@(\w+)/g` in two places — `DiscordFormatConverter.convertMentionsToDiscord` (plain/`raw` messages) and the text-node branch of `nodeToDiscordMarkdown` (markdown/AST messages): ```ts text.replace(/@(\w+)/g, "<@$1>"); ``` That pattern matches `@word` even when the `@` is preceded by a word character, so it rewrites **email addresses** and `word@word` handles into broken mentions: | input | before | after | |---|---|---| | `Contact me at user@example.com` | `Contact me at user<@example>.com` | `Contact me at user@example.com` | | `ping support@vercel.com` | `ping support<@vercel>.com` | `ping support@vercel.com` | | `hey @alice` | `hey <@alice>` | `hey <@alice>` (unchanged) | The Slack adapter already guards against exactly this with a word-boundary check (`replaceBareMentions`); the Discord converter didn't. ## Fix Introduce a shared top-level `BARE_MENTION_PATTERN = /(?<![\w@.])@(\w+)/g` (per AGENTS.md, regex literals live at top level) with a negative lookbehind, so only an `@` at a word boundary becomes a mention. Emails/handles are left intact; real bare mentions still convert. Used in both conversion sites. ## Test Adds a regression test in `markdown.test.ts` asserting `Contact me at user@example.com` round-trips through `toAst`/`fromAst` without becoming a mention. Includes a changeset (`@chat-adapter/discord` patch). Commit is signed (Verified) and DCO signed-off. --------- Signed-off-by: Osamaali313 <86572800+Osamaali313@users.noreply.github.com> Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
99c598505f |
docs: refresh agent docs, README badges, and Chat SDK skill (#646)
- Replace npm version/download badges with Agent Stack and MIT badges on the root README and all published package READMEs - Streamline root `AGENTS.md`: fix title, add an accurate monorepo map, trim duplicated CONTRIBUTING/Ultracite/env-var content, and link to package-level `AGENTS.md` files - Slim the Chat SDK agent skill (`skills/chat/SKILL.md` and published copies) to defer to bundled docs, chat-sdk.dev, Vercel KB, and `llms.txt` instead of inlining CLI flags, quick-start code, and API tables - Polish root README copy (install examples, adapter/build links, Vercel Plugin URL, Vercel KB link, “Made by Vercel” badge) - Minor `CONTRIBUTING.md` fixes: simplify DCO wording, correct preview-branch proxy file references (`proxy.ts` vs middleware) --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
ef3f0f63bd |
docs: add Weixin community adapter (#638)
Adds the [`chat-adapter-weixin`](https://github.com/wong2/weixin-chat-adapter) community adapter (Weixin / WeChat iLink bot) to the docs. ### What's included - `apps/docs/content/adapters/community/weixin.mdx` — hand-authored adapter page following the existing community-adapter structure (install, quick start, long-polling note, QR login, env vars, config `TypeTable`, thread-ID format, capabilities/limitations, and `<FeatureSupport />`). - `apps/docs/adapters.json` — registry entry (`community: true`, author, pinned README commit). - `apps/docs/content/adapters/community/meta.json` — sidebar link under **Platforms**. ### Notes The adapter talks to Weixin's iLink bot HTTP JSON APIs directly. It uses long polling for inbound messages (no webhook) and requires a Chat SDK `StateAdapter` for cursor / context-token / dedupe / history. It's 1:1 only, so messages route through `onDirectMessage`. ### Verification `docs-adapters` (322) and `docs-llms` (129) integration tests pass. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
438f5513b0 |
fix: avoid dummy message context for lightweight threads (#633)
## summary fixes #631 removes dummy `Message` casts from lightweight thread, action, and reaction paths when no incoming message context exists this keeps the existing `currentMessage` guard meaningful and prevents streaming through `chat.thread(threadId)`, `chat.openDM(...)`, action threads, and reaction threads from reading fields from an empty object when Slack lacks the thread or recipient context required by `chat.startStream`, the adapter now returns `null` before consuming the stream so Chat SDK can transparently use its post-and-edit fallback native Slack streaming remains available for webhook-created threads and DM threads with valid native stream context --------- Co-authored-by: dancer <josh@afterima.ge> |
||
|
|
64b66864b1 |
chore(changesets): ignore all example-* packages and enforce the convention (#626)
Replace the explicit per-example entries in the changesets `ignore` list with an `example-*` name glob (matched by micromatch). All example apps are private and never published, so listing them individually only adds version and changelog churn to release PRs, and each new example required editing this CODEOWNERS-gated file. Add an integration test that resolves the changesets config against the workspace and asserts every examples/* package is in the resolved ignore list and follows the `example-*` naming convention, so an off-convention example app fails CI instead of silently leaking into releases. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
937cac989e |
fix(telegram): prevent truncation of valid URLs with entity-marker characters in MarkdownV2 links (#610)
## Summary Fixes `@chat-adapter/telegram` silently truncating valid MarkdownV2 messages whose link URLs contain an odd number of entity-marker characters (`_`, `*`, `~`). `trimToMarkdownV2SafeBoundary` counted unescaped markers anywhere outside code spans and treated an odd total as an unterminated entity. But per the [MarkdownV2 spec](https://core.telegram.org/bots/api#markdownv2-style), only `)` and `\` are special inside the `(...)` URL part of an inline link — so a message ending with e.g. `[Read more](https://example.com/page?utm_campaign=a&utm_source=b&utm_channel=c)` (3 raw underscores in the URL) was sliced mid-URL, rejected by Telegram with `can't parse entities: Can't find end of a URL`, and degraded to plain text by the markdown fallback — links and formatting silently stripped. Changes in `findUnescapedPositionsOutsideCode`: - Tracks a link-URL state alongside the existing `inFence`/`inInline` tracking: it opens when an unescaped `](` is consumed outside code and closes at the first unescaped `)`. Markers inside that span are never recorded. - A link's `]` only counts toward bracket pairing once its URL closes, so hard truncation (4096-char limit) that slices mid-URL now leaves the `[` unmatched and trims back to before the link — previously the cut left an unterminated `(` that Telegram rejected. The defensive under-limit safety pass from #446 (streaming chunks) is intentionally kept; it's now link-aware. |
||
|
|
a8c4af7418 |
fix(slack): skip urls during mention resolution (#619)
## summary prevents cached Slack display names inside urls from being resolved as user mentions before payload formatting shares url-aware mention handling between cached user lookup and Slack formatting while preserving real mentions follow-up to #618, which only protected the final formatting pass |
||
|
|
efa96108bd |
docs: sync KB resources and harden sync-resources script (#635)
Syncs the bundled Chat SDK KB resources from Edge Config and hardens the `sync-resources` script that generates them. - **New guides** (4): Vercel Connect, the Slack Vercel Connect bot, AI Gateway + AI SDK, and the daily digest bot. Existing guide bodies refreshed and `templates.json` regenerated. - **Script hardening** (`scripts/sync-resources.ts`): - Fetch + validate all guides into memory **before** wiping the resources dir — a failed fetch now leaves the working tree untouched. - Validate the `resources-edge-config.json` shape with a clear error instead of a blind cast. - Reject duplicate guide slug collisions. - Retry transient fetches (5xx / network) with exponential backoff; fail fast on 4xx, bad content-type, and oversized bodies. - Mirror `skills/chat/SKILL.md` to **all four** committed copies (docs site `.well-known` + `AGENTS.md`, and the two `create-chat-sdk` scaffold templates). - TSDoc on every function. - **Tests**: new offline consistency test in `packages/integration-tests` — every guide has a non-empty file with no orphans, `templates.json` mirrors the config, no duplicate slugs, and all four `SKILL.md` copies are byte-identical to the source. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
07c1112976 |
[slack] skip mention resolution inside code blocks (#629)
Mention resolution happening inside code blocks – results in agents attempting to write NPM package names printing a Slack Bot user ID instead. <img width="837" height="627" alt="image" src="https://github.com/user-attachments/assets/6690af58-61e6-469a-910d-f71c36bcdd61" /> --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
d034b8b575 |
docs(adapters): add Linq as vendor-official adapter (#625)
Adds Linq as a vendor-official adapter — iMessage and SMS for Chat SDK. - `vendor-official/linq.mdx` adapter page (following the Velt / AgentPhone format) - catalog entry in `adapters.json` - `linq` added to the vendor-official `meta.json` Repo: https://github.com/linq-team/linq-chat-sdk · npm: `@linqapp/chat-sdk-adapter` (Apache-2.0) The adapter is built and tested end-to-end against the live Linq API and the Chat SDK runtime (real iMessage round-trip, webhooks, reactions, media). Confirmed with Benji that a repo link works and Apache-2.0 is fine. Happy to adjust the page to match any conventions I missed. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
06af3e12fd |
docs(adapters): add Novu as vendor-official adapter (#622)
## Summary Adds Novu as a vendor official adapter to Chat SDK allowing multi-channel notification delivery and quick channel setup for multi-tenant apps. Official change log entry: https://novu.co/changelog/novu-chat-sdk-adapter/ Official social post: https://x.com/novuhq/status/2067870170320679158 ## Test plan Manually tested with our team to ensure compatability with the create chat sdk and template apps, also created an example repo: https://github.com/novuhq/novu-chat-sdk-example ## Checklist - [x] All commits are signed and verified - [x] `pnpm validate` passes - [x] Changeset added (or N/A — see [CONTRIBUTING.md](./CONTRIBUTING.md)) - [x] Documentation updated (or N/A) --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
2a553aa948 |
chore(release): version packages (#600)
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @chat-adapter/slack@4.31.0 ### Minor Changes - |
||
|
|
8c7141174a |
feat(teams): add low-level primitives (#593)
Add Teams subpath exports for custom runtimes, including Bot Connector API helpers, Graph reads, parse-only webhooks, format helpers, Adaptive Cards, and Task Module primitives. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
a8bf99ab19 |
fix(adapter-slack): don't rewrite @handles inside URL paths as mentions (#618)
## Problem `linkBareMentionNames` (in `markdown.ts`) rewrites any bare `@word` into a `<@word>` Slack mention. Its lookbehind `(?<![<\w])@(\w+)` excludes `<` and word characters, but **not `/`** — so an `@handle` inside a URL path gets rewritten, corrupting the link: ``` See https://hackmd.io/@jkyang/B1W69XA-fe → See https://hackmd.io/<@jkyang>/B1W69XA-fe ❌ (Slack renders a broken mention; link dead) ``` This affects common `@handle` URLs (HackMD `/@user`, Mastodon `/@user`, Medium `/@user`, …). It reproduces on `main` via `toSlackPayload` for both the plain `text` and the native `markdown_text` paths, because `finalize()` runs the regex over the whole string. (The `renderPostable({ markdown })` AST path is unaffected — bare URLs become link nodes there — which is likely why it's gone unnoticed.) This is the same class of bug as the email fix in #394, which tuned this same regex; URL paths are the sibling case it didn't cover. ## Fix Add `/` to the negative lookbehind so a handle preceded by a path separator is left intact: ```diff -const BARE_MENTION_PATTERN = /(?<![<\w])@(\w+)/g; +const BARE_MENTION_PATTERN = /(?<![<\w/])@(\w+)/g; ``` Whitespace-/punctuation-led mentions (`(cc @george)`), emails (`user@example.com`), and `<mailto:…>` links are unaffected. ## Tests Two cases added to the `mentions` suite (plain string + markdown). Verified against current `main`: - **Without the fix:** both new tests fail (e.g. `…/@user` → `…/<@user>`). - **With the fix:** full `markdown.test.ts` suite passes (28/28). Changeset included (`patch`). --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
8f3af76565 |
feat: add create-chat-sdk CLI (#603)
Adds `create-chat-sdk`, a CLI that scaffolds a Next.js Chat SDK bot project: ```bash npm create chat-sdk@latest my-bot # non-interactive npm create chat-sdk@latest -- my-bot --adapter slack redis -y ``` The user picks platform and state adapters interactively or via `--adapter`, and the CLI generates a webhook-only project with `src/lib/bot.ts`, `.env.example`, `next.config.ts`, `package.json`, and a README, then optionally runs `git init` and installs dependencies. There are no pages or client UI in the template. Adapter choices come straight from the `chat/adapters` catalog, so the CLI has no adapter registry of its own. When a coding agent such as Cursor or Claude Code runs the CLI, it uses non-interactive defaults and requires an explicit platform adapter. `--interactive` forces prompts. ## also in this pr - `google-chat` is renamed to `gchat` everywhere, including docs pages, the OG image, and adapter catalog. Old URLs redirect permanently, including language-prefixed and `/og` paths - a new docs page is available at `chat-sdk.dev/docs/create-chat-sdk`, and the CLI is promoted on the homepage, package READMEs, and agent skill - `create-chat-sdk` releases independently with a minor changeset for its initial `0.1.0` release --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: dancer <josh@afterima.ge> |
||
|
|
4662309fe3 |
feat(telegram): support native rich messages (#616)
## summary adds native rich message support for Telegram Bot API 10.1 explicit markdown and AST messages now use `sendRichMessage`, edits use rich message payloads, and private chat streams use `sendRichMessageDraft` before persisting the completed response preserves existing behavior for plain strings, raw messages, cards, media captions, and older or custom Bot API servers through automatic fallback adds typed inbound rich message parsing, rich message limits, regression coverage, and updated adapter documentation |
||
|
|
8336a3e818 |
feat(slack): expose webClientOptions to configure the underlying WebClient (#602)
## summary adds `webClientOptions` to `SlackAdapterConfig` so users can configure the underlying Slack `WebClient` instances the options apply to both the default client and per-token clients used for multi-workspace requests, including settings such as `retryConfig`, per-request `timeout`, custom headers, and `rejectRateLimitedCalls` `slackApiUrl` is intentionally excluded from `webClientOptions` because the existing `apiUrl` option remains the single configuration path for overriding the Slack Web API base URL custom headers are cloned for each client because the Slack SDK adds authorization to the provided headers object, preventing credentials from leaking between token-bound clients --------- Co-authored-by: dancer <josh@afterima.ge> |
||
|
|
9c936f8796 |
feat(telegram): support slash commands (#586)
## Summary Adds Telegram bot command support for Chat SDK slash command handlers. - Routes Telegram `/command` and `/command@botusername` messages to `bot.onSlashCommand` - Ignores commands addressed to another bot - Keeps non-command messages on the existing normal message path ## Test plan - `pnpm validate` - Tested locally against a real Telegram bot ## Checklist - [x] All commits are signed and verified - [x] `pnpm validate` passes - [x] Changeset added - [x] Documentation updated --------- Co-authored-by: dancer <josh@afterima.ge> |
||
|
|
b14114a714 |
test(slack): expand emulator coverage for emulate.dev 0.6.0 APIs (#591)
Upgrade @emulators/* to 0.6.0 and add integration tests for DMs, reactions, fetch history, modals, scheduled messages, file uploads, member joins, and bookmarks against the in-process Slack emulator. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
778ae69abc |
add zero-dependency chat/adapters for adapters catalog (#599)
Adapter Catalog: - Adds a zero-dependency `chat/adapters` subpath for official and vendor-official adapter metadata. - Includes typed catalog entries, env specs, peer dependency metadata, and helper APIs for setup and onboarding flows. - Wires the subpath into the `chat` package export map and build config. Code Coverage: - Adds unit coverage for catalog integrity, registry sync, helper behavior, official env declarations, and peer dependency derivation. - Extends docs integration coverage for `chat/adapters` imports and vendor-official package install metadata. Documentation: - Documents the new catalog on the adapter overview page. - Splits platform-specific adapter guidance into a new `/docs/platform-adapters` page. - Renames `/docs/state` to `/docs/state-adapters` and adds a redirect for the old slug. Agent Guidance: - Updates repo-local and public agent guidance so agents know when and how to use `chat/adapters`. - Adds focused `AGENTS.md` guidance inside `packages/chat/src/adapters` for future catalog maintenance. --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |
||
|
|
171657a019 |
[chat] adding stable id to link button action handlers (#598)
Enabling overriding the `link:<url>` action ID for `LinkButton` events. |
||
|
|
7ecb9730e3 |
chore(docs): add missing Twilio logo and add official platform adapter OG images (#589)
Adds official platform adapter branding across the docs site, npm
READMEs, and social previews.
- **Homepage**: add Twilio to the supported-platforms logo grid
- **OG images**: add custom artwork for all 11 official platform
adapters under content/adapters/official/og/; serve static-first from
the existing /adapters/official/{slug}/og route with dynamic fallback
for state adapters
- **READMEs**: add linked hero banners to every official platform
adapter package README, using the live OG URL as the single image source
- **Tests**: integration-test guardrails for OG image coverage, README
banner discoverability, and knip-clean helpers
- **Changeset**: empty changeset for CI
<img width="2400" height="1256" alt="Chat SDK - Slack"
src="https://github.com/user-attachments/assets/4d186a1c-5651-44b8-8698-091ee23b44da"
/>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
|
||
|
|
9921dcd1c4 |
docs(seo): improve npm metadata, README discoverability, and structured data (#587)
Improves Chat SDK discoverability across npm, READMEs, and the docs site for search engines and AI coding agents. - **npm metadata**: point every published package `homepage` at chat-sdk.dev deep links; expand `chat` keywords/description; fix `repository.directory` (`packages/chat-sdk` → `packages/chat`); align state adapter keywords - **READMEs**: add npm callouts, Documentation/Guides links, and AI Coding Agents sections (skill install, optional Vercel Plugin, `llms.txt` / `llms-full.txt`) across all published packages and the repo root - **docs JSON-LD**: `HowTo` / `TechArticle` on getting-started, streaming, and cards; `CollectionPage` + official-only `ItemList` on `/adapters` (with split human vs JSON-LD descriptions) - **UTMs**: add `chat-sdk_site` / `chat-sdk_repo` tracking params to Resources links in selected MDX pages and adapter READMEs (discord, github, slack, liveblocks, getting-started, ai index) - **contract tests**: integration-tests guardrails for npm metadata and README discoverability so future package additions don't drift --------- Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com> |