@objectstack/service-ai 4.0.3 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +8 -0
- package/README.md +293 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/ai-service.test.ts +17 -0
- package/src/plugin.ts +2 -2
- package/vitest.config.ts +23 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/service-ai@4.0.
|
|
2
|
+
> @objectstack/service-ai@4.0.4 build /home/runner/work/framework/framework/packages/services/service-ai
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[32mCJS[39m [1mdist/index.cjs [22m[
|
|
14
|
-
[32mCJS[39m [1mdist/index.cjs.map [22m[
|
|
15
|
-
[32mCJS[39m ⚡️ Build success in
|
|
16
|
-
[32mESM[39m [1mdist/index.js [22m[32m94.
|
|
17
|
-
[32mESM[39m [1mdist/index.js.map [22m[32m194.
|
|
18
|
-
[32mESM[39m ⚡️ Build success in
|
|
13
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m96.98 KB[39m
|
|
14
|
+
[32mCJS[39m [1mdist/index.cjs.map [22m[32m194.97 KB[39m
|
|
15
|
+
[32mCJS[39m ⚡️ Build success in 220ms
|
|
16
|
+
[32mESM[39m [1mdist/index.js [22m[32m94.67 KB[39m
|
|
17
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m194.81 KB[39m
|
|
18
|
+
[32mESM[39m ⚡️ Build success in 251ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 25782ms
|
|
21
21
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m157.91 KB[39m
|
|
22
22
|
[32mDTS[39m [1mdist/index.d.cts [22m[32m157.91 KB[39m
|
package/CHANGELOG.md
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# @objectstack/service-ai
|
|
2
|
+
|
|
3
|
+
AI Service for ObjectStack — implements `IAIService` with LLM adapter layer, conversation management, tool registry, and REST/SSE routes.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-Provider LLM Support**: Supports OpenAI, Anthropic, Google, and custom gateway providers via Vercel AI SDK
|
|
8
|
+
- **Conversation Management**: Track and manage AI conversations with full history
|
|
9
|
+
- **Tool Registry**: Register and execute tools that AI agents can call
|
|
10
|
+
- **Streaming Support**: Real-time streaming responses via Server-Sent Events (SSE)
|
|
11
|
+
- **REST API**: Auto-generated endpoints for AI operations
|
|
12
|
+
- **Type-Safe**: Full TypeScript support with type inference
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @objectstack/service-ai
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Peer Dependencies
|
|
21
|
+
|
|
22
|
+
Install the LLM provider(s) you need:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# OpenAI
|
|
26
|
+
pnpm add @ai-sdk/openai
|
|
27
|
+
|
|
28
|
+
# Anthropic (Claude)
|
|
29
|
+
pnpm add @ai-sdk/anthropic
|
|
30
|
+
|
|
31
|
+
# Google (Gemini)
|
|
32
|
+
pnpm add @ai-sdk/google
|
|
33
|
+
|
|
34
|
+
# Custom Gateway
|
|
35
|
+
pnpm add @ai-sdk/gateway
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
All peer dependencies are optional — install only what you need.
|
|
39
|
+
|
|
40
|
+
## Basic Usage
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { defineStack } from '@objectstack/spec';
|
|
44
|
+
import { ServiceAI } from '@objectstack/service-ai';
|
|
45
|
+
import { openai } from '@ai-sdk/openai';
|
|
46
|
+
|
|
47
|
+
const stack = defineStack({
|
|
48
|
+
services: [
|
|
49
|
+
ServiceAI.configure({
|
|
50
|
+
models: {
|
|
51
|
+
default: openai('gpt-4'),
|
|
52
|
+
fast: openai('gpt-3.5-turbo'),
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Configuration
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
interface AIServiceConfig {
|
|
63
|
+
/** Map of model IDs to AI SDK model instances */
|
|
64
|
+
models: Record<string, LanguageModel>;
|
|
65
|
+
|
|
66
|
+
/** Default model to use when not specified */
|
|
67
|
+
defaultModel?: string;
|
|
68
|
+
|
|
69
|
+
/** Maximum conversation history length */
|
|
70
|
+
maxHistoryLength?: number;
|
|
71
|
+
|
|
72
|
+
/** Enable streaming responses (default: true) */
|
|
73
|
+
enableStreaming?: boolean;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Service API
|
|
78
|
+
|
|
79
|
+
The `IAIService` interface provides:
|
|
80
|
+
|
|
81
|
+
### Conversation Management
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// Get AI service from kernel
|
|
85
|
+
const ai = kernel.getService<IAIService>('ai');
|
|
86
|
+
|
|
87
|
+
// Create a new conversation
|
|
88
|
+
const conversation = await ai.createConversation({
|
|
89
|
+
model: 'default',
|
|
90
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Send a message
|
|
94
|
+
const response = await ai.sendMessage({
|
|
95
|
+
conversationId: conversation.id,
|
|
96
|
+
message: 'What is ObjectStack?',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Stream a message
|
|
100
|
+
const stream = await ai.streamMessage({
|
|
101
|
+
conversationId: conversation.id,
|
|
102
|
+
message: 'Explain in detail...',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
for await (const chunk of stream) {
|
|
106
|
+
process.stdout.write(chunk.text);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Tool Registry
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Register a tool
|
|
114
|
+
ai.registerTool({
|
|
115
|
+
name: 'get_weather',
|
|
116
|
+
description: 'Get current weather for a location',
|
|
117
|
+
parameters: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
location: { type: 'string', description: 'City name' },
|
|
121
|
+
},
|
|
122
|
+
required: ['location'],
|
|
123
|
+
},
|
|
124
|
+
execute: async ({ location }) => {
|
|
125
|
+
// Your tool implementation
|
|
126
|
+
return { temperature: 72, condition: 'sunny' };
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Tools are automatically available to AI agents
|
|
131
|
+
const response = await ai.sendMessage({
|
|
132
|
+
conversationId: conversation.id,
|
|
133
|
+
message: 'What is the weather in San Francisco?',
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## REST API Endpoints
|
|
138
|
+
|
|
139
|
+
When used with `@objectstack/rest`, the following endpoints are auto-generated:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
POST /api/v1/ai/conversations # Create conversation
|
|
143
|
+
GET /api/v1/ai/conversations/:id # Get conversation
|
|
144
|
+
POST /api/v1/ai/conversations/:id/messages # Send message
|
|
145
|
+
GET /api/v1/ai/conversations/:id/stream # Stream response (SSE)
|
|
146
|
+
GET /api/v1/ai/tools # List available tools
|
|
147
|
+
POST /api/v1/ai/tools/:name/execute # Execute a tool
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Multi-Model Configuration
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { openai } from '@ai-sdk/openai';
|
|
154
|
+
import { anthropic } from '@ai-sdk/anthropic';
|
|
155
|
+
import { google } from '@ai-sdk/google';
|
|
156
|
+
|
|
157
|
+
const stack = defineStack({
|
|
158
|
+
services: [
|
|
159
|
+
ServiceAI.configure({
|
|
160
|
+
models: {
|
|
161
|
+
// Fast model for simple tasks
|
|
162
|
+
fast: openai('gpt-3.5-turbo'),
|
|
163
|
+
|
|
164
|
+
// Default model for general use
|
|
165
|
+
default: openai('gpt-4'),
|
|
166
|
+
|
|
167
|
+
// Advanced reasoning
|
|
168
|
+
reasoning: openai('gpt-4-turbo'),
|
|
169
|
+
|
|
170
|
+
// Anthropic Claude
|
|
171
|
+
claude: anthropic('claude-3-opus-20240229'),
|
|
172
|
+
|
|
173
|
+
// Google Gemini
|
|
174
|
+
gemini: google('gemini-pro'),
|
|
175
|
+
},
|
|
176
|
+
defaultModel: 'default',
|
|
177
|
+
}),
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Advanced Features
|
|
183
|
+
|
|
184
|
+
### Custom System Prompts
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const conversation = await ai.createConversation({
|
|
188
|
+
model: 'default',
|
|
189
|
+
systemPrompt: `You are an expert in ObjectStack.
|
|
190
|
+
Answer questions about the framework accurately and concisely.
|
|
191
|
+
Always provide code examples when relevant.`,
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Conversation History
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Get full conversation history
|
|
199
|
+
const history = await ai.getConversationHistory(conversationId);
|
|
200
|
+
|
|
201
|
+
// Clear conversation history
|
|
202
|
+
await ai.clearConversation(conversationId);
|
|
203
|
+
|
|
204
|
+
// Delete conversation
|
|
205
|
+
await ai.deleteConversation(conversationId);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Error Handling
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
try {
|
|
212
|
+
const response = await ai.sendMessage({
|
|
213
|
+
conversationId: conversation.id,
|
|
214
|
+
message: 'Hello',
|
|
215
|
+
});
|
|
216
|
+
} catch (error) {
|
|
217
|
+
if (error.code === 'RATE_LIMIT_EXCEEDED') {
|
|
218
|
+
// Handle rate limiting
|
|
219
|
+
} else if (error.code === 'MODEL_NOT_FOUND') {
|
|
220
|
+
// Handle missing model
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Integration with ObjectStack Agents
|
|
226
|
+
|
|
227
|
+
The AI service integrates with the `@objectstack/spec/ai` agent protocol:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { defineAgent } from '@objectstack/spec';
|
|
231
|
+
|
|
232
|
+
const myAgent = defineAgent({
|
|
233
|
+
name: 'code_assistant',
|
|
234
|
+
model: 'default',
|
|
235
|
+
systemPrompt: 'You help write ObjectStack code.',
|
|
236
|
+
tools: ['create_object', 'create_field', 'create_view'],
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Agent automatically uses the AI service
|
|
240
|
+
const result = await myAgent.execute({
|
|
241
|
+
input: 'Create a contact object with name and email fields',
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Architecture
|
|
246
|
+
|
|
247
|
+
The service follows a layered architecture:
|
|
248
|
+
|
|
249
|
+
1. **Adapter Layer**: Abstracts different LLM providers (OpenAI, Anthropic, Google)
|
|
250
|
+
2. **Conversation Manager**: Handles conversation state and history
|
|
251
|
+
3. **Tool Registry**: Manages tool registration and execution
|
|
252
|
+
4. **REST Routes**: Auto-generated HTTP endpoints
|
|
253
|
+
5. **SSE Streaming**: Real-time streaming support
|
|
254
|
+
|
|
255
|
+
## Contract Implementation
|
|
256
|
+
|
|
257
|
+
Implements `IAIService` from `@objectstack/spec/contracts`:
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
interface IAIService {
|
|
261
|
+
createConversation(options: ConversationOptions): Promise<Conversation>;
|
|
262
|
+
sendMessage(options: MessageOptions): Promise<Message>;
|
|
263
|
+
streamMessage(options: MessageOptions): AsyncIterable<MessageChunk>;
|
|
264
|
+
registerTool(tool: AITool): void;
|
|
265
|
+
getConversationHistory(conversationId: string): Promise<Message[]>;
|
|
266
|
+
deleteConversation(conversationId: string): Promise<void>;
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Performance Considerations
|
|
271
|
+
|
|
272
|
+
- **Streaming**: Use streaming for long responses to improve perceived performance
|
|
273
|
+
- **Model Selection**: Choose appropriate models based on task complexity
|
|
274
|
+
- **Conversation History**: Limit history length to control token usage
|
|
275
|
+
- **Caching**: Provider-level caching is handled automatically
|
|
276
|
+
|
|
277
|
+
## Best Practices
|
|
278
|
+
|
|
279
|
+
1. **Model Selection**: Use fast models for simple tasks, advanced models for complex reasoning
|
|
280
|
+
2. **System Prompts**: Provide clear, specific instructions in system prompts
|
|
281
|
+
3. **Tool Design**: Keep tools focused and well-documented
|
|
282
|
+
4. **Error Handling**: Always handle rate limits and API errors gracefully
|
|
283
|
+
5. **Streaming**: Use streaming for better UX on long-running queries
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
Apache-2.0
|
|
288
|
+
|
|
289
|
+
## See Also
|
|
290
|
+
|
|
291
|
+
- [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
|
|
292
|
+
- [@objectstack/spec/ai Protocol](../../spec/src/ai/)
|
|
293
|
+
- [AI Agent Guide](/content/docs/guides/ai/)
|
package/dist/index.cjs
CHANGED
|
@@ -2685,8 +2685,8 @@ var AIServicePlugin = class {
|
|
|
2685
2685
|
setupNav.contribute({
|
|
2686
2686
|
areaId: "area_ai",
|
|
2687
2687
|
items: [
|
|
2688
|
-
{ id: "nav_ai_conversations", type: "object", label:
|
|
2689
|
-
{ id: "nav_ai_messages", type: "object", label:
|
|
2688
|
+
{ id: "nav_ai_conversations", type: "object", label: "Conversations", objectName: "conversations", icon: "message-square", order: 10 },
|
|
2689
|
+
{ id: "nav_ai_messages", type: "object", label: "Messages", objectName: "messages", icon: "messages-square", order: 20 }
|
|
2690
2690
|
]
|
|
2691
2691
|
});
|
|
2692
2692
|
ctx.logger.info("[AI] Navigation items contributed to Setup App");
|