From 3810443a35dc3c03e3a0576ca8172c414d6f1838 Mon Sep 17 00:00:00 2001 From: Simon Farshid Date: Thu, 20 Jun 2024 19:47:17 -0700 Subject: [PATCH] feat: assistant-ui create CLI (#272) --- .changeset/thick-baboons-confess.md | 5 ++ README.md | 35 ++++------- apps/www/pages/docs/getting-started.mdx | 49 ++++++++++------ apps/www/pages/docs/index.mdx | 15 +++++ packages/cli/src/commands/create.ts | 68 ++++++++++++++++++++++ packages/cli/src/index.ts | 4 +- packages/cli/src/utils/get-package-info.ts | 6 +- 7 files changed, 139 insertions(+), 43 deletions(-) create mode 100644 .changeset/thick-baboons-confess.md create mode 100644 packages/cli/src/commands/create.ts diff --git a/.changeset/thick-baboons-confess.md b/.changeset/thick-baboons-confess.md new file mode 100644 index 000000000..7134284d0 --- /dev/null +++ b/.changeset/thick-baboons-confess.md @@ -0,0 +1,5 @@ +--- +"assistant-ui": patch +--- + +feat: npx assistant-ui create diff --git a/README.md b/README.md index 3e5ed3a8d..7f8132aaa 100644 --- a/README.md +++ b/README.md @@ -10,30 +10,19 @@ - [Documentation](https://www.assistant-ui.com/docs/getting-started) -## Minimal Example with Vercel AI SDK +## Quick Start + +Step 1: Create a new project with `assistant-ui` pre-configured: ```sh -npx assistant-ui@latest add modal +npx assistant-ui@latest create my-app +cd my-app ``` -```tsx -"use client"; - -import { useChat } from "@ai-sdk/react"; -import { AssistantRuntimeProvider } from "@assistant-ui/react"; -import { useVercelUseChatRuntime } from "@assistant-ui/react-ai-sdk"; -import { AssistantModal } from "@/components/ui/assistant-ui/assistant-modal"; - -export default const MyApp = () => { - const chat = useChat({ - api: "/api/chat" // your backend route - }); - const runtime = useVercelUseChatRuntime(chat); - - return ( - - - - ); -} -``` +Step 2: Update the `.env` file with your OpenAI API key. + +Step 3: Run the app: + +```sh +npm run dev +``` \ No newline at end of file diff --git a/apps/www/pages/docs/getting-started.mdx b/apps/www/pages/docs/getting-started.mdx index 5872ed13e..617531caa 100644 --- a/apps/www/pages/docs/getting-started.mdx +++ b/apps/www/pages/docs/getting-started.mdx @@ -3,31 +3,42 @@ title: Getting Started description: React Components for AI Chat --- -import Image from "next/image"; -import architecture from "../../assets/docs/architecture.png"; +import { Steps } from "nextra/components"; -## Architecture +## Start with a new project -`assistant-ui` consists of two parts, **_Runtime_** and **_UI Components_**. + - +### Create a new project -The Runtime and UI Components each require independent setup and both must be set up. +Create a new project with `assistant-ui` pre-configured: -## Setup +```sh +npx assistant-ui@latest create my-app +cd my-app +``` -The recommended way to get started is with the following stack: +### Add API key -- NextJS -- Vercel's `ai` package -- `tailwindcss` for styling -- `shadcn/ui` for UI components +Add a new `.env` file to your project with your OpenAI API key: -### Step 1: Setup Runtime +```sh +OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +``` + +### Start the app + +```sh +npm run dev +``` + + +## Install in an existing app + + + + +### Setup Runtime You wrap your entire app in a `` component. @@ -36,7 +47,7 @@ The `Runtime` takes care of LLM communication, tools, streaming, state managemen Refer to [Picking a Runtime](/docs/runtimes/pick-a-runtime) to pick the right runtime for your use case. -### Step 2: Setup UI Components +### Setup UI Components The easiest way to get started is with `shadcn/ui` + `tailwind` components. @@ -45,3 +56,5 @@ Currently, two modes are supported: - [``](/docs/ui/AssistantModal): a modal chat UI in the bottom right corner - [``](/docs/ui/AssistantSidebar): a sidebar chat UI - [``](/docs/ui/Thread): the raw chat UI + + \ No newline at end of file diff --git a/apps/www/pages/docs/index.mdx b/apps/www/pages/docs/index.mdx index 1da6e9707..4add3394a 100644 --- a/apps/www/pages/docs/index.mdx +++ b/apps/www/pages/docs/index.mdx @@ -3,6 +3,9 @@ title: Introduction description: React Components for AI Chat --- +import Image from "next/image"; +import architecture from "../../assets/docs/architecture.png"; + ### Composable Primitives Inspired by [radix-ui](https://www.radix-ui.com/primitives), composable primitives allow you to mix and match the subset of features that you need. @@ -14,3 +17,15 @@ assistant-ui does not ship with any styling or CSS code. Instead, you start with ### Open and Extensible You have access to the entire internal state of assistant-ui and can mix and match your own promitives with ours. + +### Architecture + +`assistant-ui` consists of two parts, **_Runtime_** and **_UI Components_**. + + + +The Runtime and UI Components each require independent setup and both must be set up. \ No newline at end of file diff --git a/packages/cli/src/commands/create.ts b/packages/cli/src/commands/create.ts new file mode 100644 index 000000000..22968b8d4 --- /dev/null +++ b/packages/cli/src/commands/create.ts @@ -0,0 +1,68 @@ +import { Command } from "commander"; +import chalk from "chalk"; +import { spawn } from "child_process"; + +export const create = new Command() + .name("create") + .description("create a new project") + .arguments("") + .usage(`${chalk.green("")} [options]`) + .option( + "--use-npm", + ` + + Explicitly tell the CLI to bootstrap the application using npm +`, + ) + .option( + "--use-pnpm", + ` + + Explicitly tell the CLI to bootstrap the application using pnpm +`, + ) + .option( + "--use-yarn", + ` + + Explicitly tell the CLI to bootstrap the application using Yarn +`, + ) + .option( + "--use-bun", + ` + + Explicitly tell the CLI to bootstrap the application using Bun +`, + ) + .option( + "--skip-install", + ` + + Explicitly tell the CLI to skip installing packages +`, + ) + .action(() => { + const child = spawn( + "npx", + [ + `create-next-app@latest`, + ...process.argv.slice(3), + "-e", + "https://github.com/Yonom/assistant-ui-starter", + ], + { + stdio: "inherit", + }, + ); + + child.on("error", (error) => { + console.error(`Error: ${error.message}`); + }); + + child.on("close", (code) => { + if (code !== 0) { + console.log(`other-package-script process exited with code ${code}`); + } + }); + }); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 5940cfbb4..d1f160461 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -4,12 +4,13 @@ import { add } from "@/src/commands/add"; import { Command } from "commander"; import { getPackageInfo } from "./utils/get-package-info"; +import { create } from "./commands/create"; process.on("SIGINT", () => process.exit(0)); process.on("SIGTERM", () => process.exit(0)); async function main() { - const packageInfo = await getPackageInfo(); + const packageInfo = getPackageInfo(); const program = new Command() .name("assistant-ui") @@ -21,6 +22,7 @@ async function main() { ); program.addCommand(add); + program.addCommand(create); program.parse(); } diff --git a/packages/cli/src/utils/get-package-info.ts b/packages/cli/src/utils/get-package-info.ts index cdcfdd727..090c64343 100644 --- a/packages/cli/src/utils/get-package-info.ts +++ b/packages/cli/src/utils/get-package-info.ts @@ -1,8 +1,12 @@ import path from "node:path"; import fs from "node:fs"; +import { fileURLToPath } from "node:url"; export function getPackageInfo() { - const packageJsonPath = path.join("package.json"); + // Convert the current module URL to a file path + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const packageJsonPath = path.join(__dirname, "..", "package.json"); return JSON.parse(fs.readFileSync(packageJsonPath).toString("utf-8")) as { version: string;