@nordsym/apiclaw 1.3.7 → 1.3.8
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 +420 -200
- package/convex/_generated/api.d.ts +4 -0
- package/convex/agents.ts +403 -0
- package/convex/directCall.ts +80 -0
- package/convex/earnProgress.ts +753 -0
- package/convex/logs.ts +17 -0
- package/convex/providerKeys.ts +82 -2
- package/convex/schema.ts +71 -2
- package/convex/workspaces.ts +84 -2
- package/dist/adapters/base.d.ts +112 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +247 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude-desktop.d.ts +12 -0
- package/dist/adapters/claude-desktop.d.ts.map +1 -0
- package/dist/adapters/claude-desktop.js +36 -0
- package/dist/adapters/claude-desktop.js.map +1 -0
- package/dist/adapters/cline.d.ts +20 -0
- package/dist/adapters/cline.d.ts.map +1 -0
- package/dist/adapters/cline.js +77 -0
- package/dist/adapters/cline.js.map +1 -0
- package/dist/adapters/continue.d.ts +26 -0
- package/dist/adapters/continue.d.ts.map +1 -0
- package/dist/adapters/continue.js +68 -0
- package/dist/adapters/continue.js.map +1 -0
- package/dist/adapters/cursor.d.ts +12 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +38 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/custom.d.ts +47 -0
- package/dist/adapters/custom.d.ts.map +1 -0
- package/dist/adapters/custom.js +146 -0
- package/dist/adapters/custom.js.map +1 -0
- package/dist/adapters/detect.d.ts +69 -0
- package/dist/adapters/detect.d.ts.map +1 -0
- package/dist/adapters/detect.js +158 -0
- package/dist/adapters/detect.js.map +1 -0
- package/dist/adapters/index.d.ts +21 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +23 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/windsurf.d.ts +12 -0
- package/dist/adapters/windsurf.d.ts.map +1 -0
- package/dist/adapters/windsurf.js +39 -0
- package/dist/adapters/windsurf.js.map +1 -0
- package/dist/bin.d.ts +9 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +19 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +34 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +312 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/index.d.ts +9 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +9 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/restore.d.ts +50 -0
- package/dist/cli/commands/restore.d.ts.map +1 -0
- package/dist/cli/commands/restore.js +260 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +19 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +206 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +37 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +189 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +97 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/discovery.d.ts +6 -2
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +296 -2
- package/dist/discovery.js.map +1 -1
- package/dist/enterprise/env.d.ts +56 -0
- package/dist/enterprise/env.d.ts.map +1 -0
- package/dist/enterprise/env.js +124 -0
- package/dist/enterprise/env.js.map +1 -0
- package/dist/enterprise/index.d.ts +7 -0
- package/dist/enterprise/index.d.ts.map +1 -0
- package/dist/enterprise/index.js +7 -0
- package/dist/enterprise/index.js.map +1 -0
- package/dist/enterprise/script-generator.d.ts +32 -0
- package/dist/enterprise/script-generator.d.ts.map +1 -0
- package/dist/enterprise/script-generator.js +461 -0
- package/dist/enterprise/script-generator.js.map +1 -0
- package/dist/execute.d.ts +21 -0
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +231 -0
- package/dist/execute.js.map +1 -1
- package/dist/index.js +79 -7
- package/dist/index.js.map +1 -1
- package/dist/stripe.d.ts +1 -1
- package/dist/stripe.js +1 -1
- package/dist/stripe.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/colors.d.ts +111 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +185 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/errors.d.ts +69 -0
- package/dist/ui/errors.d.ts.map +1 -0
- package/dist/ui/errors.js +334 -0
- package/dist/ui/errors.js.map +1 -0
- package/dist/ui/index.d.ts +10 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +14 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +88 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +295 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/spinner.d.ts +112 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +229 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/utils/backup.d.ts +48 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +182 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/config.d.ts +80 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +221 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/os.d.ts +45 -0
- package/dist/utils/os.d.ts.map +1 -0
- package/dist/utils/os.js +106 -0
- package/dist/utils/os.js.map +1 -0
- package/dist/utils/paths.d.ts +38 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +160 -0
- package/dist/utils/paths.js.map +1 -0
- package/docs/PRD-BILLING.md +226 -0
- package/docs/PRD-EARN-SYSTEM.md +261 -0
- package/docs/PRD-MCP-AUTO-SETUP.md +623 -0
- package/docs/enterprise-deployment.md +728 -0
- package/landing/next.config.mjs +14 -0
- package/landing/public/stats.json +4 -2
- package/landing/scripts/generate-stats.js +12 -0
- package/landing/src/app/api/workspace-auth/magic-link/route.ts +6 -3
- package/landing/src/app/auth/verify/page.tsx +11 -4
- package/landing/src/app/docs/page.tsx +1 -1
- package/landing/src/app/join/page.tsx +49 -0
- package/landing/src/app/login/page.tsx +7 -1
- package/landing/src/app/page.tsx +13 -28
- package/landing/src/app/providers/register/page.tsx +1 -1
- package/landing/src/app/workspace/page.tsx +483 -710
- package/landing/src/components/CheckoutButton.tsx +1 -1
- package/landing/src/components/EarnCreditsTab.tsx +842 -0
- package/landing/src/lib/stats.json +3 -1
- package/package.json +9 -2
- package/src/adapters/base.ts +363 -0
- package/src/adapters/claude-desktop.ts +41 -0
- package/src/adapters/cline.ts +88 -0
- package/src/adapters/continue.ts +91 -0
- package/src/adapters/cursor.ts +43 -0
- package/src/adapters/custom.ts +188 -0
- package/src/adapters/detect.ts +202 -0
- package/src/adapters/index.ts +47 -0
- package/src/adapters/windsurf.ts +44 -0
- package/src/bin.ts +19 -0
- package/src/cli/commands/doctor.ts +367 -0
- package/src/cli/commands/index.ts +9 -0
- package/src/cli/commands/restore.ts +333 -0
- package/src/cli/commands/setup.ts +276 -0
- package/src/cli/commands/uninstall.ts +240 -0
- package/src/cli/index.ts +107 -0
- package/src/discovery.ts +328 -3
- package/src/enterprise/env.ts +156 -0
- package/src/enterprise/index.ts +7 -0
- package/src/enterprise/script-generator.ts +481 -0
- package/src/execute.ts +256 -0
- package/src/index.ts +85 -7
- package/src/stripe.ts +1 -1
- package/src/types.ts +32 -0
- package/src/ui/colors.ts +219 -0
- package/src/ui/errors.ts +394 -0
- package/src/ui/index.ts +17 -0
- package/src/ui/prompts.ts +390 -0
- package/src/ui/spinner.ts +325 -0
- package/src/utils/backup.ts +224 -0
- package/src/utils/config.ts +315 -0
- package/src/utils/os.ts +124 -0
- package/src/utils/paths.ts +203 -0
- package/landing/tsconfig.tsbuildinfo +0 -1
package/src/discovery.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Discovery engine for APIvault
|
|
2
2
|
// MVP: Keyword matching. Future: Embeddings + semantic search
|
|
3
3
|
|
|
4
|
-
import { APIProvider, SearchResult } from './types.js';
|
|
4
|
+
import { APIProvider, SearchResult, APIDetailsResponse } from './types.js';
|
|
5
5
|
import { readFileSync } from 'fs';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { dirname, join } from 'path';
|
|
8
|
+
import { getConnectedProviders } from './execute.js';
|
|
9
|
+
import { openAPIs, isOpenAPI } from './open-apis.js';
|
|
8
10
|
|
|
9
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
12
|
const __dirname = dirname(__filename);
|
|
@@ -14,6 +16,218 @@ const apisData = JSON.parse(
|
|
|
14
16
|
);
|
|
15
17
|
const apis: APIProvider[] = apisData.apis;
|
|
16
18
|
|
|
19
|
+
// Direct Call provider specs (hardcoded handlers with params)
|
|
20
|
+
const DIRECT_CALL_SPECS: Record<string, {
|
|
21
|
+
description: string;
|
|
22
|
+
auth: string;
|
|
23
|
+
docs: string;
|
|
24
|
+
actions: Record<string, { params: { name: string; required: boolean; desc: string }[]; desc: string }>;
|
|
25
|
+
}> = {
|
|
26
|
+
'46elks': {
|
|
27
|
+
description: 'Swedish SMS and voice API',
|
|
28
|
+
auth: 'basic',
|
|
29
|
+
docs: 'https://46elks.com/docs',
|
|
30
|
+
actions: {
|
|
31
|
+
send_sms: {
|
|
32
|
+
desc: 'Send SMS message',
|
|
33
|
+
params: [
|
|
34
|
+
{ name: 'to', required: true, desc: 'Phone number (+46...)' },
|
|
35
|
+
{ name: 'message', required: true, desc: 'SMS text (max 160 chars for 1 segment)' },
|
|
36
|
+
{ name: 'from', required: false, desc: 'Sender ID (default: APIClaw)' },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
twilio: {
|
|
42
|
+
description: 'Global SMS and voice API',
|
|
43
|
+
auth: 'basic',
|
|
44
|
+
docs: 'https://www.twilio.com/docs',
|
|
45
|
+
actions: {
|
|
46
|
+
send_sms: {
|
|
47
|
+
desc: 'Send SMS message',
|
|
48
|
+
params: [
|
|
49
|
+
{ name: 'to', required: true, desc: 'Phone number (E.164 format)' },
|
|
50
|
+
{ name: 'message', required: true, desc: 'SMS text' },
|
|
51
|
+
{ name: 'from', required: false, desc: 'Sender phone number' },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
brave_search: {
|
|
57
|
+
description: 'Web search API',
|
|
58
|
+
auth: 'api_key',
|
|
59
|
+
docs: 'https://api.search.brave.com/docs',
|
|
60
|
+
actions: {
|
|
61
|
+
search: {
|
|
62
|
+
desc: 'Search the web',
|
|
63
|
+
params: [
|
|
64
|
+
{ name: 'query', required: true, desc: 'Search query' },
|
|
65
|
+
{ name: 'count', required: false, desc: 'Number of results (default: 5)' },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
resend: {
|
|
71
|
+
description: 'Email API',
|
|
72
|
+
auth: 'bearer',
|
|
73
|
+
docs: 'https://resend.com/docs',
|
|
74
|
+
actions: {
|
|
75
|
+
send_email: {
|
|
76
|
+
desc: 'Send email',
|
|
77
|
+
params: [
|
|
78
|
+
{ name: 'to', required: true, desc: 'Recipient email' },
|
|
79
|
+
{ name: 'subject', required: true, desc: 'Email subject' },
|
|
80
|
+
{ name: 'html', required: false, desc: 'HTML body' },
|
|
81
|
+
{ name: 'text', required: false, desc: 'Plain text body' },
|
|
82
|
+
{ name: 'from', required: false, desc: 'Sender (default: noreply@apiclaw.nordsym.com)' },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
openrouter: {
|
|
88
|
+
description: 'LLM routing (100+ models)',
|
|
89
|
+
auth: 'bearer',
|
|
90
|
+
docs: 'https://openrouter.ai/docs',
|
|
91
|
+
actions: {
|
|
92
|
+
chat: {
|
|
93
|
+
desc: 'Chat completion',
|
|
94
|
+
params: [
|
|
95
|
+
{ name: 'messages', required: true, desc: 'Array of {role, content}' },
|
|
96
|
+
{ name: 'model', required: false, desc: 'Model ID (default: claude-3-haiku)' },
|
|
97
|
+
{ name: 'max_tokens', required: false, desc: 'Max response tokens (default: 1000)' },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
elevenlabs: {
|
|
103
|
+
description: 'Text-to-speech',
|
|
104
|
+
auth: 'api_key',
|
|
105
|
+
docs: 'https://elevenlabs.io/docs',
|
|
106
|
+
actions: {
|
|
107
|
+
text_to_speech: {
|
|
108
|
+
desc: 'Generate audio from text',
|
|
109
|
+
params: [
|
|
110
|
+
{ name: 'text', required: true, desc: 'Text to speak' },
|
|
111
|
+
{ name: 'voice_id', required: false, desc: 'Voice ID (default: Rachel)' },
|
|
112
|
+
{ name: 'model_id', required: false, desc: 'Model ID' },
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
replicate: {
|
|
118
|
+
description: 'Run any AI model (images, video, audio)',
|
|
119
|
+
auth: 'bearer',
|
|
120
|
+
docs: 'https://replicate.com/docs',
|
|
121
|
+
actions: {
|
|
122
|
+
run: {
|
|
123
|
+
desc: 'Run a model',
|
|
124
|
+
params: [
|
|
125
|
+
{ name: 'model', required: true, desc: 'Model ID (e.g., stability-ai/sdxl:...)' },
|
|
126
|
+
{ name: 'input', required: true, desc: 'Model input parameters' },
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
list_models: {
|
|
130
|
+
desc: 'List available models',
|
|
131
|
+
params: [],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
firecrawl: {
|
|
136
|
+
description: 'Web scraping and crawling',
|
|
137
|
+
auth: 'bearer',
|
|
138
|
+
docs: 'https://firecrawl.dev/docs',
|
|
139
|
+
actions: {
|
|
140
|
+
scrape: {
|
|
141
|
+
desc: 'Scrape a URL',
|
|
142
|
+
params: [
|
|
143
|
+
{ name: 'url', required: true, desc: 'URL to scrape' },
|
|
144
|
+
{ name: 'formats', required: false, desc: 'Output formats (default: ["markdown"])' },
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
crawl: {
|
|
148
|
+
desc: 'Start a crawl job',
|
|
149
|
+
params: [
|
|
150
|
+
{ name: 'url', required: true, desc: 'Starting URL' },
|
|
151
|
+
{ name: 'limit', required: false, desc: 'Max pages (default: 10)' },
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
map: {
|
|
155
|
+
desc: 'Map site structure',
|
|
156
|
+
params: [
|
|
157
|
+
{ name: 'url', required: true, desc: 'URL to map' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
github: {
|
|
163
|
+
description: 'Code repos and developer data',
|
|
164
|
+
auth: 'bearer',
|
|
165
|
+
docs: 'https://docs.github.com/rest',
|
|
166
|
+
actions: {
|
|
167
|
+
search_repos: {
|
|
168
|
+
desc: 'Search repositories',
|
|
169
|
+
params: [
|
|
170
|
+
{ name: 'query', required: true, desc: 'Search query' },
|
|
171
|
+
{ name: 'sort', required: false, desc: 'Sort by (default: stars)' },
|
|
172
|
+
{ name: 'limit', required: false, desc: 'Max results (default: 10)' },
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
get_repo: {
|
|
176
|
+
desc: 'Get repo details',
|
|
177
|
+
params: [
|
|
178
|
+
{ name: 'owner', required: true, desc: 'Repo owner' },
|
|
179
|
+
{ name: 'repo', required: true, desc: 'Repo name' },
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
list_issues: {
|
|
183
|
+
desc: 'List issues',
|
|
184
|
+
params: [
|
|
185
|
+
{ name: 'owner', required: true, desc: 'Repo owner' },
|
|
186
|
+
{ name: 'repo', required: true, desc: 'Repo name' },
|
|
187
|
+
{ name: 'state', required: false, desc: 'State filter (default: open)' },
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
create_issue: {
|
|
191
|
+
desc: 'Create issue',
|
|
192
|
+
params: [
|
|
193
|
+
{ name: 'owner', required: true, desc: 'Repo owner' },
|
|
194
|
+
{ name: 'repo', required: true, desc: 'Repo name' },
|
|
195
|
+
{ name: 'title', required: true, desc: 'Issue title' },
|
|
196
|
+
{ name: 'body', required: false, desc: 'Issue body' },
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
get_file: {
|
|
200
|
+
desc: 'Get file contents',
|
|
201
|
+
params: [
|
|
202
|
+
{ name: 'owner', required: true, desc: 'Repo owner' },
|
|
203
|
+
{ name: 'repo', required: true, desc: 'Repo name' },
|
|
204
|
+
{ name: 'path', required: true, desc: 'File path' },
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
e2b: {
|
|
210
|
+
description: 'Code sandbox for AI agents',
|
|
211
|
+
auth: 'api_key',
|
|
212
|
+
docs: 'https://e2b.dev/docs',
|
|
213
|
+
actions: {
|
|
214
|
+
run_code: {
|
|
215
|
+
desc: 'Execute code in sandbox',
|
|
216
|
+
params: [
|
|
217
|
+
{ name: 'code', required: true, desc: 'Code to run' },
|
|
218
|
+
{ name: 'language', required: false, desc: 'Language (default: python)' },
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
run_shell: {
|
|
222
|
+
desc: 'Execute shell command',
|
|
223
|
+
params: [
|
|
224
|
+
{ name: 'command', required: true, desc: 'Shell command' },
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
|
|
17
231
|
/**
|
|
18
232
|
* Discover APIs based on a natural language query
|
|
19
233
|
* MVP uses keyword matching; production would use embeddings
|
|
@@ -107,9 +321,120 @@ export function discoverAPIs(
|
|
|
107
321
|
|
|
108
322
|
/**
|
|
109
323
|
* Get detailed information about a specific API
|
|
324
|
+
* @param apiId - The API provider ID
|
|
325
|
+
* @param options.compact - If true, returns minified spec (saves ~60% tokens)
|
|
110
326
|
*/
|
|
111
|
-
export function getAPIDetails(
|
|
112
|
-
|
|
327
|
+
export function getAPIDetails(
|
|
328
|
+
apiId: string,
|
|
329
|
+
options: { compact?: boolean } = {}
|
|
330
|
+
): APIDetailsResponse | null {
|
|
331
|
+
const { compact = false } = options;
|
|
332
|
+
|
|
333
|
+
// Check if it's a Direct Call provider (hardcoded handlers)
|
|
334
|
+
const directSpec = DIRECT_CALL_SPECS[apiId];
|
|
335
|
+
if (directSpec) {
|
|
336
|
+
if (compact) {
|
|
337
|
+
// Minified format: ~60% smaller
|
|
338
|
+
return {
|
|
339
|
+
id: apiId,
|
|
340
|
+
type: 'direct_call',
|
|
341
|
+
desc: directSpec.description,
|
|
342
|
+
auth: directSpec.auth,
|
|
343
|
+
actions: Object.fromEntries(
|
|
344
|
+
Object.entries(directSpec.actions).map(([action, info]) => [
|
|
345
|
+
action,
|
|
346
|
+
{
|
|
347
|
+
params: info.params.map(p =>
|
|
348
|
+
p.required ? p.name : `${p.name}?`
|
|
349
|
+
),
|
|
350
|
+
},
|
|
351
|
+
])
|
|
352
|
+
),
|
|
353
|
+
} as APIDetailsResponse;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
id: apiId,
|
|
358
|
+
type: 'direct_call',
|
|
359
|
+
name: apiId,
|
|
360
|
+
description: directSpec.description,
|
|
361
|
+
auth_type: directSpec.auth,
|
|
362
|
+
docs_url: directSpec.docs,
|
|
363
|
+
direct_call: true,
|
|
364
|
+
actions: Object.fromEntries(
|
|
365
|
+
Object.entries(directSpec.actions).map(([action, info]) => [
|
|
366
|
+
action,
|
|
367
|
+
{
|
|
368
|
+
description: info.desc,
|
|
369
|
+
params: info.params,
|
|
370
|
+
},
|
|
371
|
+
])
|
|
372
|
+
),
|
|
373
|
+
} as APIDetailsResponse;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Check if it's an Open API (free, no auth)
|
|
377
|
+
if (isOpenAPI(apiId)) {
|
|
378
|
+
const openApi = openAPIs[apiId];
|
|
379
|
+
const actions = Object.keys(openApi.actions);
|
|
380
|
+
|
|
381
|
+
if (compact) {
|
|
382
|
+
return {
|
|
383
|
+
id: apiId,
|
|
384
|
+
type: 'open',
|
|
385
|
+
desc: openApi.description,
|
|
386
|
+
auth: 'none',
|
|
387
|
+
actions: Object.fromEntries(
|
|
388
|
+
actions.map(a => [a, { params: [] }])
|
|
389
|
+
),
|
|
390
|
+
} as APIDetailsResponse;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
id: apiId,
|
|
395
|
+
type: 'open',
|
|
396
|
+
name: openApi.name,
|
|
397
|
+
description: openApi.description,
|
|
398
|
+
auth_type: 'none',
|
|
399
|
+
free: true,
|
|
400
|
+
actions: Object.fromEntries(
|
|
401
|
+
actions.map(a => [a, { description: `Execute ${a}`, params: [] }])
|
|
402
|
+
),
|
|
403
|
+
} as APIDetailsResponse;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Fall back to registry (19,000+ APIs - basic info only)
|
|
407
|
+
const registryApi = apis.find(api =>
|
|
408
|
+
api.id === apiId ||
|
|
409
|
+
api.name?.toLowerCase() === apiId.toLowerCase()
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
if (!registryApi) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (compact) {
|
|
417
|
+
return {
|
|
418
|
+
id: registryApi.id || registryApi.name,
|
|
419
|
+
type: 'registry',
|
|
420
|
+
desc: registryApi.description?.slice(0, 80),
|
|
421
|
+
auth: registryApi.auth_type || (registryApi as any).auth || 'unknown',
|
|
422
|
+
url: registryApi.base_url || (registryApi as any).baseUrl,
|
|
423
|
+
} as APIDetailsResponse;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
id: registryApi.id || registryApi.name,
|
|
428
|
+
type: 'registry',
|
|
429
|
+
name: registryApi.name,
|
|
430
|
+
description: registryApi.description,
|
|
431
|
+
category: registryApi.category,
|
|
432
|
+
auth_type: registryApi.auth_type || (registryApi as any).auth,
|
|
433
|
+
base_url: registryApi.base_url || (registryApi as any).baseUrl,
|
|
434
|
+
docs_url: registryApi.docs_url || (registryApi as any).docsUrl,
|
|
435
|
+
pricing: registryApi.pricing || (registryApi as any).pricing,
|
|
436
|
+
note: 'Registry API - use call_api with customer_key or check docs for integration',
|
|
437
|
+
} as APIDetailsResponse;
|
|
113
438
|
}
|
|
114
439
|
|
|
115
440
|
/**
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Variable Handler
|
|
3
|
+
* Manages APIClaw environment variables for configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface ApiclawEnvConfig {
|
|
7
|
+
workspace?: string;
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
disableTelemetry?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ENV_VARS = {
|
|
13
|
+
WORKSPACE: 'APICLAW_WORKSPACE',
|
|
14
|
+
API_URL: 'APICLAW_API_URL',
|
|
15
|
+
DISABLE_TELEMETRY: 'APICLAW_DISABLE_TELEMETRY',
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_API_URL = 'https://api.apiclaw.com';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Read APIClaw config from environment variables
|
|
22
|
+
*/
|
|
23
|
+
export function readEnvConfig(): ApiclawEnvConfig {
|
|
24
|
+
return {
|
|
25
|
+
workspace: process.env[ENV_VARS.WORKSPACE] || undefined,
|
|
26
|
+
apiUrl: process.env[ENV_VARS.API_URL] || undefined,
|
|
27
|
+
disableTelemetry: process.env[ENV_VARS.DISABLE_TELEMETRY] === 'true' ||
|
|
28
|
+
process.env[ENV_VARS.DISABLE_TELEMETRY] === '1',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get API URL with fallback to default
|
|
34
|
+
*/
|
|
35
|
+
export function getApiUrl(): string {
|
|
36
|
+
return process.env[ENV_VARS.API_URL] || DEFAULT_API_URL;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if telemetry is disabled
|
|
41
|
+
*/
|
|
42
|
+
export function isTelemetryDisabled(): boolean {
|
|
43
|
+
const val = process.env[ENV_VARS.DISABLE_TELEMETRY];
|
|
44
|
+
return val === 'true' || val === '1';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get pre-configured workspace ID
|
|
49
|
+
*/
|
|
50
|
+
export function getWorkspaceFromEnv(): string | undefined {
|
|
51
|
+
return process.env[ENV_VARS.WORKSPACE];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Generate env block for MCP server config
|
|
56
|
+
*/
|
|
57
|
+
export function generateEnvBlock(config: ApiclawEnvConfig): Record<string, string> {
|
|
58
|
+
const env: Record<string, string> = {};
|
|
59
|
+
|
|
60
|
+
if (config.workspace) {
|
|
61
|
+
env[ENV_VARS.WORKSPACE] = config.workspace;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (config.apiUrl && config.apiUrl !== DEFAULT_API_URL) {
|
|
65
|
+
env[ENV_VARS.API_URL] = config.apiUrl;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (config.disableTelemetry) {
|
|
69
|
+
env[ENV_VARS.DISABLE_TELEMETRY] = 'true';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return env;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Format env config for display
|
|
77
|
+
*/
|
|
78
|
+
export function formatEnvConfig(config: ApiclawEnvConfig): string[] {
|
|
79
|
+
const lines: string[] = [];
|
|
80
|
+
|
|
81
|
+
if (config.workspace) {
|
|
82
|
+
lines.push(` Workspace: ${config.workspace}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (config.apiUrl) {
|
|
86
|
+
lines.push(` API URL: ${config.apiUrl}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (config.disableTelemetry) {
|
|
90
|
+
lines.push(` Telemetry: Disabled`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return lines;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Validate workspace ID format
|
|
98
|
+
*/
|
|
99
|
+
export function isValidWorkspaceId(id: string): boolean {
|
|
100
|
+
// Workspace IDs should be alphanumeric with dashes/underscores
|
|
101
|
+
return /^[a-zA-Z0-9_-]{3,64}$/.test(id);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Validate API URL format
|
|
106
|
+
*/
|
|
107
|
+
export function isValidApiUrl(url: string): boolean {
|
|
108
|
+
try {
|
|
109
|
+
const parsed = new URL(url);
|
|
110
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Generate shell export statements
|
|
118
|
+
*/
|
|
119
|
+
export function generateShellExports(config: ApiclawEnvConfig): string {
|
|
120
|
+
const lines: string[] = [];
|
|
121
|
+
|
|
122
|
+
if (config.workspace) {
|
|
123
|
+
lines.push(`export ${ENV_VARS.WORKSPACE}="${config.workspace}"`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (config.apiUrl) {
|
|
127
|
+
lines.push(`export ${ENV_VARS.API_URL}="${config.apiUrl}"`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (config.disableTelemetry) {
|
|
131
|
+
lines.push(`export ${ENV_VARS.DISABLE_TELEMETRY}="true"`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return lines.join('\n');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Generate PowerShell $env statements
|
|
139
|
+
*/
|
|
140
|
+
export function generatePowerShellEnv(config: ApiclawEnvConfig): string {
|
|
141
|
+
const lines: string[] = [];
|
|
142
|
+
|
|
143
|
+
if (config.workspace) {
|
|
144
|
+
lines.push(`$env:${ENV_VARS.WORKSPACE} = "${config.workspace}"`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (config.apiUrl) {
|
|
148
|
+
lines.push(`$env:${ENV_VARS.API_URL} = "${config.apiUrl}"`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (config.disableTelemetry) {
|
|
152
|
+
lines.push(`$env:${ENV_VARS.DISABLE_TELEMETRY} = "true"`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|