@objectstack/service-ai 4.0.3 → 4.0.5

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 (52) hide show
  1. package/README.md +293 -0
  2. package/dist/index.cjs +1176 -135
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1225 -430
  5. package/dist/index.d.ts +1225 -430
  6. package/dist/index.js +1160 -128
  7. package/dist/index.js.map +1 -1
  8. package/package.json +35 -8
  9. package/.turbo/turbo-build.log +0 -22
  10. package/CHANGELOG.md +0 -53
  11. package/src/__tests__/ai-service.test.ts +0 -964
  12. package/src/__tests__/auth-and-toolcalling.test.ts +0 -677
  13. package/src/__tests__/chatbot-features.test.ts +0 -1116
  14. package/src/__tests__/metadata-tools.test.ts +0 -970
  15. package/src/__tests__/objectql-conversation-service.test.ts +0 -382
  16. package/src/__tests__/tool-routes.test.ts +0 -191
  17. package/src/__tests__/vercel-stream-encoder.test.ts +0 -310
  18. package/src/adapters/index.ts +0 -6
  19. package/src/adapters/memory-adapter.ts +0 -72
  20. package/src/adapters/types.ts +0 -3
  21. package/src/adapters/vercel-adapter.ts +0 -148
  22. package/src/agent-runtime.ts +0 -154
  23. package/src/agents/data-chat-agent.ts +0 -79
  24. package/src/agents/index.ts +0 -4
  25. package/src/agents/metadata-assistant-agent.ts +0 -87
  26. package/src/ai-service.ts +0 -364
  27. package/src/conversation/in-memory-conversation-service.ts +0 -103
  28. package/src/conversation/index.ts +0 -4
  29. package/src/conversation/objectql-conversation-service.ts +0 -301
  30. package/src/index.ts +0 -60
  31. package/src/objects/ai-conversation.object.ts +0 -86
  32. package/src/objects/ai-message.object.ts +0 -86
  33. package/src/objects/index.ts +0 -10
  34. package/src/plugin.ts +0 -391
  35. package/src/routes/agent-routes.ts +0 -190
  36. package/src/routes/ai-routes.ts +0 -439
  37. package/src/routes/index.ts +0 -5
  38. package/src/routes/message-utils.ts +0 -90
  39. package/src/routes/tool-routes.ts +0 -142
  40. package/src/stream/index.ts +0 -3
  41. package/src/stream/vercel-stream-encoder.ts +0 -153
  42. package/src/tools/add-field.tool.ts +0 -70
  43. package/src/tools/create-object.tool.ts +0 -66
  44. package/src/tools/data-tools.ts +0 -293
  45. package/src/tools/delete-field.tool.ts +0 -38
  46. package/src/tools/describe-object.tool.ts +0 -31
  47. package/src/tools/index.ts +0 -18
  48. package/src/tools/list-objects.tool.ts +0 -34
  49. package/src/tools/metadata-tools.ts +0 -430
  50. package/src/tools/modify-field.tool.ts +0 -44
  51. package/src/tools/tool-registry.ts +0 -132
  52. package/tsconfig.json +0 -17
