@spec2tools/sdk 0.1.2 → 0.2.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/README.md +45 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib.d.ts +23 -4
- package/dist/lib.js +28 -65
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -27,6 +27,47 @@ const result = await generateText({
|
|
|
27
27
|
console.log(result.text);
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
### Code Mode
|
|
31
|
+
|
|
32
|
+
Enable code mode to collapse all endpoints into 2 tools (`search` + `execute`), reducing token usage by ~99.9%:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const tools = await createTools({
|
|
36
|
+
spec: './openapi.yaml',
|
|
37
|
+
codeMode: true,
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Code Mode for MCP Clients
|
|
42
|
+
|
|
43
|
+
Use `convertToolsToCodeMode` to apply code mode to tools from any source, such as `createMCPClient` from `@ai-sdk/mcp`:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
47
|
+
import { convertToolsToCodeMode } from '@spec2tools/sdk';
|
|
48
|
+
import { generateText, stepCountIs } from 'ai';
|
|
49
|
+
import { openai } from '@ai-sdk/openai';
|
|
50
|
+
|
|
51
|
+
const client = await createMCPClient({
|
|
52
|
+
transport: { type: 'sse', url: 'http://localhost:3000/sse' },
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const tools = convertToolsToCodeMode(await client.tools());
|
|
57
|
+
|
|
58
|
+
const result = await generateText({
|
|
59
|
+
model: openai('gpt-4o'),
|
|
60
|
+
tools,
|
|
61
|
+
prompt: 'List all users',
|
|
62
|
+
stopWhen: stepCountIs(3),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log(result.text);
|
|
66
|
+
} finally {
|
|
67
|
+
await client.close();
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
30
71
|
## API
|
|
31
72
|
|
|
32
73
|
### `createTools(options: Spec2ToolsOptions): Promise<ToolSet>`
|
|
@@ -36,6 +77,7 @@ Creates AI SDK-compatible tools from an OpenAPI specification.
|
|
|
36
77
|
#### Options
|
|
37
78
|
|
|
38
79
|
- `spec` (string, required): Path or URL to the OpenAPI specification file (JSON or YAML)
|
|
80
|
+
- `codeMode` (boolean, optional): When `true`, returns 2 code-mode tools instead of one per endpoint
|
|
39
81
|
|
|
40
82
|
#### Returns
|
|
41
83
|
|
|
@@ -43,12 +85,11 @@ A `Promise` that resolves to an object of AI SDK tools.
|
|
|
43
85
|
|
|
44
86
|
#### Throws
|
|
45
87
|
|
|
46
|
-
- `Error` if the API requires authentication. For authenticated APIs, use the `@spec2tools/cli` package instead.
|
|
88
|
+
- `Error` if the API requires authentication (unless `codeMode` is enabled). For authenticated APIs, use the `@spec2tools/cli` package instead.
|
|
47
89
|
|
|
48
|
-
|
|
90
|
+
### `convertToolsToCodeMode(tools: ToolSet): ToolSet`
|
|
49
91
|
|
|
50
|
-
|
|
51
|
-
- For authenticated APIs, use the CLI: `npx @spec2tools/cli start --spec ./openapi.yaml`
|
|
92
|
+
Converts an existing AI SDK ToolSet into code mode (2 tools: `search` + `execute`). Useful when you have tools from another source (e.g. `createMCPClient` from `@ai-sdk/mcp`) and want to reduce token usage.
|
|
52
93
|
|
|
53
94
|
## License
|
|
54
95
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createTools, type Spec2ToolsOptions } from './lib.js';
|
|
1
|
+
export { createTools, convertToolsToCodeMode, type Spec2ToolsOptions } from './lib.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createTools } from './lib.js';
|
|
1
|
+
export { createTools, convertToolsToCodeMode } from './lib.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { toCodeModeTools, type ToolSet } from '@spec2tools/core';
|
|
2
|
+
/**
|
|
3
|
+
* Convert an existing AI SDK ToolSet into code mode (2 tools: search + execute).
|
|
4
|
+
*
|
|
5
|
+
* Useful when you already have tools from another source (e.g. `createMCPClient`)
|
|
6
|
+
* and want to reduce token usage by collapsing them into code mode.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { createMCPClient } from '@ai-sdk/mcp';
|
|
11
|
+
* import { convertToolsToCodeMode } from '@spec2tools/sdk';
|
|
12
|
+
*
|
|
13
|
+
* const client = await createMCPClient({
|
|
14
|
+
* transport: { type: 'sse', url: 'http://localhost:3000/sse' },
|
|
15
|
+
* });
|
|
16
|
+
* const tools = await client.tools();
|
|
17
|
+
* const codeModeTools = convertToolsToCodeMode(tools);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const convertToolsToCodeMode: typeof toCodeModeTools;
|
|
3
21
|
export interface Spec2ToolsOptions {
|
|
4
22
|
/** Path or URL to OpenAPI specification */
|
|
5
23
|
spec: string;
|
|
24
|
+
/** Use code mode (2 tools: search + execute) instead of one tool per endpoint */
|
|
25
|
+
codeMode?: boolean;
|
|
6
26
|
}
|
|
7
27
|
/**
|
|
8
28
|
* Create AI SDK tools from an OpenAPI specification.
|
|
@@ -22,8 +42,7 @@ export interface Spec2ToolsOptions {
|
|
|
22
42
|
* });
|
|
23
43
|
* ```
|
|
24
44
|
*
|
|
25
|
-
* @throws Error if the API requires authentication
|
|
45
|
+
* @throws Error if the API requires authentication (unless codeMode is enabled)
|
|
26
46
|
*/
|
|
27
47
|
export declare function createTools(options: Spec2ToolsOptions): Promise<ToolSet>;
|
|
28
|
-
export {};
|
|
29
48
|
//# sourceMappingURL=lib.d.ts.map
|
package/dist/lib.js
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { loadOpenAPISpec, extractBaseUrl, extractAuthConfig, parseOperations, createExecutableTools, toAISDKTools, toCodeModeTools, AuthManager, } from '@spec2tools/core';
|
|
2
|
+
/**
|
|
3
|
+
* Convert an existing AI SDK ToolSet into code mode (2 tools: search + execute).
|
|
4
|
+
*
|
|
5
|
+
* Useful when you already have tools from another source (e.g. `createMCPClient`)
|
|
6
|
+
* and want to reduce token usage by collapsing them into code mode.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { createMCPClient } from '@ai-sdk/mcp';
|
|
11
|
+
* import { convertToolsToCodeMode } from '@spec2tools/sdk';
|
|
12
|
+
*
|
|
13
|
+
* const client = await createMCPClient({
|
|
14
|
+
* transport: { type: 'sse', url: 'http://localhost:3000/sse' },
|
|
15
|
+
* });
|
|
16
|
+
* const tools = await client.tools();
|
|
17
|
+
* const codeModeTools = convertToolsToCodeMode(tools);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const convertToolsToCodeMode = toCodeModeTools;
|
|
3
21
|
/**
|
|
4
22
|
* Create AI SDK tools from an OpenAPI specification.
|
|
5
23
|
*
|
|
@@ -18,80 +36,25 @@ import { loadOpenAPISpec, extractBaseUrl, extractAuthConfig, parseOperations, Au
|
|
|
18
36
|
* });
|
|
19
37
|
* ```
|
|
20
38
|
*
|
|
21
|
-
* @throws Error if the API requires authentication
|
|
39
|
+
* @throws Error if the API requires authentication (unless codeMode is enabled)
|
|
22
40
|
*/
|
|
23
41
|
export async function createTools(options) {
|
|
24
42
|
const spec = await loadOpenAPISpec(options.spec);
|
|
25
43
|
const baseUrl = extractBaseUrl(spec);
|
|
26
44
|
const authConfig = extractAuthConfig(spec);
|
|
27
|
-
// Check if auth is required
|
|
28
|
-
if (authConfig.type !== 'none') {
|
|
45
|
+
// Check if auth is required (skip in code mode — auth is handled internally)
|
|
46
|
+
if (!options.codeMode && authConfig.type !== 'none') {
|
|
29
47
|
throw new Error(`This API requires authentication (${authConfig.type}). ` +
|
|
30
48
|
`The createTools() function only supports APIs without authentication. ` +
|
|
31
49
|
`Use the CLI for authenticated APIs: npx @spec2tools/cli start --spec ${options.spec}`);
|
|
32
50
|
}
|
|
33
51
|
const toolDefs = parseOperations(spec);
|
|
34
52
|
const authManager = new AuthManager(authConfig);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
tools[name] = tool({
|
|
40
|
-
description,
|
|
41
|
-
inputSchema: parameters,
|
|
42
|
-
execute: async (params) => {
|
|
43
|
-
// Build URL with path parameters
|
|
44
|
-
let url = `${baseUrl}${path}`;
|
|
45
|
-
const queryParams = {};
|
|
46
|
-
const bodyParams = {};
|
|
47
|
-
for (const [key, value] of Object.entries(params)) {
|
|
48
|
-
if (value === undefined)
|
|
49
|
-
continue;
|
|
50
|
-
if (url.includes(`{${key}}`)) {
|
|
51
|
-
// Path parameter
|
|
52
|
-
url = url.replace(`{${key}}`, encodeURIComponent(String(value)));
|
|
53
|
-
}
|
|
54
|
-
else if (httpMethod === 'GET' || httpMethod === 'DELETE') {
|
|
55
|
-
// Query parameter for GET/DELETE
|
|
56
|
-
queryParams[key] = String(value);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
// Body parameter for POST/PUT/PATCH
|
|
60
|
-
bodyParams[key] = value;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Add query parameters
|
|
64
|
-
const queryString = new URLSearchParams(queryParams).toString();
|
|
65
|
-
if (queryString) {
|
|
66
|
-
url += `?${queryString}`;
|
|
67
|
-
}
|
|
68
|
-
// Build request options
|
|
69
|
-
const fetchOptions = {
|
|
70
|
-
method: httpMethod,
|
|
71
|
-
headers: {
|
|
72
|
-
'Content-Type': 'application/json',
|
|
73
|
-
...authManager.getAuthHeaders(),
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
// Add body for non-GET/DELETE requests
|
|
77
|
-
if (Object.keys(bodyParams).length > 0 &&
|
|
78
|
-
httpMethod !== 'GET' &&
|
|
79
|
-
httpMethod !== 'DELETE') {
|
|
80
|
-
fetchOptions.body = JSON.stringify(bodyParams);
|
|
81
|
-
}
|
|
82
|
-
const response = await fetch(url, fetchOptions);
|
|
83
|
-
if (!response.ok) {
|
|
84
|
-
const errorText = await response.text();
|
|
85
|
-
throw new ToolExecutionError(name, new Error(`HTTP ${response.status}: ${errorText}`));
|
|
86
|
-
}
|
|
87
|
-
const contentType = response.headers.get('content-type');
|
|
88
|
-
if (contentType?.includes('application/json')) {
|
|
89
|
-
return await response.json();
|
|
90
|
-
}
|
|
91
|
-
return await response.text();
|
|
92
|
-
},
|
|
93
|
-
});
|
|
53
|
+
const tools = createExecutableTools(toolDefs, baseUrl, authManager);
|
|
54
|
+
let aiTools = toAISDKTools(tools);
|
|
55
|
+
if (options.codeMode) {
|
|
56
|
+
aiTools = toCodeModeTools(aiTools);
|
|
94
57
|
}
|
|
95
|
-
return
|
|
58
|
+
return aiTools;
|
|
96
59
|
}
|
|
97
60
|
//# sourceMappingURL=lib.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spec2tools/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Create AI SDK tools from OpenAPI specifications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,14 +32,15 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"ai": "^6.0.68",
|
|
34
34
|
"zod": "^3.24.0",
|
|
35
|
-
"@spec2tools/core": "0.
|
|
35
|
+
"@spec2tools/core": "0.2.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"zod": "^3.24.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^22.0.0",
|
|
42
|
-
"typescript": "^5.6.0"
|
|
42
|
+
"typescript": "^5.6.0",
|
|
43
|
+
"vitest": "^4.0.18"
|
|
43
44
|
},
|
|
44
45
|
"engines": {
|
|
45
46
|
"node": ">=18.0.0"
|
|
@@ -47,6 +48,8 @@
|
|
|
47
48
|
"scripts": {
|
|
48
49
|
"build": "tsc",
|
|
49
50
|
"dev": "tsc --watch",
|
|
50
|
-
"typecheck": "tsc --noEmit"
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest"
|
|
51
54
|
}
|
|
52
55
|
}
|