mirror of
https://github.com/coleam00/bolt.new-any-llm
synced 2024-12-26 22:02:09 +00:00
fix: remove monorepo
This commit is contained in:
parent
d364a6f774
commit
6fb59d2bc5
1
.github/workflows/ci.yaml
vendored
1
.github/workflows/ci.yaml
vendored
@ -45,7 +45,6 @@ jobs:
|
||||
with:
|
||||
wranglerVersion: '* -w'
|
||||
packageManager: pnpm
|
||||
workingDirectory: 'packages/bolt'
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: pages deploy
|
||||
|
83
README.md
83
README.md
@ -1,55 +1,84 @@
|
||||
# Bolt Monorepo
|
||||
# Bolt
|
||||
|
||||
Welcome to the Bolt monorepo! This repository contains the codebase for Bolt, an AI assistant developed by StackBlitz.
|
||||
Bolt is an AI assistant developed by StackBlitz. This package contains the UI interface for Bolt as well as the server components, built using [Remix Run](https://remix.run/).
|
||||
|
||||
## Repository Structure
|
||||
## Prerequisites
|
||||
|
||||
Currently, this monorepo contains a single package:
|
||||
|
||||
- [`bolt`](packages/bolt): The main package containing the UI interface for Bolt as well as the server components.
|
||||
|
||||
As the project grows, additional packages may be added to this workspace.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
Before you begin, ensure you have the following installed:
|
||||
|
||||
- Node.js (v20.15.1)
|
||||
- pnpm (v9.4.0)
|
||||
|
||||
### Installation
|
||||
## Setup
|
||||
|
||||
1. Clone the repository:
|
||||
1. Clone the repository (if you haven't already):
|
||||
|
||||
```bash
|
||||
git clone https://github.com/stackblitz/bolt.git
|
||||
cd bolt
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
|
||||
```bash
|
||||
pnpm i
|
||||
pnpm install
|
||||
```
|
||||
|
||||
3. Optionally, init git hooks:
|
||||
3. Create a `.env.local` file in the root directory and add your Anthropic API key:
|
||||
|
||||
```bash
|
||||
pnpmx husky
|
||||
```
|
||||
ANTHROPIC_API_KEY=XXX
|
||||
```
|
||||
|
||||
### Development
|
||||
Optionally, you an set the debug level or disable authentication:
|
||||
|
||||
To start developing the Bolt UI:
|
||||
|
||||
1. Navigate to the bolt package:
|
||||
|
||||
```bash
|
||||
cd packages/bolt
|
||||
```
|
||||
VITE_LOG_LEVEL=debug
|
||||
VITE_DISABLE_AUTH=1
|
||||
```
|
||||
|
||||
2. Start the development server:
|
||||
If you want to run authentication against a local StackBlitz instance, add:
|
||||
|
||||
```
|
||||
VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000
|
||||
```
|
||||
|
||||
**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore.
|
||||
|
||||
## Available Scripts
|
||||
|
||||
- `pnpm run dev`: Starts the development server.
|
||||
- `pnpm run build`: Builds the project.
|
||||
- `pnpm run start`: Runs the built application locally using Wrangler Pages. This script uses `bindings.sh` to set up necessary bindings so you don't have to duplicate environment variables.
|
||||
- `pnpm run preview`: Builds the project and then starts it locally, useful for testing the production build. Note, HTTP streaming currently doesn't work as expected with `wrangler pages dev`.
|
||||
- `pnpm test:` Runs the test suite using Vitest.
|
||||
- `pnpm run typecheck`: Runs TypeScript type checking.
|
||||
- `pnpm run typegen`: Generates TypeScript types using Wrangler.
|
||||
- `pnpm run deploy`: Builds the project and deploys it to Cloudflare Pages.
|
||||
|
||||
## Development
|
||||
|
||||
To start the development server:
|
||||
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
This will start the Remix Vite development server.
|
||||
|
||||
## Testing
|
||||
|
||||
Run the test suite with:
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
To deploy the application to Cloudflare Pages:
|
||||
|
||||
```bash
|
||||
pnpm run deploy
|
||||
```
|
||||
|
||||
Make sure you have the necessary permissions and Wrangler is correctly configured for your Cloudflare account.
|
||||
|
@ -4,7 +4,6 @@ import { useChat } from 'ai/react';
|
||||
import { useAnimate } from 'framer-motion';
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
import { cssTransition, toast, ToastContainer } from 'react-toastify';
|
||||
import { AnalyticsAction, AnalyticsTrackEvent, sendAnalyticsEvent } from '~/lib/analytics';
|
||||
import { useMessageParser, usePromptEnhancer, useShortcuts, useSnapScroll } from '~/lib/hooks';
|
||||
import { useChatHistory } from '~/lib/persistence';
|
||||
import { chatStore } from '~/lib/stores/chat';
|
||||
@ -195,18 +194,6 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
|
||||
resetEnhancer();
|
||||
|
||||
textareaRef.current?.blur();
|
||||
|
||||
const event = messages.length === 0 ? AnalyticsTrackEvent.ChatCreated : AnalyticsTrackEvent.MessageSent;
|
||||
|
||||
sendAnalyticsEvent({
|
||||
action: AnalyticsAction.Track,
|
||||
payload: {
|
||||
event,
|
||||
properties: {
|
||||
message: _input,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const [messageRef, scrollRef] = useSnapScroll();
|
@ -2,7 +2,6 @@ import { useStore } from '@nanostores/react';
|
||||
import { chatStore } from '~/lib/stores/chat';
|
||||
import { workbenchStore } from '~/lib/stores/workbench';
|
||||
import { classNames } from '~/utils/classNames';
|
||||
import { OpenStackBlitz } from './OpenStackBlitz.client';
|
||||
|
||||
interface HeaderActionButtonsProps {}
|
||||
|
||||
@ -40,9 +39,6 @@ export function HeaderActionButtons({}: HeaderActionButtonsProps) {
|
||||
<div className="i-ph:code-bold" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex ml-2">
|
||||
<OpenStackBlitz />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
38
app/lib/analytics.ts
Normal file
38
app/lib/analytics.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { CLIENT_ORIGIN } from '~/lib/constants';
|
||||
import { request as doRequest } from '~/lib/fetch';
|
||||
|
||||
export interface Identity {
|
||||
userId?: string | null;
|
||||
guestId?: string | null;
|
||||
segmentWriteKey?: string | null;
|
||||
avatar?: string;
|
||||
}
|
||||
|
||||
const MESSAGE_PREFIX = 'Bolt';
|
||||
|
||||
export enum AnalyticsTrackEvent {
|
||||
MessageSent = `${MESSAGE_PREFIX} Message Sent`,
|
||||
MessageComplete = `${MESSAGE_PREFIX} Message Complete`,
|
||||
ChatCreated = `${MESSAGE_PREFIX} Chat Created`,
|
||||
}
|
||||
|
||||
export async function identifyUser(access: string): Promise<Identity | undefined> {
|
||||
const response = await doRequest(`${CLIENT_ORIGIN}/api/identify`, {
|
||||
method: 'GET',
|
||||
headers: { authorization: `Bearer ${access}` },
|
||||
});
|
||||
|
||||
const body = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// convert numerical identity values to strings
|
||||
const stringified = Object.entries(body).map(([key, value]) => [
|
||||
key,
|
||||
typeof value === 'number' ? value.toString() : value,
|
||||
]);
|
||||
|
||||
return Object.fromEntries(stringified) as Identity;
|
||||
}
|
@ -3,7 +3,6 @@ import { useState, useEffect } from 'react';
|
||||
import { atom } from 'nanostores';
|
||||
import type { Message } from 'ai';
|
||||
import { toast } from 'react-toastify';
|
||||
import { AnalyticsAction, sendAnalyticsEvent } from '~/lib/analytics';
|
||||
import { workbenchStore } from '~/lib/stores/workbench';
|
||||
import { getMessages, getNextId, getUrlId, openDatabase, setMessages } from './db';
|
||||
|
||||
@ -107,14 +106,4 @@ function navigateChat(nextId: string) {
|
||||
url.pathname = `/chat/${nextId}`;
|
||||
|
||||
window.history.replaceState({}, '', url);
|
||||
|
||||
// since the `replaceState` call doesn't trigger a page reload, we need to manually log this event
|
||||
sendAnalyticsEvent({
|
||||
action: AnalyticsAction.Page,
|
||||
payload: {
|
||||
properties: {
|
||||
url: url.href,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
import { useStore } from '@nanostores/react';
|
||||
import type { LinksFunction } from '@remix-run/cloudflare';
|
||||
import { Links, Meta, Outlet, Scripts, ScrollRestoration, useLocation } from '@remix-run/react';
|
||||
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
|
||||
import tailwindReset from '@unocss/reset/tailwind-compat.css?url';
|
||||
import { useEffect } from 'react';
|
||||
import { sendAnalyticsEvent, AnalyticsAction } from './lib/analytics';
|
||||
import { themeStore } from './lib/stores/theme';
|
||||
import { stripIndents } from './utils/stripIndent';
|
||||
|
||||
@ -55,20 +53,6 @@ const inlineThemeCode = stripIndents`
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
const theme = useStore(themeStore);
|
||||
|
||||
const { pathname } = useLocation();
|
||||
|
||||
// log page events when the window location changes
|
||||
useEffect(() => {
|
||||
sendAnalyticsEvent({
|
||||
action: AnalyticsAction.Page,
|
||||
payload: {
|
||||
properties: {
|
||||
url: window.location.href,
|
||||
},
|
||||
},
|
||||
});
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
<html lang="en" data-theme={theme}>
|
||||
<head>
|
@ -4,14 +4,12 @@ import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants';
|
||||
import { CONTINUE_PROMPT } from '~/lib/.server/llm/prompts';
|
||||
import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text';
|
||||
import SwitchableStream from '~/lib/.server/llm/switchable-stream';
|
||||
import type { Session } from '~/lib/.server/sessions';
|
||||
import { AnalyticsAction, AnalyticsTrackEvent, sendEventInternal } from '~/lib/analytics';
|
||||
|
||||
export async function action(args: ActionFunctionArgs) {
|
||||
return actionWithAuth(args, chatAction);
|
||||
}
|
||||
|
||||
async function chatAction({ context, request }: ActionFunctionArgs, session: Session) {
|
||||
async function chatAction({ context, request }: ActionFunctionArgs) {
|
||||
const { messages } = await request.json<{ messages: Messages }>();
|
||||
|
||||
const stream = new SwitchableStream();
|
||||
@ -19,19 +17,8 @@ async function chatAction({ context, request }: ActionFunctionArgs, session: Ses
|
||||
try {
|
||||
const options: StreamingOptions = {
|
||||
toolChoice: 'none',
|
||||
onFinish: async ({ text: content, finishReason, usage }) => {
|
||||
onFinish: async ({ text: content, finishReason }) => {
|
||||
if (finishReason !== 'length') {
|
||||
await sendEventInternal(session, {
|
||||
action: AnalyticsAction.Track,
|
||||
payload: {
|
||||
event: AnalyticsTrackEvent.MessageComplete,
|
||||
properties: {
|
||||
usage,
|
||||
finishReason,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return stream.close();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user