@objectstack/service-ai 4.0.1 → 4.0.3

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.
Files changed (44) hide show
  1. package/.turbo/turbo-build.log +11 -11
  2. package/CHANGELOG.md +17 -0
  3. package/dist/index.cjs +1632 -355
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +330 -87
  6. package/dist/index.d.ts +330 -87
  7. package/dist/index.js +1623 -352
  8. package/dist/index.js.map +1 -1
  9. package/package.json +27 -5
  10. package/src/__tests__/ai-service.test.ts +260 -27
  11. package/src/__tests__/auth-and-toolcalling.test.ts +81 -29
  12. package/src/__tests__/chatbot-features.test.ts +397 -102
  13. package/src/__tests__/metadata-tools.test.ts +970 -0
  14. package/src/__tests__/objectql-conversation-service.test.ts +34 -16
  15. package/src/__tests__/tool-routes.test.ts +191 -0
  16. package/src/__tests__/vercel-stream-encoder.test.ts +310 -0
  17. package/src/adapters/index.ts +2 -0
  18. package/src/adapters/memory-adapter.ts +17 -9
  19. package/src/adapters/vercel-adapter.ts +148 -0
  20. package/src/agent-runtime.ts +27 -3
  21. package/src/agents/index.ts +1 -0
  22. package/src/agents/metadata-assistant-agent.ts +87 -0
  23. package/src/ai-service.ts +75 -36
  24. package/src/conversation/in-memory-conversation-service.ts +2 -2
  25. package/src/conversation/objectql-conversation-service.ts +67 -18
  26. package/src/index.ts +22 -2
  27. package/src/plugin.ts +237 -30
  28. package/src/routes/agent-routes.ts +68 -12
  29. package/src/routes/ai-routes.ts +93 -14
  30. package/src/routes/index.ts +1 -0
  31. package/src/routes/message-utils.ts +90 -0
  32. package/src/routes/tool-routes.ts +142 -0
  33. package/src/stream/index.ts +3 -0
  34. package/src/stream/vercel-stream-encoder.ts +153 -0
  35. package/src/tools/add-field.tool.ts +70 -0
  36. package/src/tools/create-object.tool.ts +66 -0
  37. package/src/tools/data-tools.ts +4 -101
  38. package/src/tools/delete-field.tool.ts +38 -0
  39. package/src/tools/describe-object.tool.ts +31 -0
  40. package/src/tools/index.ts +12 -1
  41. package/src/tools/list-objects.tool.ts +34 -0
  42. package/src/tools/metadata-tools.ts +430 -0
  43. package/src/tools/modify-field.tool.ts +44 -0
  44. package/src/tools/tool-registry.ts +32 -9
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
- import { AIToolDefinition, AIToolCall, AIToolResult, IAIService, IAIConversationService, LLMAdapter, Logger, AIMessage, AIRequestOptions, AIResult, AIStreamEvent, ChatWithToolsOptions, AIConversation, IDataEngine, IMetadataService } from '@objectstack/spec/contracts';
1
+ import { AIToolDefinition, ToolCallPart, ToolResultPart, IAIService, IAIConversationService, LLMAdapter, Logger, ModelMessage, AIRequestOptions, AIResult, TextStreamPart, ToolSet, ChatWithToolsOptions, AIConversation, IDataEngine, IMetadataService } from '@objectstack/spec/contracts';
2
2
  export { LLMAdapter } from '@objectstack/spec/contracts';
3
3
  import { Plugin, PluginContext } from '@objectstack/core';
4
+ import { LanguageModelV2 } from '@ai-sdk/provider';
5
+ import { TextStreamPart as TextStreamPart$1, ToolSet as ToolSet$1 } from 'ai';
6
+ import { Tool } from '@objectstack/spec/ai';
4
7
  import { Agent } from '@objectstack/spec';
5
8
  import { z } from 'zod';
6
9
  import * as _objectstack_spec_data from '@objectstack/spec/data';
@@ -11,6 +14,13 @@ import * as _objectstack_spec_data from '@objectstack/spec/data';
11
14
  * Receives parsed arguments and returns the tool output as a string.
12
15
  */
13
16
  type ToolHandler = (args: Record<string, unknown>) => Promise<string> | string;
