From 62dabc01db524182f678fe005bbf0090342631a3 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Fri, 29 Nov 2024 10:48:31 +0100 Subject: [PATCH] docs (#14) --- docs/package.json | 3 + docs/rspress.config.ts | 27 ++- docs/src/_meta.json | 5 - docs/src/api/_meta.json | 23 --- docs/src/api/about.md | 3 - docs/src/api/core/_meta.json | 7 - docs/src/api/core/index.md | 3 - docs/src/api/slack/_meta.json | 7 - docs/src/api/slack/index.md | 3 - docs/src/docs/_meta.json | 10 +- docs/src/docs/about.md | 13 +- docs/src/docs/core/_meta.json | 40 +++++ docs/src/docs/core/chat-model.md | 28 +++ docs/src/docs/core/context.md | 74 ++++++++ docs/src/docs/core/error-handling.md | 23 +++ docs/src/docs/core/performance.md | 61 +++++++ docs/src/docs/core/plugins.md | 109 ++++++++++++ docs/src/docs/core/references.md | 70 ++++++++ docs/src/docs/core/system-prompt.md | 30 ++++ docs/src/docs/core/tools.md | 72 ++++++++ docs/src/docs/core/usage.md | 3 - docs/src/docs/core/usage.mdx | 59 +++++++ docs/src/docs/discord/_meta.json | 7 - docs/src/docs/discord/usage.md | 3 - docs/src/docs/getting-started.md | 3 - docs/src/docs/getting-started.mdx | 21 +++ docs/src/docs/integrations/_meta.json | 12 ++ docs/src/docs/integrations/discord-usage.md | 25 +++ docs/src/docs/integrations/slack-usage.md | 65 +++++++ docs/src/docs/slack/_meta.json | 7 - docs/src/docs/slack/usage.md | 3 - docs/src/index.md | 2 +- docs/src/public/img/favicon.ico | Bin 0 -> 15406 bytes docs/src/public/img/logo_dark.svg | 56 ++++++ docs/src/public/img/logo_light.svg | 52 ++++++ docs/src/public/img/logo_mono_dark.svg | 40 +++++ docs/src/public/img/logo_mono_light.svg | 42 +++++ docs/src/styles/index.css | 183 ++++++++++++++++++++ pnpm-lock.yaml | 129 ++------------ 39 files changed, 1118 insertions(+), 205 deletions(-) delete mode 100644 docs/src/api/_meta.json delete mode 100644 docs/src/api/about.md delete mode 100644 docs/src/api/core/_meta.json delete mode 100644 docs/src/api/core/index.md delete mode 100644 docs/src/api/slack/_meta.json delete mode 100644 docs/src/api/slack/index.md create mode 100644 docs/src/docs/core/chat-model.md create mode 100644 docs/src/docs/core/context.md create mode 100644 docs/src/docs/core/error-handling.md create mode 100644 docs/src/docs/core/performance.md create mode 100644 docs/src/docs/core/plugins.md create mode 100644 docs/src/docs/core/references.md create mode 100644 docs/src/docs/core/system-prompt.md create mode 100644 docs/src/docs/core/tools.md delete mode 100644 docs/src/docs/core/usage.md create mode 100644 docs/src/docs/core/usage.mdx delete mode 100644 docs/src/docs/discord/_meta.json delete mode 100644 docs/src/docs/discord/usage.md delete mode 100644 docs/src/docs/getting-started.md create mode 100644 docs/src/docs/getting-started.mdx create mode 100644 docs/src/docs/integrations/_meta.json create mode 100644 docs/src/docs/integrations/discord-usage.md create mode 100644 docs/src/docs/integrations/slack-usage.md delete mode 100644 docs/src/docs/slack/_meta.json delete mode 100644 docs/src/docs/slack/usage.md create mode 100644 docs/src/public/img/favicon.ico create mode 100644 docs/src/public/img/logo_dark.svg create mode 100644 docs/src/public/img/logo_light.svg create mode 100644 docs/src/public/img/logo_mono_dark.svg create mode 100644 docs/src/public/img/logo_mono_light.svg create mode 100644 docs/src/styles/index.css diff --git a/docs/package.json b/docs/package.json index 53ad3df..504a441 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,5 +13,8 @@ "rspress": "^1.35.1", "ts-node": "^10.9.2", "typescript": "^5.6.3" + }, + "dependencies": { + "rspress-plugin-font-open-sans": "^1.0.0" } } diff --git a/docs/rspress.config.ts b/docs/rspress.config.ts index 725ba09..fc0dc00 100644 --- a/docs/rspress.config.ts +++ b/docs/rspress.config.ts @@ -1,9 +1,32 @@ import { defineConfig } from 'rspress/config'; +import { pluginFontOpenSans } from 'rspress-plugin-font-open-sans'; +import * as path from 'node:path'; export default defineConfig({ root: 'src', base: '/byorg-ai/', - title: 'byorg-ai', + title: 'byorg.ai', + icon: '/img/favicon.ico', description: 'TypeScript framework for writing chatbot applications.', - plugins: [], + logo: { + light: '/img/logo_mono_light.svg', + dark: '/img/logo_mono_dark.svg', + }, + globalStyles: path.join(__dirname, 'src/styles/index.css'), + themeConfig: { + enableContentAnimation: true, + enableScrollToTop: true, + outlineTitle: 'Contents', + footer: { + message: `Copyright © ${new Date().getFullYear()} Callstack Open Source`, + }, + socialLinks: [ + { + icon: 'github', + mode: 'link', + content: 'https://github.com/callstack/byorg-ai', + }, + ], + }, + plugins: [pluginFontOpenSans()], }); diff --git a/docs/src/_meta.json b/docs/src/_meta.json index 8d4cb20..6141e46 100644 --- a/docs/src/_meta.json +++ b/docs/src/_meta.json @@ -3,10 +3,5 @@ "text": "Docs", "link": "/docs/about", "activeMatch": "^/docs/" - }, - { - "text": "API", - "link": "/api/about", - "activeMatch": "^/api/" } ] diff --git a/docs/src/api/_meta.json b/docs/src/api/_meta.json deleted file mode 100644 index 443343d..0000000 --- a/docs/src/api/_meta.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "type": "section-header", - "label": "API" - }, - { - "type": "file", - "name": "about", - "label": "About" - }, - { - "type": "dir", - "name": "core", - "label": "@callstack/core", - "collapsed": true - }, - { - "type": "dir", - "name": "slack", - "label": "@callstack/slack", - "collapsed": true - } -] diff --git a/docs/src/api/about.md b/docs/src/api/about.md deleted file mode 100644 index 0487b41..0000000 --- a/docs/src/api/about.md +++ /dev/null @@ -1,3 +0,0 @@ -# About - -This API documentation is about byorg-ai Framework diff --git a/docs/src/api/core/_meta.json b/docs/src/api/core/_meta.json deleted file mode 100644 index 3d5597f..0000000 --- a/docs/src/api/core/_meta.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "type": "file", - "name": "index", - "label": "Table of contents" - } -] diff --git a/docs/src/api/core/index.md b/docs/src/api/core/index.md deleted file mode 100644 index 8ee042d..0000000 --- a/docs/src/api/core/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# @callstack/core - -## Table of contents diff --git a/docs/src/api/slack/_meta.json b/docs/src/api/slack/_meta.json deleted file mode 100644 index 3d5597f..0000000 --- a/docs/src/api/slack/_meta.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "type": "file", - "name": "index", - "label": "Table of contents" - } -] diff --git a/docs/src/api/slack/index.md b/docs/src/api/slack/index.md deleted file mode 100644 index 41c20fa..0000000 --- a/docs/src/api/slack/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# @callstack/slack - -## Table of contents diff --git a/docs/src/docs/_meta.json b/docs/src/docs/_meta.json index ba4b9f0..b26dd84 100644 --- a/docs/src/docs/_meta.json +++ b/docs/src/docs/_meta.json @@ -17,14 +17,8 @@ }, { "type": "dir", - "name": "slack", - "label": "Slack", - "collapsed": true - }, - { - "type": "dir", - "name": "discord", - "label": "Discord", + "name": "integrations", + "label": "Integrations", "collapsed": true } ] diff --git a/docs/src/docs/about.md b/docs/src/docs/about.md index 4c019f1..87accfa 100644 --- a/docs/src/docs/about.md +++ b/docs/src/docs/about.md @@ -1,3 +1,12 @@ -# About byorg-ai +# About byorg.ai -This is main section about byorg-ai Framework +## Introduction + +byorg.ai is a framework designed for rapid development and deployment of AI assistants within companies and organizations. + +## Supported Integrations + +- Slack +- Discord + +byorg.ai supports a wide range of large language models (LLMs) via the Vercel [AI SDK](https://sdk.vercel.ai/docs/introduction). You can host byorg.ai applications on various cloud platforms or local environments. We provide examples for some popular hosting options. diff --git a/docs/src/docs/core/_meta.json b/docs/src/docs/core/_meta.json index 4c2723c..fe1c04a 100644 --- a/docs/src/docs/core/_meta.json +++ b/docs/src/docs/core/_meta.json @@ -3,5 +3,45 @@ "type": "file", "name": "usage", "label": "Usage" + }, + { + "type": "file", + "name": "chat-model", + "label": "Chat Model" + }, + { + "type": "file", + "name": "system-prompt", + "label": "System Prompt" + }, + { + "type": "file", + "name": "context", + "label": "Context" + }, + { + "type": "file", + "name": "plugins", + "label": "Plugins" + }, + { + "type": "file", + "name": "tools", + "label": "Tools" + }, + { + "type": "file", + "name": "references", + "label": "References" + }, + { + "type": "file", + "name": "performance", + "label": "Performance" + }, + { + "type": "file", + "name": "error-handling", + "label": "Error Handling" } ] diff --git a/docs/src/docs/core/chat-model.md b/docs/src/docs/core/chat-model.md new file mode 100644 index 0000000..eaabbbb --- /dev/null +++ b/docs/src/docs/core/chat-model.md @@ -0,0 +1,28 @@ +# Chat Model + +## Providers and Adapter + +You can use any AI provider supported by Vercel’s [AI SDK](https://sdk.vercel.ai/providers/ai-sdk-providers). This includes both LLM-as-a-service providers like OpenAI, Anthropic, and others, as well as locally hosted LLMs. We are also open to extending support to other types of chat models, such as LangChain’s [runnables](https://js.langchain.com/docs/how_to/streaming). + +### Providers Examples + +```js +import { createOpenAI } from '@ai-sdk/openai'; + +const openAiProvider = createOpenAI({ + apiKey: 'your-api-key', + compatibility: 'strict', +}); +``` + +After instantiating the provider client, wrap it with our `VercelAdapter` class: + +```js +import { VercelChatModelAdapter } from '@callstack/byorg-core'; + +const openAiChatModel = new VercelChatModelAdapter({ + languageModel: openAiModel, +}); +``` + +Now that the `chatModel` is ready, let’s discuss the `systemPrompt` function. diff --git a/docs/src/docs/core/context.md b/docs/src/docs/core/context.md new file mode 100644 index 0000000..6143538 --- /dev/null +++ b/docs/src/docs/core/context.md @@ -0,0 +1,74 @@ +# Context + +The `context` object holds information about the currently processed message. It allows you to modify the behavior of your assistant at runtime or alter the message processing flow. + +`Context` can be modified by [middlewares](./plugins.md) during the message processing flow to implement highly flexible logic or rules (e.g., authentication, RAG, etc.). + +### Properties in Context + +```js +export type RequestContext = { + /** All messages from given conversation */ + messages: Message[]; + + /** Convenience reference to the last `messages` item which is the latest `UserMessage`. */ + lastMessage: UserMessage; + + /** Declarations of tools for ai assistant */ + tools: ApplicationTool[]; + + /** Storage with references to documents mentioned in the conversation */ + references: ReferenceStorage; + + /** Ids of users who are a part of conversation */ + resolvedEntities: EntityInfo; + + /** Function for generating a system prompt */ + systemPrompt: () => Promise | string; + + /** + * Received partial response update with response streaming. + * Note: setting this option will switch underlying assistant calls to streaming format. + */ + onPartialResponse?: (text: string) => void; + + /** Measures and marks for performance tracking */ + performance: PerformanceTimeline; + + /** Container for additional custom properties */ + extras: MessageRequestExtras; +}; +``` + +To add typing for your custom properties to the context, create a file with the type definition and override the typing. + +```js +declare module '@callstack/byorg-core' { + interface MessageRequestExtras { + // Here you can add your own properties + example?: string; + messagesCount?: number; + isAdmin?: boolea; + } +} + +export {}; +``` + +:::warning +All custom properties must be optional, as the current context creation does not support default values for custom objects. +::: + +After setting extras, you can access them from the context object: + +```js +export const systemPrompt = (context: RequestContext): Promise | string => { + if (context.extras.isAdmin) { + return `You are currently talking to an admin.`; + } + + return `You are talking to user with regular permissions.`; +}; +``` + +Next, we’ll explore the concept of `plugins` to understand how to modify the `context`. diff --git a/docs/src/docs/core/error-handling.md b/docs/src/docs/core/error-handling.md new file mode 100644 index 0000000..6bf97ee --- /dev/null +++ b/docs/src/docs/core/error-handling.md @@ -0,0 +1,23 @@ +# Error handling + +The error handler in byorg.ai is responsible for processing error objects and returning messages that are sent back to the user. You can customize the error handling by providing your own error handler function. This allows you to define specific reactions to errors and deliver appropriate feedback to users. + +```js +function handleError(error: unknown): SystemResponse { + logger.error('Unhandled error:', error); + + return { + role: 'system', + content: 'There was a problem with Assistant. Please try again later or contact administrator.', + error, + }; +} + +const app = createApp({ + chatModel, + systemPrompt, + errorHandler: handleError, +}); +``` + +By implementing a custom error handler, you can tailor the user experience by providing meaningful responses to errors encountered within the byorg framework. diff --git a/docs/src/docs/core/performance.md b/docs/src/docs/core/performance.md new file mode 100644 index 0000000..8e97acd --- /dev/null +++ b/docs/src/docs/core/performance.md @@ -0,0 +1,61 @@ +# Performance + +To test your application's performance, you can use the performance object available in the context. + +```js +const slowPlugin: Promise = { + name: 'slow-plugin', + middleware: async (context, next): Promise => { + + context.performance.markStart("SlowPluginPerformance"); + await slowFunction(); + context.performance.markEnd("SlowPluginPerformance"); + + // Continue middleware chain + return next(); + }, +}; +``` + +After collecting your performance data, you can access it through the same performance object. Performance tracking requires all processes to complete, so it uses effect instead of middleware, as it runs after the response is finalized. + +```js +const analyticsPlugin: Promise = { + name: 'analytics', + effects: [analyticsEffect] +}; + +async function analyticsEffect(context: RequestContext, response: MessageResponse): Promise { + console.log(context.performance.getMeasureTotal("SlowPluginPerformance")) +} +``` + +## Measures vs Marks + +This concept comes from [Web Performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance). +Marks are just named 'sequences' for the performance tool to measure. +Let's say that you have a tool for your AI, and you'd like to check how it performs. +Issue might be that it's being triggered multiple times by AI. For that reason +one mark can be a part of multiple measures. +Single measure is constructed of two marks: `start` and `end`. + +This concept is inspired by the [Web Performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance). Marks are essentially named sequences that the performance tool uses to measure execution time. For instance, if you have a tool for your AI and want to evaluate its performance, you might find it triggered multiple times by the AI. Therefore, a single mark can be part of multiple measures. A measure is constructed using two marks: `start` and `end`. + +:::info +You can also access all marks and measures using `getMarks` and `getMeasures` +::: + +## Default measures + +Byorg automatically gathers performance data. Middleware measures are collected in two separate phases: before handling the response and after it. + +```js +export const PerformanceMarks = { + processMessages: 'processMessages', + middlewareBeforeHandler: 'middleware:beforeHandler', + middlewareAfterHandler: 'middleware:afterHandler', + chatModel: 'chatModel', + toolExecution: 'toolExecution', + errorHandler: 'errorHandler', +} as const; +``` diff --git a/docs/src/docs/core/plugins.md b/docs/src/docs/core/plugins.md new file mode 100644 index 0000000..2709d68 --- /dev/null +++ b/docs/src/docs/core/plugins.md @@ -0,0 +1,109 @@ +# Plugins + +Plugins allow you to modify the context before it reaches the inference and AI response phase. Each plugin consists of a name, optional middleware, and optional effects. + +## Middleware and Effects + +While middleware and effects share some similarities, they serve different purposes within the framework: + +### Middleware +- A middleware function receives the request context and an asynchronous `next()` function, which triggers the next middleware in the chain. +- Middleware can execute code before and after receiving the final response from the chat model: + - Code before the `await next()` call runs prior to receiving the chat model's response. + - Code after the `await next()` call runs after the chat model's response is received. +- Middleware execution blocks the final response from being sent to the user. To avoid delaying the user response, use effects instead. +- Partial responses (enabled via the onPartialResponse option) are streamed immediately as they are received from the chat model. These occur before the middleware code that runs after the await next() call. + +### Effects +- An effect function received the request context and the final response sent to the user. +- Effects are executed after the message processing pipeline has completed. +- Use effects for tasks like logging, analytics, or other post-processing operations that do not block the user response. + +Note that the response to the user is blocked until all middlewares finish processing. + +## Middleware Example + +Let's create a middleware that enriches the context for our system prompt function. + +```js +import { ApplicationPlugin, MessageResponse } from '@callstack/byorg-core'; + +const isAdminPlugin: Promise = { + name: 'is-admin', + middleware: async (context, next): Promise => { + const isAdmin = await checkIfUserIsAdmin(context.lastMessage.senderId) + + context.extras.isAdmin = isAdmin; + + // Continue middleware chain + return next(); + }, +}; +``` + +## Effect example + +Now, let's create an effect that runs after receiving a response from the AI. If the user is an admin or the response ends with an error, it does nothing. Otherwise, it increases the message count for the user. + +```js +import { MessageResponse } from '@callstack/byorg-core'; + +const usageCountPlugin: Promise = { + name: 'usage-count', + effects: [counterEffect] +}; + +async function counterEffect(context: RequestContext, response: MessageResponse): Promise { + const { isAdmin } = context.extras; + + if(response.error || isAdmin) { + return; + } + + await increaseMsgsCount(context.lastMessage.userId) +} +``` + +## Connecting Plugins + +Once you've written your plugins, connect them to the app: + +```js + const app = createApp({ + chatModel, + plugins: [ + usageCountPlugin, + isAdminPlugin + ] + systemPrompt, + }); +``` + +The order of plugins is important! Depending on the call to `next`, they are executed: + +- Top-down before the call to `next` +- Bottom-up after the call to `next` + +## Midleware early return + +Your middleware can also break the execution chain early, stopping the execution of any subsequent middleware. + +```js +import { ApplicationPlugin, MessageResponse } from '@callstack/byorg-core'; + +const flowBreakingPlugin: Promise = { + name: 'breaks-flow', + middleware: async (context, next): Promise => { + // Breaks the middleware chain + return { + role: 'system'; + content: "AI Assistant is unvailable now!"; + }; + }, +}; +``` + +## Pending effects + +When you trigger `processMessages` on a byorg app, one of the returned values is `pendingEffects`. +This allows you to wait for them to finish execution, which is useful to prevent the application from shutting down prematurely (e.g., in serverless functions). diff --git a/docs/src/docs/core/references.md b/docs/src/docs/core/references.md new file mode 100644 index 0000000..e069ba8 --- /dev/null +++ b/docs/src/docs/core/references.md @@ -0,0 +1,70 @@ +# References + +References provide information about the source of data retrieved by a tool call. +When a tool call is triggered, you can add references to the context and later use these entries in a plugin to provide users with referenced pages or other relevant information. References are part of the context. + +:::info +References are not automatically added for the AI. You need to implement this functionality if needed. +::: + +Let's create middleware that adds relevant weather information to the context. + +```js +async function queryWeather( + params: { query: string }, + context: RequestContext, +): Promise { + const { query } = params; + const { references } = context; + + const userWeatherInfo = await getWeather(query); + + references.addReference({ + title: userWeatherInfo.title, + url: userWeatherInfo.url + }); + + return formatWeatherInfo(userWeatherInfo); +} + +const queryWeatherTool: ApplicationTool = { + name: 'query_weather', + description: + 'Search weather data for requested city.', + parameters: z.object({ + query: z.string().describe('City'), + }), + handler: queryWeather, +}; + +const cityWeatherPlugin: ApplicationPlugin = { + name: 'weather-tool', + tools: [queryWeatherTool], +}; +``` + +In this example, the AI receives information about the requested city, and the context includes information about the source of this data. + +## Using References + +The `references` object provides two functions: `getReferences` and `addReference`. +If you want to present users with information about references, you need to manually add them to the response. + +```js +export const referencesPlugin: ApplicationPlugin = { + name: 'references', + middleware: async (context, next): Promise => { + // Continue middleware chain + const response = await next(); + + const references = context.references.getReferences(); + + return { + ...response, + content: `${response.content}${formatReferencesAnnotation(references)}`, + }; + }, +}; +``` + +By using these functions, you can ensure that users are informed about the sources of the information they receive. diff --git a/docs/src/docs/core/system-prompt.md b/docs/src/docs/core/system-prompt.md new file mode 100644 index 0000000..5b0b795 --- /dev/null +++ b/docs/src/docs/core/system-prompt.md @@ -0,0 +1,30 @@ +# System Prompt + +The `createApp` function requires a `systemPrompt` function to operate correctly. +The system prompt is a string that provides an "initial" description of the situation for the AI. +It should include details such as the assistant's personality, name, purpose, and available tools. +The system prompt can also incorporate dynamic values like the current date or time. +Think of the system prompt as your assistant's "personality" and guidelines + +## Why a function? + +Byorg requires a function to generate the system prompt because each message might need a different prompt. +This allows you to implement custom logic to modify the system prompt at runtime. + +## Example + +Here is an example that adds the current date and the user's name to the conversation: + +```js +export const systemPrompt = (context: RequestContext): Promise | string => { + let date = new Date().toDateString(); + let userName = context.extras.userName; + + return `You are a helpful AI bot. Your name is Cassandra. You work for Callstack. + Current date: ${date} + You are talking with: ${userName}`; +}; +``` + +As you can see, the `systemPrompt` function takes a `context` parameter. +The context is an object containing information about the current conversation. We’ll explore this topic further in the next section. diff --git a/docs/src/docs/core/tools.md b/docs/src/docs/core/tools.md new file mode 100644 index 0000000..3819d09 --- /dev/null +++ b/docs/src/docs/core/tools.md @@ -0,0 +1,72 @@ +# Tools + +You can extend the capabilities of your assistant by providing it with tools. +Tools are functions attached to the AI request. Once the request is received, the AI can decide to use these tools to enrich the context, +fetch more data, or save information. + +:::info +OpenAI has implemented tools, but not all AI providers do. +::: + +## Adding tools + +First lets start by implementing the tool function. There are two inputs for it `params` that are decided +by the AI and context that is passed by byorg. Tool function has to return a string, as the information +returned by it will be then passed back to AI as an 'addition' to system prompt. + +To start, implement the tool function. It takes two inputs: `params`, which are determined by the AI, and `context`, which is passed by byorg. +The tool function must return a string, as this information will be passed back to the AI as an addition to the system prompt. + +```js + +async function queryUsers(params: { query: string }, context: RequestContext): Promise { + const { query } = params; + const { references } = context; + + const users = await getMatchingusers(query); + + return formatUsersResponse(users); +} +``` + +Next, describe this function for the AI to help it understand when and how to use it. + +```js +import z from 'zod'; + +const queryUsersTool: ApplicationTool = { + name: 'query_users', + parameters: z.object({ + query: z + .string() + .describe( + 'Query to users list, can include user name, id, email or role in company etc.', + ), + }), + description: + 'Search information about users, by name, id, email or role etc.', + handler: queryUsers, +}; +``` + +Once the function is implemented and described, wrap it into the plugin system and connect it to the app. + +```js +const toolsPlugin: ApplicationPlugin = { + name: 'tools', + tools: [queryUsersTool], +}; + +const app = createApp({ + chatModel, + plugins: [ + toolsPlugin, + ] + systemPrompt, +}); +``` + +Tools are an excellent place to implement embedding for inserts or other RAG (Retrieval-Augmented Generation) functionalities. + +Your tools might attach data from a specific source. If you want to inform users about the data source, you can use `references` from the context object. +We’ll discuss that next. diff --git a/docs/src/docs/core/usage.md b/docs/src/docs/core/usage.md deleted file mode 100644 index e76d40a..0000000 --- a/docs/src/docs/core/usage.md +++ /dev/null @@ -1,3 +0,0 @@ -# Usage - -This section is about usage of Core diff --git a/docs/src/docs/core/usage.mdx b/docs/src/docs/core/usage.mdx new file mode 100644 index 0000000..5a5b530 --- /dev/null +++ b/docs/src/docs/core/usage.mdx @@ -0,0 +1,59 @@ +import { Steps } from 'rspress/theme'; + +# Usage + +## Creating an app + +Here is step by step how to start with byorg. + +{/* prettier-ignore-start */} + + + ### Create a chat model instance + ```js + import { VercelChatModelAdapter } from '@callstack/byorg-core'; + import OpenAI from 'openai'; + import { createOpenAI } from '@ai-sdk/openai'; + + const LANGUAGE_MODEL = 'gpt-4o-2024-08-06'; + + const openAiProvider = createOpenAI({ + apiKey: 'your-api-key', + compatibility: 'strict', // strict mode, enable when using the OpenAI API + }); + + const openAiModel = openAiProvider.languageModel(LANGUAGE_MODEL); + + const chatModel = new VercelChatModelAdapter({ + languageModel: openAiModel, + }); + ``` + ### Prepare a system prompt function + ```js + import { RequestContext } from '@callstack/byorg-core'; + + const systemPrompt = (context: RequestContext): Promise | string => { + return "You are a helpful AI assistant named Cassandra"; + }; + ``` + ### Create an Application instance + ```js + import { VercelChatModelAdapter } from '@callstack/byorg-core'; + + const app = createApp({ + chatModel, + systemPrompt, + }); + ``` + ### Process user messages + ```js + const messages = [{ role: 'user', content: 'First message!' }] + const response = await app.processMessages(messages); + ``` + + +{/* prettier-ignore-end */} + +That's it! Your message is being handled an processed by byorg. + +In next sections we will go through customisation, error handling and changing LLM provider, to better suit your needs. diff --git a/docs/src/docs/discord/_meta.json b/docs/src/docs/discord/_meta.json deleted file mode 100644 index 4c2723c..0000000 --- a/docs/src/docs/discord/_meta.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "type": "file", - "name": "usage", - "label": "Usage" - } -] diff --git a/docs/src/docs/discord/usage.md b/docs/src/docs/discord/usage.md deleted file mode 100644 index 2d97984..0000000 --- a/docs/src/docs/discord/usage.md +++ /dev/null @@ -1,3 +0,0 @@ -# Usage - -This section is about usage of Discord diff --git a/docs/src/docs/getting-started.md b/docs/src/docs/getting-started.md deleted file mode 100644 index 5fa4121..0000000 --- a/docs/src/docs/getting-started.md +++ /dev/null @@ -1,3 +0,0 @@ -# Getting Started - -How to get started with byorg-ai diff --git a/docs/src/docs/getting-started.mdx b/docs/src/docs/getting-started.mdx new file mode 100644 index 0000000..5f52d28 --- /dev/null +++ b/docs/src/docs/getting-started.mdx @@ -0,0 +1,21 @@ +import { PackageManagerTabs } from 'rspress/theme'; + +# Getting Started + +To start using byorg.ai, you don't need an extensive setup. All you need is an LLM provider of your choice. + +## Pre-requisites + +- API keys to LLM Provider supported by Vercel's AI SDK (e.g. OpenAI, Anthropic, ...) [complete list here](https://sdk.vercel.ai/providers/ai-sdk-providers). + +:::tip +You can even use a self-hosted LLM, as long as it is compatible with the Vercel AI SDK. +::: + +## Installation + +The easiest way to begin is by installing byorg.ai packages and `ai` package using your preferred package manager. + + + +In the next section, we'll demonstrate how to use our core library to handle your requests. diff --git a/docs/src/docs/integrations/_meta.json b/docs/src/docs/integrations/_meta.json new file mode 100644 index 0000000..86b0187 --- /dev/null +++ b/docs/src/docs/integrations/_meta.json @@ -0,0 +1,12 @@ +[ + { + "type": "file", + "name": "slack-usage", + "label": "Slack" + }, + { + "type": "file", + "name": "discord-usage", + "label": "Discord" + } +] diff --git a/docs/src/docs/integrations/discord-usage.md b/docs/src/docs/integrations/discord-usage.md new file mode 100644 index 0000000..1986a02 --- /dev/null +++ b/docs/src/docs/integrations/discord-usage.md @@ -0,0 +1,25 @@ +# Integrating with Discord + +Byorg provides built-in functionality to integrate your application with Discord. To set this up, use the `createDiscordApp` function and provide the necessary parameters. + +## Endpoint mode + +```js +const app = createApp({ + chatModel, + systemPrompt, +}); + +const discord = createDiscordApp({ + app, +}); +``` + +:::warning +Discord implementation is still in progress, treat it as experimental. +::: + + diff --git a/docs/src/docs/integrations/slack-usage.md b/docs/src/docs/integrations/slack-usage.md new file mode 100644 index 0000000..1d89c06 --- /dev/null +++ b/docs/src/docs/integrations/slack-usage.md @@ -0,0 +1,65 @@ +## Integrating with Slack + +Byorg provides built-in functionality to integrate your application with Slack. To set this up, use the `createSlackApp` function and provide the necessary parameters. + +## Http endpoint mode + +In this mode you use SlackApp to receive Slack event objects directly. +Here's a [tutorial](https://cloud.google.com/functions/docs/tutorials/slack) on setting up a Google Cloud Function with event receiver. + +```js +const app = createApp({ + chatModel, + systemPrompt, +}); + +const slack = createSlackApp({ + app, + token: 'slack_bot_token', + appToken: 'slack_app_token', + signingSecret: 'slack_signing_secret', +}); +``` + +Once you have an instance of an app wrapped in slack handler, you need to pass it the event +received from slack endpoint. + +```js +slack.processEvent(event); +``` + +We provide automatic parsing from slack event to our internal event. We also provide custom formatter to +[slack blocks](https://api.slack.com/block-kit) that uses `slack-rich-text` package. + +## Websocket mode + +Alternatively, you can use [Slack SDK](https://tools.slack.dev/bolt-js/concepts/socket-mode) ability to connect to Slack API using WebSockets. This can be helpful in cases when you want to setup your server in a setting without public IP connection and/or for development purposes. + +```js +const slack = createSlackApp({ + app, + websocket: true, + token: 'slack_bot_token', + appToken: 'slack_app_token', + signingSecret: 'slack_signing_secret', +}); + +slack.start(); +``` + +## Types + +When using byorg-slack package, the context.extras field will contain various Slack-related fields. + +```js +declare module '@callstack/byorg-core' { + interface MessageRequestExtras { + // Set by "byorg-slack" plugin + threadTs?: string; // Thread timestamp (used as id) + messageTs?: string; // Message timestamp (used as id) + conversationMode?: ConversationMode; // Whether message was a `public_channel` or `direct` + } +} + +export {}; +``` diff --git a/docs/src/docs/slack/_meta.json b/docs/src/docs/slack/_meta.json deleted file mode 100644 index 4c2723c..0000000 --- a/docs/src/docs/slack/_meta.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "type": "file", - "name": "usage", - "label": "Usage" - } -] diff --git a/docs/src/docs/slack/usage.md b/docs/src/docs/slack/usage.md deleted file mode 100644 index 14c24d7..0000000 --- a/docs/src/docs/slack/usage.md +++ /dev/null @@ -1,3 +0,0 @@ -# Usage - -This section is about usage of Slack diff --git a/docs/src/index.md b/docs/src/index.md index a7a0fba..9949f68 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,7 +2,7 @@ pageType: home hero: - name: byorg-ai + name: 'byorg.ai' text: 'AI Assistants Framework' tagline: A framework to make development of your AI Assistant faster and easier. actions: diff --git a/docs/src/public/img/favicon.ico b/docs/src/public/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5088acb3ef00e7d47e0a1d0574039b848e9f756b GIT binary patch literal 15406 zcmeI32~<;88pq$%1w;iZA_$H~!lHl?P(g821hoZcaOniCIEqrS2L@)uii)+ywW2c> zTuLn}iUJA(0!bij5rS+6OOPD_S%QKH718Xuz0aj5I3Yuxc|m%-=lsrn@7?=-|L@+s zBro@VL6AQoBM@C(1l9!P>yZdzk01zv@cMklrwDQhUbC@z({7F+1^Ngw1NMO?(Bk!V zSSekek;xMP*>{}MhHngbn^$`aHn08ytG#fCW2h+5k%HA;bj0+I=&%_Li#<56HCb|2 zMeNrG>1ICFG}E)SG}FR5Dp6ENH30)4sHGBFHECvHRcRL96->)!pJM5*Zhi6hgzMtt1b`wrPWWD(`XCM& zEeX@_mW1kq*G#HVtNzbpy`<;0fGi+F(@7mMJiUf!3omQ7h%RdYS%g68JEy>u6n_$$; zO_&S@LwkZzMQg(3HF0phl#Qb`eaeLTRDx4Os!3o&^7QzoR6=)S$~1rlX#1!!W%|{| z)aiZ?s6xwX*Prs=InJPOxuWJrfp{t(-vT% z%g)btaHCL=PvnnK`KwH( zlV(=Y;`13ri@-o+7A=xy7XIY`mivCN5mDJL=Tg}&Kps@K^EZR_gSB5=1$p$%GS^B7 zkR_qaEd#4hW$mIX+}B^LTm@u_tz6}xtRJlXPuII@T&neWcCnTWP%hPytFijRY8T$< zdE>`MPk<8M;2DC|4_3R-<}KS#wQK<>p)FfJ!|DgC-HEnsHpknygOEqtrKftl&?OzU zmh-@8)S)N-!h@XwO==aE5!>6nvog46CspQ>S`P!C2j2|r+pF{%gsOt{6YXE{Z^5@S zRpsxaAN9`wx=vyP@q+wO*Gb^ea4mrBqXS(1HEjwYr(V)!hOQ4Lp7Fwz+QO`?$V@JP~bM zxeQM&Rr`kP6`%0@oDU29oTY+)y1WqjFWahW4LtpIqHB;l9HRs~76M`5LWyAKf`jOo z@YGbLZ$NRJB-%4CPq=$7c*UN%QQ#ZWSXFA^=?hS1nTWod#T9*L4c?Fsf~^hk)KsN! zaL9Ct_=uSp?nMF=c>EX~HYKW315aO)kf{`L$W-tP=pJ#T29Sp&QiCgu(wd7`4DaLj*C?IoysKLIZ*vgj)>pJ7Fi+tI zh}MBwBp*%zOoC=_j1KL2jJ6o=H2_8QMr#XtV{|`=`v_f!?TIxcbl;djdwN|DD8&uE zu--&tJv4V@C|-$rI-&vdPX7M*ra^vZ{3LM)%s){M0|B(X^(e{E2>|ttfyqQhwj~-n zbCaepVBOP}U<9~{n2~T3jXPQsjbhqTjc2QPU410FFVjRL7(PfQnl{`rSqArdjx?nZ z${(golQtz!1FGa<@>CJ@%W6m=?1p*^;qmkb4C17UILmSH_4&WguIPSPZL0a~8mg&# z9o@{ohHiGUo<_W0MsWQzXzJhMi2J7xhx`m)B%^Z9vRKi#wJQ&;4%5;n7igb(PvhR6xFQ}Yhb*h|U zSP{gz=D!gqcfdG}lwBr}wwo5C{vE9UG&Y4ld zv^0eAj#c&V&Nw)xg4}tItX%t)ygd6ZxCbfC%X0u25wr5_+w)oW7jkp$W~%dh03FBe z!uhVu`~~!!0!LvE%s*5HW`W~NX2F8XIjs3=+h3Etx6osBzVh-G>1Px#4rdfE27_mb zm{GVSfL`Pvci;bA9d(@3*e+pk4_83F>jD(x+?RIO$y*&UDWj2C?4k#APj5k_Z}U*) z)WW3F<)KlW6(8PO3cQ!%IIhld9JkJRjvJ6i9A{U@N^FIDVsynS zAdlF}zXhu^9xPhXRcjZ+JY?`c)O_)4%zgI{ehmxegN(db>rr#D&I9zL)*}YXd<=z6 zc;kknFn0jWA9%%2jh>S52kX}iMJ!k}Pd9E{bmrk^A>>1P90n)5o_%Y!qc6C5$BTXC{$Tj! f5Rd_Rgg^g4L;!z(;4ql(k0E}XfsZpV1T*j(!kYQ3 literal 0 HcmV?d00001 diff --git a/docs/src/public/img/logo_dark.svg b/docs/src/public/img/logo_dark.svg new file mode 100644 index 0000000..2466d31 --- /dev/null +++ b/docs/src/public/img/logo_dark.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/public/img/logo_light.svg b/docs/src/public/img/logo_light.svg new file mode 100644 index 0000000..11aa510 --- /dev/null +++ b/docs/src/public/img/logo_light.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/public/img/logo_mono_dark.svg b/docs/src/public/img/logo_mono_dark.svg new file mode 100644 index 0000000..cf3688c --- /dev/null +++ b/docs/src/public/img/logo_mono_dark.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/src/public/img/logo_mono_light.svg b/docs/src/public/img/logo_mono_light.svg new file mode 100644 index 0000000..724ccda --- /dev/null +++ b/docs/src/public/img/logo_mono_light.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/styles/index.css b/docs/src/styles/index.css new file mode 100644 index 0000000..cd7b9dd --- /dev/null +++ b/docs/src/styles/index.css @@ -0,0 +1,183 @@ +.home-hero-name-img { + width: 75%; + margin-top: 1.5rem; + margin-bottom: 1.5rem; + margin-left: auto; + margin-right: auto; + + min-height: 190px; + + content: url('../public/img/logo_light.svg'); +} + +.dark .home-hero-name-img { + content: url('../public/img/logo_dark.svg'); +} + +:root { + --rp-sidebar-width: 320px !important; + --rp-aside-width: 268px !important; +} + +:root { + --rp-c-bg: #ffffff !important; + --rp-c-bg-soft: #fafafa !important; + --rp-c-bg-mute: #ececec !important; + + --rp-c-divider: rgba(60, 60, 60, 0.29) !important; + --rp-c-divider-light: rgba(60, 60, 60, 0.12) !important; + + --rp-c-text-1: rgb(50, 50, 50) !important; + --rp-c-text-2: rgba(50, 50, 50, 0.8) !important; + --rp-c-text-3: rgba(50, 50, 50, 0.6) !important; + --rp-c-text-4: rgba(50, 50, 50, 0.4) !important; + + --rp-c-text-code: var(--rp-c-brand-dark) !important; + + --rp-c-brand: #19e1e5 !important; + --rp-c-brand-light: #19dcdf !important; + --rp-c-brand-lighter: #1aeaed !important; + --rp-c-brand-dark: #129ea1 !important; + --rp-c-brand-darker: #0e7d7f !important; + --rp-c-brand-tint: rgba(16, 123, 125, 0.16) !important; + + --rp-c-gray: #8e8e8e !important; + --rp-c-gray-light-1: #aeaeae !important; + --rp-c-gray-light-2: #c7c7c7 !important; + --rp-c-gray-light-3: #d1d1d1 !important; + --rp-c-gray-light-4: #e5e5e5 !important; + --rp-c-gray-light-5: #f2f2f2 !important; + + --rp-c-dark: #000000 !important; + --rp-c-dark-light-1: #2f2f2f !important; + --rp-c-dark-light-2: #3a3a3a !important; + --rp-c-dark-light-3: #4a4a4a !important; + --rp-c-dark-light-4: #5c5c5c !important; + --rp-c-dark-light-5: #6b6b6b !important; + + --rp-radius: 1rem !important; + --rp-radius-small: 0.5rem !important; + --rp-radius-large: 1.5rem !important; +} + +.dark { + --rp-c-bg: #161618 !important; + --rp-c-bg-soft: #191b1e !important; + --rp-c-bg-mute: #65758529 !important; + + --rp-c-divider-light: #65758529 !important; + + --rp-c-text-1: #dde1e6 !important; + --rp-c-text-2: #b2b8bf !important; + --rp-c-text-3: #878c92 !important; + --rp-c-text-4: #5c6166 !important; + + /* Will be used in overview page */ + --rp-c-text-code: var(--rp-c-brand-light) !important; +} + +/* Code blocks */ +:root { + --rp-code-block-bg: var(--rp-c-bg-soft); + --rp-code-title-bg: var(--rp-c-bg-mute); +} + +.dark { + --rp-code-block-bg: var(--rp-c-bg-soft); + --rp-code-title-bg: var(--rp-c-bg-mute); +} + +/* MD Containers */ +:root { + --rp-container-info-border: rgba(155, 109, 255, 0.2) !important; + --rp-container-info-text: #9b6dff !important; + --rp-container-info-bg: rgba(155, 109, 255, 0.06) !important; + --rp-container-info-code-bg: rgba(155, 109, 255, 0.1) !important; +} + +.dark { + --rp-container-info-text: #9b6dff !important; +} + +/* Home background gradient */ +:root { + --rp-home-mask-background-image: conic-gradient( + from 180deg at 50% 50%, + var(--rp-c-brand) 0deg, + 180deg, + var(--rp-c-brand-darker) 1turn + ); +} + +p.rspress-home-hero-text { + font-size: 1.35rem; +} + +.home-hero-name-img { + min-height: 30px; +} + +@media (min-width: 370px) { + .home-hero-name-img { + min-height: 50px; + } + + p.rspress-home-hero-text { + font-size: 1.5rem; + } +} + +@media (min-width: 640px) { + .home-hero-name-img { + min-height: 100px; + } + + p.rspress-home-hero-text { + font-size: 2rem; + } +} + +@media (min-width: 768px) { + .home-hero-name-img { + min-height: 150px; + } + + p.rspress-home-hero-text { + font-size: 3rem; + } +} + +/* Nav header */ +.rspress-nav { + background-color: var(--rp-c-bg-soft) !important; + border-bottom: 1px solid var(--rp-c-divider-light) !important; +} + +/* Sidebar item vertical line */ +.rspress-sidebar-group::before { + content: none; +} + +/* Sidebar section items */ +.rspress-sidebar-group > div > a > div { + background-color: transparent !important; + font-size: 14px !important; + padding-top: 0.3rem; + padding-bottom: 0.3rem; + + &:hover { + color: var(--rp-c-brand) !important; + } + + &::before { + content: none; + } +} + +div:has(> p.rspress-home-hero-text) { + align-items: stretch; +} + +a:has(> span.home-hero-primary-action) { + background: var(--rp-c-brand) !important; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bcb3256..e6605cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,6 +64,10 @@ importers: version: 5.7.2 docs: + dependencies: + rspress-plugin-font-open-sans: + specifier: ^1.0.0 + version: 1.0.0 devDependencies: '@rspress/plugin-client-redirects': specifier: ^1.35.1 @@ -1517,9 +1521,6 @@ packages: '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -1571,10 +1572,6 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@6.21.0': - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/scope-manager@8.5.0': resolution: {integrity: sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1588,23 +1585,10 @@ packages: typescript: optional: true - '@typescript-eslint/types@6.21.0': - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/types@8.5.0': resolution: {integrity: sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@6.21.0': - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/typescript-estree@8.5.0': resolution: {integrity: sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1614,22 +1598,12 @@ packages: typescript: optional: true - '@typescript-eslint/utils@6.21.0': - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - '@typescript-eslint/utils@8.5.0': resolution: {integrity: sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - '@typescript-eslint/visitor-keys@6.21.0': - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/visitor-keys@8.5.0': resolution: {integrity: sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1979,11 +1953,6 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.23.3: - resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - browserslist@4.24.2: resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -2429,9 +2398,6 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.13: - resolution: {integrity: sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==} - electron-to-chromium@1.5.51: resolution: {integrity: sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==} @@ -4056,10 +4022,6 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -4649,6 +4611,9 @@ packages: rspack-plugin-virtual-module@0.1.13: resolution: {integrity: sha512-VC0HiVHH6dtGfTgfpbDgVTt6LlYv+uAg9CWGWAR5lBx9FbKPEZeGz7iRUUP8vMymx+PGI8ps0u4a25dne0rtuQ==} + rspress-plugin-font-open-sans@1.0.0: + resolution: {integrity: sha512-4GP0pd7h3W8EWdqE0VkA62nzUJZNy4ZnYK7be8+lOKHQKsQ5nZ+22A/VurNssi1eZFx3kjwbmIuoAkgb5W8S9Q==} + rspress@1.35.3: resolution: {integrity: sha512-yaPWVsSB5ULxi3AGZANE9CowCnVe53d8Ga6Ia3IDyIgfeqCQ4tyOVZkrKevXY/TGzuKurBizRzLgw3vilwqvyg==} hasBin: true @@ -5338,12 +5303,6 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - update-browserslist-db@1.1.0: - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - update-browserslist-db@1.1.1: resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true @@ -5677,7 +5636,7 @@ snapshots: '@babel/traverse': 7.25.6 '@babel/types': 7.25.6 convert-source-map: 2.0.0 - debug: 4.3.6 + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -5707,7 +5666,7 @@ snapshots: dependencies: '@babel/compat-data': 7.25.4 '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.3 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -5877,7 +5836,7 @@ snapshots: '@babel/parser': 7.25.6 '@babel/template': 7.25.0 '@babel/types': 7.25.6 - debug: 4.3.6 + debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -7259,8 +7218,6 @@ snapshots: '@types/retry@0.12.0': {} - '@types/semver@7.5.8': {} - '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 @@ -7318,18 +7275,13 @@ snapshots: '@typescript-eslint/types': 8.5.0 '@typescript-eslint/typescript-estree': 8.5.0(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.5.0 - debug: 4.3.6 + debug: 4.3.7 eslint: 8.57.1 optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@6.21.0': - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - '@typescript-eslint/scope-manager@8.5.0': dependencies: '@typescript-eslint/types': 8.5.0 @@ -7347,25 +7299,8 @@ snapshots: - eslint - supports-color - '@typescript-eslint/types@6.21.0': {} - '@typescript-eslint/types@8.5.0': {} - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.7.2)': - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.7.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.5.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.5.0 @@ -7381,20 +7316,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.7.2)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2) - eslint: 8.57.1 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - typescript - '@typescript-eslint/utils@8.5.0(eslint@8.57.1)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -7406,11 +7327,6 @@ snapshots: - supports-color - typescript - '@typescript-eslint/visitor-keys@6.21.0': - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - '@typescript-eslint/visitor-keys@8.5.0': dependencies: '@typescript-eslint/types': 8.5.0 @@ -7868,13 +7784,6 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.23.3: - dependencies: - caniuse-lite: 1.0.30001660 - electron-to-chromium: 1.5.13 - node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.3) - browserslist@4.24.2: dependencies: caniuse-lite: 1.0.30001677 @@ -8298,8 +8207,6 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.13: {} - electron-to-chromium@1.5.51: {} emittery@0.13.1: {} @@ -8568,7 +8475,7 @@ snapshots: eslint-plugin-jest@28.8.3(@typescript-eslint/eslint-plugin@8.5.0(@typescript-eslint/parser@8.5.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.9.1)(ts-node@10.9.2(@types/node@22.9.1)(typescript@5.7.2)))(typescript@5.7.2): dependencies: - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.7.2) + '@typescript-eslint/utils': 8.5.0(eslint@8.57.1)(typescript@5.7.2) eslint: 8.57.1 optionalDependencies: '@typescript-eslint/eslint-plugin': 8.5.0(@typescript-eslint/parser@8.5.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2) @@ -10634,10 +10541,6 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@9.0.3: - dependencies: - brace-expansion: 2.0.1 - minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -11278,6 +11181,8 @@ snapshots: dependencies: fs-extra: 11.2.0 + rspress-plugin-font-open-sans@1.0.0: {} + rspress@1.35.3(webpack@5.96.1): dependencies: '@rsbuild/core': 1.0.19 @@ -11984,12 +11889,6 @@ snapshots: unpipe@1.0.0: {} - update-browserslist-db@1.1.0(browserslist@4.23.3): - dependencies: - browserslist: 4.23.3 - escalade: 3.1.2 - picocolors: 1.1.1 - update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: browserslist: 4.24.2