@@ -1,34 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { defineTool } from '@objectstack/spec/ai';
4
-
5
- /**
6
- * list_objects — AI Tool Metadata
7
- *
8
- * Lists all registered data objects (tables) with optional filtering
9
- * and field summaries. This is the single, unified tool for listing
10
- * objects — used by both data_chat and metadata_assistant agents.
11
- */
12
- export const listObjectsTool = defineTool({
13
- name: 'list_objects',
14
- label: 'List Objects',
15
- description:
16
- 'Lists all registered data objects (tables) in the current environment. ' +
17
- 'Use this when the user wants to see what tables, entities, or data models are available.',
18
- category: 'data',
19
- builtIn: true,
20
- parameters: {
21
- type: 'object',
22
- properties: {
23
- filter: {
24
- type: 'string',
25
- description: 'Optional name or label substring to filter objects',
26
- },
27
- includeFields: {
28
- type: 'boolean',
29
- description: 'Whether to include field summaries for each object (default: false)',
30
- },
31
- },
32
- additionalProperties: false,
33
- },
34
- });
@@ -1,430 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import type { IMetadataService } from '@objectstack/spec/contracts';
4
- import type { Tool } from '@objectstack/spec/ai';
5
- import type { ToolHandler } from './tool-registry.js';
6
- import type { ToolRegistry } from './tool-registry.js';
7
-
8
- // ---------------------------------------------------------------------------
9
- // Tool Metadata — individual .tool.ts files (single source of truth)
10
- // ---------------------------------------------------------------------------
11
-
12
- export { createObjectTool } from './create-object.tool.js';
13
- export { addFieldTool } from './add-field.tool.js';
14
- export { modifyFieldTool } from './modify-field.tool.js';
15
- export { deleteFieldTool } from './delete-field.tool.js';
16
- export { listObjectsTool } from './list-objects.tool.js';
17
- export { describeObjectTool } from './describe-object.tool.js';
18
-
19
- import { createObjectTool } from './create-object.tool.js';
20
- import { addFieldTool } from './add-field.tool.js';
21
- import { modifyFieldTool } from './modify-field.tool.js';
22
- import { deleteFieldTool } from './delete-field.tool.js';
23
- import { listObjectsTool } from './list-objects.tool.js';
24
- import { describeObjectTool } from './describe-object.tool.js';
25
-
26
- /** All built-in metadata management tool definitions (Tool metadata). */
27
- export const METADATA_TOOL_DEFINITIONS: Tool[] = [
28
- createObjectTool,
29
- addFieldTool,
30
- modifyFieldTool,
31
- deleteFieldTool,
32
- listObjectsTool,
33
- describeObjectTool,
34
- ];
35
-
36
- // ---------------------------------------------------------------------------
37
- // Internal type aliases for metadata payloads (returned as `unknown` from
38
- // IMetadataService — we cast to these lightweight shapes for field access).
39
- // ---------------------------------------------------------------------------
40
-
41
- /** Minimal shape of an object definition as returned by IMetadataService. */
42
- interface ObjectDef {
43
- name: string;
44
- label?: string;
45
- fields?: Record<string, FieldDef>;
46
- enable?: Record<string, boolean>;
47
- }
48
-
49
- /** Minimal shape of a field definition inside an object. */
50
- interface FieldDef {
51
- name?: string;
52
- type?: string;
53
- label?: string;
54
- required?: boolean;
55
- reference?: string;
56
- options?: unknown;
57
- defaultValue?: unknown;
58
- }
59
-
60
- // ---------------------------------------------------------------------------
61
- // Shared validation helpers
62
- // ---------------------------------------------------------------------------
63
-
64
- /** snake_case identifier pattern (e.g. `project_task`, `due_date`). */
65
- const SNAKE_CASE_RE = /^[a-z_][a-z0-9_]*$/;
66
-
67
- /** Validate that a value matches snake_case. */
68
- function isSnakeCase(value: string): boolean {
69
- return SNAKE_CASE_RE.test(value);
70
- }
71
-
72
- // ---------------------------------------------------------------------------
73
- // Context — injected once at registration time
74
- // ---------------------------------------------------------------------------
75
-
76
- /**
77
- * Services required by the metadata management tools.
78
- *
79
- * Provided by the kernel at `ai:ready` time and closed over
80
- * by the handler functions so they stay framework-agnostic.
81
- */
82
- export interface MetadataToolContext {
83
- /** Metadata service for schema CRUD operations. */
84
- metadataService: IMetadataService;
85
- }
86
-
87
- // ---------------------------------------------------------------------------
88
- // Handler Factories
89
- // ---------------------------------------------------------------------------
90
-
91
- function createCreateObjectHandler(ctx: MetadataToolContext): ToolHandler {
92
- return async (args) => {
93
- const { name, label, fields, enableFeatures } = args as {
94
- name: string;
95
- label: string;
96
- fields?: Array<{ name: string; label?: string; type: string; required?: boolean }>;
97
- enableFeatures?: Record<string, boolean>;
98
- };
99
-
100
- if (!name || !label) {
101
- return JSON.stringify({ error: 'Both "name" and "label" are required' });
102
- }
103
-
104
- // Validate snake_case name
105
- if (!isSnakeCase(name)) {
106
- return JSON.stringify({ error: `Invalid object name "${name}". Must be snake_case.` });
107
- }
108
-
109
- // Check if the object already exists
110
- const existing = await ctx.metadataService.getObject(name);
111
- if (existing) {
112
- return JSON.stringify({ error: `Object "${name}" already exists` });
113
- }
114
-
115
- // Build field map from array input with per-field validation
116
- const fieldMap: Record<string, Record<string, unknown>> = {};
117
- if (fields && Array.isArray(fields)) {
118
- const seenNames = new Set<string>();
119
- for (const f of fields) {
120
- if (!f.name) {
121
- return JSON.stringify({ error: 'Each field must have a "name" property' });
122
- }
123
- if (!isSnakeCase(f.name)) {
124
- return JSON.stringify({ error: `Invalid field name "${f.name}". Must be snake_case.` });
125
- }
126
- if (seenNames.has(f.name)) {
127
- return JSON.stringify({ error: `Duplicate field name "${f.name}" in initial fields` });
128
- }
129
- seenNames.add(f.name);
130
- fieldMap[f.name] = {
131
- type: f.type,
132
- ...(f.label ? { label: f.label } : {}),
133
- ...(f.required !== undefined ? { required: f.required } : {}),
134
- };
135
- }
136
- }
137
-
138
- const objectDef: Record<string, unknown> = {
139
- name,
140
- label,
141
- ...(Object.keys(fieldMap).length > 0 ? { fields: fieldMap } : {}),
142
- ...(enableFeatures ? { enable: enableFeatures } : {}),
143
- };
144
-
145
- await ctx.metadataService.register('object', name, objectDef);
146
-
147
- return JSON.stringify({
148
- name,
149
- label,
150
- fieldCount: Object.keys(fieldMap).length,
151
- });
152
- };
153
- }
154
-
155
- function createAddFieldHandler(ctx: MetadataToolContext): ToolHandler {
156
- return async (args) => {
157
- const { objectName, name, label, type, required, defaultValue, options, reference } = args as {
158
- objectName: string;
159
- name: string;
160
- label?: string;
161
- type: string;
162
- required?: boolean;
163
- defaultValue?: unknown;
164
- options?: Array<{ label: string; value: string }>;
165
- reference?: string;
166
- };
167
-
168
- if (!objectName || !name || !type) {
169
- return JSON.stringify({ error: '"objectName", "name", and "type" are required' });
170
- }
171
-
172
- // Validate snake_case names
173
- if (!isSnakeCase(objectName)) {
174
- return JSON.stringify({ error: `Invalid object name "${objectName}". Must be snake_case.` });
175
- }
176
- if (!isSnakeCase(name)) {
177
- return JSON.stringify({ error: `Invalid field name "${name}". Must be snake_case.` });
178
- }
179
-
180
- // Validate reference as snake_case if provided
181
- if (reference && !isSnakeCase(reference)) {
182
- return JSON.stringify({ error: `Invalid reference "${reference}". Must be a snake_case object name.` });
183
- }
184
-
185
- // Validate select option values as snake_case if provided
186
- if (options && Array.isArray(options)) {
187
- for (const opt of options) {
188
- if (opt.value && !isSnakeCase(opt.value)) {
189
- return JSON.stringify({ error: `Invalid option value "${opt.value}". Must be lowercase snake_case.` });
190
- }
191
- }
192
- }
193
-
194
- // Verify the target object exists
195
- const objectDef = await ctx.metadataService.getObject(objectName);
196
- if (!objectDef) {
197
- return JSON.stringify({ error: `Object "${objectName}" not found` });
198
- }
199
-
200
- // Check if field already exists
201
- const def = objectDef as ObjectDef;
202
- if (def.fields && def.fields[name]) {
203
- return JSON.stringify({ error: `Field "${name}" already exists on object "${objectName}"` });
204
- }
205
-
206
- // Build new field definition
207
- const fieldDef: Record<string, unknown> = {
208
- type,
209
- ...(label ? { label } : {}),
210
- ...(required !== undefined ? { required } : {}),
211
- ...(defaultValue !== undefined ? { defaultValue } : {}),
212
- ...(options ? { options } : {}),
213
- ...(reference ? { reference } : {}),
214
- };
215
-
216
- // Merge the new field into the existing object definition and re-register
217
- const updatedFields = { ...(def.fields ?? {}), [name]: fieldDef };
218
- await ctx.metadataService.register('object', objectName, {
219
- ...def,
220
- fields: updatedFields,
221
- });
222
-
223
- return JSON.stringify({
224
- objectName,
225
- fieldName: name,
226
- fieldType: type,
227
- });
228
- };
229
- }
230
-
231
- function createModifyFieldHandler(ctx: MetadataToolContext): ToolHandler {
232
- return async (args) => {
233
- const { objectName, fieldName, changes } = args as {
234
- objectName: string;
235
- fieldName: string;
236
- changes: Record<string, unknown>;
237
- };
238
-
239
- if (!objectName || !fieldName || !changes) {
240
- return JSON.stringify({ error: '"objectName", "fieldName", and "changes" are required' });
241
- }
242
-
243
- // Validate snake_case names
244
- if (!isSnakeCase(objectName)) {
245
- return JSON.stringify({ error: `Invalid object name "${objectName}". Must be snake_case.` });
246
- }
247
- if (!isSnakeCase(fieldName)) {
248
- return JSON.stringify({ error: `Invalid field name "${fieldName}". Must be snake_case.` });
249
- }
250
-
251
- // Verify the target object exists
252
- const objectDef = await ctx.metadataService.getObject(objectName);
253
- if (!objectDef) {
254
- return JSON.stringify({ error: `Object "${objectName}" not found` });
255
- }
256
-
257
- const def = objectDef as ObjectDef;
258
- if (!def.fields || !def.fields[fieldName]) {
259
- return JSON.stringify({ error: `Field "${fieldName}" not found on object "${objectName}"` });
260
- }
261
-
262
- // Apply changes to the field definition
263
- const existingField = def.fields[fieldName];
264
- const updatedField = { ...existingField, ...changes };
265
- const updatedFields = { ...def.fields, [fieldName]: updatedField };
266
-
267
- await ctx.metadataService.register('object', objectName, {
268
- ...def,
269
- fields: updatedFields,
270
- });
271
-
272
- return JSON.stringify({
273
- objectName,
274
- fieldName,
275
- updatedProperties: Object.keys(changes),
276
- });
277
- };
278
- }
279
-
280
- function createDeleteFieldHandler(ctx: MetadataToolContext): ToolHandler {
281
- return async (args) => {
282
- const { objectName, fieldName } = args as {
283
- objectName: string;
284
- fieldName: string;
285
- };
286
-
287
- if (!objectName || !fieldName) {
288
- return JSON.stringify({ error: '"objectName" and "fieldName" are required' });
289
- }
290
-
291
- // Validate snake_case names
292
- if (!isSnakeCase(objectName)) {
293
- return JSON.stringify({ error: `Invalid object name "${objectName}". Must be snake_case.` });
294
- }
295
- if (!isSnakeCase(fieldName)) {
296
- return JSON.stringify({ error: `Invalid field name "${fieldName}". Must be snake_case.` });
297
- }
298
-
299
- // Verify the target object exists
300
- const objectDef = await ctx.metadataService.getObject(objectName);
301
- if (!objectDef) {
302
- return JSON.stringify({ error: `Object "${objectName}" not found` });
303
- }
304
-
305
- const def = objectDef as ObjectDef;
306
- if (!def.fields || !def.fields[fieldName]) {
307
- return JSON.stringify({ error: `Field "${fieldName}" not found on object "${objectName}"` });
308
- }
309
-
310
- // Remove the field and re-register
311
- const { [fieldName]: _removed, ...remainingFields } = def.fields;
312
- await ctx.metadataService.register('object', objectName, {
313
- ...def,
314
- fields: remainingFields,
315
- });
316
-
317
- return JSON.stringify({
318
- objectName,
319
- fieldName,
320
- success: true,
321
- });
322
- };
323
- }
324
-
325
- function createListObjectsHandler(ctx: MetadataToolContext): ToolHandler {
326
- return async (args) => {
327
- const { filter, includeFields } = (args ?? {}) as {
328
- filter?: string;
329
- includeFields?: boolean;
330
- };
331
-
332
- const objects = await ctx.metadataService.listObjects();
333
- let result = (objects as ObjectDef[]).map(o => {
334
- const base: Record<string, unknown> = {
335
- name: o.name,
336
- label: o.label ?? o.name,
337
- fieldCount: o.fields ? Object.keys(o.fields).length : 0,
338
- };
339
- if (includeFields && o.fields) {
340
- base.fields = Object.entries(o.fields).map(([key, f]) => ({
341
- name: key,
342
- type: f.type,
343
- label: f.label ?? key,
344
- }));
345
- }
346
- return base;
347
- });
348
-
349
- // Apply optional name/label substring filter
350
- if (filter) {
351
- const lower = filter.toLowerCase();
352
- result = result.filter(o =>
353
- (o.name as string).toLowerCase().includes(lower) ||
354
- (o.label as string).toLowerCase().includes(lower),
355
- );
356
- }
357
-
358
- return JSON.stringify({
359
- objects: result,
360
- totalCount: result.length,
361
- });
362
- };
363
- }
364
-
365
- function createDescribeObjectHandler(ctx: MetadataToolContext): ToolHandler {
366
- return async (args) => {
367
- const { objectName } = args as { objectName: string };
368
-
369
- if (!objectName) {
370
- return JSON.stringify({ error: '"objectName" is required' });
371
- }
372
-
373
- // Validate snake_case name
374
- if (!isSnakeCase(objectName)) {
375
- return JSON.stringify({ error: `Invalid object name "${objectName}". Must be snake_case.` });
376
- }
377
-
378
- const objectDef = await ctx.metadataService.getObject(objectName);
379
- if (!objectDef) {
380
- return JSON.stringify({ error: `Object "${objectName}" not found` });
381
- }
382
-
383
- const def = objectDef as ObjectDef;
384
- const fields = def.fields ?? {};
385
- const fieldSummary = Object.entries(fields).map(([key, f]) => ({
386
- name: key,
387
- type: f.type,
388
- label: f.label ?? key,
389
- required: f.required ?? false,
390
- ...(f.reference ? { reference: f.reference } : {}),
391
- ...(f.options ? { options: f.options } : {}),
392
- }));
393
-
394
- return JSON.stringify({
395
- name: def.name,
396
- label: def.label ?? def.name,
397
- fields: fieldSummary,
398
- enableFeatures: def.enable ?? {},
399
- });
400
- };
401
- }
402
-
403
- // ---------------------------------------------------------------------------
404
- // Public Registration Helper
405
- // ---------------------------------------------------------------------------
406
-
407
- /**
408
- * Register all built-in metadata management tools on the given {@link ToolRegistry}.
409
- *
410
- * Typically called from the `ai:ready` hook after the metadata service is available.
411
- *
412
- * @example
413
- * ```ts
414
- * ctx.hook('ai:ready', async (aiService) => {
415
- * const metadataService = ctx.getService<IMetadataService>('metadata');
416
- * registerMetadataTools(aiService.toolRegistry, { metadataService });
417
- * });
418
- * ```
419
- */
420
- export function registerMetadataTools(
421
- registry: ToolRegistry,
422
- context: MetadataToolContext,
423
- ): void {
424
- registry.register(createObjectTool, createCreateObjectHandler(context));
425
- registry.register(addFieldTool, createAddFieldHandler(context));
426
- registry.register(modifyFieldTool, createModifyFieldHandler(context));
427
- registry.register(deleteFieldTool, createDeleteFieldHandler(context));
428
- registry.register(listObjectsTool, createListObjectsHandler(context));
429
- registry.register(describeObjectTool, createDescribeObjectHandler(context));
430
- }
@@ -1,44 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { defineTool } from '@objectstack/spec/ai';
4
-
5
- /**
6
- * modify_field — AI Tool Metadata
7
- *
8
- * Modifies an existing field definition (label, type, required, default value, etc.)
9
- * on a data object. Does not support renaming the field.
10
- */
11
- export const modifyFieldTool = defineTool({
12
- name: 'modify_field',
13
- label: 'Modify Field',
14
- description:
15
- 'Modifies an existing field definition (label, type, required, default value, etc.) on a data object. ' +
16
- 'Use this when the user wants to change or reconfigure an existing column or attribute (not rename it).',
17
- category: 'data',
18
- builtIn: true,
19
- parameters: {
20
- type: 'object',
21
- properties: {
22
- objectName: {
23
- type: 'string',
24
- description: 'Target object machine name (snake_case)',
25
- },
26
- fieldName: {
27
- type: 'string',
28
- description: 'Existing field machine name to modify (snake_case)',
29
- },
30
- changes: {
31
- type: 'object',
32
- description: 'Field properties to update (partial patch)',
33
- properties: {
34
- label: { type: 'string', description: 'New display label' },
35
- type: { type: 'string', description: 'New field type' },
36
- required: { type: 'boolean', description: 'Update required constraint' },
37
- defaultValue: { description: 'New default value' },
38
- },
39
- },
40
- },
41
- required: ['objectName', 'fieldName', 'changes'],
42
- additionalProperties: false,
43
- },
44
- });
@@ -1,132 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import type { AIToolDefinition, ToolCallPart, ToolResultPart } from '@objectstack/spec/contracts';
4
-
5
- /**
6
- * Handler function for a registered tool.
7
- *
8
- * Receives parsed arguments and returns the tool output as a string.
9
- */
10
- export type ToolHandler = (args: Record<string, unknown>) => Promise<string> | string;
11
-
12
- /**
13
- * Extended ToolResultPart that carries an `isError` flag for internal
14
- * error-tracking in the tool-call loop.
15
- */
16
- export interface ToolExecutionResult extends ToolResultPart {
17
- isError?: boolean;
18
- }
19
-
20
- /**
21
- * ToolRegistry — Central registry for AI-callable tools.
22
- *
23
- * Plugins register tools (metadata helpers, data queries, business actions)
24
- * during the `ai:ready` hook. The AI service resolves tool calls against
25
- * this registry and feeds the results back to the LLM.
26
- */
27
- export class ToolRegistry {
28
- private readonly definitions = new Map<string, AIToolDefinition>();
29
- private readonly handlers = new Map<string, ToolHandler>();
30
-
31
- /**
32
- * Register a tool with its definition and handler.
33
- * @param definition - Tool definition (name, description, parameters schema)
34
- * @param handler - Async function that executes the tool
35
- */
36
- register(definition: AIToolDefinition, handler: ToolHandler): void {
37
- this.definitions.set(definition.name, definition);
38
- this.handlers.set(definition.name, handler);
39
- }
40
-
41
- /**
42
- * Unregister a tool by name.
43
- */
44
- unregister(name: string): void {
45
- this.definitions.delete(name);
46
- this.handlers.delete(name);
47
- }
48
-
49
- /**
50
- * Check whether a tool is registered.
51
- */
52
- has(name: string): boolean {
53
- return this.definitions.has(name);
54
- }
55
-
56
- /**
57
- * Get the definition for a registered tool.
58
- */
59
- getDefinition(name: string): AIToolDefinition | undefined {
60
- return this.definitions.get(name);
61
- }
62
-
63
- /**
64
- * Return all registered tool definitions.
65
- */
66
- getAll(): AIToolDefinition[] {
67
- return Array.from(this.definitions.values());
68
- }
69
-
70
- /** Number of registered tools. */
71
- get size(): number {
72
- return this.definitions.size;
73
- }
74
-
75
- /** All registered tool names. */
76
- names(): string[] {
77
- return Array.from(this.definitions.keys());
78
- }
79
-
80
- /**
81
- * Execute a tool call and return the result.
82
- */
83
- async execute(toolCall: ToolCallPart): Promise<ToolExecutionResult> {
84
- const handler = this.handlers.get(toolCall.toolName);
85
- if (!handler) {
86
- return {
87
- type: 'tool-result',
88
- toolCallId: toolCall.toolCallId,
89
- toolName: toolCall.toolName,
90
- output: { type: 'text', value: `Tool "${toolCall.toolName}" is not registered` },
91
- isError: true,
92
- };
93
- }
94
-
95
- try {
96
- const args = typeof toolCall.input === 'string'
97
- ? JSON.parse(toolCall.input)
98
- : (toolCall.input as Record<string, unknown>) ?? {};
99
- const content = await handler(args);
100
- return {
101
- type: 'tool-result',
102
- toolCallId: toolCall.toolCallId,
103
- toolName: toolCall.toolName,
104
- output: { type: 'text', value: content },
105
- };
106
- } catch (err) {
107
- const message = err instanceof Error ? err.message : String(err);
108
- return {
109
- type: 'tool-result',
110
- toolCallId: toolCall.toolCallId,
111
- toolName: toolCall.toolName,
112
- output: { type: 'text', value: message },
113
- isError: true,
114
- };
115
- }
116
- }
117
-
118
- /**
119
- * Execute multiple tool calls in parallel.
120
- */
121
- async executeAll(toolCalls: ToolCallPart[]): Promise<ToolExecutionResult[]> {
122
- return Promise.all(toolCalls.map(tc => this.execute(tc)));
123
- }
124
-
125
- /**
126
- * Clear all registered tools.
127
- */
128
- clear(): void {
129
- this.definitions.clear();
130
- this.handlers.clear();
131
- }
132
- }
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src",
6
- "types": [
7
- "node"
8
- ]
9
- },
10
- "include": [
11
- "src"
12
- ],
13
- "exclude": [
14
- "node_modules",
15
- "dist"
16
- ]
17
- }