### Install Dependencies (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Installs the necessary project dependencies using npm. This command should be run after navigating into the 'example' directory. ```bash cd example npm install ``` -------------------------------- ### Start Convex Dev Server (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Starts the Convex development server, which is essential for running the database and backend logic. ```bash npx convex dev ``` -------------------------------- ### Start Development Server (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Launches the main development server, likely including both the backend and frontend. This is the primary command to run the application locally. ```bash npm run dev ``` -------------------------------- ### Installation and Setup Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Instructions on how to add the Convex Database Chat component to your Convex app and set up the necessary environment variables. ```APIDOC ## Installation and Setup Add the component to your Convex app configuration. ```typescript // convex/convex.config.ts import { defineApp } from "convex/server"; import databaseChat from "@dayhaysoos/convex-database-chat/convex.config"; const app = defineApp(); app.use(databaseChat); export default app; ``` Set up the OpenRouter API key in your Convex environment: ```bash npx convex env set OPENROUTER_API_KEY your_key_here ``` ``` -------------------------------- ### Run Vite UI Only (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Starts only the Vite-based user interface. Useful for frontend-focused development or debugging. ```bash npm run dev:ui ``` -------------------------------- ### Run Convex Only (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Starts only the Convex development server, without the UI. Useful for backend-focused development or debugging. ```bash npm run convex ``` -------------------------------- ### Run Development Server (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/README.md Commands to start the development server for the project. These commands are typically executed in a terminal within the project's root directory. Ensure you have npm, pnpm, or yarn installed. ```bash npm run dev # or pnpm dev # or yarn dev ``` -------------------------------- ### Serve Production Build (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Serves the production-ready build of the application. This command is typically used for testing the final deployment. ```bash npm run start ``` -------------------------------- ### Seed Database (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx Populates the database with initial data. This script is typically used to set up the demo environment. ```bash npm run seed ``` -------------------------------- ### Example LLM Tool: Search Products (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md An example TypeScript interface for a 'searchProducts' tool, demonstrating how to define LLM-accessible functions. It includes parameters for query, category, price range, and result limits, along with descriptions for the LLM. This structure facilitates dynamic function calling by the LLM. ```typescript const searchProductsTool = { name: "searchProducts", description: "Search products by name, category, or price range", parameters: { type: "object", properties: { query: { type: "string", description: "Search text to match against product name", }, category: { type: "string", description: "Filter by category", enum: ["electronics", "clothing", "home", "sports"], }, minPrice: { type: "number", description: "Minimum price", }, maxPrice: { type: "number", description: "Maximum price", }, limit: { type: "number", description: "Maximum results (default: 20)", }, }, required: [], }, handler: "searchProducts", }; ``` -------------------------------- ### Install Convex Database Chat Component Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/installation.mdx Installs the @dayhaysoos/convex-database-chat package using different Node.js package managers. This is the first step to integrating the component into your project. ```bash pnpm add @dayhaysoos/convex-database-chat ``` ```bash npm install @dayhaysoos/convex-database-chat ``` ```bash yarn add @dayhaysoos/convex-database-chat ``` ```bash bun add @dayhaysoos/convex-database-chat ``` -------------------------------- ### Manual Local Package Linking (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/example/README.md Manual steps to link a local package using npm link. This involves building the package in watch mode and then linking it in the example directory. ```bash # From repo root npm run build:watch npm link # From example/ npm link @dayhaysoos/convex-database-chat ``` -------------------------------- ### Link Local Package (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/example/README.md Helper script to link the local package for development without publishing. This allows testing changes in the example app immediately. ```bash ./dev-link.sh link ``` -------------------------------- ### Add Component to Convex Configuration Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/installation.mdx Integrates the databaseChat component into your Convex project by importing and using it within the `convex/convex.config.ts` file. This step ensures the component's functionality is available within your Convex application. ```typescript // convex/convex.config.ts import { defineApp } from "convex/server"; import databaseChat from "./components/databaseChat/convex.config"; const app = defineApp(); app.use(databaseChat); export default app; ``` -------------------------------- ### Set OpenRouter API Key for Convex Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/installation.mdx Configures the necessary OpenRouter API key for the `chat.send` and `chat.sendForExternalId` functions within your Convex environment. This is crucial for enabling chat functionalities that rely on external routing. ```bash npx convex env set OPENROUTER_API_KEY your_key_here ``` -------------------------------- ### Seed Embeddings (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/example-app.mdx An optional script to seed embeddings, likely for AI or search functionality. This is used in conjunction with the main seeding process. ```bash npm run seed:embeddings ``` -------------------------------- ### Install and Configure Convex Database Chat Component Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Add the @dayhaysoos/convex-database-chat component to your Convex app configuration by importing and using the `databaseChat` export in your `convex/convex.config.ts` file. Ensure your OpenRouter API key is set in your Convex environment variables. ```typescript // convex/convex.config.ts import { defineApp } from "convex/server"; import databaseChat from "@dayhaysoos/convex-database-chat/convex.config"; const app = defineApp(); app.use(databaseChat); export default app; ``` ```bash npx convex env set OPENROUTER_API_KEY your_key_here ``` -------------------------------- ### Auto-generate Tools from Schema (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/tools.mdx Shows how to automatically generate tools from schema definitions using `generateToolsFromSchema`. This example defines a 'products' table with specific fields and then configures handlers for query, count, and aggregate operations, linking them to Convex API functions. ```typescript import { createFunctionHandle } from "convex/server"; import { defineTable, generateToolsFromSchema } from "./components/databaseChat/schemaTools"; import { api } from "./_generated/api"; const tables = [ defineTable("products", [ { name: "name", type: "string" }, { name: "category", type: "string" }, { name: "price", type: "number" }, ]), ]; const tools = generateToolsFromSchema({ tables, allowedTables: ["products"], handlers: { query: createFunctionHandle(api.chatTools.queryTable), count: createFunctionHandle(api.chatTools.countRecords), aggregate: createFunctionHandle(api.chatTools.aggregate), }, }); ``` -------------------------------- ### Explicit Tool Definition Example (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/tools.mdx Demonstrates how to explicitly define a tool for searching products using TypeScript. It imports necessary functions and types, defines the tool's name, description, parameters with enums and types, and specifies the handler using `createFunctionHandle`. ```typescript import { createFunctionHandle } from "convex/server"; import { api } from "./_generated/api"; import type { DatabaseChatTool } from "./components/databaseChat/tools"; const tools: DatabaseChatTool[] = [ { name: "searchProducts", description: "Search products by name, category, or price range", parameters: { type: "object", properties: { query: { type: "string", description: "Search text" }, category: { type: "string", enum: ["electronics", "clothing", "home", "sports"], }, minPrice: { type: "number" }, maxPrice: { type: "number" }, limit: { type: "number" }, }, }, handler: createFunctionHandle(api.chatTools.searchProducts), }, ]; ``` -------------------------------- ### Install DatabaseChat Component - TypeScript Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md Adds the DatabaseChat component to your Convex application by importing and using `defineApp` and `databaseChat` from the component's configuration file. ```typescript // convex/convex.config.ts import { defineApp } from "convex/server"; import databaseChat from "./components/databaseChat/convex.config"; const app = defineApp(); app.use(databaseChat); export default app; ``` -------------------------------- ### Provider Setup for Convex Database Chat Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/react-hooks.mdx Sets up the DatabaseChatProvider by wrapping your application. It requires mapping Convex API actions to the provider's expected props. This ensures that chat-related functionalities are available throughout your component tree. ```tsx import { DatabaseChatProvider } from "@dayhaysoos/convex-database-chat"; import { api } from "../convex/_generated/api"; export function AppProviders({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` -------------------------------- ### Include Actionable URLs in Query Results (Convex) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md This example demonstrates how to include `viewUrl` properties in query results returned from a Convex backend. By adding a `viewUrl` field (e.g., `/items/${item._id}`) to each item, you provide a direct link to a detail page. This enables LLMs to generate actionable responses, linking users to specific content. ```typescript // In your query handler, include viewUrl in results return items.map((item) => ({ id: item._id, name: item.name, // Include the URL to view this item viewUrl: `/items/${item._id}`, })); ``` -------------------------------- ### Wire Chat Endpoints with DatabaseChat (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/quick-start.mdx Sets up the chat endpoints using `defineDatabaseChat`, creating a typed wrapper around the chat component. It defines available tools, system prompts, and various mutation/query functions for managing conversations and messages. ```typescript // convex/chat.ts import { v } from "convex/values"; import { action, mutation, query } from "./_generated/server"; import { createFunctionHandle } from "convex/server"; import { components, api } from "./_generated/api"; import { defineDatabaseChat } from "./components/databaseChat/client"; import type { DatabaseChatTool } from "./components/databaseChat/tools"; const tools: DatabaseChatTool[] = [ { name: "countRecords", description: "Count records in a table. Available tables: users, orders", parameters: { type: "object", properties: { table: { type: "string", enum: ["users", "orders"] }, }, required: ["table"], }, handler: createFunctionHandle(api.chatTools.countRecords), }, ]; const chat = defineDatabaseChat(components.databaseChat, { tools, systemPrompt: "You are a helpful assistant. Use the available tools to answer questions about the database.", }); export const createConversation = mutation({ args: { externalId: v.string(), title: v.optional(v.string()) }, handler: async (ctx, args) => chat.createConversation(ctx, args), }); export const listConversations = query({ args: { externalId: v.string() }, handler: async (ctx, args) => chat.listConversations(ctx, args.externalId), }); export const getMessages = query({ args: { conversationId: v.string() }, handler: async (ctx, args) => chat.getMessages(ctx, args.conversationId), }); export const getStreamState = query({ args: { conversationId: v.string() }, handler: async (ctx, args) => chat.getStreamState(ctx, args.conversationId), }); export const getStreamDeltas = query({ args: { streamId: v.string(), cursor: v.number() }, handler: async (ctx, args) => chat.getStreamDeltas(ctx, args.streamId, args.cursor), }); export const abortStream = mutation({ args: { conversationId: v.string(), reason: v.optional(v.string()) }, handler: async (ctx, args) => chat.abortStream(ctx, args.conversationId, args.reason ?? "User cancelled"), }); export const sendMessage = action({ args: { conversationId: v.string(), message: v.string() }, handler: async (ctx, args) => chat.send(ctx, { conversationId: args.conversationId, message: args.message, apiKey: process.env.OPENROUTER_API_KEY!, }), }); ``` -------------------------------- ### Minimal UI with DatabaseChat Provider (React/TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/quick-start.mdx Implements a basic chat UI using React hooks and the `DatabaseChatProvider`. It handles conversation creation, message display, streaming content, and user interactions like sending messages and aborting streams. ```tsx import { useEffect, useState } from "react"; import { useMutation } from "convex/react"; import { api } from "../convex/_generated/api"; import { DatabaseChatProvider, useDatabaseChat, } from "@dayhaysoos/convex-database-chat"; function ChatWidget() { const [conversationId, setConversationId] = useState(null); const createConversation = useMutation(api.chat.createConversation); useEffect(() => { createConversation({ externalId: "user:demo" }).then(setConversationId); }, [createConversation]); const { messages, streamingContent, isStreaming, isLoading, send, abort, } = useDatabaseChat({ conversationId }); return (
{messages?.map((msg) => (
{msg.content}
))} {streamingContent &&
{streamingContent}
} {isStreaming && }
); } export default function App() { return ( ); } ``` -------------------------------- ### Get Stream State - Convex Query Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Retrieves the current state of a streaming conversation. This query is useful for checking if a stream is active, finished, or aborted, and provides details like start and end times. It depends on the Convex server environment and the 'streamingMessages' table. ```typescript // convex/chat.ts import { v } from "convex/values"; import { query } from "./_generated/server"; import { components } from "./_generated/api"; export const getStreamState = query({ args: { conversationId: v.string() }, returns: v.union( v.object({ streamId: v.id("streamingMessages"), status: v.union(v.literal("streaming"), v.literal("finished"), v.literal("aborted")), startedAt: v.number(), endedAt: v.optional(v.number()), abortReason: v.optional(v.string()), }), v.null() ), handler: async (ctx, args) => { return await ctx.runQuery(components.databaseChat.stream.getStream, { conversationId: args.conversationId as any, }); }, }); // Example response during streaming: // { streamId: "s1...", status: "streaming", startedAt: 1704067200000 } // After completion: // { streamId: "s1...", status: "finished", startedAt: 1704067200000, endedAt: 1704067205000 } ``` -------------------------------- ### chat.send Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Send a message and get a streaming response from the LLM. This is the main action that orchestrates the chat flow. ```APIDOC ## POST /chat.send ### Description Send a message and get a streaming response from the LLM. This is the main action that orchestrates the chat flow. ### Method POST ### Endpoint /chat.send ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **conversationId** (string) - Required - The ID of the conversation to send the message in. - **message** (string) - Required - The user's message content. ### Request Example ```json { "conversationId": "conv_123", "message": "What is the weather today?" } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the operation was successful. - **content** (string) - Optional - The response content from the LLM. - **error** (string) - Optional - An error message if the operation failed. - **toolCalls** (array) - Optional - An array of tool calls generated by the LLM. - **name** (string) - The name of the tool. - **args** (any) - The arguments for the tool call. - **result** (any) - The result of the tool call. #### Response Example ```json { "success": true, "content": "The weather today is sunny.", "toolCalls": [ { "name": "getWeather", "args": {"location": "New York"}, "result": "Sunny, 75F" } ] } ``` ``` -------------------------------- ### Running Tests (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md Provides bash commands for running tests within the project. Includes options for running all tests or running tests in watch mode for continuous testing during development. ```bash # Run all tests npm test # Run tests in watch mode npm test -- --watch ``` -------------------------------- ### Securely Get Conversation and Messages in TypeScript Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Retrieves conversation and message data scoped to a specific user, ensuring multi-tenant security. It uses Convex's query functions and requires user authentication. ```typescript // convex/secureChat.ts import { v } from "convex/values"; import { action, mutation, query } from "./_generated/server"; import { components } from "./_generated/api"; // Get conversation scoped to user export const getConversation = query({ args: { conversationId: v.string() }, handler: async (ctx, args) => { const userId = await getAuthUserId(ctx); // Throws "Not found" if conversation doesn't belong to user return await ctx.runQuery(components.databaseChat.conversations.getForExternalId, { conversationId: args.conversationId as any, externalId: `user:${userId}`, }); }, }); // Get messages scoped to user export const getMessages = query({ args: { conversationId: v.string() }, handler: async (ctx, args) => { const userId = await getAuthUserId(ctx); return await ctx.runQuery(components.databaseChat.messages.listForExternalId, { conversationId: args.conversationId as any, externalId: `user:${userId}`, }); }, }); ``` -------------------------------- ### defineDatabaseChat - Initialize Client Wrapper Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Details on how to use the `defineDatabaseChat` function to create a type-safe client wrapper for interacting with the component, including configuration options. ```APIDOC ## defineDatabaseChat - Initialize Client Wrapper The `defineDatabaseChat` function creates a type-safe client wrapper for interacting with the component. It configures default settings and tools for all chat operations. ```typescript // convex/chat.ts import { v } from "convex/values"; import { action, mutation, query } from "./_generated/server"; import { components } from "./_generated/api"; import { defineDatabaseChat } from "@dayhaysoos/convex-database-chat/client"; const chat = defineDatabaseChat(components.databaseChat, { model: "anthropic/claude-sonnet-4", systemPrompt: `You are a helpful e-commerce assistant. You help store managers understand their inventory and sales. You have access to tools that let you: - Search products by name, category, or price - Get order statistics and revenue data - Check inventory levels When answering: - Be concise and use specific numbers - Always include links using the viewUrl field: [Product Name](viewUrl) - Format prices with currency symbols - If inventory is low (< 10), mention it`, maxMessagesForDisplay: 100, maxMessagesForLLM: 50, tools: [ { name: "searchProducts", description: "Search products by name, category, or price range", parameters: { type: "object", properties: { query: { type: "string", description: "Search text to match against product name" }, category: { type: "string", enum: ["electronics", "clothing", "home", "sports"] }, minPrice: { type: "number", description: "Minimum price" }, maxPrice: { type: "number", description: "Maximum price" }, limit: { type: "number", description: "Maximum results (default: 20)" }, }, required: [], }, handler: "searchProducts", // Function handle string }, ], }); export { chat }; ``` ``` -------------------------------- ### Get Conversation Messages - Convex TypeScript Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Retrieves messages within a specific conversation, ordered chronologically. It uses the `query` function and accepts a `conversationId` and an optional `limit` for the number of messages. The response is an array of message objects. ```typescript import { v } from "convex/values"; import { query } from "./_generated/server"; import { components } from "./_generated/api"; export const getMessages = query({ args: { conversationId: v.string(), limit: v.optional(v.number()), // Default: 100, max: 1000 }, returns: v.array(v.any()), handler: async (ctx, args) => { return await ctx.runQuery(components.databaseChat.messages.list, { conversationId: args.conversationId as any, limit: args.limit, }); }, }); ``` -------------------------------- ### Project Management Assistant System Prompt (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/system-prompts.mdx Outlines the system prompt for a project management assistant. It details the assistant's role in helping team leads track tasks, lists available tools for searching and filtering tasks, and provides guidelines for response formatting, emphasizing actionable information and highlighting urgent items. ```typescript const SYSTEM_PROMPT = `You are a project management assistant. You help team leads track tasks and project progress. You have access to tools that let you: - Search and filter tasks by status, assignee, or project - Get project statistics and completion rates - Find overdue or blocked tasks When answering: - Prioritize actionable information - Include links to tasks: [Task Title](viewUrl) - Highlight urgent or overdue items `; ``` -------------------------------- ### Define a Convex Query Tool (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/quick-start.mdx Defines a Convex query function that can be called by an LLM to count records in specified tables ('users' or 'orders'). It takes a table name as input and returns the count. ```typescript // convex/chatTools.ts import { query } from "./_generated/server"; import { v } from "convex/values"; export const countRecords = query({ args: { table: v.string() }, returns: v.object({ count: v.number() }), handler: async (ctx, args) => { if (args.table === "users") { const users = await ctx.db.query("users").collect(); return { count: users.length }; } if (args.table === "orders") { const orders = await ctx.db.query("orders").collect(); return { count: orders.length }; } return { count: 0 }; }, }); ``` -------------------------------- ### Efficient LLM Streaming with DeltaStreamer in Convex Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt This code demonstrates using DeltaStreamer for efficient, batched streaming of LLM responses within Convex. It covers both manual token streaming and consuming an async iterable stream. Key features include configurable throttling and abort handling. Dependencies include Convex server functions and the '@dayhaysoos/convex-database-chat/deltaStreamer' library. ```typescript // convex/customChat.ts import { action } from "./_generated/server"; import { api } from "./_generated/api"; import { v } from "convex/values"; import { DeltaStreamer } from "@dayhaysoos/convex-database-chat/deltaStreamer"; export const sendWithCustomLLM = action({ args: { conversationId: v.id("conversations"), message: v.string(), }, handler: async (ctx, args) => { // Create DeltaStreamer for efficient O(n) streaming const streamer = new DeltaStreamer(ctx, api, args.conversationId, { throttleMs: 100, // Batch writes every 100ms onAbort: async (reason) => { console.log("Stream aborted:", reason); }, }); try { // Save user message await ctx.runMutation(api.messages.add, { conversationId: args.conversationId, role: "user", content: args.message, }); // Initialize the stream await streamer.getStreamId(); // Your custom LLM call (Vercel AI SDK, OpenAI, etc.) const response = await yourLLMCall({ messages: [{ role: "user", content: args.message }], onToken: async (token: string) => { // Stream tokens through DeltaStreamer await streamer.addParts([{ type: "text-delta", text: token }]); }, signal: streamer.abortController.signal, }); // Finish streaming await streamer.finish(); // Save assistant response await ctx.runMutation(api.messages.add, { conversationId: args.conversationId, role: "assistant", content: response.content, }); return { success: true, content: response.content }; } catch (error) { await streamer.fail(error.message); return { success: false, error: error.message }; } }, }); // Alternative: Consume an async iterable stream export const sendWithStream = action({ args: { conversationId: v.id("conversations"), message: v.string() }, handler: async (ctx, args) => { const streamer = new DeltaStreamer(ctx, api, args.conversationId); // Get stream from your LLM const stream = await getStreamFromLLM(args.message); // Consume the entire stream (handles finish automatically) await streamer.consumeTextStream(stream); return { success: true }; }, }); ``` -------------------------------- ### Get Stream Deltas - Convex Query Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Fetches incremental updates (deltas) for a stream from a specified cursor position. Clients use these deltas to reconstruct the full stream content. It requires a stream ID and a cursor, returning an array of delta objects. ```typescript // convex/chat.ts import { v } from "convex/values"; import { query } from "./_generated/server"; import { components } from "./_generated/api"; export const getStreamDeltas = query({ args: { streamId: v.string(), cursor: v.number(), // Start position (0 for beginning) }, returns: v.array( v.object({ start: v.number(), end: v.number(), parts: v.array(v.object({ type: v.union( v.literal("text-delta"), v.literal("tool-call"), v.literal("tool-result"), v.literal("error") ), text: v.optional(v.string()), toolCallId: v.optional(v.string()), toolName: v.optional(v.string()), args: v.optional(v.string()), result: v.optional(v.string()), error: v.optional(v.string()), })), }) ), handler: async (ctx, args) => { return await ctx.runQuery(components.databaseChat.stream.listDeltas, { streamId: args.streamId as any, cursor: args.cursor, }); }, }); // Example response: // [ // { start: 0, end: 3, parts: [{ type: "text-delta", text: "Hello" }] }, // { start: 3, end: 6, parts: [{ type: "text-delta", text: " there!" }] }, // ] ``` -------------------------------- ### Unlink Local Package (Bash) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/example/README.md Reverts to using the published version of the package by unlinking the local version and reinstalling dependencies. ```bash npm unlink @dayhaysoos/convex-database-chat npm install ``` -------------------------------- ### E-commerce Assistant System Prompt (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md Defines a system prompt for an e-commerce assistant, outlining its role, available tools (product search, order stats, inventory check), and specific response formatting rules. It emphasizes conciseness, currency symbols, and highlighting low stock. ```typescript const SYSTEM_PROMPT = `You are a helpful e-commerce assistant. You help store managers understand their inventory and sales. You have access to tools that let you: - Search products by name, category, or price - Get order statistics and revenue data - Check inventory levels When answering: - Be concise and use specific numbers - Always include links using the viewUrl field: [Product Name](viewUrl) - Format prices with currency symbols - If inventory is low (< 10), mention it Example response: "Found 3 products under $50 in Electronics: - [Wireless Mouse](/products/abc123) - $29.99 (In Stock) - [USB Cable](/products/def456) - $12.99 (Low Stock: 5 left) - [Phone Stand](/products/ghi789) - $19.99 (In Stock)"`; ``` -------------------------------- ### Implement Vector Search for Semantic Queries in Convex Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt This snippet demonstrates how to set up and use vector search for semantic queries in Convex. It includes defining a tool for LLM interaction, generating embeddings, performing vector searches, fetching full documents, and formatting results. Dependencies include Convex server functions and the '@dayhaysoos/convex-database-chat/vector' library. ```typescript // convex/semanticSearch.ts import { action, internalQuery } from "./_generated/server"; import { internal } from "./_generated/api"; import { v } from "convex/values"; import { generateEmbedding, formatVectorResults, defineVectorSearchTool, } from "@dayhaysoos/convex-database-chat/vector"; // Define the tool for the LLM export const semanticSearchTool = defineVectorSearchTool({ name: "semanticSearchProducts", description: "Find products by meaning or concept using semantic search", handler: "semanticSearchProducts", parameters: { query: { type: "string", description: "Semantic search query" }, limit: { type: "number", description: "Max results", optional: true }, }, }); // Action implementation (vector search requires actions) export const semanticSearchProducts = action({ args: { query: v.string(), limit: v.optional(v.number()), }, handler: async (ctx, args) => { // Generate embedding for the query const embedding = await generateEmbedding({ apiKey: process.env.OPENROUTER_API_KEY!, text: args.query, // model: "openai/text-embedding-3-small", // default }); // Perform vector search const results = await ctx.vectorSearch("products", "by_description_embedding", { vector: embedding, limit: args.limit ?? 20, }); // Fetch full documents const docs = await ctx.runQuery(internal.semanticSearch.fetchByIds, { ids: results.map((r) => r._id), }); // Format results for LLM context return formatVectorResults(results, docs, { includeScore: true, snippetLength: 200, fields: ["name", "description", "price", "viewUrl"], }); }, }); // Internal query to fetch documents by IDs export const fetchByIds = internalQuery({ args: { ids: v.array(v.id("products")) }, handler: async (ctx, args) => { return await Promise.all(args.ids.map((id) => ctx.db.get(id))); }, }); ``` -------------------------------- ### Create a New Chat Conversation Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Create a new conversation using the `chat.createConversation` mutation. This function accepts an optional title and uses an `externalId` to scope conversations to specific users or tenants, ensuring proper data segregation. A direct component usage example is also provided. ```typescript // convex/chat.ts import { v } from "convex/values"; import { mutation } from "./_generated/server"; import { chat } from "./chatClient"; export const createConversation = mutation({ args: { title: v.optional(v.string()) }, returns: v.string(), handler: async (ctx, args) => { const userId = await getAuthUserId(ctx); // Your auth system return await chat.createConversation(ctx, { externalId: `user:${userId}`, title: args.title ?? "New Chat", }); }, }); // Direct component usage (without client wrapper) export const createConversationDirect = mutation({ args: { title: v.optional(v.string()) }, returns: v.id("conversations"), handler: async (ctx, args) => { const userId = await getAuthUserId(ctx); return await ctx.runMutation(components.databaseChat.conversations.create, { externalId: `user:${userId}`, title: args.title ?? "New Chat", }); }, }); ``` -------------------------------- ### E-commerce Assistant System Prompt (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/system-prompts.mdx Defines the role, capabilities, response format, and domain-specific rules for an e-commerce assistant. It specifies how the assistant should interact with users, what tools it has access to, and how to format its responses, including price formatting and low inventory warnings. ```typescript const SYSTEM_PROMPT = `You are a helpful e-commerce assistant. You help store managers understand their inventory and sales. You have access to tools that let you: - Search products by name, category, or price - Get order statistics and revenue data - Check inventory levels When answering: - Be concise and use specific numbers - Always include links using the viewUrl field: [Product Name](viewUrl) - Format prices with currency symbols - If inventory is low (< 10), mention it `; ``` -------------------------------- ### Set OpenRouter API Key - Bash Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md Configures the OpenRouter API key for your Convex environment by using the `convex env set` command in your terminal. ```bash npx convex env set OPENROUTER_API_KEY your_key_here ``` -------------------------------- ### Use a Convex Query Function in React (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/example/convex/README.md This snippet shows how to consume a Convex query function within a React component using the `useQuery` hook. It passes the necessary arguments to the query and receives the data asynchronously. Ensure the `api` object is correctly imported from your Convex setup. ```typescript const data = useQuery(api.myFunctions.myQueryFunction, { first: 10, second: "hello", }); ``` -------------------------------- ### Create Generic Tool Helpers in TypeScript Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Provides utility functions to create common tool types like query, count, aggregate, and search for database tables. It uses helper functions from '@dayhaysoos/convex-database-chat/tools'. ```typescript // convex/tools.ts import { createQueryTableTool, createCountTool, createAggregateTool, createSearchTool, } from "@dayhaysoos/convex-database-chat/tools"; const allowedTables = ["products", "orders", "users"]; // Generic query tool const queryTool = createQueryTableTool( allowedTables, "queryTable" // Function handle string ); // { name: "queryTable", description: "Query a database table with optional filters. Available tables: products, orders, users", ... } // Count records tool const countTool = createCountTool( allowedTables, "countRecords" ); // Aggregation tool const aggregateTool = createAggregateTool( allowedTables, "aggregate" ); // Full-text search tool const searchTool = createSearchTool( allowedTables, "searchRecords" ); export const tools = [queryTool, countTool, aggregateTool, searchTool]; ``` -------------------------------- ### Project Management Assistant System Prompt (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md Defines a system prompt for a project management assistant, specifying its role, available tools (task search, project stats, overdue task identification), and response guidelines. It prioritizes actionable information, task links, and highlighting urgent items. ```typescript const SYSTEM_PROMPT = `You are a project management assistant. You help team leads track tasks and project progress. You have access to tools that let you: - Search and filter tasks by status, assignee, or project - Get project statistics and completion rates - Find overdue or blocked tasks When answering: - Prioritize actionable information - Include links to tasks: [Task Title](viewUrl) - Highlight urgent or overdue items - Show completion percentages when relevant Example response: "Project 'Website Redesign' has 12 open tasks: - 3 urgent: [Fix checkout bug](/tasks/abc), [Update SSL](/tasks/def), [Mobile nav](/tasks/ghi) - 5 in review - 4 in progress Overall: 68% complete"`; ``` -------------------------------- ### Content Platform Assistant System Prompt (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/README.md Defines a system prompt for a content analytics assistant, detailing its role, available tools (article search, engagement stats, trending content identification), and response formatting. It focuses on including article links, key metrics, and actionable insights. ```typescript const SYSTEM_PROMPT = `You are a content analytics assistant. You help editors understand article performance. You have access to tools that let you: - Search articles by title, author, or tags - Get engagement statistics (views, shares, comments) - Find trending or underperforming content When answering: - Include article links: [Article Title](viewUrl) - Show key metrics inline - Compare to averages when helpful - Suggest actionable insights Example response: "Your top 3 articles this week: 1. [Getting Started with React](/articles/abc) - 12.5k views, 342 shares 2. [CSS Grid Tutorial](/articles/def) - 8.2k views, 256 shares 3. [TypeScript Tips](/articles/ghi) - 6.1k views, 189 shares All performing above your 5k average!"`; ``` -------------------------------- ### Define Product Search Tool for LLM in TypeScript Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt Defines a tool for LLMs to search products by name, category, or price range. It specifies the tool's name, description, parameters (including enums for categories), and the handler function. The implementation filters products based on provided arguments and returns a limited set of product details. ```typescript // convex/chatTools.ts import { query } from "./_generated/server"; import { v } from "convex/values"; // Tool definition (passed to chat.send config) const searchProductsTool = { name: "searchProducts", description: "Search products by name, category, or price range. Returns product details with links.", parameters: { type: "object" as const, properties: { query: { type: "string" as const, description: "Search text to match against product name" }, category: { type: "string" as const, description: "Filter by category", enum: ["electronics", "clothing", "home", "sports"], }, minPrice: { type: "number" as const, description: "Minimum price" }, maxPrice: { type: "number" as const, description: "Maximum price" }, limit: { type: "number" as const, description: "Maximum results (default: 20)" }, }, required: [] as string[], }, handler: "searchProducts", // Function handle string }; // Query implementation export const searchProducts = query({ args: { query: v.optional(v.string()), category: v.optional(v.string()), minPrice: v.optional(v.number()), maxPrice: v.optional(v.number()), limit: v.optional(v.number()), }, returns: v.array(v.object({ id: v.string(), name: v.string(), category: v.string(), price: v.number(), inStock: v.boolean(), viewUrl: v.string(), })), handler: async (ctx, args) => { const limit = Math.min(args.limit ?? 20, 100); let products = await ctx.db.query("products").collect(); if (args.category) { products = products.filter((p) => p.category === args.category); } if (args.minPrice !== undefined) { products = products.filter((p) => p.price >= args.minPrice!); } if (args.maxPrice !== undefined) { products = products.filter((p) => p.price <= args.maxPrice!); } if (args.query) { const q = args.query.toLowerCase(); products = products.filter((p) => p.name.toLowerCase().includes(q)); } return products.slice(0, limit).map((p) => ({ id: p._id, name: p.name, category: p.category, price: p.price, inStock: p.stockCount > 0, viewUrl: `/products/${p._id}`, })); }, }); ``` -------------------------------- ### Define DatabaseChatTool Interface (TypeScript) Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/guides/tools.mdx Defines the structure for a tool that an LLM assistant can query. It includes properties for the tool's name, description, JSON schema for parameters, and a handler string. The handler type can be 'query', 'mutation', or 'action', defaulting to 'query'. ```typescript interface DatabaseChatTool { name: string; description: string; parameters: { type: "object"; properties: Record< string, { type: "string" | "number" | "boolean" | "array" | "object"; description?: string; enum?: string[]; items?: { type: string }; } >; required?: string[]; }; handlerType?: "query" | "mutation" | "action"; handler: string; } ``` -------------------------------- ### Initialize Database Chat Client Wrapper with Custom Settings Source: https://context7.com/dayhaysoos/convex-database-chat/llms.txt The `defineDatabaseChat` function from `@dayhaysoos/convex-database-chat/client` creates a type-safe client wrapper. Configure model, system prompts, message limits, and define custom tools with their descriptions and handlers for interacting with your database. ```typescript // convex/chat.ts import { v } from "convex/values"; import { action, mutation, query } from "./_generated/server"; import { components } from "./_generated/api"; import { defineDatabaseChat } from "@dayhaysoos/convex-database-chat/client"; const chat = defineDatabaseChat(components.databaseChat, { model: "anthropic/claude-sonnet-4", systemPrompt: `You are a helpful e-commerce assistant. You help store managers understand their inventory and sales. You have access to tools that let you: - Search products by name, category, or price - Get order statistics and revenue data - Check inventory levels When answering: - Be concise and use specific numbers - Always include links using the viewUrl field: [Product Name](viewUrl) - Format prices with currency symbols - If inventory is low (< 10), mention it`, maxMessagesForDisplay: 100, maxMessagesForLLM: 50, tools: [ { name: "searchProducts", description: "Search products by name, category, or price range", parameters: { type: "object", properties: { query: { type: "string", description: "Search text to match against product name" }, category: { type: "string", enum: ["electronics", "clothing", "home", "sports"] }, minPrice: { type: "number", description: "Minimum price" }, maxPrice: { type: "number", description: "Maximum price" }, limit: { type: "number", description: "Maximum results (default: 20)" }, }, required: [], }, handler: "searchProducts", // Function handle string }, ], }); export { chat }; ``` -------------------------------- ### Initialize DatabaseChatClient with defineDatabaseChat Source: https://github.com/dayhaysoos/convex-database-chat/blob/main/docs/content/docs/reference/client-wrapper.mdx Initializes a DatabaseChatClient using the defineDatabaseChat function. This client wraps component endpoints with a consistent API for chat functionalities. It requires component definitions and configuration options such as the model, system prompt, and tool definitions. ```typescript import { defineDatabaseChat } from "./components/databaseChat/client"; const chat = defineDatabaseChat(components.databaseChat, { model: "openai/gpt-4o", systemPrompt: "You are a helpful assistant.", tools, maxMessagesForDisplay: 100, maxMessagesForLLM: 50, }); ```