confused-ai-core 0.1.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.
Files changed (114) hide show
  1. package/FEATURES.md +169 -0
  2. package/package.json +119 -0
  3. package/src/agent.ts +187 -0
  4. package/src/agentic/index.ts +87 -0
  5. package/src/agentic/runner.ts +386 -0
  6. package/src/agentic/types.ts +91 -0
  7. package/src/artifacts/artifact.ts +417 -0
  8. package/src/artifacts/index.ts +42 -0
  9. package/src/artifacts/media.ts +304 -0
  10. package/src/cli/index.ts +122 -0
  11. package/src/core/base-agent.ts +151 -0
  12. package/src/core/context-builder.ts +106 -0
  13. package/src/core/index.ts +8 -0
  14. package/src/core/schemas.ts +17 -0
  15. package/src/core/types.ts +158 -0
  16. package/src/create-agent.ts +309 -0
  17. package/src/debug-logger.ts +188 -0
  18. package/src/dx/agent.ts +88 -0
  19. package/src/dx/define-agent.ts +183 -0
  20. package/src/dx/dev-logger.ts +57 -0
  21. package/src/dx/index.ts +11 -0
  22. package/src/errors.ts +175 -0
  23. package/src/execution/engine.ts +522 -0
  24. package/src/execution/graph-builder.ts +362 -0
  25. package/src/execution/index.ts +8 -0
  26. package/src/execution/types.ts +257 -0
  27. package/src/execution/worker-pool.ts +308 -0
  28. package/src/extensions/index.ts +123 -0
  29. package/src/guardrails/allowlist.ts +155 -0
  30. package/src/guardrails/index.ts +17 -0
  31. package/src/guardrails/types.ts +159 -0
  32. package/src/guardrails/validator.ts +265 -0
  33. package/src/index.ts +74 -0
  34. package/src/knowledge/index.ts +5 -0
  35. package/src/knowledge/types.ts +52 -0
  36. package/src/learning/in-memory-store.ts +72 -0
  37. package/src/learning/index.ts +6 -0
  38. package/src/learning/types.ts +42 -0
  39. package/src/llm/cache.ts +300 -0
  40. package/src/llm/index.ts +22 -0
  41. package/src/llm/model-resolver.ts +81 -0
  42. package/src/llm/openai-provider.ts +313 -0
  43. package/src/llm/openrouter-provider.ts +29 -0
  44. package/src/llm/types.ts +131 -0
  45. package/src/memory/in-memory-store.ts +255 -0
  46. package/src/memory/index.ts +7 -0
  47. package/src/memory/types.ts +193 -0
  48. package/src/memory/vector-store.ts +251 -0
  49. package/src/observability/console-logger.ts +123 -0
  50. package/src/observability/index.ts +12 -0
  51. package/src/observability/metrics.ts +85 -0
  52. package/src/observability/otlp-exporter.ts +417 -0
  53. package/src/observability/tracer.ts +105 -0
  54. package/src/observability/types.ts +341 -0
  55. package/src/orchestration/agent-adapter.ts +33 -0
  56. package/src/orchestration/index.ts +34 -0
  57. package/src/orchestration/load-balancer.ts +151 -0
  58. package/src/orchestration/mcp-types.ts +59 -0
  59. package/src/orchestration/message-bus.ts +192 -0
  60. package/src/orchestration/orchestrator.ts +349 -0
  61. package/src/orchestration/pipeline.ts +66 -0
  62. package/src/orchestration/supervisor.ts +107 -0
  63. package/src/orchestration/swarm.ts +1099 -0
  64. package/src/orchestration/toolkit.ts +47 -0
  65. package/src/orchestration/types.ts +339 -0
  66. package/src/planner/classical-planner.ts +383 -0
  67. package/src/planner/index.ts +8 -0
  68. package/src/planner/llm-planner.ts +353 -0
  69. package/src/planner/types.ts +227 -0
  70. package/src/planner/validator.ts +297 -0
  71. package/src/production/circuit-breaker.ts +290 -0
  72. package/src/production/graceful-shutdown.ts +251 -0
  73. package/src/production/health.ts +333 -0
  74. package/src/production/index.ts +57 -0
  75. package/src/production/latency-eval.ts +62 -0
  76. package/src/production/rate-limiter.ts +287 -0
  77. package/src/production/resumable-stream.ts +289 -0
  78. package/src/production/types.ts +81 -0
  79. package/src/sdk/index.ts +374 -0
  80. package/src/session/db-driver.ts +50 -0
  81. package/src/session/in-memory-store.ts +235 -0
  82. package/src/session/index.ts +12 -0
  83. package/src/session/sql-store.ts +315 -0
  84. package/src/session/sqlite-store.ts +61 -0
  85. package/src/session/types.ts +153 -0
  86. package/src/tools/base-tool.ts +223 -0
  87. package/src/tools/browser-tool.ts +123 -0
  88. package/src/tools/calculator-tool.ts +265 -0
  89. package/src/tools/file-tools.ts +394 -0
  90. package/src/tools/github-tool.ts +432 -0
  91. package/src/tools/hackernews-tool.ts +187 -0
  92. package/src/tools/http-tool.ts +118 -0
  93. package/src/tools/index.ts +99 -0
  94. package/src/tools/jira-tool.ts +373 -0
  95. package/src/tools/notion-tool.ts +322 -0
  96. package/src/tools/openai-tool.ts +236 -0
  97. package/src/tools/registry.ts +131 -0
  98. package/src/tools/serpapi-tool.ts +234 -0
  99. package/src/tools/shell-tool.ts +118 -0
  100. package/src/tools/slack-tool.ts +327 -0
  101. package/src/tools/telegram-tool.ts +127 -0
  102. package/src/tools/types.ts +229 -0
  103. package/src/tools/websearch-tool.ts +335 -0
  104. package/src/tools/wikipedia-tool.ts +177 -0
  105. package/src/tools/yfinance-tool.ts +33 -0
  106. package/src/voice/index.ts +17 -0
  107. package/src/voice/voice-provider.ts +228 -0
  108. package/tests/artifact.test.ts +241 -0
  109. package/tests/circuit-breaker.test.ts +171 -0
  110. package/tests/health.test.ts +192 -0
  111. package/tests/llm-cache.test.ts +186 -0
  112. package/tests/rate-limiter.test.ts +161 -0
  113. package/tsconfig.json +29 -0
  114. package/vitest.config.ts +47 -0
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Agentic runner: ReAct-style loop (reason → tool call → observe → repeat)
3
+ */
4
+
5
+ import type { Message, ToolCall as LLMToolCall, LLMToolDefinition, GenerateResult } from '../llm/types.js';
6
+ import type { Tool, ToolParameters, ToolResult } from '../tools/types.js';
7
+ import type {
8
+ AgenticRunConfig,
9
+ AgenticRunResult,
10
+ AgenticRunnerConfig,
11
+ AgenticStreamHooks,
12
+ AgenticRetryPolicy,
13
+ } from './types.js';
14
+ import type { HumanInTheLoopHooks, GuardrailContext } from '../guardrails/types.js';
15
+ import type { GuardrailEngine } from '../guardrails/types.js';
16
+ import { LLMError } from '../errors.js';
17
+
18
+ const DEFAULT_MAX_STEPS = 10;
19
+ const DEFAULT_TIMEOUT_MS = 60_000;
20
+ const DEFAULT_RETRIES = 2;
21
+ const DEFAULT_BACKOFF_MS = 1000;
22
+
23
+ /**
24
+ * Convert a framework Tool to LLM tool definition.
25
+ * Uses a minimal JSON Schema for parameters (tool execution validates with Zod).
26
+ */
27
+ function toolToLLMDef(tool: Tool<ToolParameters, unknown>): LLMToolDefinition {
28
+ const params = tool.parameters as { _def?: { typeName?: string }; shape?: Record<string, unknown> };
29
+ const properties: Record<string, { type: string; description?: string }> = {};
30
+ const required: string[] = [];
31
+
32
+ if (params?.shape && typeof params.shape === 'object') {
33
+ for (const [key, value] of Object.entries(params.shape)) {
34
+ const zodType = value as { _def?: { typeName?: string; checks?: unknown[] }; description?: string; isOptional?: () => boolean };
35
+ const typeName = zodType?._def?.typeName ?? 'unknown';
36
+
37
+ // Map Zod types to JSON Schema types
38
+ let jsonType = 'string';
39
+ switch (typeName) {
40
+ case 'ZodString':
41
+ jsonType = 'string';
42
+ break;
43
+ case 'ZodNumber':
44
+ case 'ZodBigInt':
45
+ jsonType = 'number';
46
+ break;
47
+ case 'ZodBoolean':
48
+ jsonType = 'boolean';
49
+ break;
50
+ case 'ZodArray':
51
+ jsonType = 'array';
52
+ break;
53
+ case 'ZodObject':
54
+ case 'ZodRecord':
55
+ jsonType = 'object';
56
+ break;
57
+ case 'ZodEnum':
58
+ jsonType = 'string';
59
+ break;
60
+ case 'ZodOptional':
61
+ case 'ZodNullable':
62
+ jsonType = 'string'; // Simplified - actual type would need unwrapping
63
+ break;
64
+ default:
65
+ jsonType = 'string'; // Default to string for unknown types
66
+ }
67
+
68
+ properties[key] = {
69
+ type: jsonType,
70
+ description: zodType?.description,
71
+ };
72
+
73
+ // Check if field is required (not optional)
74
+ if (typeName !== 'ZodOptional' && !zodType?.isOptional?.()) {
75
+ required.push(key);
76
+ }
77
+ }
78
+ }
79
+
80
+ const parameters: Record<string, unknown> = {
81
+ type: 'object',
82
+ properties: Object.keys(properties).length ? properties : {},
83
+ additionalProperties: true,
84
+ };
85
+
86
+ if (required.length > 0) {
87
+ parameters.required = required;
88
+ }
89
+
90
+ return {
91
+ name: tool.name,
92
+ description: tool.description,
93
+ parameters,
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Sleep for backoff
99
+ */
100
+ function sleep(ms: number): Promise<void> {
101
+ return new Promise((resolve) => setTimeout(resolve, ms));
102
+ }
103
+
104
+ /**
105
+ * Execute with retry
106
+ */
107
+ async function withRetry<T>(
108
+ fn: () => Promise<T>,
109
+ policy: AgenticRetryPolicy
110
+ ): Promise<T> {
111
+ const maxRetries = policy.maxRetries ?? DEFAULT_RETRIES;
112
+ const backoffMs = policy.backoffMs ?? DEFAULT_BACKOFF_MS;
113
+ const maxBackoffMs = policy.maxBackoffMs ?? 30_000;
114
+ let lastError: Error | undefined;
115
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
116
+ try {
117
+ return await fn();
118
+ } catch (err) {
119
+ lastError = err instanceof Error ? err : new Error(String(err));
120
+ if (attempt < maxRetries) {
121
+ const delay = Math.min(backoffMs * Math.pow(2, attempt), maxBackoffMs);
122
+ await sleep(delay);
123
+ }
124
+ }
125
+ }
126
+ throw lastError;
127
+ }
128
+
129
+ /**
130
+ * AgenticRunner runs a ReAct-style loop: LLM generates → tool calls → execute tools → feed results → repeat.
131
+ */
132
+ export class AgenticRunner {
133
+ private config: AgenticRunnerConfig;
134
+ private humanInTheLoop?: HumanInTheLoopHooks;
135
+ private guardrails?: GuardrailEngine;
136
+
137
+ constructor(config: AgenticRunnerConfig) {
138
+ this.config = { ...config, toolMiddleware: config.toolMiddleware ?? [] };
139
+ }
140
+
141
+ /**
142
+ * Set human-in-the-loop hooks
143
+ */
144
+ setHumanInTheLoop(hooks: HumanInTheLoopHooks): void {
145
+ this.humanInTheLoop = hooks;
146
+ }
147
+
148
+ /**
149
+ * Set guardrail engine
150
+ */
151
+ setGuardrails(engine: GuardrailEngine): void {
152
+ this.guardrails = engine;
153
+ }
154
+
155
+ /**
156
+ * Run the agentic loop until the model returns no tool calls or max steps / timeout.
157
+ */
158
+ async run(
159
+ runConfig: AgenticRunConfig,
160
+ hooks?: AgenticStreamHooks
161
+ ): Promise<AgenticRunResult> {
162
+ const maxSteps = runConfig.maxSteps ?? this.config.maxSteps ?? DEFAULT_MAX_STEPS;
163
+ const timeoutMs = runConfig.timeoutMs ?? this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
164
+ const retry = this.config.retry ?? { maxRetries: DEFAULT_RETRIES, backoffMs: DEFAULT_BACKOFF_MS };
165
+
166
+ const tools = this.config.tools.list();
167
+ const llmTools: LLMToolDefinition[] = tools.map((t) => toolToLLMDef(t));
168
+
169
+ const messages: Message[] = runConfig.messages?.length
170
+ ? [...runConfig.messages]
171
+ : [
172
+ { role: 'system', content: runConfig.instructions },
173
+ { role: 'user', content: runConfig.prompt },
174
+ ];
175
+
176
+ const startTime = Date.now();
177
+ let steps = 0;
178
+ let lastText = '';
179
+ let usage: AgenticRunResult['usage'];
180
+ let finishReason = 'stop';
181
+
182
+ const agentId = this.config.agentId ?? 'agent';
183
+ const sessionId = this.config.sessionId ?? `session-${Date.now()}`;
184
+
185
+ while (steps < maxSteps) {
186
+ if (Date.now() - startTime > timeoutMs) {
187
+ finishReason = 'timeout';
188
+ break;
189
+ }
190
+
191
+ steps++;
192
+ hooks?.onStep?.(steps);
193
+
194
+ let result: GenerateResult;
195
+ try {
196
+ result = await withRetry(
197
+ () =>
198
+ this.config.llm.generateText(messages, {
199
+ temperature: 0.7,
200
+ maxTokens: 4096,
201
+ tools: llmTools.length ? llmTools : undefined,
202
+ toolChoice: llmTools.length ? 'auto' : 'none',
203
+ }),
204
+ retry
205
+ );
206
+ } catch (err) {
207
+ finishReason = 'error';
208
+ throw err instanceof LLMError ? err : new LLMError(err instanceof Error ? err.message : String(err), { cause: err instanceof Error ? err : undefined });
209
+ }
210
+
211
+ lastText = result.text ?? '';
212
+ if (result.usage) {
213
+ usage = {
214
+ promptTokens: result.usage.promptTokens,
215
+ completionTokens: result.usage.completionTokens,
216
+ totalTokens: result.usage.totalTokens,
217
+ };
218
+ }
219
+
220
+ if (result.text) {
221
+ messages.push({ role: 'assistant', content: result.text });
222
+ hooks?.onChunk?.(result.text);
223
+ }
224
+
225
+ if (!result.toolCalls?.length) {
226
+ // Check beforeFinish hook
227
+ const guardrailContext: GuardrailContext = {
228
+ agentId,
229
+ sessionId,
230
+ output: lastText,
231
+ };
232
+
233
+ if (this.humanInTheLoop?.beforeFinish) {
234
+ const approved = await this.humanInTheLoop.beforeFinish(lastText, guardrailContext);
235
+ if (!approved) {
236
+ finishReason = 'human_rejected';
237
+ break;
238
+ }
239
+ }
240
+
241
+ finishReason = 'stop';
242
+ break;
243
+ }
244
+
245
+ messages.push({
246
+ role: 'assistant',
247
+ content: result.text || '',
248
+ toolCalls: result.toolCalls,
249
+ } as Message & { toolCalls: LLMToolCall[] });
250
+
251
+ for (const tc of result.toolCalls) {
252
+ const tool = this.config.tools.getByName(tc.name);
253
+ if (!tool) {
254
+ messages.push({
255
+ role: 'tool',
256
+ content: JSON.stringify({ error: `Unknown tool: ${tc.name}` }),
257
+ toolCallId: tc.id,
258
+ } as Message & { toolCallId: string });
259
+ continue;
260
+ }
261
+
262
+ // Check guardrails
263
+ const guardrailContext: GuardrailContext = {
264
+ agentId,
265
+ sessionId,
266
+ toolName: tc.name,
267
+ toolArgs: tc.arguments,
268
+ };
269
+
270
+ if (this.guardrails) {
271
+ const results = await this.guardrails.checkToolCall(tc.name, tc.arguments, guardrailContext);
272
+ const violations = this.guardrails.getViolations(results);
273
+ if (violations.length > 0) {
274
+ const errorMsg = `Guardrail violation: ${violations.map(v => v.message).join(', ')}`;
275
+ messages.push({
276
+ role: 'tool',
277
+ content: JSON.stringify({ error: errorMsg }),
278
+ toolCallId: tc.id,
279
+ } as Message & { toolCallId: string });
280
+ if (this.humanInTheLoop?.onViolation) {
281
+ for (const v of violations) {
282
+ await this.humanInTheLoop.onViolation(v, guardrailContext);
283
+ }
284
+ }
285
+ continue;
286
+ }
287
+ }
288
+
289
+ // Check human-in-the-loop before tool call
290
+ if (this.humanInTheLoop?.beforeToolCall) {
291
+ const approved = await this.humanInTheLoop.beforeToolCall(tc.name, tc.arguments, guardrailContext);
292
+ if (!approved) {
293
+ messages.push({
294
+ role: 'tool',
295
+ content: JSON.stringify({ error: 'Tool call rejected by human' }),
296
+ toolCallId: tc.id,
297
+ } as Message & { toolCallId: string });
298
+ continue;
299
+ }
300
+ }
301
+
302
+ hooks?.onToolCall?.(tc.name, tc.arguments);
303
+
304
+ const toolContext = {
305
+ toolId: tool.id,
306
+ agentId,
307
+ sessionId,
308
+ timeoutMs: 30_000,
309
+ permissions: tool.permissions,
310
+ } as import('../tools/types.js').ToolContext;
311
+
312
+ // Tool middleware: beforeExecute
313
+ const middleware = this.config.toolMiddleware ?? [];
314
+ for (const m of middleware) {
315
+ if (m.beforeExecute) await m.beforeExecute(tool, tc.arguments, toolContext);
316
+ }
317
+
318
+ let toolResult: unknown;
319
+ let toolResultObj: ToolResult<unknown> | undefined;
320
+ try {
321
+ const out = await tool.execute(
322
+ tc.arguments as Record<string, unknown>,
323
+ toolContext
324
+ );
325
+ toolResultObj = out;
326
+ toolResult = out.success ? out.data : (out.error ? { error: out.error.message } : out);
327
+ } catch (err) {
328
+ const error = err instanceof Error ? err : new Error(String(err));
329
+ for (const m of middleware) {
330
+ if (m.onError) await m.onError(tool, error, toolContext);
331
+ }
332
+ toolResult = { error: error.message };
333
+ // Do not throw: let the agent see the error and continue or respond
334
+ }
335
+
336
+ // Tool middleware: afterExecute
337
+ if (toolResultObj !== undefined) {
338
+ for (const m of middleware) {
339
+ if (m.afterExecute) await m.afterExecute(tool, toolResultObj, toolContext);
340
+ }
341
+ }
342
+
343
+ // Check output guardrails
344
+ if (this.guardrails && toolResult !== undefined) {
345
+ const outputContext: GuardrailContext = {
346
+ ...guardrailContext,
347
+ output: toolResult,
348
+ };
349
+ const results = await this.guardrails.validateOutput(toolResult, outputContext);
350
+ const violations = this.guardrails.getViolations(results);
351
+ if (violations.length > 0) {
352
+ toolResult = { error: `Output guardrail violation: ${violations.map(v => v.message).join(', ')}` };
353
+ if (this.humanInTheLoop?.onViolation) {
354
+ for (const v of violations) {
355
+ await this.humanInTheLoop.onViolation(v, outputContext);
356
+ }
357
+ }
358
+ }
359
+ }
360
+
361
+ hooks?.onToolResult?.(tc.name, toolResult);
362
+
363
+ const resultContent =
364
+ typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult);
365
+
366
+ messages.push({
367
+ role: 'tool',
368
+ content: resultContent,
369
+ toolCallId: tc.id,
370
+ } as Message & { toolCallId: string });
371
+ }
372
+
373
+ if (steps >= maxSteps) {
374
+ finishReason = 'max_steps';
375
+ }
376
+ }
377
+
378
+ return {
379
+ text: lastText,
380
+ messages,
381
+ steps,
382
+ finishReason,
383
+ usage,
384
+ };
385
+ }
386
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Agentic loop (ReAct-style) types
3
+ */
4
+
5
+ import type { Message, LLMToolDefinition } from '../llm/types.js';
6
+ import type { LLMProvider } from '../llm/types.js';
7
+ import type { ToolRegistry, ToolMiddleware } from '../tools/types.js';
8
+ import type { EntityId } from '../core/types.js';
9
+
10
+ /** Observability: optional tracer and metrics for production monitoring */
11
+ export interface RunObservability {
12
+ readonly tracer?: import('../observability/types.js').Tracer;
13
+ readonly metrics?: import('../observability/types.js').MetricsCollector;
14
+ }
15
+
16
+ export interface AgenticRunConfig {
17
+ /** System prompt / instructions for the agent */
18
+ readonly instructions: string;
19
+ /** User prompt for this run */
20
+ readonly prompt: string;
21
+ /** Optional conversation history to continue */
22
+ readonly messages?: Message[];
23
+ /** Max reasoning steps (LLM + tool calls per step). Default 10 */
24
+ readonly maxSteps?: number;
25
+ /** Timeout for the entire run (ms). Default 60000 */
26
+ readonly timeoutMs?: number;
27
+ /** Optional run ID for tracing and logs */
28
+ readonly runId?: string;
29
+ /** Optional trace ID for distributed tracing */
30
+ readonly traceId?: string;
31
+ /** AbortSignal to cancel the run */
32
+ readonly signal?: AbortSignal;
33
+ }
34
+
35
+ /** AbortSignal-compatible (subset for cancellation) */
36
+ export type AbortSignal = { aborted: boolean; addEventListener?: (type: 'abort', handler: () => void) => void; removeEventListener?: (type: 'abort', handler: () => void) => void };
37
+
38
+ export interface AgenticRunResult {
39
+ /** Final assistant text response */
40
+ readonly text: string;
41
+ /** All messages in the conversation (including tool calls/results) */
42
+ readonly messages: Message[];
43
+ /** Number of steps taken */
44
+ readonly steps: number;
45
+ /** Finish reason: 'stop' | 'max_steps' | 'timeout' | 'error' | 'human_rejected' */
46
+ readonly finishReason: string;
47
+ /** Optional usage stats */
48
+ readonly usage?: { promptTokens?: number; completionTokens?: number; totalTokens?: number };
49
+ /** Run ID when provided in config */
50
+ readonly runId?: string;
51
+ /** Trace ID when provided in config */
52
+ readonly traceId?: string;
53
+ }
54
+
55
+ /** Retry policy for LLM and tool calls in the agentic loop */
56
+ export interface AgenticRetryPolicy {
57
+ readonly maxRetries?: number;
58
+ readonly backoffMs?: number;
59
+ readonly maxBackoffMs?: number;
60
+ }
61
+
62
+ /** Stream / progress hooks */
63
+ export interface AgenticStreamHooks {
64
+ onChunk?: (text: string) => void;
65
+ onToolCall?: (name: string, args: Record<string, unknown>) => void;
66
+ onToolResult?: (name: string, result: unknown) => void;
67
+ onStep?: (step: number) => void;
68
+ }
69
+
70
+ export interface AgenticRunnerConfig {
71
+ readonly llm: LLMProvider;
72
+ readonly tools: ToolRegistry;
73
+ readonly agentId?: EntityId;
74
+ readonly sessionId?: string;
75
+ readonly maxSteps?: number;
76
+ readonly timeoutMs?: number;
77
+ readonly retry?: AgenticRetryPolicy;
78
+ /** Optional tool middleware for cross-tool integration (logging, rate limit, etc.) */
79
+ readonly toolMiddleware?: ToolMiddleware[];
80
+ /** Optional observability for production (tracer + metrics) */
81
+ readonly observability?: RunObservability;
82
+ }
83
+
84
+ /** Convert a framework Tool to LLM tool definition (name, description, parameters as JSON Schema) */
85
+ export function toolToLLMDefinition(
86
+ name: string,
87
+ description: string,
88
+ parametersSchema: Record<string, unknown>
89
+ ): LLMToolDefinition {
90
+ return { name, description, parameters: parametersSchema };
91
+ }