17
+ /**
18
+ * Extended ToolResultPart that carries an `isError` flag for internal
19
+ * error-tracking in the tool-call loop.
20
+ */
21
+ interface ToolExecutionResult extends ToolResultPart {
22
+ isError?: boolean;
23
+ }
14
24
  /**
15
25
  * ToolRegistry — Central registry for AI-callable tools.
16
26
  *
@@ -50,11 +60,11 @@ declare class ToolRegistry {
50
60
  /**
51
61
  * Execute a tool call and return the result.
52
62
  */
53
- execute(toolCall: AIToolCall): Promise<AIToolResult>;
63
+ execute(toolCall: ToolCallPart): Promise<ToolExecutionResult>;
54
64
  /**
55
65
  * Execute multiple tool calls in parallel.
56
66
  */
57
- executeAll(toolCalls: AIToolCall[]): Promise<AIToolResult[]>;
67
+ executeAll(toolCalls: ToolCallPart[]): Promise<ToolExecutionResult[]>;
58
68
  /**
59
69
  * Clear all registered tools.
60
70
  */
@@ -97,13 +107,15 @@ declare class AIService implements IAIService {
97
107
  constructor(config?: AIServiceConfig);
98
108
  /** The name of the active LLM adapter. */
99
109
  get adapterName(): string;
100
- chat(messages: AIMessage[], options?: AIRequestOptions): Promise<AIResult>;
110
+ chat(messages: ModelMessage[], options?: AIRequestOptions): Promise<AIResult>;
101
111
  complete(prompt: string, options?: AIRequestOptions): Promise<AIResult>;
102
- streamChat(messages: AIMessage[], options?: AIRequestOptions): AsyncIterable<AIStreamEvent>;
112
+ streamChat(messages: ModelMessage[], options?: AIRequestOptions): AsyncIterable<TextStreamPart<ToolSet>>;
103
113
  embed(input: string | string[], model?: string): Promise<number[][]>;
104
114
  listModels(): Promise<string[]>;
105
115
  /** Default maximum iterations for the tool call loop. */
106
116
  static readonly DEFAULT_MAX_ITERATIONS = 10;
117
+ /** Extract the text value from a ToolExecutionResult's output. */
118
+ private static extractOutputText;
107
119
  /**
108
120
  * Chat with automatic tool call resolution.
109
121
  *
@@ -115,7 +127,7 @@ declare class AIService implements IAIService {
115
127
  * 4. Repeats until the model produces a final text response or the
116
128
  * maximum number of iterations (`maxIterations`) is reached.
117
129
  */
118
- chatWithTools(messages: AIMessage[], options?: ChatWithToolsOptions): Promise<AIResult>;
130
+ chatWithTools(messages: ModelMessage[], options?: ChatWithToolsOptions): Promise<AIResult>;
119
131
  /**
120
132
  * Stream chat with automatic tool call resolution.
121
133
  *
@@ -123,7 +135,7 @@ declare class AIService implements IAIService {
123
135
  * requests tool calls during streaming, they are executed and the results
124
136
  * fed back until a final text stream is produced.
125
137
  */
126
- streamChatWithTools(messages: AIMessage[], options?: ChatWithToolsOptions): AsyncIterable<AIStreamEvent>;
138
+ streamChatWithTools(messages: ModelMessage[], options?: ChatWithToolsOptions): AsyncIterable<TextStreamPart<ToolSet>>;
127
139
  }
128
140
 
129
141
  /**
@@ -168,6 +180,19 @@ declare class AIServicePlugin implements Plugin {
168
180
  private service?;
169
181
  private readonly options;
170
182
  constructor(options?: AIServicePluginOptions);
183
+ /**
184
+ * Auto-detect LLM provider from environment variables.
185
+ *
186
+ * Priority order:
187
+ * 1. AI_GATEWAY_MODEL → Vercel AI Gateway
188
+ * 2. OPENAI_API_KEY → OpenAI
189
+ * 3. ANTHROPIC_API_KEY → Anthropic
190
+ * 4. GOOGLE_GENERATIVE_AI_API_KEY → Google
191
+ * 5. Fallback → MemoryLLMAdapter
192
+ *
193
+ * Returns the adapter and a description for logging.
194
+ */
195
+ private detectAdapter;
171
196
  init(ctx: PluginContext): Promise<void>;
172
197
  start(ctx: PluginContext): Promise<void>;
173
198
  destroy(): Promise<void>;
