@objectstack/service-ai
v6.9.0
Published
AI Service for ObjectStack — implements IAIService with LLM adapter layer, conversation management, tool registry, and REST/SSE routes
Maintainers
Readme
@objectstack/service-ai
AI Service for ObjectStack — implements IAIService with LLM adapter layer, conversation management, tool registry, and REST/SSE routes.
Features
- Multi-Provider LLM Support: Supports OpenAI, Anthropic, Google, and custom gateway providers via Vercel AI SDK
- Conversation Management: Track and manage AI conversations with full history
- Tool Registry: Register and execute tools that AI agents can call
- Streaming Support: Real-time streaming responses via Server-Sent Events (SSE)
- REST API: Auto-generated endpoints for AI operations
- Type-Safe: Full TypeScript support with type inference
Installation
pnpm add @objectstack/service-aiPeer Dependencies
Install the LLM provider(s) you need:
# OpenAI
pnpm add @ai-sdk/openai
# Anthropic (Claude)
pnpm add @ai-sdk/anthropic
# Google (Gemini)
pnpm add @ai-sdk/google
# Custom Gateway
pnpm add @ai-sdk/gatewayAll peer dependencies are optional — install only what you need.
Basic Usage
import { defineStack } from '@objectstack/spec';
import { ServiceAI } from '@objectstack/service-ai';
import { openai } from '@ai-sdk/openai';
const stack = defineStack({
services: [
ServiceAI.configure({
models: {
default: openai('gpt-4'),
fast: openai('gpt-3.5-turbo'),
},
}),
],
});Configuration
interface AIServiceConfig {
/** Map of model IDs to AI SDK model instances */
models: Record<string, LanguageModel>;
/** Default model to use when not specified */
defaultModel?: string;
/** Maximum conversation history length */
maxHistoryLength?: number;
/** Enable streaming responses (default: true) */
enableStreaming?: boolean;
}Service API
The IAIService interface provides:
Conversation Management
// Get AI service from kernel
const ai = kernel.getService<IAIService>('ai');
// Create a new conversation
const conversation = await ai.createConversation({
model: 'default',
systemPrompt: 'You are a helpful assistant.',
});
// Send a message
const response = await ai.sendMessage({
conversationId: conversation.id,
message: 'What is ObjectStack?',
});
// Stream a message
const stream = await ai.streamMessage({
conversationId: conversation.id,
message: 'Explain in detail...',
});
for await (const chunk of stream) {
process.stdout.write(chunk.text);
}Tool Registry
// Register a tool
ai.registerTool({
name: 'get_weather',
description: 'Get current weather for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' },
},
required: ['location'],
},
execute: async ({ location }) => {
// Your tool implementation
return { temperature: 72, condition: 'sunny' };
},
});
// Tools are automatically available to AI agents
const response = await ai.sendMessage({
conversationId: conversation.id,
message: 'What is the weather in San Francisco?',
});REST API Endpoints
When used with @objectstack/rest, the following endpoints are auto-generated:
POST /api/v1/ai/conversations # Create conversation
GET /api/v1/ai/conversations/:id # Get conversation
POST /api/v1/ai/conversations/:id/messages # Send message
GET /api/v1/ai/conversations/:id/stream # Stream response (SSE)
GET /api/v1/ai/tools # List available tools
POST /api/v1/ai/tools/:name/execute # Execute a toolMulti-Model Configuration
import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';
const stack = defineStack({
services: [
ServiceAI.configure({
models: {
// Fast model for simple tasks
fast: openai('gpt-3.5-turbo'),
// Default model for general use
default: openai('gpt-4'),
// Advanced reasoning
reasoning: openai('gpt-4-turbo'),
// Anthropic Claude
claude: anthropic('claude-3-opus-20240229'),
// Google Gemini
gemini: google('gemini-pro'),
},
defaultModel: 'default',
}),
],
});Advanced Features
Custom System Prompts
const conversation = await ai.createConversation({
model: 'default',
systemPrompt: `You are an expert in ObjectStack.
Answer questions about the framework accurately and concisely.
Always provide code examples when relevant.`,
});Conversation History
// Get full conversation history
const history = await ai.getConversationHistory(conversationId);
// Clear conversation history
await ai.clearConversation(conversationId);
// Delete conversation
await ai.deleteConversation(conversationId);Error Handling
try {
const response = await ai.sendMessage({
conversationId: conversation.id,
message: 'Hello',
});
} catch (error) {
if (error.code === 'RATE_LIMIT_EXCEEDED') {
// Handle rate limiting
} else if (error.code === 'MODEL_NOT_FOUND') {
// Handle missing model
}
}Integration with ObjectStack Agents
The AI service integrates with the @objectstack/spec/ai agent protocol:
import { defineAgent } from '@objectstack/spec';
const myAgent = defineAgent({
name: 'code_assistant',
model: 'default',
systemPrompt: 'You help write ObjectStack code.',
tools: ['create_object', 'create_field', 'create_view'],
});
// Agent automatically uses the AI service
const result = await myAgent.execute({
input: 'Create a contact object with name and email fields',
});Architecture
The service follows a layered architecture:
- Adapter Layer: Abstracts different LLM providers (OpenAI, Anthropic, Google)
- Conversation Manager: Handles conversation state and history
- Tool Registry: Manages tool registration and execution
- REST Routes: Auto-generated HTTP endpoints
- SSE Streaming: Real-time streaming support
Contract Implementation
Implements IAIService from @objectstack/spec/contracts:
interface IAIService {
createConversation(options: ConversationOptions): Promise<Conversation>;
sendMessage(options: MessageOptions): Promise<Message>;
streamMessage(options: MessageOptions): AsyncIterable<MessageChunk>;
registerTool(tool: AITool): void;
getConversationHistory(conversationId: string): Promise<Message[]>;
deleteConversation(conversationId: string): Promise<void>;
}Performance Considerations
- Streaming: Use streaming for long responses to improve perceived performance
- Model Selection: Choose appropriate models based on task complexity
- Conversation History: Limit history length to control token usage
- Caching: Provider-level caching is handled automatically
Best Practices
- Model Selection: Use fast models for simple tasks, advanced models for complex reasoning
- System Prompts: Provide clear, specific instructions in system prompts
- Tool Design: Keep tools focused and well-documented
- Error Handling: Always handle rate limits and API errors gracefully
- Streaming: Use streaming for better UX on long-running queries
License
Apache-2.0. See LICENSING.md.
