@supertools-ai/core 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Supertools
2
2
 
3
3
  <p align="center">
4
- <img src="assets/banner.svg" alt="Supertools - Let LLMs write code that calls your tools" width="100%">
4
+ <img src="https://raw.githubusercontent.com/bxxf/supertools/refs/heads/main/assets/banner.svg" alt="Supertools - Let LLMs write code that calls your tools" width="100%">
5
5
  </p>
6
6
 
7
- > **🚧 Work in Progress** — This project is under active development. The npm package will be published soon. Contributions are welcome, especially for adding support for other AI providers (OpenAI, Vercel AI SDK, etc.)!
7
+ > **🚧 Work in Progress** — This project is under active development. Contributions are welcome, especially for adding support for other AI providers (OpenAI, Vercel AI SDK, etc.)!
8
8
 
9
9
  <p align="center">
10
10
  <a href="#quick-start">Quick Start</a> •
@@ -47,58 +47,75 @@ User Request → LLM generates code → Sandbox executes → Result
47
47
  ## Quick Start
48
48
 
49
49
  ```bash
50
- bun add @supertools-ai/core
50
+ bun add @supertools-ai/core @anthropic-ai/sdk e2b
51
51
  ```
52
52
 
53
+ Set your API keys:
54
+ ```bash
55
+ export ANTHROPIC_API_KEY=your-key
56
+ export E2B_API_KEY=your-key
57
+ ```
58
+
59
+ Create `index.ts` and run with `bun run index.ts`:
60
+
53
61
  ```typescript
54
62
  import { supertools, defineTool, z } from '@supertools-ai/core';
55
63
  import { Sandbox } from 'e2b';
56
64
  import Anthropic from '@anthropic-ai/sdk';
57
65
 
58
- // Define your tools with Zod schemas
59
- const queryDatabase = defineTool({
60
- name: 'queryDatabase',
61
- description: 'Execute a SQL query',
62
- parameters: z.object({
63
- sql: z.string().describe('The SQL query to execute'),
64
- }),
65
- returns: z.array(z.record(z.unknown())), // Array of row objects
66
- execute: async ({ sql }) => db.query(sql),
67
- });
68
-
69
- const sendEmail = defineTool({
70
- name: 'sendEmail',
71
- description: 'Send an email',
66
+ // Sample data
67
+ const orders = [
68
+ { id: 1, customer: 'Alice', total: 150, status: 'completed' },
69
+ { id: 2, customer: 'Bob', total: 75, status: 'pending' },
70
+ { id: 3, customer: 'Alice', total: 200, status: 'completed' },
71
+ { id: 4, customer: 'Charlie', total: 50, status: 'completed' },
72
+ ];
73
+
74
+ // Define tools with Zod schemas
75
+ const getOrders = defineTool({
76
+ name: 'getOrders',
77
+ description: 'Get orders, optionally filtered by status',
72
78
  parameters: z.object({
73
- to: z.string(),
74
- subject: z.string(),
75
- body: z.string(),
79
+ status: z.enum(['pending', 'completed']).optional(),
76
80
  }),
77
- returns: z.object({ success: z.boolean(), messageId: z.string() }),
78
- execute: async ({ to, subject, body }) => mailer.send({ to, subject, body }),
81
+ returns: z.array(z.object({
82
+ id: z.number(),
83
+ customer: z.string(),
84
+ total: z.number(),
85
+ status: z.string(),
86
+ })),
87
+ execute: async ({ status }) =>
88
+ status ? orders.filter(o => o.status === status) : orders,
79
89
  });
80
90
 
81
- // Create sandbox and wrap your SDK client
91
+ // Main
82
92
  const sandbox = await Sandbox.create('supertools-bun');
83
- const client = supertools(new Anthropic(), {
84
- tools: [queryDatabase, sendEmail],
85
- sandbox,
86
- });
87
93
 
88
- // Use exactly like the normal Anthropic SDK
89
- const response = await client.messages.create({
90
- model: 'claude-haiku-4-5-20251001',
91
- max_tokens: 1024,
92
- messages: [{
93
- role: 'user',
94
- content: 'Query sales for all 50 states, find the top 5, and email a report to the CEO'
95
- }],
96
- });
94
+ try {
95
+ const client = supertools(new Anthropic(), {
96
+ tools: [getOrders],
97
+ sandbox,
98
+ onEvent: (e) => {
99
+ if (e.type === 'tool_call') console.log(`→ ${e.tool}()`);
100
+ if (e.type === 'result') console.log('Result:', e.data);
101
+ },
102
+ });
97
103
 
98
- // Traditional: 2-3 LLM round-trips + tokens for all 50 results in context
99
- // Supertools: 1 LLM call, loop runs in sandbox, only final result returned
104
+ await client.messages.create({
105
+ model: 'claude-sonnet-4-5-20241022',
106
+ max_tokens: 1024,
107
+ messages: [{
108
+ role: 'user',
109
+ content: 'Get all completed orders and calculate the total revenue',
110
+ }],
111
+ });
112
+ } finally {
113
+ await sandbox.kill();
114
+ }
100
115
  ```
