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.
- package/FEATURES.md +169 -0
- package/package.json +119 -0
- package/src/agent.ts +187 -0
- package/src/agentic/index.ts +87 -0
- package/src/agentic/runner.ts +386 -0
- package/src/agentic/types.ts +91 -0
- package/src/artifacts/artifact.ts +417 -0
- package/src/artifacts/index.ts +42 -0
- package/src/artifacts/media.ts +304 -0
- package/src/cli/index.ts +122 -0
- package/src/core/base-agent.ts +151 -0
- package/src/core/context-builder.ts +106 -0
- package/src/core/index.ts +8 -0
- package/src/core/schemas.ts +17 -0
- package/src/core/types.ts +158 -0
- package/src/create-agent.ts +309 -0
- package/src/debug-logger.ts +188 -0
- package/src/dx/agent.ts +88 -0
- package/src/dx/define-agent.ts +183 -0
- package/src/dx/dev-logger.ts +57 -0
- package/src/dx/index.ts +11 -0
- package/src/errors.ts +175 -0
- package/src/execution/engine.ts +522 -0
- package/src/execution/graph-builder.ts +362 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/types.ts +257 -0
- package/src/execution/worker-pool.ts +308 -0
- package/src/extensions/index.ts +123 -0
- package/src/guardrails/allowlist.ts +155 -0
- package/src/guardrails/index.ts +17 -0
- package/src/guardrails/types.ts +159 -0
- package/src/guardrails/validator.ts +265 -0
- package/src/index.ts +74 -0
- package/src/knowledge/index.ts +5 -0
- package/src/knowledge/types.ts +52 -0
- package/src/learning/in-memory-store.ts +72 -0
- package/src/learning/index.ts +6 -0
- package/src/learning/types.ts +42 -0
- package/src/llm/cache.ts +300 -0
- package/src/llm/index.ts +22 -0
- package/src/llm/model-resolver.ts +81 -0
- package/src/llm/openai-provider.ts +313 -0
- package/src/llm/openrouter-provider.ts +29 -0
- package/src/llm/types.ts +131 -0
- package/src/memory/in-memory-store.ts +255 -0
- package/src/memory/index.ts +7 -0
- package/src/memory/types.ts +193 -0
- package/src/memory/vector-store.ts +251 -0
- package/src/observability/console-logger.ts +123 -0
- package/src/observability/index.ts +12 -0
- package/src/observability/metrics.ts +85 -0
- package/src/observability/otlp-exporter.ts +417 -0
- package/src/observability/tracer.ts +105 -0
- package/src/observability/types.ts +341 -0
- package/src/orchestration/agent-adapter.ts +33 -0
- package/src/orchestration/index.ts +34 -0
- package/src/orchestration/load-balancer.ts +151 -0
- package/src/orchestration/mcp-types.ts +59 -0
- package/src/orchestration/message-bus.ts +192 -0
- package/src/orchestration/orchestrator.ts +349 -0
- package/src/orchestration/pipeline.ts +66 -0
- package/src/orchestration/supervisor.ts +107 -0
- package/src/orchestration/swarm.ts +1099 -0
- package/src/orchestration/toolkit.ts +47 -0
- package/src/orchestration/types.ts +339 -0
- package/src/planner/classical-planner.ts +383 -0
- package/src/planner/index.ts +8 -0
- package/src/planner/llm-planner.ts +353 -0
- package/src/planner/types.ts +227 -0
- package/src/planner/validator.ts +297 -0
- package/src/production/circuit-breaker.ts +290 -0
- package/src/production/graceful-shutdown.ts +251 -0
- package/src/production/health.ts +333 -0
- package/src/production/index.ts +57 -0
- package/src/production/latency-eval.ts +62 -0
- package/src/production/rate-limiter.ts +287 -0
- package/src/production/resumable-stream.ts +289 -0
- package/src/production/types.ts +81 -0
- package/src/sdk/index.ts +374 -0
- package/src/session/db-driver.ts +50 -0
- package/src/session/in-memory-store.ts +235 -0
- package/src/session/index.ts +12 -0
- package/src/session/sql-store.ts +315 -0
- package/src/session/sqlite-store.ts +61 -0
- package/src/session/types.ts +153 -0
- package/src/tools/base-tool.ts +223 -0
- package/src/tools/browser-tool.ts +123 -0
- package/src/tools/calculator-tool.ts +265 -0
- package/src/tools/file-tools.ts +394 -0
- package/src/tools/github-tool.ts +432 -0
- package/src/tools/hackernews-tool.ts +187 -0
- package/src/tools/http-tool.ts +118 -0
- package/src/tools/index.ts +99 -0
- package/src/tools/jira-tool.ts +373 -0
- package/src/tools/notion-tool.ts +322 -0
- package/src/tools/openai-tool.ts +236 -0
- package/src/tools/registry.ts +131 -0
- package/src/tools/serpapi-tool.ts +234 -0
- package/src/tools/shell-tool.ts +118 -0
- package/src/tools/slack-tool.ts +327 -0
- package/src/tools/telegram-tool.ts +127 -0
- package/src/tools/types.ts +229 -0
- package/src/tools/websearch-tool.ts +335 -0
- package/src/tools/wikipedia-tool.ts +177 -0
- package/src/tools/yfinance-tool.ts +33 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/voice-provider.ts +228 -0
- package/tests/artifact.test.ts +241 -0
- package/tests/circuit-breaker.test.ts +171 -0
- package/tests/health.test.ts +192 -0
- package/tests/llm-cache.test.ts +186 -0
- package/tests/rate-limiter.test.ts +161 -0
- package/tsconfig.json +29 -0
- package/vitest.config.ts +47 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base tool implementation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import {
|
|
7
|
+
Tool,
|
|
8
|
+
ToolParameters,
|
|
9
|
+
ToolContext,
|
|
10
|
+
ToolResult,
|
|
11
|
+
ToolError,
|
|
12
|
+
ToolExecutionMetadata,
|
|
13
|
+
ToolPermissions,
|
|
14
|
+
ToolCategory,
|
|
15
|
+
} from './types.js';
|
|
16
|
+
import type { EntityId } from '../core/types.js';
|
|
17
|
+
import { DebugLogger, createDebugLogger } from '../debug-logger.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Configuration for creating a base tool
|
|
21
|
+
*/
|
|
22
|
+
export interface BaseToolConfig<TParams extends ToolParameters> {
|
|
23
|
+
id?: EntityId;
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
parameters: TParams;
|
|
27
|
+
permissions?: Partial<ToolPermissions>;
|
|
28
|
+
category?: ToolCategory;
|
|
29
|
+
version?: string;
|
|
30
|
+
author?: string;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
/** Enable debug logging for this tool */
|
|
33
|
+
debug?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Abstract base class for tools
|
|
38
|
+
*/
|
|
39
|
+
export abstract class BaseTool<TParams extends ToolParameters = ToolParameters, TOutput = unknown>
|
|
40
|
+
implements Tool<TParams, TOutput> {
|
|
41
|
+
readonly id: EntityId;
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly description: string;
|
|
44
|
+
readonly parameters: TParams;
|
|
45
|
+
readonly permissions: ToolPermissions;
|
|
46
|
+
readonly category: ToolCategory;
|
|
47
|
+
readonly version: string;
|
|
48
|
+
readonly author?: string;
|
|
49
|
+
readonly tags?: string[];
|
|
50
|
+
protected logger: DebugLogger;
|
|
51
|
+
|
|
52
|
+
constructor(config: BaseToolConfig<TParams>) {
|
|
53
|
+
this.id = config.id ?? `tool-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
54
|
+
this.name = config.name;
|
|
55
|
+
this.description = config.description;
|
|
56
|
+
this.parameters = config.parameters;
|
|
57
|
+
this.permissions = {
|
|
58
|
+
allowNetwork: config.permissions?.allowNetwork ?? false,
|
|
59
|
+
allowFileSystem: config.permissions?.allowFileSystem ?? false,
|
|
60
|
+
allowedPaths: config.permissions?.allowedPaths,
|
|
61
|
+
allowedHosts: config.permissions?.allowedHosts,
|
|
62
|
+
maxExecutionTimeMs: config.permissions?.maxExecutionTimeMs ?? 30000,
|
|
63
|
+
};
|
|
64
|
+
this.category = config.category ?? ToolCategory.UTILITY;
|
|
65
|
+
this.version = config.version ?? '1.0.0';
|
|
66
|
+
this.author = config.author;
|
|
67
|
+
this.tags = config.tags;
|
|
68
|
+
this.logger = createDebugLogger(`Tool:${this.name}`, config.debug ?? false);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Execute the tool with the given parameters
|
|
73
|
+
*/
|
|
74
|
+
async execute(params: z.infer<TParams>, context: ToolContext): Promise<ToolResult<TOutput>> {
|
|
75
|
+
const startTime = new Date();
|
|
76
|
+
let retries = 0;
|
|
77
|
+
|
|
78
|
+
this.logger.logStart(`Tool execution: ${this.name}`, {
|
|
79
|
+
toolId: this.id,
|
|
80
|
+
category: this.category,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Validate parameters
|
|
85
|
+
this.logger.debug('Validating parameters');
|
|
86
|
+
const validation = this.parameters.safeParse(params);
|
|
87
|
+
if (!validation.success) {
|
|
88
|
+
this.logger.error('Parameter validation failed', undefined, {
|
|
89
|
+
error: validation.error.message,
|
|
90
|
+
});
|
|
91
|
+
return this.createErrorResult(
|
|
92
|
+
startTime,
|
|
93
|
+
retries,
|
|
94
|
+
'VALIDATION_ERROR',
|
|
95
|
+
`Invalid parameters: ${validation.error.message}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Check permissions
|
|
100
|
+
this.logger.debug('Checking permissions');
|
|
101
|
+
const permissionError = this.checkPermissions(context);
|
|
102
|
+
if (permissionError) {
|
|
103
|
+
this.logger.error('Permission denied', undefined, { error: permissionError });
|
|
104
|
+
return this.createErrorResult(
|
|
105
|
+
startTime,
|
|
106
|
+
retries,
|
|
107
|
+
'PERMISSION_DENIED',
|
|
108
|
+
permissionError
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Execute with timeout
|
|
113
|
+
this.logger.debug('Executing tool logic');
|
|
114
|
+
const timeoutMs = context.timeoutMs ?? this.permissions.maxExecutionTimeMs;
|
|
115
|
+
const data = await this.executeWithTimeout(validation.data, context, timeoutMs);
|
|
116
|
+
|
|
117
|
+
const endTime = new Date();
|
|
118
|
+
const metadata: ToolExecutionMetadata = {
|
|
119
|
+
startTime,
|
|
120
|
+
endTime,
|
|
121
|
+
retries,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
this.logger.logComplete(`Tool execution: ${this.name}`, endTime.getTime() - startTime.getTime());
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
data,
|
|
128
|
+
executionTimeMs: endTime.getTime() - startTime.getTime(),
|
|
129
|
+
metadata,
|
|
130
|
+
};
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
133
|
+
this.logger.error(`Tool execution failed: ${this.name}`, undefined, { error: errorMessage });
|
|
134
|
+
return this.createErrorResult(startTime, retries, 'EXECUTION_ERROR', errorMessage);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Validate parameters without executing
|
|
140
|
+
*/
|
|
141
|
+
validate(params: unknown): params is z.infer<TParams> {
|
|
142
|
+
return this.parameters.safeParse(params).success;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Execute the tool's core logic - must be implemented by subclasses
|
|
147
|
+
*/
|
|
148
|
+
protected abstract performExecute(
|
|
149
|
+
params: z.infer<TParams>,
|
|
150
|
+
context: ToolContext
|
|
151
|
+
): Promise<TOutput>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Execute with timeout support
|
|
155
|
+
*/
|
|
156
|
+
private async executeWithTimeout(
|
|
157
|
+
params: z.infer<TParams>,
|
|
158
|
+
context: ToolContext,
|
|
159
|
+
timeoutMs: number
|
|
160
|
+
): Promise<TOutput> {
|
|
161
|
+
return new Promise((resolve, reject) => {
|
|
162
|
+
const timeoutId = setTimeout(() => {
|
|
163
|
+
reject(new Error(`Tool execution timed out after ${timeoutMs}ms`));
|
|
164
|
+
}, timeoutMs);
|
|
165
|
+
|
|
166
|
+
this.performExecute(params, context)
|
|
167
|
+
.then(result => {
|
|
168
|
+
clearTimeout(timeoutId);
|
|
169
|
+
resolve(result);
|
|
170
|
+
})
|
|
171
|
+
.catch(error => {
|
|
172
|
+
clearTimeout(timeoutId);
|
|
173
|
+
reject(error);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Check if the tool has required permissions
|
|
180
|
+
*/
|
|
181
|
+
private checkPermissions(context: ToolContext): string | null {
|
|
182
|
+
// Check network permission
|
|
183
|
+
if (this.permissions.allowNetwork && !context.permissions.allowNetwork) {
|
|
184
|
+
return 'Network access not permitted in context';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Check filesystem permission
|
|
188
|
+
if (this.permissions.allowFileSystem && !context.permissions.allowFileSystem) {
|
|
189
|
+
return 'Filesystem access not permitted in context';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Create an error result
|
|
197
|
+
*/
|
|
198
|
+
private createErrorResult(
|
|
199
|
+
startTime: Date,
|
|
200
|
+
retries: number,
|
|
201
|
+
code: string,
|
|
202
|
+
message: string
|
|
203
|
+
): ToolResult<TOutput> {
|
|
204
|
+
const endTime = new Date();
|
|
205
|
+
const error: ToolError = {
|
|
206
|
+
code,
|
|
207
|
+
message,
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const metadata: ToolExecutionMetadata = {
|
|
211
|
+
startTime,
|
|
212
|
+
endTime,
|
|
213
|
+
retries,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
success: false,
|
|
218
|
+
error,
|
|
219
|
+
executionTimeMs: endTime.getTime() - startTime.getTime(),
|
|
220
|
+
metadata,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser tool – fetch a URL and return page title, text content, and links
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { BaseTool, BaseToolConfig } from './base-tool.js';
|
|
7
|
+
import { ToolContext, ToolCategory } from './types.js';
|
|
8
|
+
|
|
9
|
+
const BrowserToolParameters = z.object({
|
|
10
|
+
url: z.string().url(),
|
|
11
|
+
timeout: z.number().min(1000).max(60000).optional(),
|
|
12
|
+
includeLinks: z.boolean().default(true),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
interface BrowserPageResult {
|
|
16
|
+
url: string;
|
|
17
|
+
title: string;
|
|
18
|
+
textContent: string;
|
|
19
|
+
links: string[];
|
|
20
|
+
status: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function extractTitle(html: string): string {
|
|
24
|
+
const match = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
|
|
25
|
+
return match ? stripTags(match[1]).trim() : '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function stripTags(html: string): string {
|
|
29
|
+
return html
|
|
30
|
+
.replace(/<script[\s\S]*?<\/script>/gi, ' ')
|
|
31
|
+
.replace(/<style[\s\S]*?<\/style>/gi, ' ')
|
|
32
|
+
.replace(/<[^>]+>/g, ' ')
|
|
33
|
+
.replace(/\s+/g, ' ')
|
|
34
|
+
.replace(/ /g, ' ')
|
|
35
|
+
.replace(/&/g, '&')
|
|
36
|
+
.replace(/</g, '<')
|
|
37
|
+
.replace(/>/g, '>')
|
|
38
|
+
.replace(/"/g, '"')
|
|
39
|
+
.replace(/'/g, "'")
|
|
40
|
+
.trim();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function extractLinks(html: string, baseUrl: string): string[] {
|
|
44
|
+
const hrefRegex = /<a[^>]+href\s*=\s*["']([^"']+)["']/gi;
|
|
45
|
+
const seen = new Set<string>();
|
|
46
|
+
const links: string[] = [];
|
|
47
|
+
let m: RegExpExecArray | null;
|
|
48
|
+
while ((m = hrefRegex.exec(html)) !== null) {
|
|
49
|
+
let href = m[1].trim();
|
|
50
|
+
if (!href || href.startsWith('#') || href.startsWith('javascript:')) continue;
|
|
51
|
+
try {
|
|
52
|
+
const resolved = new URL(href, baseUrl).href;
|
|
53
|
+
if (!seen.has(resolved)) {
|
|
54
|
+
seen.add(resolved);
|
|
55
|
+
links.push(resolved);
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// skip invalid URLs
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return links;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class BrowserTool extends BaseTool<typeof BrowserToolParameters, BrowserPageResult> {
|
|
65
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof BrowserToolParameters>, 'parameters'>>) {
|
|
66
|
+
super({
|
|
67
|
+
name: config?.name ?? 'browser.fetch',
|
|
68
|
+
description:
|
|
69
|
+
config?.description ??
|
|
70
|
+
'Fetch a web page and return its title, main text content, and links (for reading and navigating pages)',
|
|
71
|
+
parameters: BrowserToolParameters,
|
|
72
|
+
category: config?.category ?? ToolCategory.WEB,
|
|
73
|
+
permissions: {
|
|
74
|
+
allowNetwork: true,
|
|
75
|
+
maxExecutionTimeMs: 30000,
|
|
76
|
+
...config?.permissions,
|
|
77
|
+
},
|
|
78
|
+
version: config?.version,
|
|
79
|
+
author: config?.author,
|
|
80
|
+
tags: config?.tags,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
protected async performExecute(
|
|
85
|
+
params: z.infer<typeof BrowserToolParameters>,
|
|
86
|
+
_context: ToolContext
|
|
87
|
+
): Promise<BrowserPageResult> {
|
|
88
|
+
const { url, timeout, includeLinks } = params;
|
|
89
|
+
|
|
90
|
+
const controller = new AbortController();
|
|
91
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout ?? 30000);
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const response = await fetch(url, {
|
|
95
|
+
method: 'GET',
|
|
96
|
+
headers: {
|
|
97
|
+
Accept: 'text/html, application/xhtml+xml, */*',
|
|
98
|
+
'User-Agent':
|
|
99
|
+
'Mozilla/5.0 (compatible; ConfusedAI/1.0; +https://github.com/confused-ai)',
|
|
100
|
+
},
|
|
101
|
+
signal: controller.signal,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
clearTimeout(timeoutId);
|
|
105
|
+
|
|
106
|
+
const html = await response.text();
|
|
107
|
+
const title = extractTitle(html);
|
|
108
|
+
const textContent = stripTags(html);
|
|
109
|
+
const links = includeLinks ? extractLinks(html, url) : [];
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
url,
|
|
113
|
+
title,
|
|
114
|
+
textContent,
|
|
115
|
+
links,
|
|
116
|
+
status: response.status,
|
|
117
|
+
};
|
|
118
|
+
} catch (error) {
|
|
119
|
+
clearTimeout(timeoutId);
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculator tool implementation - TypeScript CalculatorTools
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { BaseTool, BaseToolConfig } from './base-tool.js';
|
|
7
|
+
import { ToolContext, ToolCategory } from './types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parameters for calculator operations
|
|
11
|
+
*/
|
|
12
|
+
const CalculatorOperationParameters = z.object({
|
|
13
|
+
a: z.number().describe('First number'),
|
|
14
|
+
b: z.number().describe('Second number'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const CalculatorSingleNumberParameters = z.object({
|
|
18
|
+
n: z.number().describe('Number to operate on'),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
interface CalculatorResult {
|
|
22
|
+
operation: string;
|
|
23
|
+
result?: number;
|
|
24
|
+
error?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Add two numbers
|
|
29
|
+
*/
|
|
30
|
+
export class CalculatorAddTool extends BaseTool<typeof CalculatorOperationParameters, CalculatorResult> {
|
|
31
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorOperationParameters>, 'parameters'>>) {
|
|
32
|
+
super({
|
|
33
|
+
name: config?.name ?? 'calculator.add',
|
|
34
|
+
description: config?.description ?? 'Add two numbers and return the result',
|
|
35
|
+
parameters: CalculatorOperationParameters,
|
|
36
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
37
|
+
...config,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected async performExecute(
|
|
42
|
+
params: z.infer<typeof CalculatorOperationParameters>,
|
|
43
|
+
_context: ToolContext
|
|
44
|
+
): Promise<CalculatorResult> {
|
|
45
|
+
const result = params.a + params.b;
|
|
46
|
+
return { operation: 'addition', result };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Subtract two numbers
|
|
52
|
+
*/
|
|
53
|
+
export class CalculatorSubtractTool extends BaseTool<typeof CalculatorOperationParameters, CalculatorResult> {
|
|
54
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorOperationParameters>, 'parameters'>>) {
|
|
55
|
+
super({
|
|
56
|
+
name: config?.name ?? 'calculator.subtract',
|
|
57
|
+
description: config?.description ?? 'Subtract second number from first and return the result',
|
|
58
|
+
parameters: CalculatorOperationParameters,
|
|
59
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
60
|
+
...config,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected async performExecute(
|
|
65
|
+
params: z.infer<typeof CalculatorOperationParameters>,
|
|
66
|
+
_context: ToolContext
|
|
67
|
+
): Promise<CalculatorResult> {
|
|
68
|
+
const result = params.a - params.b;
|
|
69
|
+
return { operation: 'subtraction', result };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Multiply two numbers
|
|
75
|
+
*/
|
|
76
|
+
export class CalculatorMultiplyTool extends BaseTool<typeof CalculatorOperationParameters, CalculatorResult> {
|
|
77
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorOperationParameters>, 'parameters'>>) {
|
|
78
|
+
super({
|
|
79
|
+
name: config?.name ?? 'calculator.multiply',
|
|
80
|
+
description: config?.description ?? 'Multiply two numbers and return the result',
|
|
81
|
+
parameters: CalculatorOperationParameters,
|
|
82
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
83
|
+
...config,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
protected async performExecute(
|
|
88
|
+
params: z.infer<typeof CalculatorOperationParameters>,
|
|
89
|
+
_context: ToolContext
|
|
90
|
+
): Promise<CalculatorResult> {
|
|
91
|
+
const result = params.a * params.b;
|
|
92
|
+
return { operation: 'multiplication', result };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Divide two numbers
|
|
98
|
+
*/
|
|
99
|
+
export class CalculatorDivideTool extends BaseTool<typeof CalculatorOperationParameters, CalculatorResult> {
|
|
100
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorOperationParameters>, 'parameters'>>) {
|
|
101
|
+
super({
|
|
102
|
+
name: config?.name ?? 'calculator.divide',
|
|
103
|
+
description: config?.description ?? 'Divide first number by second and return the result',
|
|
104
|
+
parameters: CalculatorOperationParameters,
|
|
105
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
106
|
+
...config,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected async performExecute(
|
|
111
|
+
params: z.infer<typeof CalculatorOperationParameters>,
|
|
112
|
+
_context: ToolContext
|
|
113
|
+
): Promise<CalculatorResult> {
|
|
114
|
+
if (params.b === 0) {
|
|
115
|
+
return { operation: 'division', error: 'Division by zero is undefined' };
|
|
116
|
+
}
|
|
117
|
+
const result = params.a / params.b;
|
|
118
|
+
return { operation: 'division', result };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Raise a number to a power
|
|
124
|
+
*/
|
|
125
|
+
export class CalculatorExponentiateTool extends BaseTool<typeof CalculatorOperationParameters, CalculatorResult> {
|
|
126
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorOperationParameters>, 'parameters'>>) {
|
|
127
|
+
super({
|
|
128
|
+
name: config?.name ?? 'calculator.exponentiate',
|
|
129
|
+
description: config?.description ?? 'Raise first number to the power of the second number',
|
|
130
|
+
parameters: CalculatorOperationParameters,
|
|
131
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
132
|
+
...config,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
protected async performExecute(
|
|
137
|
+
params: z.infer<typeof CalculatorOperationParameters>,
|
|
138
|
+
_context: ToolContext
|
|
139
|
+
): Promise<CalculatorResult> {
|
|
140
|
+
const result = Math.pow(params.a, params.b);
|
|
141
|
+
return { operation: 'exponentiation', result };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Calculate factorial of a number
|
|
147
|
+
*/
|
|
148
|
+
export class CalculatorFactorialTool extends BaseTool<typeof CalculatorSingleNumberParameters, CalculatorResult> {
|
|
149
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorSingleNumberParameters>, 'parameters'>>) {
|
|
150
|
+
super({
|
|
151
|
+
name: config?.name ?? 'calculator.factorial',
|
|
152
|
+
description: config?.description ?? 'Calculate the factorial of a number',
|
|
153
|
+
parameters: CalculatorSingleNumberParameters,
|
|
154
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
155
|
+
...config,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
protected async performExecute(
|
|
160
|
+
params: z.infer<typeof CalculatorSingleNumberParameters>,
|
|
161
|
+
_context: ToolContext
|
|
162
|
+
): Promise<CalculatorResult> {
|
|
163
|
+
if (params.n < 0) {
|
|
164
|
+
return { operation: 'factorial', error: 'Factorial of a negative number is undefined' };
|
|
165
|
+
}
|
|
166
|
+
if (!Number.isInteger(params.n)) {
|
|
167
|
+
return { operation: 'factorial', error: 'Factorial is only defined for integers' };
|
|
168
|
+
}
|
|
169
|
+
let result = 1;
|
|
170
|
+
for (let i = 2; i <= params.n; i++) {
|
|
171
|
+
result *= i;
|
|
172
|
+
}
|
|
173
|
+
return { operation: 'factorial', result };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Check if a number is prime
|
|
179
|
+
*/
|
|
180
|
+
export class CalculatorIsPrimeTool extends BaseTool<typeof CalculatorSingleNumberParameters, CalculatorResult> {
|
|
181
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorSingleNumberParameters>, 'parameters'>>) {
|
|
182
|
+
super({
|
|
183
|
+
name: config?.name ?? 'calculator.is_prime',
|
|
184
|
+
description: config?.description ?? 'Check if a number is prime',
|
|
185
|
+
parameters: CalculatorSingleNumberParameters,
|
|
186
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
187
|
+
...config,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
protected async performExecute(
|
|
192
|
+
params: z.infer<typeof CalculatorSingleNumberParameters>,
|
|
193
|
+
_context: ToolContext
|
|
194
|
+
): Promise<CalculatorResult> {
|
|
195
|
+
const n = params.n;
|
|
196
|
+
if (n <= 1) {
|
|
197
|
+
return { operation: 'prime_check', result: 0 }; // 0 = false
|
|
198
|
+
}
|
|
199
|
+
if (n <= 3) {
|
|
200
|
+
return { operation: 'prime_check', result: 1 }; // 1 = true
|
|
201
|
+
}
|
|
202
|
+
if (n % 2 === 0 || n % 3 === 0) {
|
|
203
|
+
return { operation: 'prime_check', result: 0 };
|
|
204
|
+
}
|
|
205
|
+
for (let i = 5; i * i <= n; i += 6) {
|
|
206
|
+
if (n % i === 0 || n % (i + 2) === 0) {
|
|
207
|
+
return { operation: 'prime_check', result: 0 };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return { operation: 'prime_check', result: 1 };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Calculate square root of a number
|
|
216
|
+
*/
|
|
217
|
+
export class CalculatorSquareRootTool extends BaseTool<typeof CalculatorSingleNumberParameters, CalculatorResult> {
|
|
218
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof CalculatorSingleNumberParameters>, 'parameters'>>) {
|
|
219
|
+
super({
|
|
220
|
+
name: config?.name ?? 'calculator.square_root',
|
|
221
|
+
description: config?.description ?? 'Calculate the square root of a number',
|
|
222
|
+
parameters: CalculatorSingleNumberParameters,
|
|
223
|
+
category: config?.category ?? ToolCategory.UTILITY,
|
|
224
|
+
...config,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
protected async performExecute(
|
|
229
|
+
params: z.infer<typeof CalculatorSingleNumberParameters>,
|
|
230
|
+
_context: ToolContext
|
|
231
|
+
): Promise<CalculatorResult> {
|
|
232
|
+
if (params.n < 0) {
|
|
233
|
+
return { operation: 'square_root', error: 'Square root of a negative number is undefined' };
|
|
234
|
+
}
|
|
235
|
+
const result = Math.sqrt(params.n);
|
|
236
|
+
return { operation: 'square_root', result };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Calculator toolkit - provides all calculator tools
|
|
242
|
+
*/
|
|
243
|
+
export class CalculatorToolkit {
|
|
244
|
+
static createAll(): Array<
|
|
245
|
+
| CalculatorAddTool
|
|
246
|
+
| CalculatorSubtractTool
|
|
247
|
+
| CalculatorMultiplyTool
|
|
248
|
+
| CalculatorDivideTool
|
|
249
|
+
| CalculatorExponentiateTool
|
|
250
|
+
| CalculatorFactorialTool
|
|
251
|
+
| CalculatorIsPrimeTool
|
|
252
|
+
| CalculatorSquareRootTool
|
|
253
|
+
> {
|
|
254
|
+
return [
|
|
255
|
+
new CalculatorAddTool(),
|
|
256
|
+
new CalculatorSubtractTool(),
|
|
257
|
+
new CalculatorMultiplyTool(),
|
|
258
|
+
new CalculatorDivideTool(),
|
|
259
|
+
new CalculatorExponentiateTool(),
|
|
260
|
+
new CalculatorFactorialTool(),
|
|
261
|
+
new CalculatorIsPrimeTool(),
|
|
262
|
+
new CalculatorSquareRootTool(),
|
|
263
|
+
];
|
|
264
|
+
}
|
|
265
|
+
}
|