mirror of
https://github.com/vercel/chat.git
synced 2026-09-14 18:32:29 +08:00
8f3af76565
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>
77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import DynamicLink from "fumadocs-core/dynamic-link";
|
|
import {
|
|
listPlatformAdapters,
|
|
listStateAdapters,
|
|
type CatalogAdapter,
|
|
} from "chat/adapters";
|
|
|
|
const adapterHref = (adapter: CatalogAdapter): string => {
|
|
const group =
|
|
adapter.group === "vendor-official" ? "vendor-official" : "official";
|
|
return `/[lang]/adapters/${group}/${adapter.slug}`;
|
|
};
|
|
|
|
const byName = (first: CatalogAdapter, second: CatalogAdapter): number =>
|
|
first.name.localeCompare(second.name);
|
|
|
|
const getGroups = () => [
|
|
{
|
|
label: "Official platform adapters",
|
|
adapters: listPlatformAdapters()
|
|
.filter((adapter) => adapter.group === "official")
|
|
.sort(byName),
|
|
},
|
|
{
|
|
label: "Vendor-official platform adapters",
|
|
adapters: listPlatformAdapters()
|
|
.filter((adapter) => adapter.group === "vendor-official")
|
|
.sort(byName),
|
|
},
|
|
{
|
|
label: "State adapters",
|
|
adapters: [...listStateAdapters()].sort(byName),
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Collapsible adapter slug list sourced from the `chat/adapters` catalog.
|
|
*/
|
|
export const AdapterSlugList = () => {
|
|
const groups = getGroups();
|
|
const adapterCount = groups.reduce(
|
|
(count, group) => count + group.adapters.length,
|
|
0
|
|
);
|
|
|
|
return (
|
|
<details className="rounded-sm border bg-background p-3">
|
|
<summary className="cursor-pointer font-medium text-sm">
|
|
View available adapter slugs
|
|
</summary>
|
|
<div className="mt-4 grid gap-4 md:grid-cols-3">
|
|
{groups.map((group) => (
|
|
<section key={group.label}>
|
|
<h3 className="font-medium text-sm">{group.label}</h3>
|
|
<ul className="mt-2 space-y-1 text-sm">
|
|
{group.adapters.map((adapter) => (
|
|
<li key={adapter.slug}>
|
|
<DynamicLink
|
|
className="font-mono text-primary text-xs no-underline"
|
|
href={adapterHref(adapter)}
|
|
>
|
|
{adapter.slug}
|
|
</DynamicLink>
|
|
<span className="text-muted-foreground">
|
|
{" "}
|
|
- {adapter.name}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
))}
|
|
</div>
|
|
</details>
|
|
);
|
|
};
|