@spec2tools/cli 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # @spec2tools/cli
2
+
3
+ CLI for interacting with OpenAPI-based AI tools.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @spec2tools/cli
9
+ ```
10
+
11
+ Or use directly with npx:
12
+
13
+ ```bash
14
+ npx @spec2tools/cli start --spec ./openapi.yaml
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### Set Environment Variables
20
+
21
+ Define a `.env` file and set the `OPENAI_API_KEY` environment variable:
22
+
23
+ ```
24
+ OPENAI_API_KEY=your-api-key
25
+ ```
26
+
27
+ ### Start the Agent
28
+
29
+ ```bash
30
+ # With a remote OpenAPI spec URL
31
+ npx @spec2tools/cli start --spec https://api.example.com/openapi.json
32
+
33
+ # With a local file
34
+ npx @spec2tools/cli start --spec ./openapi.yaml
35
+
36
+ # Skip authentication
37
+ npx @spec2tools/cli start --spec ./openapi.yaml --no-auth
38
+
39
+ # Provide token directly
40
+ npx @spec2tools/cli start --spec ./openapi.yaml --token "your-access-token"
41
+ ```
42
+
43
+ ### Chat Mode
44
+
45
+ Once started, you can interact with the AI agent naturally:
46
+
47
+ ```
48
+ > What can you do?
49
+ I have access to the following tools:
50
+ - createUser: Create a new user
51
+ - getUser: Retrieve user by ID
52
+ - listUsers: List all users
53
+
54
+ > Create a user named John with email john@example.com
55
+ [Calling createUser with {"name":"John","email":"john@example.com"}]
56
+ Created user successfully: { id: "123", name: "John", email: "john@example.com" }
57
+ ```
58
+
59
+ ### Special Commands
60
+
61
+ ```bash
62
+ # List available tools
63
+ > /tools
64
+
65
+ # Call a tool directly
66
+ > /call createUser --name "John" --email "john@example.com"
67
+
68
+ # Show tool schema
69
+ > /schema createUser
70
+
71
+ # Clear conversation history
72
+ > /clear
73
+
74
+ # Show help
75
+ > /help
76
+
77
+ # Exit
78
+ > /exit
79
+ ```
80
+
81
+ ## Examples
82
+
83
+ The `examples/` directory contains sample OpenAPI specifications:
84
+
85
+ - `sample-api.yaml` - Simple API without authentication
86
+ - `authenticated-api.yaml` - API with OAuth2 authentication
87
+ - `context7.yaml` - Context7 API with OAuth2 (PKCE + dynamic client registration)
88
+
89
+ ## Supported OpenAPI Features
90
+
91
+ ### Supported
92
+ - `GET`, `POST`, `PUT`, `PATCH`, `DELETE` operations
93
+ - Path parameters (string, number, boolean)
94
+ - Query parameters (string, number, boolean)
95
+ - Request body with simple JSON schemas (primitives, flat objects)
96
+ - Security schemes: OAuth2 (authorization code with PKCE), API Key, Bearer token
97
+ - OAuth2 Dynamic Client Registration (auto-registers client with the auth server)
98
+
99
+ ### Not Supported (throws error)
100
+ - Nested objects beyond 1 level
101
+ - Arrays of objects
102
+ - `anyOf`, `oneOf`, `allOf` schemas
103
+ - File uploads
104
+ - `$ref` references
105
+
106
+ ## License
107
+
108
+ MIT
@@ -0,0 +1,38 @@
1
+ import { type Tool } from '@spec2tools/core';
2
+ interface AgentConfig {
3
+ tools: Tool[];
4
+ model?: string;
5
+ maxSteps?: number;
6
+ }
7
+ /**
8
+ * AI Agent that uses OpenAPI tools
9
+ */
10
+ export declare class Agent {
11
+ private tools;
12
+ private model;
13
+ private maxSteps;
14
+ private conversationHistory;
15
+ constructor(config: AgentConfig);
16
+ /**
17
+ * Get available tools description for the agent
18
+ */
19
+ getToolsDescription(): string;
20
+ /**
21
+ * Process a user message and return the response
22
+ */
23
+ chat(userMessage: string): Promise<string>;
24
+ /**
25
+ * Clear conversation history
26
+ */
27
+ clearHistory(): void;
28
+ /**
29
+ * Get the list of tool names
30
+ */
31
+ getToolNames(): string[];
32
+ /**
33
+ * Get a specific tool by name
34
+ */
35
+ getTool(name: string): Tool | undefined;
36
+ }
37
+ export {};
38
+ //# sourceMappingURL=agent.d.ts.map
package/dist/agent.js ADDED
@@ -0,0 +1,126 @@
1
+ import { generateText, tool, stepCountIs } from 'ai';
2
+ import { openai } from '@ai-sdk/openai';
3
+ import { ToolExecutionError } from '@spec2tools/core';
4
+ import chalk from 'chalk';
5
+ const MAX_OUTPUT_LENGTH = 500;
6
+ /**
7
+ * Trim a string if it exceeds the maximum length
8
+ */
9
+ function trimOutput(value) {
10
+ const str = typeof value === 'string' ? value : JSON.stringify(value);
11
+ if (str.length > MAX_OUTPUT_LENGTH) {
12
+ return str.substring(0, MAX_OUTPUT_LENGTH) + '...';
13
+ }
14
+ return str;
15
+ }
16
+ /**
17
+ * AI Agent that uses OpenAPI tools
18
+ */
19
+ export class Agent {
20
+ tools;
21
+ model;
22
+ maxSteps;
23
+ conversationHistory;
24
+ constructor(config) {
25
+ this.tools = config.tools;
26
+ this.model = config.model || 'gpt-5.1-chat-latest';
27
+ this.maxSteps = config.maxSteps || 10;
28
+ this.conversationHistory = [];
29
+ }
30
+ /**
31
+ * Get available tools description for the agent
32
+ */
33
+ getToolsDescription() {
34
+ if (this.tools.length === 0) {
35
+ return 'No tools available.';
36
+ }
37
+ const toolDescriptions = this.tools.map((tool) => {
38
+ return `- ${tool.name}: ${tool.description}`;
39
+ });
40
+ return `I have access to the following tools:\n${toolDescriptions.join('\n')}`;
41
+ }
42
+ /**
43
+ * Process a user message and return the response
44
+ */
45
+ async chat(userMessage) {
46
+ // Add user message to history
47
+ this.conversationHistory.push({
48
+ role: 'user',
49
+ content: userMessage,
50
+ });
51
+ try {
52
+ // Build AI SDK tools from our tool definitions
53
+ const aiTools = {};
54
+ for (const t of this.tools) {
55
+ const toolExecute = t.execute;
56
+ const toolName = t.name;
57
+ aiTools[t.name] = tool({
58
+ description: t.description,
59
+ inputSchema: t.parameters,
60
+ execute: async (params) => {
61
+ console.log(chalk.dim(`\n[Calling ${toolName} with ${JSON.stringify(params)}]`));
62
+ try {
63
+ const result = await toolExecute(params);
64
+ console.log(chalk.dim(`[${toolName} returned: ${trimOutput(result)}]\n`));
65
+ return result;
66
+ }
67
+ catch (error) {
68
+ if (error instanceof ToolExecutionError) {
69
+ console.log(chalk.red(`[${toolName} failed: ${error.message}]\n`));
70
+ throw error;
71
+ }
72
+ throw error;
73
+ }
74
+ },
75
+ });
76
+ }
77
+ // Build system prompt
78
+ const systemPrompt = `You are a helpful AI assistant with access to various API tools.
79
+ When the user asks you to perform actions, use the available tools to help them.
80
+ Always explain what you're doing and present results in a clear, readable format.
81
+ If a tool call fails, explain the error to the user.`;
82
+ // Generate response with tool use
83
+ const result = await generateText({
84
+ model: openai(this.model),
85
+ system: systemPrompt,
86
+ messages: this.conversationHistory,
87
+ tools: aiTools,
88
+ stopWhen: stepCountIs(this.maxSteps),
89
+ });
90
+ // Add assistant response to history
91
+ this.conversationHistory.push({
92
+ role: 'assistant',
93
+ content: result.text,
94
+ });
95
+ return result.text;
96
+ }
97
+ catch (error) {
98
+ const errorMessage = error instanceof Error ? error.message : String(error);
99
+ // Add error response to history
100
+ this.conversationHistory.push({
101
+ role: 'assistant',
102
+ content: `I encountered an error: ${errorMessage}`,
103
+ });
104
+ throw error;
105
+ }
106
+ }
107
+ /**
108
+ * Clear conversation history
109
+ */
110
+ clearHistory() {
111
+ this.conversationHistory = [];
112
+ }
113
+ /**
114
+ * Get the list of tool names
115
+ */
116
+ getToolNames() {
117
+ return this.tools.map((t) => t.name);
118
+ }
119
+ /**
120
+ * Get a specific tool by name
121
+ */
122
+ getTool(name) {
123
+ return this.tools.find((t) => t.name === name);
124
+ }
125
+ }
126
+ //# sourceMappingURL=agent.js.map
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createCLI(): Command;
3
+ //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js ADDED
@@ -0,0 +1,312 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import * as readline from 'readline';
5
+ import { loadOpenAPISpec, extractBaseUrl, extractAuthConfig, parseOperations, formatToolSchema, formatToolSignature, AuthManager, createExecutableTools, executeToolByName, UnsupportedSchemaError, AuthenticationError, ToolExecutionError, SpecLoadError, } from '@spec2tools/core';
6
+ import { Agent } from './agent.js';
7
+ const VERSION = '0.1.6';
8
+ export function createCLI() {
9
+ const program = new Command();
10
+ program
11
+ .name('spec2tools')
12
+ .description('Dynamically convert OpenAPI specs into AI agent tools at runtime')
13
+ .version(VERSION);
14
+ program
15
+ .command('start')
16
+ .description('Start the agent with an OpenAPI specification')
17
+ .requiredOption('-s, --spec <path>', 'Path or URL to OpenAPI specification')
18
+ .option('--no-auth', 'Skip authentication even if required by spec')
19
+ .option('--token <token>', 'Provide access token directly')
20
+ .action(async (options) => {
21
+ await startAgent(options);
22
+ });
23
+ return program;
24
+ }
25
+ async function startAgent(options) {
26
+ const spinner = ora();
27
+ try {
28
+ // Load OpenAPI spec
29
+ spinner.start('Loading OpenAPI specification...');
30
+ const spec = await loadOpenAPISpec(options.spec);
31
+ spinner.succeed(`Loaded: ${spec.info.title} v${spec.info.version}`);
32
+ // Extract base URL
33
+ const baseUrl = extractBaseUrl(spec);
34
+ console.log(chalk.dim(`Base URL: ${baseUrl}`));
35
+ // Extract auth config
36
+ const authConfig = extractAuthConfig(spec);
37
+ // Parse operations
38
+ spinner.start('Parsing operations...');
39
+ const toolDefs = parseOperations(spec);
40
+ spinner.succeed(`Found ${toolDefs.length} operations`);
41
+ if (toolDefs.length === 0) {
42
+ console.log(chalk.yellow('No operations found in the specification.'));
43
+ return;
44
+ }
45
+ // Initialize auth manager
46
+ const authManager = new AuthManager(authConfig);
47
+ // Handle authentication
48
+ if (options.token) {
49
+ authManager.setAccessToken(options.token);
50
+ console.log(chalk.green('Using provided access token'));
51
+ }
52
+ else if (options.auth && authManager.requiresAuth()) {
53
+ console.log(chalk.yellow(`\nAuthentication required (${authConfig.type})`));
54
+ await authManager.authenticate();
55
+ console.log(chalk.green('Authentication successful!'));
56
+ }
57
+ else if (authManager.requiresAuth()) {
58
+ console.log(chalk.yellow('\nWarning: API requires authentication but --no-auth was specified'));
59
+ }
60
+ // Create executable tools
61
+ const tools = createExecutableTools(toolDefs, baseUrl, authManager);
62
+ // Initialize session
63
+ const session = {
64
+ baseUrl,
65
+ tools,
66
+ authConfig,
67
+ accessToken: authManager.getAccessToken(),
68
+ };
69
+ // Start chat loop
70
+ await startChatLoop(session);
71
+ }
72
+ catch (error) {
73
+ spinner.fail();
74
+ if (error instanceof UnsupportedSchemaError) {
75
+ console.error(chalk.red(`\nSchema Error: ${error.message}`));
76
+ console.error(chalk.dim('This OpenAPI specification contains features that are not supported.'));
77
+ }
78
+ else if (error instanceof AuthenticationError) {
79
+ console.error(chalk.red(`\nAuth Error: ${error.message}`));
80
+ }
81
+ else if (error instanceof SpecLoadError) {
82
+ console.error(chalk.red(`\nSpec Error: ${error.message}`));
83
+ }
84
+ else {
85
+ console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : String(error)}`));
86
+ }
87
+ process.exit(1);
88
+ }
89
+ }
90
+ async function startChatLoop(session) {
91
+ // Initialize agent
92
+ const agent = new Agent({ tools: session.tools });
93
+ console.log(chalk.bold('\n--- Spec2Tools ---'));
94
+ console.log(chalk.dim('Type your message or use special commands:'));
95
+ console.log(chalk.dim(' /tools - List available tools'));
96
+ console.log(chalk.dim(' /call - Call a tool directly'));
97
+ console.log(chalk.dim(' /schema - Show tool schema'));
98
+ console.log(chalk.dim(' /help - Show help'));
99
+ console.log(chalk.dim(' /exit - Exit the CLI'));
100
+ console.log('');
101
+ const rl = readline.createInterface({
102
+ input: process.stdin,
103
+ output: process.stdout,
104
+ });
105
+ const prompt = () => {
106
+ rl.question(chalk.cyan('> '), async (input) => {
107
+ const trimmedInput = input.trim();
108
+ if (!trimmedInput) {
109
+ prompt();
110
+ return;
111
+ }
112
+ // Pause readline during async operations to prevent corruption
113
+ rl.pause();
114
+ try {
115
+ await handleInput(trimmedInput, session, agent);
116
+ }
117
+ catch (error) {
118
+ console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
119
+ }
120
+ finally {
121
+ rl.resume();
122
+ prompt();
123
+ }
124
+ });
125
+ };
126
+ rl.on('close', () => {
127
+ console.log(chalk.dim('\nGoodbye!'));
128
+ process.exit(0);
129
+ });
130
+ prompt();
131
+ }
132
+ async function handleInput(input, session, agent) {
133
+ // Handle special commands
134
+ if (input.startsWith('/')) {
135
+ await handleCommand(input, session, agent);
136
+ return;
137
+ }
138
+ // Regular chat message
139
+ const spinner = ora('Thinking...').start();
140
+ try {
141
+ const response = await agent.chat(input);
142
+ spinner.stop();
143
+ console.log(chalk.white('\n' + response + '\n'));
144
+ }
145
+ catch (error) {
146
+ spinner.fail('Failed to get response');
147
+ throw error;
148
+ }
149
+ }
150
+ async function handleCommand(input, session, agent) {
151
+ const parts = input.slice(1).split(/\s+/);
152
+ const command = parts[0].toLowerCase();
153
+ const args = parts.slice(1);
154
+ switch (command) {
155
+ case 'tools':
156
+ listTools(session.tools);
157
+ break;
158
+ case 'call':
159
+ await callTool(session.tools, args);
160
+ break;
161
+ case 'schema':
162
+ showSchema(session.tools, args[0]);
163
+ break;
164
+ case 'help':
165
+ showHelp();
166
+ break;
167
+ case 'exit':
168
+ case 'quit':
169
+ console.log(chalk.dim('Goodbye!'));
170
+ process.exit(0);
171
+ case 'clear':
172
+ agent.clearHistory();
173
+ console.log(chalk.dim('Conversation history cleared.'));
174
+ break;
175
+ default:
176
+ console.log(chalk.yellow(`Unknown command: ${command}`));
177
+ console.log(chalk.dim('Type /help for available commands.'));
178
+ }
179
+ }
180
+ function listTools(tools) {
181
+ console.log(chalk.bold('\nAvailable tools:'));
182
+ tools.forEach((tool, index) => {
183
+ const signature = formatToolSignature(tool);
184
+ console.log(chalk.cyan(`${index + 1}. ${signature}`));
185
+ console.log(chalk.dim(` ${tool.description}`));
186
+ });
187
+ console.log('');
188
+ }
189
+ async function callTool(tools, args) {
190
+ if (args.length === 0) {
191
+ console.log(chalk.yellow('Usage: /call <toolName> [--param value ...]'));
192
+ console.log(chalk.dim('Example: /call createUser --name "John" --email "john@example.com"'));
193
+ return;
194
+ }
195
+ const toolName = args[0];
196
+ const tool = tools.find((t) => t.name === toolName);
197
+ if (!tool) {
198
+ console.log(chalk.red(`Tool not found: ${toolName}`));
199
+ console.log(chalk.dim('Use /tools to see available tools.'));
200
+ return;
201
+ }
202
+ // Parse remaining args as --key value pairs
203
+ const params = parseCallArgs(args.slice(1));
204
+ const spinner = ora(`Calling ${toolName}...`).start();
205
+ try {
206
+ const result = await executeToolByName(tools, toolName, params);
207
+ spinner.succeed(`${toolName} completed`);
208
+ console.log(chalk.white('\nResult:'));
209
+ console.log(JSON.stringify(result, null, 2));
210
+ console.log('');
211
+ }
212
+ catch (error) {
213
+ spinner.fail(`${toolName} failed`);
214
+ if (error instanceof ToolExecutionError) {
215
+ console.error(chalk.red(error.message));
216
+ }
217
+ else {
218
+ console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
219
+ }
220
+ }
221
+ }
222
+ function parseCallArgs(args) {
223
+ const params = {};
224
+ let i = 0;
225
+ while (i < args.length) {
226
+ const arg = args[i];
227
+ if (arg.startsWith('--')) {
228
+ const key = arg.slice(2);
229
+ const value = args[i + 1];
230
+ if (value === undefined) {
231
+ params[key] = true;
232
+ i++;
233
+ }
234
+ else if (value.startsWith('--')) {
235
+ params[key] = true;
236
+ i++;
237
+ }
238
+ else {
239
+ // Try to parse as JSON, number, or boolean
240
+ params[key] = parseValue(value);
241
+ i += 2;
242
+ }
243
+ }
244
+ else {
245
+ i++;
246
+ }
247
+ }
248
+ return params;
249
+ }
250
+ function parseValue(value) {
251
+ // Remove quotes if present
252
+ if ((value.startsWith('"') && value.endsWith('"')) ||
253
+ (value.startsWith("'") && value.endsWith("'"))) {
254
+ return value.slice(1, -1);
255
+ }
256
+ // Try parsing as number
257
+ const num = Number(value);
258
+ if (!isNaN(num)) {
259
+ return num;
260
+ }
261
+ // Check for boolean
262
+ if (value.toLowerCase() === 'true')
263
+ return true;
264
+ if (value.toLowerCase() === 'false')
265
+ return false;
266
+ // Try parsing as JSON
267
+ try {
268
+ return JSON.parse(value);
269
+ }
270
+ catch {
271
+ return value;
272
+ }
273
+ }
274
+ function showSchema(tools, toolName) {
275
+ if (!toolName) {
276
+ console.log(chalk.yellow('Usage: /schema <toolName>'));
277
+ return;
278
+ }
279
+ const tool = tools.find((t) => t.name === toolName);
280
+ if (!tool) {
281
+ console.log(chalk.red(`Tool not found: ${toolName}`));
282
+ console.log(chalk.dim('Use /tools to see available tools.'));
283
+ return;
284
+ }
285
+ console.log(chalk.bold(`\nSchema for ${toolName}:`));
286
+ console.log(chalk.white(formatToolSchema(tool)));
287
+ console.log('');
288
+ }
289
+ function showHelp() {
290
+ console.log(chalk.bold('\nAgent CLI Help'));
291
+ console.log('');
292
+ console.log(chalk.cyan('Chat Mode:'));
293
+ console.log(' Just type your message to chat with the AI agent.');
294
+ console.log(' The agent can use available tools to help you.');
295
+ console.log('');
296
+ console.log(chalk.cyan('Special Commands:'));
297
+ console.log(chalk.white(' /tools') + chalk.dim(' - List all available tools'));
298
+ console.log(chalk.white(' /call <tool> [args]') +
299
+ chalk.dim(' - Call a tool directly'));
300
+ console.log(chalk.white(' /schema <tool>') + chalk.dim(' - Show tool parameter schema'));
301
+ console.log(chalk.white(' /clear') + chalk.dim(' - Clear conversation history'));
302
+ console.log(chalk.white(' /help') + chalk.dim(' - Show this help message'));
303
+ console.log(chalk.white(' /exit') + chalk.dim(' - Exit the CLI'));
304
+ console.log('');
305
+ console.log(chalk.cyan('Examples:'));
306
+ console.log(chalk.dim(' > What can you do?'));
307
+ console.log(chalk.dim(' > Create a user named John with email john@example.com'));
308
+ console.log(chalk.dim(' > /call createUser --name "John" --email "john@example.com"'));
309
+ console.log(chalk.dim(' > /schema createUser'));
310
+ console.log('');
311
+ }
312
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ import { createCLI } from './cli.js';
4
+ const program = createCLI();
5
+ program.parse(process.argv);
6
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@spec2tools/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for interacting with OpenAPI-based AI tools",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "bin": {
15
+ "spec2tools": "./dist/index.js"
16
+ },
17
+ "files": [
18
+ "dist/**/*.js",
19
+ "dist/**/*.d.ts"
20
+ ],
21
+ "keywords": [
22
+ "openapi",
23
+ "cli",
24
+ "ai",
25
+ "agent",
26
+ "tools",
27
+ "ai-sdk"
28
+ ],
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/CahidArda/spec2tools.git",
33
+ "directory": "packages/cli"
34
+ },
35
+ "dependencies": {
36
+ "@ai-sdk/openai": "^3.0.25",
37
+ "ai": "^6.0.68",
38
+ "chalk": "^5.3.0",
39
+ "commander": "^14.0.0",
40
+ "dotenv": "^17.2.3",
41
+ "ora": "^8.1.0",
42
+ "@spec2tools/core": "0.1.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^22.0.0",
46
+ "typescript": "^5.6.0"
47
+ },
48
+ "engines": {
49
+ "node": ">=18.0.0"
50
+ },
51
+ "scripts": {
52
+ "build": "tsc",
53
+ "postbuild": "chmod +x dist/index.js",
54
+ "dev": "tsc --watch",
55
+ "start": "node dist/index.js",
56
+ "typecheck": "tsc --noEmit"
57
+ }
58
+ }