@@ -181,13 +206,81 @@ declare class AIServicePlugin implements Plugin {
181
206
  */
182
207
  declare class MemoryLLMAdapter implements LLMAdapter {
183
208
  readonly name = "memory";
184
- chat(messages: AIMessage[], options?: AIRequestOptions): Promise<AIResult>;
209
+ chat(messages: ModelMessage[], options?: AIRequestOptions): Promise<AIResult>;
185
210
  complete(prompt: string, options?: AIRequestOptions): Promise<AIResult>;
186
- streamChat(messages: AIMessage[], _options?: AIRequestOptions): AsyncIterable<AIStreamEvent>;
211
+ streamChat(messages: ModelMessage[], _options?: AIRequestOptions): AsyncIterable<TextStreamPart<ToolSet>>;
187
212
  embed(input: string | string[]): Promise<number[][]>;
188
213
  listModels(): Promise<string[]>;
189
214
  }
190
215
 
216
+ /**
217
+ * VercelLLMAdapter — Production LLM adapter powered by the Vercel AI SDK.
218
+ *
219
+ * Wraps `generateText` / `streamText` from the `ai` package, delegating to
220
+ * any Vercel AI SDK–compatible model provider (OpenAI, Anthropic, Google,
221
+ * Ollama, etc.).
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * import { openai } from '@ai-sdk/openai';
226
+ * import { VercelLLMAdapter } from '@objectstack/service-ai';
227
+ *
228
+ * const adapter = new VercelLLMAdapter({ model: openai('gpt-4o') });
229
+ * ```
230
+ */
231
+ declare class VercelLLMAdapter implements LLMAdapter {
232
+ readonly name = "vercel";
233
+ private readonly model;
234
+ constructor(config: VercelLLMAdapterConfig);
235
+ chat(messages: ModelMessage[], options?: AIRequestOptions): Promise<AIResult>;
236
+ complete(prompt: string, options?: AIRequestOptions): Promise<AIResult>;
237
+ streamChat(messages: ModelMessage[], options?: AIRequestOptions): AsyncIterable<TextStreamPart<ToolSet>>;
238
+ embed(_input: string | string[]): Promise<number[][]>;
239
+ listModels(): Promise<string[]>;
240
+ }
241
+ /**
242
+ * Configuration for the Vercel LLM adapter.
243
+ */
244
+ interface VercelLLMAdapterConfig {
245
+ /**
246
+ * A Vercel AI SDK–compatible language model instance.
247
+ *
248
+ * @example `openai('gpt-4o')` or `anthropic('claude-sonnet-4-20250514')`
249
+ */
250
+ model: LanguageModelV2;
251
+ }
252
+
253
+ /**
254
+ * Vercel AI SDK v6 — UI Message Stream Encoder
255
+ *
256
+ * Converts `AsyncIterable<TextStreamPart<ToolSet>>` (the internal ObjectStack
257
+ * streaming format) into the Vercel AI SDK v6 **UI Message Stream Protocol**.
258
+ *
259
+ * Wire format: Server-Sent Events (SSE) with JSON payloads.
260
+ * `data: {"type":"text-delta","id":"0","delta":"Hello"}\n\n`
261
+ *
262
+ * The client-side `DefaultChatTransport` from `ai` v6 uses
263
+ * `parseJsonEventStream` to parse these SSE events.
264
+ *
265
+ * @see https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol
266
+ */
267
+
268
+ /**
269
+ * Encode a single `TextStreamPart` event into SSE-formatted UI Message
270
+ * Stream chunk(s).
271
+ *
272
+ * Returns an empty string for event types that have no wire-format mapping.
273
+ */
274
+ declare function encodeStreamPart(part: TextStreamPart$1<ToolSet$1>): string;
275
+ /**
276
+ * Transform an `AsyncIterable<TextStreamPart>` into an `AsyncIterable<string>`
277
+ * where each yielded string is an SSE-formatted UI Message Stream chunk.
278
+ *
279
+ * Lifecycle order required by the client:
280
+ * start → start-step → text-start → text-delta* → text-end → finish-step → finish → [DONE]
281
+ */
282
+ declare function encodeVercelDataStream(events: AsyncIterable<TextStreamPart$1<ToolSet$1>>): AsyncIterable<string>;
283
+
191
284
  /**
192
285
  * InMemoryConversationService — Reference implementation of IAIConversationService.
193
286
  *
@@ -211,7 +304,7 @@ declare class InMemoryConversationService implements IAIConversationService {
211
304
  limit?: number;
212
305
  cursor?: string;
213
306
  }): Promise<AIConversation[]>;
214
- addMessage(conversationId: string, message: AIMessage): Promise<AIConversation>;
307
+ addMessage(conversationId: string, message: ModelMessage): Promise<AIConversation>;
215
308
  delete(conversationId: string): Promise<void>;
216
309
  /** Total number of stored conversations. */
217
310
  get size(): number;
@@ -245,7 +338,7 @@ declare class ObjectQLConversationService implements IAIConversationService {
245
338
  limit?: number;
246
339
  cursor?: string;
247
340
  }): Promise<AIConversation[]>;
