Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/adapters.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"type": "platform",
"description": "Hold encrypted 1:1 and group conversations on XChat with all cryptography handled inside the adapter.",
"packageName": "@chat-adapter/x",
"icon": "x",
"icon": "xchat",
"beta": true,
"readme": "https://github.com/vercel/chat/tree/main/packages/adapter-x"
},
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/app/[lang]/adapters/components/adapter-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
web,
whatsapp,
x,
xchat,
} from "@/lib/logos";

const iconMap: Record<
Expand All @@ -47,6 +48,7 @@ const iconMap: Record<
twilio,
messenger,
x,
xchat,
};

interface AdapterCardProps {
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/components/geistdocs/adapter-hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
web,
whatsapp,
x,
xchat,
} from "@/lib/logos";

const ICON_MAP: Record<
Expand All @@ -37,6 +38,7 @@ const ICON_MAP: Record<
twilio,
messenger,
x,
xchat,
};

interface AdapterHeroProps {
Expand Down
Binary file modified apps/docs/content/adapters/official/og/xchat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions apps/docs/content/adapters/official/x.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ export async function POST(request: Request) {
}
```

## X Adapter vs XChat Adapter

Both adapters ship from [`@chat-adapter/x`](https://www.npmjs.com/package/@chat-adapter/x), but they target different X surfaces and use different factories.

Use this **X** adapter (`createXAdapter` from `@chat-adapter/x`) when you want:

- Public timeline mentions and replies (`post.mention.create`)
- Classic (unencrypted) direct messages
- Posting from the bot account to the public timeline (`x:public`)
- Likes as reactions

Use the [**XChat** adapter](/adapters/official/xchat) (`createXchatAdapter` from `@chat-adapter/x/chat`) when you want:

- Encrypted XChat 1:1 and group conversations
- Typing indicators, read receipts, and emoji reactions
- Crypto handled inside the adapter (Juicebox PIN, key exchange, signed messages)

You can register both adapters on the same `Chat` instance if your bot needs public posts/DMs and encrypted XChat.

## Configuration

<TypeTable
Expand Down
21 changes: 20 additions & 1 deletion apps/docs/content/adapters/official/xchat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: XChat (encrypted messaging) adapter using the X API v2 chat endpoin
packageName: "@chat-adapter/x"
slug: xchat
type: platform
logo: x
logo: xchat
tagline: Hold encrypted 1:1 and group conversations on XChat, with all cryptography handled inside the adapter.
beta: true
features:
Expand Down Expand Up @@ -108,6 +108,25 @@ export async function POST(request: Request) {
}
```

## XChat Adapter vs X Adapter

Both adapters ship from [`@chat-adapter/x`](https://www.npmjs.com/package/@chat-adapter/x), but they target different X surfaces and use different factories.

Use this **XChat** adapter (`createXchatAdapter` from `@chat-adapter/x/chat`) when you want:

- Encrypted XChat 1:1 and group conversations
- Typing indicators, read receipts, and emoji reactions
- Crypto handled inside the adapter (Juicebox PIN, key exchange, signed messages)

Use the [**X** adapter](/adapters/official/x) (`createXAdapter` from `@chat-adapter/x`) when you want:

- Public timeline mentions and replies (`post.mention.create`)
- Classic (unencrypted) direct messages
- Posting from the bot account to the public timeline (`x:public`)
- Likes as reactions

You can register both adapters on the same `Chat` instance if your bot needs encrypted XChat and public posts/DMs.

## Configuration

<TypeTable
Expand Down
15 changes: 15 additions & 0 deletions apps/docs/lib/logos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,18 @@ export const x = (props: ComponentProps<"svg">) => (
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
</svg>
);

export const xchat = (props: ComponentProps<"svg">) => (
<svg
fill="currentColor"
viewBox="1.25 1.75 22.75 21.75"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
clipRule="evenodd"
d="M19.95 4.65C20.01 4.71 20.07 4.76 20.14 4.82C20.21 4.87 20.27 4.93 20.34 4.98C20.83 5.41 21.24 5.87 21.63 6.39C21.68 6.45 21.73 6.51 21.78 6.57C23.44 8.82 24 11.58 23.63 14.33C23.56 14.71 23.47 15.07 23.37 15.44C23.35 15.49 23.33 15.54 23.32 15.6C22.94 16.79 22.33 18.13 21.48 19.06C21.43 19.06 21.37 19.06 21.32 19.06C21.3 19.1 21.28 19.14 21.26 19.19C20.89 19.87 20.21 20.41 19.59 20.86C19.53 20.91 19.47 20.95 19.41 21C17.16 22.64 14.25 23.48 11.47 23.09C10.56 22.94 9.69 22.66 8.89 22.19C8.7 22.11 8.61 22.13 8.4 22.18C8.34 22.2 8.28 22.21 8.22 22.23C8.15 22.25 8.09 22.26 8.02 22.28C7.96 22.3 7.9 22.31 7.84 22.33C7.6 22.4 7.36 22.47 7.12 22.54C5.33 23.04 3.62 22.77 2.02 21.88C1.76 21.74 1.51 21.58 1.26 21.42C1.37 21.1 1.52 20.83 1.69 20.55C2.4 19.33 2.83 18.18 2.47 16.76C2.37 16.43 2.27 16.1 2.16 15.76C2.14 15.7 2.12 15.63 2.1 15.57C2.06 15.44 2.02 15.32 1.98 15.19C1.7 14.35 1.62 13.58 1.62 12.69C1.62 12.61 1.62 12.61 1.62 12.53C1.63 11.61 1.71 10.74 1.97 9.85C1.98 9.79 2 9.74 2.02 9.68C2.38 8.45 2.97 7.3 3.78 6.31C3.81 6.27 3.84 6.23 3.88 6.18C5.78 3.8 8.52 2.46 11.52 2.1C14.56 1.77 17.6 2.72 19.95 4.65ZM5.5 7.54C4.11 9.34 3.51 11.55 3.8 13.81C3.87 14.16 3.98 14.48 4.09 14.81C4.17 15.06 4.26 15.32 4.34 15.58C4.36 15.64 4.38 15.71 4.4 15.78C4.85 17.2 4.89 18.66 4.31 20.07C4.24 20.26 4.25 20.35 4.33 20.55C5.57 20.95 6.94 20.43 8.07 19.94C8.73 19.7 8.73 19.7 9.05 19.83C9.22 19.92 9.39 20.02 9.56 20.13C11.24 21.12 12.99 21.2 14.87 20.79C14.92 20.77 14.98 20.76 15.04 20.75C17.06 20.28 19.03 18.96 20.17 17.21C20.21 17.14 20.26 17.08 20.3 17.01C20.34 16.94 20.39 16.87 20.44 16.8C21.53 15.03 21.88 12.85 21.43 10.82C20.9 8.63 19.46 6.71 17.54 5.52C13.55 3.17 8.51 4.02 5.5 7.54Z"
fillRule="evenodd"
/>
</svg>
);
4 changes: 2 additions & 2 deletions packages/adapter-x/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export async function POST(request: Request) {

When using `createXchatAdapter()` without arguments, credentials are auto-detected from environment variables. The bot's @handle is resolved from `GET /2/users/me` at startup, so mention detection works without any hardcoding.

### X Chat setup
### XChat setup

### 1. Register encryption keys

Expand Down Expand Up @@ -369,7 +369,7 @@ X_VERIFY_SIGNATURES=true # Optional; set false to accept unverifiable
| Post cards | Yes (first `x.com/.../status/...` URL in outgoing text auto-attaches) |
| Media out | Yes (files encrypt-streamed and uploaded via the 3-step media upload flow) |
| Media in | Yes (attachments exposed with lazy download + decrypt via `fetchData()`) |
| Cards / buttons / modals | No (X Chat has no interactive message surface) |
| Cards / buttons / modals | No (XChat has no interactive message surface) |
| Tables | ASCII code blocks |

### Conversations
Expand Down
4 changes: 2 additions & 2 deletions packages/adapter-x/src/chat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1955,7 +1955,7 @@ export class XchatAdapter implements Adapter<XchatThreadId, XchatRawMessage> {
);
}

// Resolve to a unicode emoji (X Chat reactions are unicode). The shared
// Resolve to a unicode emoji (XChat reactions are unicode). The shared
// resolver's Google Chat profile is its plain-unicode output, so it is
// the right conversion here despite the name.
const unicodeEmoji = defaultEmojiResolver.toGChat(emoji);
Expand Down Expand Up @@ -2146,7 +2146,7 @@ export class XchatAdapter implements Adapter<XchatThreadId, XchatRawMessage> {

/**
* Send a typing indicator and keep re-sending it every few seconds until
* the next postMessage in this conversation (or a safety timeout). X Chat
* the next postMessage in this conversation (or a safety timeout). XChat
* typing pills expire quickly, so a single POST is invisible during a
* longer generation.
*/
Expand Down
Loading