@objectstack/service-ai 4.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/ai-service.ts","../src/adapters/memory-adapter.ts","../src/tools/tool-registry.ts","../src/conversation/in-memory-conversation-service.ts","../src/routes/ai-routes.ts","../src/routes/agent-routes.ts","../src/conversation/objectql-conversation-service.ts","../src/objects/ai-conversation.object.ts","../src/objects/ai-message.object.ts","../src/tools/data-tools.ts","../src/agent-runtime.ts","../src/agents/data-chat-agent.ts","../src/plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n// Core service\nexport { AIService } from './ai-service.js';\nexport type { AIServiceConfig } from './ai-service.js';\n\n// Kernel plugin\nexport { AIServicePlugin } from './plugin.js';\nexport type { AIServicePluginOptions } from './plugin.js';\n\n// Adapters\nexport { MemoryLLMAdapter } from './adapters/memory-adapter.js';\nexport type { LLMAdapter } from '@objectstack/spec/contracts';\n\n// Conversation\nexport { InMemoryConversationService } from './conversation/in-memory-conversation-service.js';\nexport { ObjectQLConversationService } from './conversation/objectql-conversation-service.js';\n\n// Tool registry\nexport { ToolRegistry } from './tools/tool-registry.js';\nexport type { ToolHandler } from './tools/tool-registry.js';\n\n// Data tools\nexport { registerDataTools, DATA_TOOL_DEFINITIONS } from './tools/data-tools.js';\nexport type { DataToolContext } from './tools/data-tools.js';\n\n// Agent runtime\nexport { AgentRuntime } from './agent-runtime.js';\nexport type { AgentChatContext } from './agent-runtime.js';\n\n// Built-in agents\nexport { DATA_CHAT_AGENT } from './agents/index.js';\n\n// Object definitions\nexport { AiConversationObject, AiMessageObject } from './objects/index.js';\n\n// Routes\nexport { buildAIRoutes } from './routes/ai-routes.js';\nexport { buildAgentRoutes } from './routes/agent-routes.js';\nexport type { RouteDefinition, RouteRequest, RouteResponse } from './routes/ai-routes.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n AIMessage,\n AIRequestOptions,\n AIResult,\n AIStreamEvent,\n IAIService,\n IAIConversationService,\n ChatWithToolsOptions,\n LLMAdapter,\n} from '@objectstack/spec/contracts';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport { createLogger } from '@objectstack/core';\nimport { MemoryLLMAdapter } from './adapters/memory-adapter.js';\nimport { ToolRegistry } from './tools/tool-registry.js';\nimport { InMemoryConversationService } from './conversation/in-memory-conversation-service.js';\n\n/**\n * Configuration for AIService.\n */\nexport interface AIServiceConfig {\n /** LLM adapter to delegate calls to (defaults to MemoryLLMAdapter). */\n adapter?: LLMAdapter;\n /** Logger instance. */\n logger?: Logger;\n /** Pre-registered tools. */\n toolRegistry?: ToolRegistry;\n /** Conversation service (defaults to InMemoryConversationService). */\n conversationService?: IAIConversationService;\n}\n\n/**\n * AIService — Unified AI capability service.\n *\n * Implements {@link IAIService} by delegating to a pluggable {@link LLMAdapter}\n * and managing tools and conversations through dedicated sub-components:\n *\n * | Component | Responsibility |\n * |:---|:---|\n * | {@link LLMAdapter} | LLM provider abstraction (chat, complete, stream, embed) |\n * | {@link ToolRegistry} | Tool definition storage & execution |\n * | {@link IAIConversationService} | Conversation CRUD & message persistence |\n *\n * The service is registered as `'ai'` in the kernel service registry by\n * the {@link AIServicePlugin}.\n */\nexport class AIService implements IAIService {\n private readonly adapter: LLMAdapter;\n private readonly logger: Logger;\n readonly toolRegistry: ToolRegistry;\n readonly conversationService: IAIConversationService;\n\n constructor(config: AIServiceConfig = {}) {\n this.adapter = config.adapter ?? new MemoryLLMAdapter();\n this.logger = config.logger ?? createLogger({ level: 'info', format: 'pretty' });\n this.toolRegistry = config.toolRegistry ?? new ToolRegistry();\n this.conversationService = config.conversationService ?? new InMemoryConversationService();\n\n this.logger.info(\n `[AI] Service initialized with adapter=\"${this.adapter.name}\", ` +\n `tools=${this.toolRegistry.size}`,\n );\n }\n\n /** The name of the active LLM adapter. */\n get adapterName(): string {\n return this.adapter.name;\n }\n\n // ── IAIService implementation ──────────────────────────────────\n\n async chat(messages: AIMessage[], options?: AIRequestOptions): Promise<AIResult> {\n this.logger.debug('[AI] chat', { messageCount: messages.length, model: options?.model });\n return this.adapter.chat(messages, options);\n }\n\n async complete(prompt: string, options?: AIRequestOptions): Promise<AIResult> {\n this.logger.debug('[AI] complete', { promptLength: prompt.length, model: options?.model });\n return this.adapter.complete(prompt, options);\n }\n\n async *streamChat(\n messages: AIMessage[],\n options?: AIRequestOptions,\n ): AsyncIterable<AIStreamEvent> {\n this.logger.debug('[AI] streamChat', { messageCount: messages.length, model: options?.model });\n\n if (!this.adapter.streamChat) {\n // Fallback: emit the entire response as a single text-delta + finish\n const result = await this.adapter.chat(messages, options);\n yield { type: 'text-delta', textDelta: result.content };\n yield { type: 'finish', result };\n return;\n }\n\n yield* this.adapter.streamChat(messages, options);\n }\n\n async embed(input: string | string[], model?: string): Promise<number[][]> {\n if (!this.adapter.embed) {\n throw new Error(`[AI] Adapter \"${this.adapter.name}\" does not support embeddings`);\n }\n return this.adapter.embed(input, model);\n }\n\n async listModels(): Promise<string[]> {\n if (!this.adapter.listModels) {\n return [];\n }\n return this.adapter.listModels();\n }\n\n // ── Tool Call Loop ────────────────────────────────────────────\n\n /** Default maximum iterations for the tool call loop. */\n static readonly DEFAULT_MAX_ITERATIONS = 10;\n\n /**\n * Chat with automatic tool call resolution.\n *\n * 1. Merges registered tool definitions into `options.tools`.\n * 2. Calls the LLM adapter.\n * 3. If the response contains `toolCalls`, executes them via the\n * {@link ToolRegistry}, appends tool results as `role: 'tool'`\n * messages, and loops back to step 2.\n * 4. Repeats until the model produces a final text response or the\n * maximum number of iterations (`maxIterations`) is reached.\n */\n async chatWithTools(\n messages: AIMessage[],\n options?: ChatWithToolsOptions,\n ): Promise<AIResult> {\n // Destructure maxIterations out so it is never forwarded to the adapter\n const { maxIterations: maxIter, ...restOptions } = options ?? {};\n const maxIterations = maxIter ?? AIService.DEFAULT_MAX_ITERATIONS;\n const registeredTools = this.toolRegistry.getAll();\n\n // Merge registered tools with any explicitly provided tools\n const mergedTools = [\n ...registeredTools,\n ...(restOptions.tools ?? []),\n ];\n\n // Build the options that will be sent to every LLM call in the loop\n const chatOptions: AIRequestOptions = {\n ...restOptions,\n tools: mergedTools.length > 0 ? mergedTools : undefined,\n toolChoice: mergedTools.length > 0 ? (restOptions.toolChoice ?? 'auto') : undefined,\n };\n\n // Working copy of the conversation\n const conversation = [...messages];\n\n this.logger.debug('[AI] chatWithTools start', {\n messageCount: conversation.length,\n toolCount: mergedTools.length,\n maxIterations,\n });\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n const result = await this.adapter.chat(conversation, chatOptions);\n\n // If the model did not request any tool calls we're done\n if (!result.toolCalls || result.toolCalls.length === 0) {\n this.logger.debug('[AI] chatWithTools finished', { iteration, content: result.content.slice(0, 80) });\n return result;\n }\n\n this.logger.debug('[AI] chatWithTools tool calls', {\n iteration,\n calls: result.toolCalls.map(tc => tc.name),\n });\n\n // Append the assistant's response (with tool call metadata) to the conversation\n conversation.push({\n role: 'assistant',\n content: result.content ?? '',\n toolCalls: result.toolCalls,\n });\n\n // Execute all tool calls in parallel\n const toolResults = await this.toolRegistry.executeAll(result.toolCalls);\n\n // Append each tool result as a `role: 'tool'` message\n for (const tr of toolResults) {\n conversation.push({\n role: 'tool',\n content: tr.content,\n toolCallId: tr.toolCallId,\n });\n }\n }\n\n // If we exhausted the loop without a final response, make one last\n // call *without* tools so the model is forced to produce text.\n this.logger.warn('[AI] chatWithTools max iterations reached, forcing final response');\n const finalResult = await this.adapter.chat(conversation, {\n ...chatOptions,\n tools: undefined,\n toolChoice: undefined,\n });\n return finalResult;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n AIMessage,\n AIRequestOptions,\n AIResult,\n AIStreamEvent,\n} from '@objectstack/spec/contracts';\nimport type { LLMAdapter } from '@objectstack/spec/contracts';\n\n/**\n * MemoryLLMAdapter — deterministic in-memory adapter for testing & development.\n *\n * Always echoes back the last user message prefixed with \"[memory] \".\n * Useful for unit tests, CI pipelines, and local dev without an LLM key.\n */\nexport class MemoryLLMAdapter implements LLMAdapter {\n readonly name = 'memory';\n\n async chat(messages: AIMessage[], options?: AIRequestOptions): Promise<AIResult> {\n const lastUserMessage = [...messages].reverse().find(m => m.role === 'user');\n const content = lastUserMessage\n ? `[memory] ${lastUserMessage.content}`\n : '[memory] (no user message)';\n\n return {\n content,\n model: options?.model ?? 'memory',\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },\n };\n }\n\n async complete(prompt: string, options?: AIRequestOptions): Promise<AIResult> {\n return {\n content: `[memory] ${prompt}`,\n model: options?.model ?? 'memory',\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },\n };\n }\n\n async *streamChat(\n messages: AIMessage[],\n _options?: AIRequestOptions,\n ): AsyncIterable<AIStreamEvent> {\n const result = await this.chat(messages);\n // Emit word-by-word deltas for realistic streaming simulation\n const words = result.content.split(' ');\n for (let i = 0; i < words.length; i++) {\n const textDelta = i === 0 ? words[i] : ` ${words[i]}`;\n yield { type: 'text-delta', textDelta };\n }\n yield { type: 'finish', result };\n }\n\n async embed(input: string | string[]): Promise<number[][]> {\n const texts = Array.isArray(input) ? input : [input];\n // Return deterministic zero vectors of dimension 3\n return texts.map(() => [0, 0, 0]);\n }\n\n async listModels(): Promise<string[]> {\n return ['memory'];\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { AIToolDefinition, AIToolCall, AIToolResult } from '@objectstack/spec/contracts';\n\n/**\n * Handler function for a registered tool.\n *\n * Receives parsed arguments and returns the tool output as a string.\n */\nexport type ToolHandler = (args: Record<string, unknown>) => Promise<string> | string;\n\n/**\n * ToolRegistry — Central registry for AI-callable tools.\n *\n * Plugins register tools (metadata helpers, data queries, business actions)\n * during the `ai:ready` hook. The AI service resolves tool calls against\n * this registry and feeds the results back to the LLM.\n */\nexport class ToolRegistry {\n private readonly definitions = new Map<string, AIToolDefinition>();\n private readonly handlers = new Map<string, ToolHandler>();\n\n /**\n * Register a tool with its definition and handler.\n * @param definition - Tool definition (name, description, parameters schema)\n * @param handler - Async function that executes the tool\n */\n register(definition: AIToolDefinition, handler: ToolHandler): void {\n this.definitions.set(definition.name, definition);\n this.handlers.set(definition.name, handler);\n }\n\n /**\n * Unregister a tool by name.\n */\n unregister(name: string): void {\n this.definitions.delete(name);\n this.handlers.delete(name);\n }\n\n /**\n * Check whether a tool is registered.\n */\n has(name: string): boolean {\n return this.definitions.has(name);\n }\n\n /**\n * Get the definition for a registered tool.\n */\n getDefinition(name: string): AIToolDefinition | undefined {\n return this.definitions.get(name);\n }\n\n /**\n * Return all registered tool definitions.\n */\n getAll(): AIToolDefinition[] {\n return Array.from(this.definitions.values());\n }\n\n /** Number of registered tools. */\n get size(): number {\n return this.definitions.size;\n }\n\n /** All registered tool names. */\n names(): string[] {\n return Array.from(this.definitions.keys());\n }\n\n /**\n * Execute a tool call and return the result.\n */\n async execute(toolCall: AIToolCall): Promise<AIToolResult> {\n const handler = this.handlers.get(toolCall.name);\n if (!handler) {\n return {\n toolCallId: toolCall.id,\n content: `Tool \"${toolCall.name}\" is not registered`,\n isError: true,\n };\n }\n\n try {\n const args: Record<string, unknown> = JSON.parse(toolCall.arguments);\n const content = await handler(args);\n return { toolCallId: toolCall.id, content };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { toolCallId: toolCall.id, content: message, isError: true };\n }\n }\n\n /**\n * Execute multiple tool calls in parallel.\n */\n async executeAll(toolCalls: AIToolCall[]): Promise<AIToolResult[]> {\n return Promise.all(toolCalls.map(tc => this.execute(tc)));\n }\n\n /**\n * Clear all registered tools.\n */\n clear(): void {\n this.definitions.clear();\n this.handlers.clear();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n AIConversation,\n AIMessage,\n IAIConversationService,\n} from '@objectstack/spec/contracts';\n\n/**\n * InMemoryConversationService — Reference implementation of IAIConversationService.\n *\n * Stores conversations in a simple Map. Suitable for development, testing,\n * and single-process deployments. Production environments should replace\n * this with a persistent implementation (e.g., backed by ObjectQL/SQL).\n */\nexport class InMemoryConversationService implements IAIConversationService {\n private readonly store = new Map<string, AIConversation>();\n private counter = 0;\n\n async create(options: {\n title?: string;\n agentId?: string;\n userId?: string;\n metadata?: Record<string, unknown>;\n } = {}): Promise<AIConversation> {\n const now = new Date().toISOString();\n const id = `conv_${++this.counter}`;\n\n const conversation: AIConversation = {\n id,\n title: options.title,\n agentId: options.agentId,\n userId: options.userId,\n messages: [],\n createdAt: now,\n updatedAt: now,\n metadata: options.metadata,\n };\n\n this.store.set(id, conversation);\n return conversation;\n }\n\n async get(conversationId: string): Promise<AIConversation | null> {\n return this.store.get(conversationId) ?? null;\n }\n\n async list(options: {\n userId?: string;\n agentId?: string;\n limit?: number;\n cursor?: string;\n } = {}): Promise<AIConversation[]> {\n let results = Array.from(this.store.values());\n\n if (options.userId) {\n results = results.filter(c => c.userId === options.userId);\n }\n if (options.agentId) {\n results = results.filter(c => c.agentId === options.agentId);\n }\n\n // Simple cursor-based pagination: cursor = conversation ID\n if (options.cursor) {\n const idx = results.findIndex(c => c.id === options.cursor);\n if (idx >= 0) {\n results = results.slice(idx + 1);\n }\n }\n\n if (options.limit && options.limit > 0) {\n results = results.slice(0, options.limit);\n }\n\n return results;\n }\n\n async addMessage(conversationId: string, message: AIMessage): Promise<AIConversation> {\n const conversation = this.store.get(conversationId);\n if (!conversation) {\n throw new Error(`Conversation \"${conversationId}\" not found`);\n }\n\n conversation.messages.push(message);\n conversation.updatedAt = new Date().toISOString();\n return conversation;\n }\n\n async delete(conversationId: string): Promise<void> {\n this.store.delete(conversationId);\n }\n\n /** Total number of stored conversations. */\n get size(): number {\n return this.store.size;\n }\n\n /** Clear all conversations. */\n clear(): void {\n this.store.clear();\n this.counter = 0;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { IAIService, IAIConversationService, AIMessage } from '@objectstack/spec/contracts';\nimport type { Logger } from '@objectstack/spec/contracts';\n\n/**\n * Minimal HTTP handler abstraction so routes stay framework-agnostic.\n *\n * Consumers wire these handlers to their HTTP server of choice\n * (Hono, Express, Fastify, etc.) via the kernel's HTTP server service.\n */\nexport interface RouteDefinition {\n /** HTTP method */\n method: 'GET' | 'POST' | 'DELETE';\n /** Path pattern (e.g. '/api/v1/ai/chat') */\n path: string;\n /** Human-readable description */\n description: string;\n /**\n * Handler receives a plain request-like object and returns a response-like\n * object. SSE responses set `stream: true` and provide an async iterable.\n */\n handler: (req: RouteRequest) => Promise<RouteResponse>;\n}\n\nexport interface RouteRequest {\n /** Parsed JSON body (for POST requests) */\n body?: unknown;\n /** Route/query parameters */\n params?: Record<string, string>;\n /** Query string parameters */\n query?: Record<string, string>;\n}\n\nexport interface RouteResponse {\n /** HTTP status code */\n status: number;\n /** JSON-serializable body (for non-streaming responses) */\n body?: unknown;\n /** If true, `stream` provides SSE events */\n stream?: boolean;\n /** Async iterable of SSE events (when stream=true) */\n events?: AsyncIterable<unknown>;\n}\n\n/** Valid message roles accepted by the AI routes. */\nconst VALID_ROLES = new Set<string>(['system', 'user', 'assistant', 'tool']);\n\n/**\n * Validate that `raw` is a well-formed AIMessage.\n * Returns null on success, or an error string on failure.\n */\nfunction validateMessage(raw: unknown): string | null {\n if (typeof raw !== 'object' || raw === null) {\n return 'each message must be an object';\n }\n const msg = raw as Record<string, unknown>;\n if (typeof msg.role !== 'string' || !VALID_ROLES.has(msg.role)) {\n return `message.role must be one of ${[...VALID_ROLES].map(r => `\"${r}\"`).join(', ')}`;\n }\n if (typeof msg.content !== 'string') {\n return 'message.content must be a string';\n }\n return null;\n}\n\n/**\n * Build the standard AI REST/SSE routes.\n *\n * Depends on contracts ({@link IAIService} + {@link IAIConversationService})\n * rather than concrete implementations, so any compliant service pair can\n * be wired in.\n *\n * Routes:\n * | Method | Path | Description |\n * |:---|:---|:---|\n * | POST | /api/v1/ai/chat | Synchronous chat completion |\n * | POST | /api/v1/ai/chat/stream | SSE streaming chat completion |\n * | POST | /api/v1/ai/complete | Text completion |\n * | GET | /api/v1/ai/models | List available models |\n * | POST | /api/v1/ai/conversations | Create a conversation |\n * | GET | /api/v1/ai/conversations | List conversations |\n * | POST | /api/v1/ai/conversations/:id/messages | Add message to conversation |\n * | DELETE | /api/v1/ai/conversations/:id | Delete conversation |\n */\nexport function buildAIRoutes(\n aiService: IAIService,\n conversationService: IAIConversationService,\n logger: Logger,\n): RouteDefinition[] {\n return [\n // ── Chat ────────────────────────────────────────────────────\n {\n method: 'POST',\n path: '/api/v1/ai/chat',\n description: 'Synchronous chat completion',\n handler: async (req) => {\n const { messages, options } = (req.body ?? {}) as {\n messages?: unknown[];\n options?: Record<string, unknown>;\n };\n\n if (!Array.isArray(messages) || messages.length === 0) {\n return { status: 400, body: { error: 'messages array is required' } };\n }\n\n for (const msg of messages) {\n const err = validateMessage(msg);\n if (err) return { status: 400, body: { error: err } };\n }\n\n try {\n const result = await aiService.chat(messages as AIMessage[], options as any);\n return { status: 200, body: result };\n } catch (err) {\n logger.error('[AI Route] /chat error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n\n // ── Stream Chat (SSE) ──────────────────────────────────────\n {\n method: 'POST',\n path: '/api/v1/ai/chat/stream',\n description: 'SSE streaming chat completion',\n handler: async (req) => {\n const { messages, options } = (req.body ?? {}) as {\n messages?: unknown[];\n options?: Record<string, unknown>;\n };\n\n if (!Array.isArray(messages) || messages.length === 0) {\n return { status: 400, body: { error: 'messages array is required' } };\n }\n\n for (const msg of messages) {\n const err = validateMessage(msg);\n if (err) return { status: 400, body: { error: err } };\n }\n\n try {\n if (!aiService.streamChat) {\n return { status: 501, body: { error: 'Streaming is not supported by the configured AI service' } };\n }\n const events = aiService.streamChat(messages as AIMessage[], options as any);\n return { status: 200, stream: true, events };\n } catch (err) {\n logger.error('[AI Route] /chat/stream error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n\n // ── Complete ────────────────────────────────────────────────\n {\n method: 'POST',\n path: '/api/v1/ai/complete',\n description: 'Text completion',\n handler: async (req) => {\n const { prompt, options } = (req.body ?? {}) as {\n prompt?: string;\n options?: Record<string, unknown>;\n };\n\n if (!prompt || typeof prompt !== 'string') {\n return { status: 400, body: { error: 'prompt string is required' } };\n }\n\n try {\n const result = await aiService.complete(prompt, options as any);\n return { status: 200, body: result };\n } catch (err) {\n logger.error('[AI Route] /complete error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n\n // ── Models ──────────────────────────────────────────────────\n {\n method: 'GET',\n path: '/api/v1/ai/models',\n description: 'List available models',\n handler: async () => {\n try {\n const models = aiService.listModels ? await aiService.listModels() : [];\n return { status: 200, body: { models } };\n } catch (err) {\n logger.error('[AI Route] /models error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n\n // ── Conversations ──────────────────────────────────────────\n {\n method: 'POST',\n path: '/api/v1/ai/conversations',\n description: 'Create a conversation',\n handler: async (req) => {\n try {\n const options = (req.body ?? {}) as Record<string, unknown>;\n const conversation = await conversationService.create(options as any);\n return { status: 201, body: conversation };\n } catch (err) {\n logger.error('[AI Route] POST /conversations error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n {\n method: 'GET',\n path: '/api/v1/ai/conversations',\n description: 'List conversations',\n handler: async (req) => {\n try {\n const rawQuery = req.query ?? {};\n const options: Record<string, unknown> = { ...rawQuery };\n\n if (typeof rawQuery.limit === 'string') {\n const parsedLimit = Number(rawQuery.limit);\n if (!Number.isFinite(parsedLimit) || parsedLimit <= 0 || !Number.isInteger(parsedLimit)) {\n return { status: 400, body: { error: 'Invalid limit parameter' } };\n }\n options.limit = parsedLimit;\n }\n\n const conversations = await conversationService.list(options as any);\n return { status: 200, body: { conversations } };\n } catch (err) {\n logger.error('[AI Route] GET /conversations error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n {\n method: 'POST',\n path: '/api/v1/ai/conversations/:id/messages',\n description: 'Add message to a conversation',\n handler: async (req) => {\n const id = req.params?.id;\n if (!id) {\n return { status: 400, body: { error: 'conversation id is required' } };\n }\n\n const message = req.body;\n const validationError = validateMessage(message);\n if (validationError) {\n return { status: 400, body: { error: validationError } };\n }\n\n try {\n const conversation = await conversationService.addMessage(id, message as AIMessage);\n return { status: 200, body: conversation };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('not found')) {\n return { status: 404, body: { error: msg } };\n }\n logger.error('[AI Route] POST /conversations/:id/messages error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n {\n method: 'DELETE',\n path: '/api/v1/ai/conversations/:id',\n description: 'Delete a conversation',\n handler: async (req) => {\n const id = req.params?.id;\n if (!id) {\n return { status: 400, body: { error: 'conversation id is required' } };\n }\n\n try {\n await conversationService.delete(id);\n return { status: 204 };\n } catch (err) {\n logger.error('[AI Route] DELETE /conversations/:id error', err instanceof Error ? err : undefined);\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n ];\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { AIMessage } from '@objectstack/spec/contracts';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { AIService } from '../ai-service.js';\nimport type { AgentRuntime, AgentChatContext } from '../agent-runtime.js';\nimport type { RouteDefinition } from './ai-routes.js';\n\n/**\n * Allowed message roles for the agent chat endpoint.\n *\n * Only `user` and `assistant` are accepted from clients.\n * `system` messages are injected server-side from agent instructions,\n * and `tool` messages are produced by the tool-call loop — accepting\n * either from the client would allow callers to override agent\n * guardrails or inject fabricated tool results.\n */\nconst ALLOWED_AGENT_ROLES = new Set<string>(['user', 'assistant']);\n\nfunction validateAgentMessage(raw: unknown): string | null {\n if (typeof raw !== 'object' || raw === null) {\n return 'each message must be an object';\n }\n const msg = raw as Record<string, unknown>;\n if (typeof msg.role !== 'string' || !ALLOWED_AGENT_ROLES.has(msg.role)) {\n return `message.role must be one of ${[...ALLOWED_AGENT_ROLES].map(r => `\"${r}\"`).join(', ')} for agent chat`;\n }\n if (typeof msg.content !== 'string') {\n return 'message.content must be a string';\n }\n return null;\n}\n\n/**\n * Build agent-specific REST routes.\n *\n * | Method | Path | Description |\n * |:---|:---|:---|\n * | POST | /api/v1/ai/agents/:agentName/chat | Chat with a specific agent |\n */\nexport function buildAgentRoutes(\n aiService: AIService,\n agentRuntime: AgentRuntime,\n logger: Logger,\n): RouteDefinition[] {\n return [\n {\n method: 'POST',\n path: '/api/v1/ai/agents/:agentName/chat',\n description: 'Chat with a specific AI agent',\n handler: async (req) => {\n const agentName = req.params?.agentName;\n if (!agentName) {\n return { status: 400, body: { error: 'agentName parameter is required' } };\n }\n\n // Parse request body\n const {\n messages: rawMessages,\n context: chatContext,\n options: extraOptions,\n } = (req.body ?? {}) as {\n messages?: unknown[];\n context?: AgentChatContext;\n options?: Record<string, unknown>;\n };\n\n if (!Array.isArray(rawMessages) || rawMessages.length === 0) {\n return { status: 400, body: { error: 'messages array is required' } };\n }\n\n for (const msg of rawMessages) {\n const err = validateAgentMessage(msg);\n if (err) return { status: 400, body: { error: err } };\n }\n\n // Load agent definition\n const agent = await agentRuntime.loadAgent(agentName);\n if (!agent) {\n return { status: 404, body: { error: `Agent \"${agentName}\" not found` } };\n }\n if (!agent.active) {\n return { status: 403, body: { error: `Agent \"${agentName}\" is not active` } };\n }\n\n try {\n // Build system messages from agent instructions + UI context\n const systemMessages = agentRuntime.buildSystemMessages(agent, chatContext);\n\n // Resolve agent model/tools → request options\n const agentOptions = agentRuntime.buildRequestOptions(\n agent,\n aiService.toolRegistry.getAll(),\n );\n\n // Whitelist only safe caller overrides — block tools/toolChoice/model\n // to prevent tool-definition injection or DoS via unregistered tools.\n const safeOverrides: Record<string, unknown> = {};\n if (extraOptions) {\n const ALLOWED_KEYS = new Set(['temperature', 'maxTokens', 'stop']);\n for (const key of Object.keys(extraOptions)) {\n if (ALLOWED_KEYS.has(key)) {\n safeOverrides[key] = extraOptions[key];\n }\n }\n }\n const mergedOptions = { ...agentOptions, ...safeOverrides };\n\n // Prepend system messages then user conversation\n const fullMessages: AIMessage[] = [\n ...systemMessages,\n ...(rawMessages as AIMessage[]),\n ];\n\n // Use chatWithTools for automatic tool resolution\n const result = await aiService.chatWithTools(fullMessages, {\n ...mergedOptions,\n maxIterations: agent.planning?.maxIterations,\n });\n\n return { status: 200, body: result };\n } catch (err) {\n logger.error(\n '[AI Route] /agents/:agentName/chat error',\n err instanceof Error ? err : undefined,\n );\n return { status: 500, body: { error: 'Internal AI service error' } };\n }\n },\n },\n ];\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { randomUUID } from 'node:crypto';\nimport type {\n AIConversation,\n AIMessage,\n IAIConversationService,\n IDataEngine,\n} from '@objectstack/spec/contracts';\n\n/** Object names used for persistence. */\nconst CONVERSATIONS_OBJECT = 'ai_conversations';\nconst MESSAGES_OBJECT = 'ai_messages';\n\n/** Database row shape for ai_conversations. */\ninterface DbConversationRow {\n id: string;\n title: string | null;\n agent_id: string | null;\n user_id: string | null;\n metadata: string | null;\n created_at: string;\n updated_at: string;\n}\n\n/** Database row shape for ai_messages. */\ninterface DbMessageRow {\n id: string;\n conversation_id: string;\n role: 'system' | 'user' | 'assistant' | 'tool';\n content: string;\n tool_calls: string | null;\n tool_call_id: string | null;\n created_at: string;\n}\n\n/** Deterministic ordering for conversations (total order). */\nconst CONVERSATION_ORDER = [\n { field: 'created_at', order: 'asc' as const },\n { field: 'id', order: 'asc' as const },\n];\n\n/** Deterministic ordering for messages within a conversation. */\nconst MESSAGE_ORDER = [\n { field: 'created_at', order: 'asc' as const },\n { field: 'id', order: 'asc' as const },\n];\n\n/**\n * ObjectQLConversationService — Persistent implementation of IAIConversationService.\n *\n * Delegates all storage to an {@link IDataEngine} instance, using the\n * `ai_conversations` and `ai_messages` objects. This decouples the service\n * from any specific database driver (Turso, Postgres, SQLite, etc.).\n *\n * Production environments should use this implementation to ensure\n * conversation history survives service restarts.\n */\nexport class ObjectQLConversationService implements IAIConversationService {\n private readonly engine: IDataEngine;\n\n constructor(engine: IDataEngine) {\n this.engine = engine;\n }\n\n async create(options: {\n title?: string;\n agentId?: string;\n userId?: string;\n metadata?: Record<string, unknown>;\n } = {}): Promise<AIConversation> {\n const now = new Date().toISOString();\n const id = `conv_${randomUUID()}`;\n\n const record = {\n id,\n title: options.title ?? null,\n agent_id: options.agentId ?? null,\n user_id: options.userId ?? null,\n metadata: options.metadata ? JSON.stringify(options.metadata) : null,\n created_at: now,\n updated_at: now,\n };\n\n await this.engine.insert(CONVERSATIONS_OBJECT, record);\n\n return {\n id,\n title: options.title,\n agentId: options.agentId,\n userId: options.userId,\n messages: [],\n createdAt: now,\n updatedAt: now,\n metadata: options.metadata,\n };\n }\n\n async get(conversationId: string): Promise<AIConversation | null> {\n const row: DbConversationRow | null = await this.engine.findOne(CONVERSATIONS_OBJECT, {\n where: { id: conversationId },\n });\n\n if (!row) return null;\n\n const messages: DbMessageRow[] = await this.engine.find(MESSAGES_OBJECT, {\n where: { conversation_id: conversationId },\n orderBy: MESSAGE_ORDER,\n });\n\n return this.toConversation(row, messages);\n }\n\n async list(options: {\n userId?: string;\n agentId?: string;\n limit?: number;\n cursor?: string;\n } = {}): Promise<AIConversation[]> {\n const where: Record<string, unknown> = {};\n if (options.userId) where.user_id = options.userId;\n if (options.agentId) where.agent_id = options.agentId;\n\n // Stable cursor-based pagination using composite (created_at, id) order.\n // This avoids skips/duplicates when multiple conversations share a timestamp.\n if (options.cursor) {\n const cursorRow = await this.engine.findOne(CONVERSATIONS_OBJECT, {\n where: { id: options.cursor },\n fields: ['created_at', 'id'],\n });\n if (cursorRow) {\n where.$or = [\n { created_at: { $gt: cursorRow.created_at } },\n { created_at: cursorRow.created_at, id: { $gt: cursorRow.id } },\n ];\n }\n }\n\n const rows: DbConversationRow[] = await this.engine.find(CONVERSATIONS_OBJECT, {\n where: Object.keys(where).length > 0 ? where : undefined,\n orderBy: CONVERSATION_ORDER,\n limit: options.limit && options.limit > 0 ? options.limit : undefined,\n });\n\n // Load messages per conversation in parallel.\n // N+1 is bounded by the pagination limit; driver-agnostic $in is not guaranteed.\n const conversations: AIConversation[] = await Promise.all(\n rows.map(async (row) => {\n const messages: DbMessageRow[] = await this.engine.find(MESSAGES_OBJECT, {\n where: { conversation_id: row.id },\n orderBy: MESSAGE_ORDER,\n });\n return this.toConversation(row, messages);\n }),\n );\n\n return conversations;\n }\n\n async addMessage(conversationId: string, message: AIMessage): Promise<AIConversation> {\n // Verify conversation exists\n const row: DbConversationRow | null = await this.engine.findOne(CONVERSATIONS_OBJECT, {\n where: { id: conversationId },\n });\n if (!row) {\n throw new Error(`Conversation \"${conversationId}\" not found`);\n }\n\n const now = new Date().toISOString();\n const msgId = `msg_${randomUUID()}`;\n\n // Insert the message\n await this.engine.insert(MESSAGES_OBJECT, {\n id: msgId,\n conversation_id: conversationId,\n role: message.role,\n content: message.content,\n tool_calls: message.toolCalls ? JSON.stringify(message.toolCalls) : null,\n tool_call_id: message.toolCallId ?? null,\n created_at: now,\n });\n\n // Update conversation timestamp\n await this.engine.update(CONVERSATIONS_OBJECT, { id: conversationId, updated_at: now }, {\n where: { id: conversationId },\n });\n\n // Return the full updated conversation\n return (await this.get(conversationId))!;\n }\n\n async delete(conversationId: string): Promise<void> {\n // Delete messages first (child records)\n await this.engine.delete(MESSAGES_OBJECT, {\n where: { conversation_id: conversationId },\n multi: true,\n });\n\n // Delete the conversation\n await this.engine.delete(CONVERSATIONS_OBJECT, {\n where: { id: conversationId },\n });\n }\n\n // ── Private helpers ──────────────────────────────────────────────\n\n /**\n * Safely parse a JSON string, returning `undefined` on failure.\n */\n private safeParse<T>(value: string | null, fallback?: T): T | undefined {\n if (!value) return undefined;\n try {\n return JSON.parse(value) as T;\n } catch {\n return fallback;\n }\n }\n\n /**\n * Map a database row + message rows to an AIConversation.\n */\n private toConversation(row: DbConversationRow, messageRows: DbMessageRow[]): AIConversation {\n return {\n id: row.id,\n title: row.title ?? undefined,\n agentId: row.agent_id ?? undefined,\n userId: row.user_id ?? undefined,\n messages: messageRows.map(m => this.toMessage(m)),\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n metadata: this.safeParse<Record<string, unknown>>(row.metadata),\n };\n }\n\n /**\n * Map a database row to an AIMessage.\n */\n private toMessage(row: DbMessageRow): AIMessage {\n const msg: AIMessage = {\n role: row.role,\n content: row.content,\n };\n const toolCalls = this.safeParse<any[]>(row.tool_calls);\n if (toolCalls) {\n msg.toolCalls = toolCalls;\n }\n if (row.tool_call_id) {\n msg.toolCallId = row.tool_call_id;\n }\n return msg;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * ai_conversations — AI Conversation Object\n *\n * Stores conversation metadata for persistent AI conversation management.\n * Messages are stored separately in `ai_messages` to support efficient\n * querying and pagination.\n *\n * @namespace ai\n */\nexport const AiConversationObject = ObjectSchema.create({\n namespace: 'ai',\n name: 'conversations',\n label: 'AI Conversation',\n pluralLabel: 'AI Conversations',\n icon: 'message-square',\n isSystem: true,\n description: 'Persistent AI conversation metadata',\n\n fields: {\n id: Field.text({\n label: 'Conversation ID',\n required: true,\n readonly: true,\n }),\n\n title: Field.text({\n label: 'Title',\n required: false,\n maxLength: 500,\n description: 'Conversation title or summary',\n }),\n\n agent_id: Field.text({\n label: 'Agent ID',\n required: false,\n maxLength: 255,\n description: 'Associated AI agent identifier',\n }),\n\n user_id: Field.text({\n label: 'User ID',\n required: false,\n maxLength: 255,\n description: 'User who owns the conversation',\n }),\n\n metadata: Field.textarea({\n label: 'Metadata',\n required: false,\n description: 'JSON-serialized conversation metadata',\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n\n updated_at: Field.datetime({\n label: 'Updated At',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['user_id'] },\n { fields: ['agent_id'] },\n { fields: ['created_at'] },\n ],\n\n enable: {\n trackHistory: false,\n searchable: false,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'update', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * ai_messages — AI Message Object\n *\n * Stores individual messages within an AI conversation.\n * Each message belongs to a conversation via `conversation_id` foreign key.\n *\n * @namespace ai\n */\nexport const AiMessageObject = ObjectSchema.create({\n namespace: 'ai',\n name: 'messages',\n label: 'AI Message',\n pluralLabel: 'AI Messages',\n icon: 'message-circle',\n isSystem: true,\n description: 'Individual messages within AI conversations',\n\n fields: {\n id: Field.text({\n label: 'Message ID',\n required: true,\n readonly: true,\n }),\n\n conversation_id: Field.text({\n label: 'Conversation ID',\n required: true,\n description: 'Foreign key to ai_conversations',\n }),\n\n role: Field.select({\n label: 'Role',\n required: true,\n options: [\n { label: 'System', value: 'system' },\n { label: 'User', value: 'user' },\n { label: 'Assistant', value: 'assistant' },\n { label: 'Tool', value: 'tool' },\n ],\n }),\n\n content: Field.textarea({\n label: 'Content',\n required: true,\n description: 'Message content',\n }),\n\n tool_calls: Field.textarea({\n label: 'Tool Calls',\n required: false,\n description: 'JSON-serialized tool calls (when role=assistant)',\n }),\n\n tool_call_id: Field.text({\n label: 'Tool Call ID',\n required: false,\n maxLength: 255,\n description: 'ID of the tool call this message responds to (when role=tool)',\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['conversation_id'] },\n { fields: ['conversation_id', 'created_at'] },\n ],\n\n enable: {\n trackHistory: false,\n searchable: false,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { AIToolDefinition, IDataEngine, IMetadataService } from '@objectstack/spec/contracts';\nimport type { ToolHandler } from './tool-registry.js';\nimport type { ToolRegistry } from './tool-registry.js';\n\n// ---------------------------------------------------------------------------\n// Internal type aliases for metadata payloads (returned as `unknown` from\n// IMetadataService — we cast to these lightweight shapes for field access).\n// ---------------------------------------------------------------------------\n\n/** Minimal shape of an object definition as returned by IMetadataService. */\ninterface ObjectDef {\n name: string;\n label?: string;\n fields?: Record<string, FieldDef>;\n}\n\n/** Minimal shape of a field definition inside an object. */\ninterface FieldDef {\n type?: string;\n label?: string;\n required?: boolean;\n reference?: string;\n options?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Data context — injected once at registration time\n// ---------------------------------------------------------------------------\n\n/**\n * Services required by the built-in data tools.\n *\n * These are provided by the kernel at `ai:ready` time and closed over\n * by the handler functions so they stay framework-agnostic.\n */\nexport interface DataToolContext {\n /** ObjectQL data engine for record-level operations. */\n dataEngine: IDataEngine;\n /** Metadata service for schema/object introspection. */\n metadataService: IMetadataService;\n}\n\n// ---------------------------------------------------------------------------\n// Tool Definitions\n// ---------------------------------------------------------------------------\n\n/** Maximum number of records a single query may return. */\nconst MAX_QUERY_LIMIT = 200;\n\n/** Default record limit when not specified. */\nconst DEFAULT_QUERY_LIMIT = 20;\n\nexport const LIST_OBJECTS_TOOL: AIToolDefinition = {\n name: 'list_objects',\n description: 'List all available data objects (tables) in the system. Returns object names and labels.',\n parameters: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n};\n\nexport const DESCRIBE_OBJECT_TOOL: AIToolDefinition = {\n name: 'describe_object',\n description:\n 'Get the schema (fields, types, labels) of a specific data object. ' +\n 'Use this to understand the structure of a table before querying it.',\n parameters: {\n type: 'object',\n properties: {\n objectName: {\n type: 'string',\n description: 'The snake_case name of the object to describe',\n },\n },\n required: ['objectName'],\n additionalProperties: false,\n },\n};\n\nexport const QUERY_RECORDS_TOOL: AIToolDefinition = {\n name: 'query_records',\n description:\n 'Query records from a data object with optional filters, field selection, ' +\n 'sorting, and pagination. Returns an array of matching records.',\n parameters: {\n type: 'object',\n properties: {\n objectName: {\n type: 'string',\n description: 'The snake_case name of the object to query',\n },\n where: {\n type: 'object',\n description:\n 'Filter conditions as key-value pairs (e.g. { \"status\": \"active\" }) ' +\n 'or MongoDB-style operators (e.g. { \"amount\": { \"$gt\": 100 } })',\n },\n fields: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of field names to return (omit for all fields)',\n },\n orderBy: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n field: { type: 'string' },\n order: { type: 'string', enum: ['asc', 'desc'] },\n },\n },\n description: 'Sort order (e.g. [{ \"field\": \"created_at\", \"order\": \"desc\" }])',\n },\n limit: {\n type: 'number',\n description: `Maximum number of records to return (default ${DEFAULT_QUERY_LIMIT}, max ${MAX_QUERY_LIMIT})`,\n },\n offset: {\n type: 'number',\n description: 'Number of records to skip for pagination',\n },\n },\n required: ['objectName'],\n additionalProperties: false,\n },\n};\n\nexport const GET_RECORD_TOOL: AIToolDefinition = {\n name: 'get_record',\n description: 'Get a single record by its ID from a data object.',\n parameters: {\n type: 'object',\n properties: {\n objectName: {\n type: 'string',\n description: 'The snake_case name of the object',\n },\n recordId: {\n type: 'string',\n description: 'The unique ID of the record',\n },\n fields: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of field names to return (omit for all fields)',\n },\n },\n required: ['objectName', 'recordId'],\n additionalProperties: false,\n },\n};\n\nexport const AGGREGATE_DATA_TOOL: AIToolDefinition = {\n name: 'aggregate_data',\n description:\n 'Perform aggregation/statistical operations on a data object. ' +\n 'Supports count, sum, avg, min, max with optional groupBy and where filters.',\n parameters: {\n type: 'object',\n properties: {\n objectName: {\n type: 'string',\n description: 'The snake_case name of the object to aggregate',\n },\n aggregations: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n function: {\n type: 'string',\n enum: ['count', 'sum', 'avg', 'min', 'max', 'count_distinct'],\n description: 'Aggregation function',\n },\n field: {\n type: 'string',\n description: 'Field to aggregate (optional for count)',\n },\n alias: {\n type: 'string',\n description: 'Result column alias',\n },\n },\n required: ['function', 'alias'],\n },\n description: 'Aggregation definitions',\n },\n groupBy: {\n type: 'array',\n items: { type: 'string' },\n description: 'Fields to group by',\n },\n where: {\n type: 'object',\n description: 'Filter conditions applied before aggregation',\n },\n },\n required: ['objectName', 'aggregations'],\n additionalProperties: false,\n },\n};\n\n/** All built-in data tool definitions. */\nexport const DATA_TOOL_DEFINITIONS: AIToolDefinition[] = [\n LIST_OBJECTS_TOOL,\n DESCRIBE_OBJECT_TOOL,\n QUERY_RECORDS_TOOL,\n GET_RECORD_TOOL,\n AGGREGATE_DATA_TOOL,\n];\n\n// ---------------------------------------------------------------------------\n// Handler Factories\n// ---------------------------------------------------------------------------\n\nfunction createListObjectsHandler(ctx: DataToolContext): ToolHandler {\n return async () => {\n const objects = await ctx.metadataService.listObjects();\n const summary = (objects as ObjectDef[]).map(o => ({\n name: o.name,\n label: o.label ?? o.name,\n }));\n return JSON.stringify(summary);\n };\n}\n\nfunction createDescribeObjectHandler(ctx: DataToolContext): ToolHandler {\n return async (args) => {\n const { objectName } = args as { objectName: string };\n const objectDef = await ctx.metadataService.getObject(objectName);\n if (!objectDef) {\n return JSON.stringify({ error: `Object \"${objectName}\" not found` });\n }\n\n const def = objectDef as ObjectDef;\n const fields = def.fields ?? {};\n const fieldSummary: Record<string, Record<string, unknown>> = {};\n for (const [key, f] of Object.entries(fields)) {\n fieldSummary[key] = {\n type: f.type,\n label: f.label ?? key,\n required: f.required ?? false,\n ...(f.reference ? { reference: f.reference } : {}),\n ...(f.options ? { options: f.options } : {}),\n };\n }\n\n return JSON.stringify({\n name: def.name,\n label: def.label ?? def.name,\n fields: fieldSummary,\n });\n };\n}\n\nfunction createQueryRecordsHandler(ctx: DataToolContext): ToolHandler {\n return async (args) => {\n const {\n objectName,\n where,\n fields,\n orderBy,\n limit,\n offset,\n } = args as {\n objectName: string;\n where?: Record<string, unknown>;\n fields?: string[];\n orderBy?: Array<{ field: string; order: 'asc' | 'desc' }>;\n limit?: number;\n offset?: number;\n };\n\n // Validate and clamp limit to [1, MAX_QUERY_LIMIT]\n const rawLimit = limit ?? DEFAULT_QUERY_LIMIT;\n const safeLimit = Number.isFinite(rawLimit) && rawLimit > 0\n ? Math.min(Math.floor(rawLimit), MAX_QUERY_LIMIT)\n : DEFAULT_QUERY_LIMIT;\n\n // Validate offset: must be a non-negative finite integer\n const safeOffset = (Number.isFinite(offset) && (offset as number) >= 0)\n ? Math.floor(offset as number)\n : undefined;\n\n const records = await ctx.dataEngine.find(objectName, {\n where,\n fields,\n orderBy,\n limit: safeLimit,\n offset: safeOffset,\n });\n\n return JSON.stringify({ count: records.length, records });\n };\n}\n\nfunction createGetRecordHandler(ctx: DataToolContext): ToolHandler {\n return async (args) => {\n const { objectName, recordId, fields } = args as {\n objectName: string;\n recordId: string;\n fields?: string[];\n };\n\n const record = await ctx.dataEngine.findOne(objectName, {\n where: { id: recordId },\n fields,\n });\n\n if (!record) {\n return JSON.stringify({ error: `Record \"${recordId}\" not found in \"${objectName}\"` });\n }\n\n return JSON.stringify(record);\n };\n}\n\n/** Aggregation function names supported by the data engine. */\ntype AggFn = 'count' | 'sum' | 'avg' | 'min' | 'max' | 'count_distinct';\n\n/** Set of valid aggregation function names for runtime validation. */\nconst VALID_AGG_FUNCTIONS = new Set<string>([\n 'count', 'sum', 'avg', 'min', 'max', 'count_distinct',\n]);\n\nfunction createAggregateDataHandler(ctx: DataToolContext): ToolHandler {\n return async (args) => {\n const { objectName, aggregations, groupBy, where } = args as {\n objectName: string;\n aggregations: Array<{ function: string; field?: string; alias: string }>;\n groupBy?: string[];\n where?: Record<string, unknown>;\n };\n\n // Validate aggregation functions at runtime\n for (const a of aggregations) {\n if (!VALID_AGG_FUNCTIONS.has(a.function)) {\n return JSON.stringify({\n error: `Invalid aggregation function \"${a.function}\". ` +\n `Allowed: ${[...VALID_AGG_FUNCTIONS].join(', ')}`,\n });\n }\n }\n\n const result = await ctx.dataEngine.aggregate(objectName, {\n where,\n groupBy,\n aggregations: aggregations.map(a => ({\n function: a.function as AggFn,\n field: a.field,\n alias: a.alias,\n })),\n });\n\n return JSON.stringify(result);\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public Registration Helper\n// ---------------------------------------------------------------------------\n\n/**\n * Register all built-in data tools on the given {@link ToolRegistry}.\n *\n * Typically called from the `ai:ready` hook after both the data engine\n * and metadata service are available.\n *\n * @example\n * ```ts\n * ctx.hook('ai:ready', async (aiService) => {\n * const dataEngine = ctx.getService<IDataEngine>('data');\n * const metadataService = ctx.getService<IMetadataService>('metadata');\n * registerDataTools(aiService.toolRegistry, { dataEngine, metadataService });\n * });\n * ```\n */\nexport function registerDataTools(\n registry: ToolRegistry,\n context: DataToolContext,\n): void {\n registry.register(LIST_OBJECTS_TOOL, createListObjectsHandler(context));\n registry.register(DESCRIBE_OBJECT_TOOL, createDescribeObjectHandler(context));\n registry.register(QUERY_RECORDS_TOOL, createQueryRecordsHandler(context));\n registry.register(GET_RECORD_TOOL, createGetRecordHandler(context));\n registry.register(AGGREGATE_DATA_TOOL, createAggregateDataHandler(context));\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n AIMessage,\n AIRequestOptions,\n AIToolDefinition,\n IMetadataService,\n} from '@objectstack/spec/contracts';\nimport type { Agent } from '@objectstack/spec';\nimport { AgentSchema } from '@objectstack/spec/ai';\n\n/**\n * Context passed alongside a user message when chatting with an agent.\n *\n * UI clients set these fields to tell the agent which object, record,\n * or view the user is currently looking at so it can provide contextual\n * answers without additional tool calls.\n */\nexport interface AgentChatContext {\n /** Current object the user is viewing (e.g. \"account\") */\n objectName?: string;\n /** Currently selected record ID */\n recordId?: string;\n /** Current view name */\n viewName?: string;\n}\n\n/**\n * AgentRuntime — Resolves an agent definition into runnable chat parameters.\n *\n * Responsibilities:\n * 1. Load & validate agent metadata from the metadata service.\n * 2. Build the system prompt from agent `instructions` + UI context.\n * 3. Derive {@link AIRequestOptions} from agent `model` and `tools`.\n * 4. Map agent tool references to concrete {@link AIToolDefinition}s\n * registered in the {@link ToolRegistry}.\n */\nexport class AgentRuntime {\n constructor(private readonly metadataService: IMetadataService) {}\n\n // ── Public API ────────────────────────────────────────────────\n\n /**\n * Load and validate an agent definition by name.\n *\n * The raw metadata is validated through {@link AgentSchema} to ensure\n * required fields (`instructions`, `name`, `role`, etc.) are present\n * and well-typed. Returns `undefined` when the agent does not exist\n * or validation fails.\n */\n async loadAgent(agentName: string): Promise<Agent | undefined> {\n const raw = await this.metadataService.get('agent', agentName);\n if (!raw) return undefined;\n\n const result = AgentSchema.safeParse(raw);\n if (!result.success) {\n return undefined;\n }\n return result.data;\n }\n\n /**\n * Build the system message(s) that should be prepended to the\n * conversation when chatting with the given agent.\n */\n buildSystemMessages(agent: Agent, context?: AgentChatContext): AIMessage[] {\n const parts: string[] = [];\n\n // Base instructions\n parts.push(agent.instructions);\n\n // Contextual hints from the user's current UI state\n if (context) {\n const ctx: string[] = [];\n if (context.objectName) ctx.push(`Current object: ${context.objectName}`);\n if (context.recordId) ctx.push(`Selected record ID: ${context.recordId}`);\n if (context.viewName) ctx.push(`Current view: ${context.viewName}`);\n if (ctx.length > 0) {\n parts.push('\\n--- Current Context ---\\n' + ctx.join('\\n'));\n }\n }\n\n return [{ role: 'system', content: parts.join('\\n') }];\n }\n\n /**\n * Derive {@link AIRequestOptions} from an agent definition.\n *\n * Tool references declared in `agent.tools` are resolved by name against\n * `availableTools` (i.e. the full set of ToolRegistry definitions).\n * Any unresolved references (tools the agent declares but that are not\n * registered) are silently skipped — this is intentional so that agents\n * can be defined before all tools are available.\n *\n * @param agent - The agent definition to derive options from\n * @param availableTools - All tool definitions currently registered in the ToolRegistry\n * @returns Request options with model config and resolved tool definitions\n */\n buildRequestOptions(\n agent: Agent,\n availableTools: AIToolDefinition[],\n ): AIRequestOptions {\n const options: AIRequestOptions = {};\n\n // Model config\n if (agent.model) {\n options.model = agent.model.model;\n options.temperature = agent.model.temperature;\n options.maxTokens = agent.model.maxTokens;\n }\n\n // Resolve agent tool references → concrete tool definitions\n if (agent.tools && agent.tools.length > 0) {\n const toolMap = new Map(availableTools.map(t => [t.name, t]));\n const resolved: AIToolDefinition[] = [];\n for (const ref of agent.tools) {\n const def = toolMap.get(ref.name);\n if (def) {\n resolved.push(def);\n }\n }\n if (resolved.length > 0) {\n options.tools = resolved;\n options.toolChoice = 'auto';\n }\n }\n\n return options;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Agent } from '@objectstack/spec';\n\n/**\n * Built-in `data_chat` agent definition.\n *\n * This agent powers the Airtable-style data conversation Chatbot.\n * It is registered automatically by the AI service plugin when a\n * data engine is available.\n *\n * @example\n * ```\n * POST /api/v1/ai/agents/data_chat/chat\n * {\n * \"messages\": [{ \"role\": \"user\", \"content\": \"Show me all active accounts\" }],\n * \"context\": { \"objectName\": \"account\" }\n * }\n * ```\n */\nexport const DATA_CHAT_AGENT: Agent = {\n name: 'data_chat',\n label: 'Data Assistant',\n role: 'Business Data Analyst',\n instructions: `You are a helpful data assistant that helps users explore and understand their business data through natural language.\n\nCapabilities:\n- List available data objects (tables) and their schemas\n- Query records with filters, sorting, and pagination\n- Look up individual records by ID\n- Perform aggregations and statistical analysis (count, sum, avg, min, max)\n\nGuidelines:\n1. Always use the describe_object tool first to understand a table's structure before querying it.\n2. Respect the user's current context — if they are viewing a specific object or record, use that as the default scope.\n3. When presenting data, format it in a clear and readable way using markdown tables or bullet lists.\n4. For large result sets, summarize the data and mention the total count.\n5. When performing aggregations, explain the results in plain language.\n6. If a query returns no results, suggest possible reasons and alternative queries.\n7. Never expose internal IDs unless the user explicitly asks for them.\n8. Always answer in the same language the user is using.`,\n\n model: {\n provider: 'openai',\n model: 'gpt-4',\n temperature: 0.3,\n maxTokens: 4096,\n },\n\n tools: [\n { type: 'query', name: 'list_objects', description: 'List all available data objects' },\n { type: 'query', name: 'describe_object', description: 'Get schema/fields of a data object' },\n { type: 'query', name: 'query_records', description: 'Query records with filters and pagination' },\n { type: 'query', name: 'get_record', description: 'Get a single record by ID' },\n { type: 'query', name: 'aggregate_data', description: 'Aggregate/statistics on data' },\n ],\n\n active: true,\n visibility: 'global',\n\n guardrails: {\n maxTokensPerInvocation: 8192,\n maxExecutionTimeSec: 30,\n blockedTopics: ['delete_records', 'drop_table', 'alter_schema'],\n },\n\n planning: {\n strategy: 'react',\n maxIterations: 5,\n allowReplan: false,\n },\n\n memory: {\n shortTerm: {\n maxMessages: 20,\n maxTokens: 4096,\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type { IAIService, IAIConversationService, IDataEngine, IMetadataService, LLMAdapter } from '@objectstack/spec/contracts';\nimport { AIService } from './ai-service.js';\nimport type { AIServiceConfig } from './ai-service.js';\nimport { buildAIRoutes } from './routes/ai-routes.js';\nimport { buildAgentRoutes } from './routes/agent-routes.js';\nimport { ObjectQLConversationService } from './conversation/objectql-conversation-service.js';\nimport { AiConversationObject, AiMessageObject } from './objects/index.js';\nimport { registerDataTools } from './tools/data-tools.js';\nimport { AgentRuntime } from './agent-runtime.js';\nimport { DATA_CHAT_AGENT } from './agents/index.js';\n\n/**\n * Configuration options for the AIServicePlugin.\n */\nexport interface AIServicePluginOptions {\n /** LLM adapter to use (defaults to MemoryLLMAdapter). */\n adapter?: LLMAdapter;\n /** Enable debug logging. */\n debug?: boolean;\n /** Explicit conversation service override. When set, auto-detection is skipped. */\n conversationService?: IAIConversationService;\n}\n\n/**\n * AIServicePlugin — Kernel plugin for the unified AI capability service.\n *\n * Lifecycle:\n * 1. **init** — Creates {@link AIService}, registers as `'ai'` service.\n * If an existing AI service is already registered, it is replaced.\n * 2. **start** — Triggers `'ai:ready'` hook so other plugins can register\n * tools or extend the service. Registers REST/SSE routes.\n * 3. **destroy** — Cleans up references.\n *\n * @example\n * ```ts\n * import { LiteKernel } from '@objectstack/core';\n * import { AIServicePlugin } from '@objectstack/service-ai';\n *\n * const kernel = new LiteKernel();\n * kernel.use(new AIServicePlugin());\n * await kernel.bootstrap();\n *\n * const ai = kernel.getService<IAIService>('ai');\n * const result = await ai.chat([{ role: 'user', content: 'Hello' }]);\n * ```\n */\nexport class AIServicePlugin implements Plugin {\n name = 'com.objectstack.service-ai';\n version = '1.0.0';\n type = 'standard' as const;\n dependencies: string[] = [];\n\n private service?: AIService;\n private readonly options: AIServicePluginOptions;\n\n constructor(options: AIServicePluginOptions = {}) {\n this.options = options;\n }\n\n async init(ctx: PluginContext): Promise<void> {\n // Check if there is an existing AI service (e.g. from dev-plugin)\n let hasExisting = false;\n try {\n const existing = ctx.getService<IAIService>('ai');\n if (existing && typeof existing.chat === 'function') {\n hasExisting = true;\n ctx.logger.debug('[AI] Found existing AI service, replacing');\n }\n } catch {\n // No existing service — that's fine\n }\n\n // Determine conversation service: explicit > auto-detect IDataEngine > InMemory fallback\n let conversationService: IAIConversationService | undefined = this.options.conversationService;\n if (!conversationService) {\n try {\n const engine = ctx.getService<IDataEngine>('data');\n if (engine && typeof engine.find === 'function') {\n conversationService = new ObjectQLConversationService(engine);\n ctx.logger.info('[AI] Using ObjectQLConversationService (IDataEngine detected)');\n }\n } catch {\n // No data engine — fall back to InMemory\n }\n }\n\n const config: AIServiceConfig = {\n adapter: this.options.adapter,\n logger: ctx.logger,\n conversationService,\n };\n\n this.service = new AIService(config);\n\n // Register or replace the AI service\n if (hasExisting) {\n ctx.replaceService('ai', this.service);\n } else {\n ctx.registerService('ai', this.service);\n }\n\n // Register AI system objects so ObjectQLPlugin auto-discovers them\n ctx.registerService('app.com.objectstack.service-ai', {\n id: 'com.objectstack.service-ai',\n name: 'AI Service',\n version: '1.0.0',\n type: 'plugin',\n namespace: 'ai',\n objects: [AiConversationObject, AiMessageObject],\n });\n\n if (this.options.debug) {\n ctx.hook('ai:beforeChat', async (messages: unknown) => {\n ctx.logger.debug('[AI] Before chat', { messages });\n });\n }\n\n ctx.logger.info('[AI] Service initialized');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n if (!this.service) return;\n\n // ── Auto-register built-in data tools if data engine + metadata are available ──\n try {\n const dataEngine = ctx.getService<IDataEngine>('data');\n const metadataService = ctx.getService<IMetadataService>('metadata');\n if (dataEngine && metadataService) {\n registerDataTools(this.service.toolRegistry, { dataEngine, metadataService });\n ctx.logger.info('[AI] Built-in data tools registered');\n\n // Register the built-in data_chat agent only if it does not already exist\n const agentExists =\n typeof metadataService.exists === 'function'\n ? await metadataService.exists('agent', DATA_CHAT_AGENT.name)\n : false;\n\n if (!agentExists) {\n await metadataService.register('agent', DATA_CHAT_AGENT.name, DATA_CHAT_AGENT);\n ctx.logger.info('[AI] data_chat agent registered');\n } else {\n ctx.logger.debug('[AI] data_chat agent already exists, skipping auto-registration');\n }\n }\n } catch {\n // Data engine or metadata service not available — skip data tools\n ctx.logger.debug('[AI] Data engine or metadata service not available, skipping data tools');\n }\n\n // Trigger hook to notify AI service is ready — other plugins can register tools\n await ctx.trigger('ai:ready', this.service);\n\n // Build and expose route definitions\n const routes = buildAIRoutes(this.service, this.service.conversationService, ctx.logger);\n\n // Build agent routes if metadata service is available\n try {\n const metadataService = ctx.getService<IMetadataService>('metadata');\n if (metadataService) {\n const agentRuntime = new AgentRuntime(metadataService);\n const agentRoutes = buildAgentRoutes(this.service, agentRuntime, ctx.logger);\n routes.push(...agentRoutes);\n }\n } catch {\n ctx.logger.debug('[AI] Metadata service not available, skipping agent routes');\n }\n\n // Trigger hook so HTTP server plugins can mount these routes\n await ctx.trigger('ai:routes', routes);\n\n ctx.logger.info(\n `[AI] Service started — adapter=\"${this.service.adapterName}\", ` +\n `tools=${this.service.toolRegistry.size}, ` +\n `routes=${routes.length}`,\n );\n }\n\n async destroy(): Promise<void> {\n this.service = undefined;\n }\n}\n"],"mappings":"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","names":["import_data"]}