### 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,
});
```