248
- addMessage(conversationId: string, message: AIMessage): Promise<AIConversation>;
341
+ addMessage(conversationId: string, message: ModelMessage): Promise<AIConversation>;
249
342
  delete(conversationId: string): Promise<void>;
250
343
  /**
251
344
  * Safely parse a JSON string, returning `undefined` on failure.
@@ -256,7 +349,7 @@ declare class ObjectQLConversationService implements IAIConversationService {
256
349
  */
257
350
  private toConversation;
258
351
  /**
259
- * Map a database row to an AIMessage.
352
+ * Map a database row to a ModelMessage.
260
353
  */
261
354
  private toMessage;
262
355
  }
@@ -270,28 +363,175 @@ declare class ObjectQLConversationService implements IAIConversationService {
270
363
  interface DataToolContext {
271
364
  /** ObjectQL data engine for record-level operations. */
272
365
  dataEngine: IDataEngine;
273
- /** Metadata service for schema/object introspection. */
274
- metadataService: IMetadataService;
275
366
  }
276
- /** All built-in data tool definitions. */
367
+ /** All built-in data tools definitions. */
277
368
  declare const DATA_TOOL_DEFINITIONS: AIToolDefinition[];
278
369
  /**
279
370
  * Register all built-in data tools on the given {@link ToolRegistry}.
280
371
  *
281
- * Typically called from the `ai:ready` hook after both the data engine
282
- * and metadata service are available.
372
+ * Typically called from the `ai:ready` hook after the data engine is available.
283
373
  *
284
374
  * @example
285
375
  * ```ts
286
376
  * ctx.hook('ai:ready', async (aiService) => {
287
377
  * const dataEngine = ctx.getService<IDataEngine>('data');
288
- * const metadataService = ctx.getService<IMetadataService>('metadata');
289
- * registerDataTools(aiService.toolRegistry, { dataEngine, metadataService });
378
+ * registerDataTools(aiService.toolRegistry, { dataEngine });
290
379
  * });
291
380
  * ```
292
381
  */
293
382
  declare function registerDataTools(registry: ToolRegistry, context: DataToolContext): void;
294
383
 
384
+ /**
385
+ * create_object — AI Tool Metadata
386
+ *
387
+ * Creates a new data object (table) with schema validation.
388
+ * Validates snake_case naming for object and initial fields,
389
+ * checks for duplicates, and registers the object definition.
390
+ */
391
+ declare const createObjectTool: {
392
+ name: string;
393
+ label: string;
394
+ description: string;
395
+ parameters: Record<string, unknown>;
396
+ requiresConfirmation: boolean;
397
+ active: boolean;
398
+ builtIn: boolean;
399
+ category?: "action" | "flow" | "vector_search" | "data" | "utility" | "integration" | "analytics" | undefined;
400
+ outputSchema?: Record<string, unknown> | undefined;
401
+ objectName?: string | undefined;
402
+ permissions?: string[] | undefined;
403
+ };
404
+
405
+ /**
406
+ * add_field — AI Tool Metadata
407
+ *
408
+ * Adds a new field (column) to an existing data object.
409
+ * Validates snake_case for objectName, field name, reference,
410
+ * and select option values before merging into the definition.
411
+ */
412
+ declare const addFieldTool: {
413
+ name: string;
414
+ label: string;
415
+ description: string;
416
+ parameters: Record<string, unknown>;
417
+ requiresConfirmation: boolean;
418
+ active: boolean;
419
+ builtIn: boolean;
420
+ category?: "action" | "flow" | "vector_search" | "data" | "utility" | "integration" | "analytics" | undefined;
421
+ outputSchema?: Record<string, unknown> | undefined;
422
+ objectName?: string | undefined;
423
+ permissions?: string[] | undefined;
424
+ };
425
+
426
+ /**
427
+ * modify_field — AI Tool Metadata
428
+ *
429
+ * Modifies an existing field definition (label, type, required, default value, etc.)
430
+ * on a data object. Does not support renaming the field.
431
+ */
432
+ declare const modifyFieldTool: {
433
+ name: string;
434
+ label: string;
435
+ description: string;
436
+ parameters: Record<string, unknown>;
437
+ requiresConfirmation: boolean;
438
+ active: boolean;
439
+ builtIn: boolean;
440
+ category?: "action" | "flow" | "vector_search" | "data" | "utility" | "integration" | "analytics" | undefined;
441
+ outputSchema?: Record<string, unknown> | undefined;
442
+ objectName?: string | undefined;
443
+ permissions?: string[] | undefined;
444
+ };
445
+
446
+ /**
447
+ * delete_field — AI Tool Metadata
448
+ *
449
+ * Removes a field (column) from an existing data object.
450
+ * This is a destructive operation.
451
+ */
452
+ declare const deleteFieldTool: {
453
+ name: string;
454
+ label: string;
455
+ description: string;
456
+ parameters: Record<string, unknown>;
457
+ requiresConfirmation: boolean;
458
+ active: boolean;
459
+ builtIn: boolean;
460
+ category?: "action" | "flow" | "vector_search" | "data" | "utility" | "integration" | "analytics" | undefined;
461
+ outputSchema?: Record<string, unknown> | undefined;
462
+ objectName?: string | undefined;
463
+ permissions?: string[] | undefined;
464
+ };
465
+
466
+ /**
467
+ * list_objects — AI Tool Metadata
468
+ *
469
+ * Lists all registered data objects (tables) with optional filtering
470
+ * and field summaries. This is the single, unified tool for listing
471
+ * objects — used by both data_chat and metadata_assistant agents.
472
+ */
473
+ declare const listObjectsTool: {
474
+ name: string;
475
+ label: string;
476
+ description: string;
477
+ parameters: Record<string, unknown>;
478
+ requiresConfirmation: boolean;
479
+ active: boolean;
480
+ builtIn: boolean;
481
+ category?: "action" | "flow" | "vector_search" | "data" | "utility" | "integration" | "analytics" | undefined;
482
+ outputSchema?: Record<string, unknown> | undefined;
483
+ objectName?: string | undefined;
484
+ permissions?: string[] | undefined;
485
+ };
486
+
487
+ /**
488
+ * describe_object — AI Tool Metadata
489
+ *
490
+ * Returns the full schema of a data object including all fields, types,
491
+ * relationships, and configuration. This is the single, unified tool for
492
+ * describing objects — used by both data_chat and metadata_assistant agents.
493
+ */
494
+ declare const describeObjectTool: {
495
+ name: string;
496
+ label: string;
497
+ description: string;
498
+ parameters: Record<string, unknown>;
499
+ requiresConfirmation: boolean;
500
+ active: boolean;
501
+ builtIn: boolean;
502
+ category?: "action" | "flow" | "vector_search" | "data" | "utility" | "integration" | "analytics" | undefined;
503
+ outputSchema?: Record<string, unknown> | undefined;
504
+ objectName?: string | undefined;
505
+ permissions?: string[] | undefined;
506
+ };
507
+
508
+ /** All built-in metadata management tool definitions (Tool metadata). */
509
+ declare const METADATA_TOOL_DEFINITIONS: Tool[];
510
+ /**
511
+ * Services required by the metadata management tools.
512
+ *
513
+ * Provided by the kernel at `ai:ready` time and closed over
514
+ * by the handler functions so they stay framework-agnostic.
515
+ */
516
+ interface MetadataToolContext {
517
+ /** Metadata service for schema CRUD operations. */
518
+ metadataService: IMetadataService;
519
+ }
520
+ /**
521
+ * Register all built-in metadata management tools on the given {@link ToolRegistry}.
522
+ *
523
+ * Typically called from the `ai:ready` hook after the metadata service is available.
524
+ *
525
+ * @example
526
+ * ```ts
527
+ * ctx.hook('ai:ready', async (aiService) => {
528
+ * const metadataService = ctx.getService<IMetadataService>('metadata');
529
+ * registerMetadataTools(aiService.toolRegistry, { metadataService });
530
+ * });
531
+ * ```
532
+ */
533
+ declare function registerMetadataTools(registry: ToolRegistry, context: MetadataToolContext): void;
534
+
295
535
  /**
296
536
  * Context passed alongside a user message when chatting with an agent.
297
537
  *
@@ -320,6 +560,17 @@ interface AgentChatContext {
320
560
  declare class AgentRuntime {
321
561
  private readonly metadataService;
322
562
  constructor(metadataService: IMetadataService);
563
+ /**
564
+ * List all active agents registered in the metadata service.
565
+ *
566
+ * Returns a summary for each agent (name, label, role) suitable
567
+ * for populating an agent selector dropdown in the UI.
568
+ */
569
+ listAgents(): Promise<Array<{
570
+ name: string;
571
+ label: string;
572
+ role: string;
573
+ }>>;
323
574
  /**
324
575
  * Load and validate an agent definition by name.
325
576
  *
@@ -333,7 +584,7 @@ declare class AgentRuntime {
333
584
  * Build the system message(s) that should be prepended to the
334
585
  * conversation when chatting with the given agent.
335
586
  */
336
- buildSystemMessages(agent: Agent, context?: AgentChatContext): AIMessage[];
587
+ buildSystemMessages(agent: Agent, context?: AgentChatContext): ModelMessage[];
337
588
  /**
338
589
  * Derive {@link AIRequestOptions} from an agent definition.
339
590
  *
@@ -368,6 +619,27 @@ declare class AgentRuntime {
368
619
  */
369
620
  declare const DATA_CHAT_AGENT: Agent;
370
621
 
622
+ /**
623
+ * Built-in `metadata_assistant` agent definition.
624
+ *
625
+ * This agent powers AI-driven metadata management — users can create objects,
626
+ * add/modify/delete fields, and inspect schema definitions through natural
627
+ * language conversation.
628
+ *
629
+ * It is registered automatically by the AI service plugin alongside the
630
+ * `data_chat` agent when the metadata service is available.
631
+ *
632
+ * @example
633
+ * ```
634
+ * POST /api/v1/ai/agents/metadata_assistant/chat
635
+ * {
636
+ * "messages": [{ "role": "user", "content": "Create a contracts table with name, value, and status fields" }],
637
+ * "context": {}
638
+ * }
639
+ * ```
640
+ */
641
+ declare const METADATA_ASSISTANT_AGENT: Agent;
642
+
371
643
  /**
372
644
  * XState-inspired State Machine Protocol
373
645
  * Used to define strict business logic constraints and lifecycle management.
@@ -431,7 +703,7 @@ declare const AiConversationObject: Omit<{
431
703
  abstract: boolean;
432
704
  datasource: string;
433
705
  fields: Record<string, {
434
- type: "number" | "boolean" | "file" | "json" | "text" | "avatar" | "vector" | "date" | "tags" | "lookup" | "url" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress";
706
+ type: "number" | "boolean" | "file" | "text" | "json" | "code" | "avatar" | "vector" | "date" | "tags" | "lookup" | "url" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress";
435
707
  required: boolean;
436
708
  searchable: boolean;
437
709
  multiple: boolean;
@@ -615,7 +887,7 @@ declare const AiConversationObject: Omit<{
615
887
  } | undefined;
616
888
  versioning?: {
617
889
  enabled: boolean;
618
- strategy: "snapshot" | "delta" | "event-sourcing";
890
+ strategy: "delta" | "snapshot" | "event-sourcing";
619
891
  versionField: string;
620
892
  retentionDays?: number | undefined;
621
893
  } | undefined;
@@ -691,12 +963,8 @@ declare const AiConversationObject: Omit<{
691
963
  keyPrefix?: string | undefined;
692
964
  actions?: {
693
965
  name: string;
694
- label: string | {
695
- key: string;
696
- defaultValue?: string | undefined;
697
- params?: Record<string, string | number | boolean> | undefined;
698
- };
699
- type: "url" | "script" | "modal" | "flow" | "api";
966
+ label: string;
967
+ type: "url" | "flow" | "api" | "script" | "modal";
700
968
  refreshAfter: boolean;
701
969
  objectName?: string | undefined;
702
970
  icon?: string | undefined;
@@ -706,44 +974,24 @@ declare const AiConversationObject: Omit<{
706
974
  execute?: string | undefined;
707
975
  params?: {
708
976
  name: string;
709
- label: string | {
710
- key: string;
711
- defaultValue?: string | undefined;
712
- params?: Record<string, string | number | boolean> | undefined;
713
- };
977
+ label: string;
714
978
  type: "number" | "boolean" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector";
715
979
  required: boolean;
716
980
  options?: {
717
- label: string | {
718
- key: string;
719
- defaultValue?: string | undefined;
720
- params?: Record<string, string | number | boolean> | undefined;
721
- };
981
+ label: string;
722
982
  value: string;
723
983
  }[] | undefined;
724
984
  }[] | undefined;
725
985
  variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | undefined;
726
- confirmText?: string | {
727
- key: string;
728
- defaultValue?: string | undefined;
729
- params?: Record<string, string | number | boolean> | undefined;
730
- } | undefined;
731
- successMessage?: string | {
732
- key: string;
733
- defaultValue?: string | undefined;
734
- params?: Record<string, string | number | boolean> | undefined;
735
- } | undefined;
986
+ confirmText?: string | undefined;
987
+ successMessage?: string | undefined;
736
988
  visible?: string | undefined;
737
989
  disabled?: string | boolean | undefined;
738
990
  shortcut?: string | undefined;
739
991
  bulkEnabled?: boolean | undefined;
740
992
  timeout?: number | undefined;
741
993
  aria?: {
742
- ariaLabel?: string | {
743
- key: string;
744
- defaultValue?: string | undefined;
745
- params?: Record<string, string | number | boolean> | undefined;
746
- } | undefined;
994
+ ariaLabel?: string | undefined;
747
995
  ariaDescribedBy?: string | undefined;
748
996
  role?: string | undefined;
749
997
  } | undefined;
@@ -1896,7 +2144,7 @@ declare const AiMessageObject: Omit<{
1896
2144
  abstract: boolean;
1897
2145
  datasource: string;
1898
2146
  fields: Record<string, {
1899
- type: "number" | "boolean" | "file" | "json" | "text" | "avatar" | "vector" | "date" | "tags" | "lookup" | "url" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress";
2147
+ type: "number" | "boolean" | "file" | "text" | "json" | "code" | "avatar" | "vector" | "date" | "tags" | "lookup" | "url" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress";
1900
2148
  required: boolean;
1901
2149
  searchable: boolean;
1902
2150
  multiple: boolean;
@@ -2080,7 +2328,7 @@ declare const AiMessageObject: Omit<{
2080
2328
  } | undefined;
2081
2329
  versioning?: {
2082
2330
  enabled: boolean;
2083
- strategy: "snapshot" | "delta" | "event-sourcing";
2331
+ strategy: "delta" | "snapshot" | "event-sourcing";
2084
2332
  versionField: string;
2085
2333
  retentionDays?: number | undefined;
2086
2334
  } | undefined;
@@ -2156,12 +2404,8 @@ declare const AiMessageObject: Omit<{
2156
2404
  keyPrefix?: string | undefined;
2157
2405
  actions?: {
2158
2406
  name: string;
2159
- label: string | {
2160
- key: string;
2161
- defaultValue?: string | undefined;
2162
- params?: Record<string, string | number | boolean> | undefined;
2163
- };
2164
- type: "url" | "script" | "modal" | "flow" | "api";
2407
+ label: string;
2408
+ type: "url" | "flow" | "api" | "script" | "modal";
2165
2409
  refreshAfter: boolean;
2166
2410
  objectName?: string | undefined;
2167
2411
  icon?: string | undefined;
@@ -2171,44 +2415,24 @@ declare const AiMessageObject: Omit<{
2171
2415
  execute?: string | undefined;
2172
2416
  params?: {
2173
2417
  name: string;
2174
- label: string | {
2175
- key: string;
2176
- defaultValue?: string | undefined;
2177
- params?: Record<string, string | number | boolean> | undefined;
2178
- };
2418
+ label: string;
2179
2419
  type: "number" | "boolean" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector";
2180
2420
  required: boolean;
2181
2421
  options?: {
2182
- label: string | {
2183
- key: string;
2184
- defaultValue?: string | undefined;
2185
- params?: Record<string, string | number | boolean> | undefined;
2186
- };
2422
+ label: string;
2187
2423
  value: string;
2188
2424
  }[] | undefined;
2189
2425
  }[] | undefined;
2190
2426
  variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | undefined;
2191
- confirmText?: string | {
2192
- key: string;
2193
- defaultValue?: string | undefined;
2194
- params?: Record<string, string | number | boolean> | undefined;
2195
- } | undefined;
2196
- successMessage?: string | {
2197
- key: string;
2198
- defaultValue?: string | undefined;
2199
- params?: Record<string, string | number | boolean> | undefined;
2200
- } | undefined;
2427
+ confirmText?: string | undefined;
2428
+ successMessage?: string | undefined;
2201
2429
  visible?: string | undefined;
2202
2430
  disabled?: string | boolean | undefined;
2203
2431
  shortcut?: string | undefined;
2204
2432
  bulkEnabled?: boolean | undefined;
2205
2433
  timeout?: number | undefined;
2206
2434
  aria?: {
2207
- ariaLabel?: string | {
2208
- key: string;
2209
- defaultValue?: string | undefined;
2210
- params?: Record<string, string | number | boolean> | undefined;
2211
- } | undefined;
2435
+ ariaLabel?: string | undefined;
2212
2436
  ariaDescribedBy?: string | undefined;
2213
2437
  role?: string | undefined;
2214
2438
  } | undefined;
@@ -3401,6 +3625,14 @@ interface RouteResponse {
3401
3625
  stream?: boolean;
3402
3626
  /** Async iterable of SSE events (when stream=true) */
3403
3627
  events?: AsyncIterable<unknown>;
3628
+ /**
3629
+ * When `true`, the HTTP server layer should encode the `events` iterable
3630
+ * using the Vercel AI Data Stream Protocol frame format (`0:`, `9:`, `d:`, …)
3631
+ * instead of generic SSE `data:` lines.
3632
+ *
3633
+ * @see https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol
3634
+ */
3635
+ vercelDataStream?: boolean;
3404
3636
  }