101
116
 
117
+ **What happens:** The LLM writes code that calls `getOrders()`, loops through results, and calculates the sum — all in one API call.
118
+
102
119
  ## How It Works
103
120
 
104
121
  When you ask: *"Query sales for all 50 states, find top 5, email a report"*
@@ -139,7 +156,7 @@ return { topStates: top5, reportSent: true };
139
156
  ## Why Supertools?
140
157
 
141
158
  <p align="center">
142
- <img src="assets/benchmark.svg" alt="Benchmark Results" width="100%">
159
+ <img src="https://raw.githubusercontent.com/bxxf/supertools/refs/heads/main/assets/benchmark.svg" alt="Benchmark Results" width="100%">
143
160
  </p>
144
161
 
145
162
  The benchmark compares three approaches on the same model (Claude Sonnet 4.5):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supertools-ai/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Programmatic tool calling for LLMs - let AI write code that orchestrates your tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,8 @@
18
18
  "README.md"
19
19
  ],
20
20
  "scripts": {
21
- "build": "bun build src/index.ts --outdir dist --target node --format esm && tsc --emitDeclarationOnly",
21
+ "clean": "rm -rf dist",
22
+ "build": "bun run clean && bun build src/index.ts --outdir dist --target node --format esm && tsc --emitDeclarationOnly",
22
23
  "dev": "bun --watch src/index.ts",
23
24
  "test": "bun test",
24
25
  "typecheck": "tsc --noEmit",
@@ -1,5 +0,0 @@
1
- /**
2
- * Protocol Validation Tests
3
- */
4
- export {};
5
- //# sourceMappingURL=protocol.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/protocol.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Security Module Tests
3
- */
4
- export {};
5
- //# sourceMappingURL=security.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"security.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/security.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Tool Module Tests
3
- */
4
- export {};
5
- //# sourceMappingURL=tool.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tool.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/dist/errors.d.ts DELETED
@@ -1,64 +0,0 @@
1
- export type ErrorCode = 'CODE_GENERATION_ERROR' | 'EXECUTION_ERROR' | 'TOOL_ERROR' | 'RELAY_CONNECTION_ERROR' | 'RELAY_TIMEOUT_ERROR' | 'PROTOCOL_ERROR' | 'SANDBOX_ERROR' | 'AUTHENTICATION_ERROR' | 'VALIDATION_ERROR' | 'CONFIGURATION_ERROR';
2
- export declare class OPTError extends Error {
3
- readonly code: ErrorCode;
4
- readonly cause?: Error;
5
- constructor(message: string, code: ErrorCode, cause?: Error);
6
- toJSON(): {
7
- name: string;
8
- code: ErrorCode;
9
- message: string;
10
- cause: string | undefined;
11
- };
12
- }
13
- export declare class CodeGenerationError extends OPTError {
14
- constructor(message: string, cause?: Error);
15
- }
16
- export declare class ExecutionError extends OPTError {
17
- readonly output?: string;
18
- constructor(message: string, output?: string, cause?: Error);
19
- toJSON(): {
20
- output: string | undefined;
21
- name: string;
22
- code: ErrorCode;
23
- message: string;
24
- cause: string | undefined;
25
- };
26
- }
27
- export declare class ToolError extends OPTError {
28
- readonly toolName: string;
29
- constructor(message: string, toolName: string, cause?: Error);
30
- toJSON(): {
31
- toolName: string;
32
- name: string;
33
- code: ErrorCode;
34
- message: string;
35
- cause: string | undefined;
36
- };
37
- }
38
- export declare class RelayConnectionError extends OPTError {
39
- constructor(message: string, cause?: Error);
40
- }
41
- export declare class RelayTimeoutError extends OPTError {
42
- constructor(message: string);
43
- }
44
- export declare class SandboxError extends OPTError {
45
- constructor(message: string, cause?: Error);
46
- }
47
- export declare class AuthenticationError extends OPTError {
48
- constructor(message: string);
49
- }
50
- export declare class ConfigurationError extends OPTError {
51
- constructor(message: string);
52
- }
53
- export declare class ValidationError extends OPTError {
54
- readonly field?: string;
55
- constructor(message: string, field?: string);
56
- toJSON(): {
57
- field: string | undefined;
58
- name: string;
59
- code: ErrorCode;
60
- message: string;
61
- cause: string | undefined;
62
- };
63
- }
64
- //# sourceMappingURL=errors.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,uBAAuB,GACvB,iBAAiB,GACjB,YAAY,GACZ,wBAAwB,GACxB,qBAAqB,GACrB,gBAAgB,GAChB,eAAe,GACf,sBAAsB,GACtB,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,KAAK;IAQ3D,MAAM;;;;;;CAQP;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AAED,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;IAMlD,MAAM;;;;;;;CAGhB;AAED,qBAAa,SAAU,SAAQ,QAAQ;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;IAMnD,MAAM;;;;;;;CAGhB;AAED,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,YAAa,SAAQ,QAAQ;gBAC5B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAMlC,MAAM;;;;;;;CAGhB"}
package/dist/index.d.mts DELETED
@@ -1,183 +0,0 @@
1
- import { z } from 'zod';
2
- export { z } from 'zod';
3
-
4
- declare const TOOL_BRAND: unique symbol;
5
- type ZodSchema = z.ZodType;
6
- type InferInput<T extends ZodSchema> = z.infer<T>;
7
- type ExecuteFn<T extends ZodSchema> = (params: InferInput<T>) => unknown | Promise<unknown>;
8
- interface ToolDefinition<T extends ZodSchema> {
9
- readonly name: string;
10
- readonly description: string;
11
- readonly parameters: T;
12
- readonly execute: ExecuteFn<T>;
13
- }
14
- interface Tool<T extends ZodSchema = ZodSchema> {
15
- readonly name: string;
16
- readonly description: string;
17
- readonly parameters: T;
18
- readonly execute: ExecuteFn<T>;
19
- readonly [TOOL_BRAND]: true;
20
- }
21
- interface NormalizedParameter {
22
- readonly name: string;
23
- readonly type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'any';
24
- readonly description: string;
25
- readonly required: boolean;
26
- readonly default?: unknown;
27
- }
28
- interface NormalizedTool {
29
- readonly name: string;
30
- readonly description: string;
31
- readonly parameters: readonly NormalizedParameter[];
32
- readonly execute: (params: Record<string, unknown>) => unknown | Promise<unknown>;
33
- }
34
- /**
35
- * Define a tool with type-safe parameters.
36
- *
37
- * @example
38
- * const searchUsers = defineTool({
39
- * name: 'searchUsers',
40
- * description: 'Search users by name or email',
41
- * parameters: z.object({
42
- * query: z.string().describe('Search query'),
43
- * limit: z.number().optional().default(10),
44
- * }),
45
- * execute: async ({ query, limit }) => db.users.search(query).limit(limit),
46
- * });
47
- */
48
- declare function defineTool<T extends ZodSchema>(definition: ToolDefinition<T>): Tool<T>;
49
- declare function isTool(value: unknown): value is Tool;
50
- declare function normalizeTools(tools: readonly Tool[]): NormalizedTool[];
51
-
52
- type ToolCollection = readonly Tool[];
53
- interface ExecutionResult {
54
- readonly success: boolean;
55
- readonly output: string;
56
- readonly error?: string;
57
- readonly executionTimeMs: number;
58
- readonly images?: readonly string[];
59
- }
60
- interface GeneratedCode {
61
- readonly code: string;
62
- readonly explanation?: string;
63
- readonly rawResponse?: string;
64
- }
65
- interface ProgrammaticResult {
66
- readonly code: string;
67
- readonly explanation?: string;
68
- readonly result: ExecutionResult;
69
- }
70
- interface ToolCallRequest {
71
- readonly tool: string;
72
- readonly arguments: Readonly<Record<string, unknown>>;
73
- }
74
- interface ToolCallResponse {
75
- readonly success: boolean;
76
- readonly result?: unknown;
77
- readonly error?: string;
78
- }
79
- interface LLMAdapter {
80
- generateCode(userRequest: string, systemPrompt: string): Promise<GeneratedCode>;
81
- }
82
- interface ExecutorConfig {
83
- readonly tools: ToolCollection;
84
- readonly timeout?: number;
85
- readonly e2bApiKey?: string;
86
- readonly instructions?: string;
87
- readonly debug?: boolean;
88
- }
89
-
90
- /**
91
- * Programmatic Executor
92
- *
93
- * Orchestrates the complete flow:
94
- * 1. LLM generates JavaScript code
95
- * 2. Code executes in secure E2B Bun sandbox
96
- * 3. Tool calls relay back to host via WebSocket
97
- * 4. Results return to user
98
- */
99
-
100
- interface CreateExecutorOptions extends ExecutorConfig {
101
- readonly llm: LLMAdapter;
102
- }
103
- declare function createExecutor(options: CreateExecutorOptions): ProgrammaticExecutor;
104
- declare class ProgrammaticExecutor {
105
- private readonly originalTools;
106
- private readonly normalizedTools;
107
- private readonly toolsMap;
108
- private readonly llm;
109
- private readonly timeout;
110
- private readonly e2bApiKey?;
111
- private readonly instructions?;
112
- private readonly debug;
113
- constructor(options: CreateExecutorOptions);
114
- run(userRequest: string): Promise<ProgrammaticResult>;
115
- executeCode(code: string): Promise<ExecutionResult>;
116
- getTools(): readonly NormalizedTool[];
117
- getToolDocumentation(): string;
118
- private generateCode;
119
- private createSandbox;
120
- private connectRelay;
121
- private cleanup;
122
- private log;
123
- }
124
-
125
- type ErrorCode = 'CODE_GENERATION_ERROR' | 'EXECUTION_ERROR' | 'TOOL_ERROR' | 'RELAY_CONNECTION_ERROR' | 'RELAY_TIMEOUT_ERROR' | 'PROTOCOL_ERROR' | 'SANDBOX_ERROR' | 'AUTHENTICATION_ERROR' | 'VALIDATION_ERROR' | 'CONFIGURATION_ERROR';
126
- declare class OPTError extends Error {
127
- readonly code: ErrorCode;
128
- readonly cause?: Error;
129
- constructor(message: string, code: ErrorCode, cause?: Error);
130
- toJSON(): {
131
- name: string;
132
- code: ErrorCode;
133
- message: string;
134
- cause: string | undefined;
135
- };
136
- }
137
- declare class CodeGenerationError extends OPTError {
138
- constructor(message: string, cause?: Error);
139
- }
140
- declare class ExecutionError extends OPTError {
141
- readonly output?: string;
142
- constructor(message: string, output?: string, cause?: Error);
143
- toJSON(): {
144
- output: string | undefined;
145
- name: string;
146
- code: ErrorCode;
147
- message: string;
148
- cause: string | undefined;
149
- };
150
- }
151
- declare class ToolError extends OPTError {
152
- readonly toolName: string;
153
- constructor(message: string, toolName: string, cause?: Error);
154
- toJSON(): {
155
- toolName: string;
156
- name: string;
157
- code: ErrorCode;
158
- message: string;
159
- cause: string | undefined;
160
- };
161
- }
162
- declare class RelayConnectionError extends OPTError {
163
- constructor(message: string, cause?: Error);
164
- }
165
- declare class RelayTimeoutError extends OPTError {
166
- constructor(message: string);
167
- }
168
- declare class SandboxError extends OPTError {
169
- constructor(message: string, cause?: Error);
170
- }
171
- declare class AuthenticationError extends OPTError {
172
- constructor(message: string);
173
- }
174
- declare class ConfigurationError extends OPTError {
175
- constructor(message: string);
176
- }
177
-
178
- declare function buildSystemPrompt(toolDefinitions: string, additionalInstructions?: string): string;
179
- declare function extractCode(response: string): string;
180
-
181
- declare function generateTypeHints(tools: readonly Tool[]): string;
182
-
183
- export { AuthenticationError, CodeGenerationError, ConfigurationError, type CreateExecutorOptions, ExecutionError, type ExecutionResult, type ExecutorConfig, type GeneratedCode, type LLMAdapter, type NormalizedParameter, type NormalizedTool, OPTError, ProgrammaticExecutor, type ProgrammaticResult, RelayConnectionError, RelayTimeoutError, SandboxError, type Tool, type ToolCallRequest, type ToolCallResponse, type ToolCollection, type ToolDefinition, ToolError, buildSystemPrompt, createExecutor, defineTool, extractCode, generateTypeHints, isTool, normalizeTools };