3405
3637
  /**
3406
3638
  * Build the standard AI REST/SSE routes.
@@ -3428,8 +3660,19 @@ declare function buildAIRoutes(aiService: IAIService, conversationService: IAICo
3428
3660
  *
3429
3661
  * | Method | Path | Description |
3430
3662
  * |:---|:---|:---|
3663
+ * | GET | /api/v1/ai/agents | List all active agents |
3431
3664
  * | POST | /api/v1/ai/agents/:agentName/chat | Chat with a specific agent |
3432
3665
  */
3433
3666
  declare function buildAgentRoutes(aiService: AIService, agentRuntime: AgentRuntime, logger: Logger): RouteDefinition[];
3434
3667
 
3435
- export { AIService, type AIServiceConfig, AIServicePlugin, type AIServicePluginOptions, type AgentChatContext, AgentRuntime, AiConversationObject, AiMessageObject, DATA_CHAT_AGENT, DATA_TOOL_DEFINITIONS, type DataToolContext, InMemoryConversationService, MemoryLLMAdapter, ObjectQLConversationService, type RouteDefinition, type RouteRequest, type RouteResponse, type RouteUserContext, type ToolHandler, ToolRegistry, buildAIRoutes, buildAgentRoutes, registerDataTools };
3668
+ /**
3669
+ * Build tool-specific REST routes.
3670
+ *
3671
+ * | Method | Path | Description |
3672
+ * |:---|:---|:---|
3673
+ * | GET | /api/v1/ai/tools | List all registered tools |
3674
+ * | POST | /api/v1/ai/tools/:toolName/execute | Execute a tool with parameters |
3675
+ */
3676
+ declare function buildToolRoutes(aiService: AIService, logger: Logger): RouteDefinition[];
3677
+
3678
+ export { AIService, type AIServiceConfig, AIServicePlugin, type AIServicePluginOptions, type AgentChatContext, AgentRuntime, AiConversationObject, AiMessageObject, DATA_CHAT_AGENT, DATA_TOOL_DEFINITIONS, type DataToolContext, InMemoryConversationService, METADATA_ASSISTANT_AGENT, METADATA_TOOL_DEFINITIONS, MemoryLLMAdapter, type MetadataToolContext, ObjectQLConversationService, type RouteDefinition, type RouteRequest, type RouteResponse, type RouteUserContext, type ToolExecutionResult, type ToolHandler, ToolRegistry, VercelLLMAdapter, type VercelLLMAdapterConfig, addFieldTool, buildAIRoutes, buildAgentRoutes, buildToolRoutes, createObjectTool, deleteFieldTool, describeObjectTool, encodeStreamPart, encodeVercelDataStream, listObjectsTool, modifyFieldTool, registerDataTools, registerMetadataTools };