@nordsym/apiclaw 2.1.0 → 2.2.1

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.
Files changed (185) hide show
  1. package/README.md +15 -2
  2. package/dist/bin-http.js +0 -0
  3. package/dist/bin.bundled.js +79288 -0
  4. package/dist/funnel-client.d.ts +24 -0
  5. package/dist/funnel-client.d.ts.map +1 -0
  6. package/dist/funnel-client.js +131 -0
  7. package/dist/funnel-client.js.map +1 -0
  8. package/dist/funnel.test.d.ts +2 -0
  9. package/dist/funnel.test.d.ts.map +1 -0
  10. package/dist/funnel.test.js +145 -0
  11. package/dist/funnel.test.js.map +1 -0
  12. package/dist/gateway-client.d.ts.map +1 -1
  13. package/dist/gateway-client.js +24 -2
  14. package/dist/gateway-client.js.map +1 -1
  15. package/dist/index.bundled.js +61263 -0
  16. package/dist/index.js +161 -74
  17. package/dist/index.js.map +1 -1
  18. package/dist/postinstall.d.ts +0 -5
  19. package/dist/postinstall.d.ts.map +1 -1
  20. package/dist/postinstall.js +24 -3
  21. package/dist/postinstall.js.map +1 -1
  22. package/dist/registration-guard.d.ts +29 -0
  23. package/dist/registration-guard.d.ts.map +1 -0
  24. package/dist/registration-guard.js +87 -0
  25. package/dist/registration-guard.js.map +1 -0
  26. package/package.json +7 -2
  27. package/.claude/settings.local.json +0 -9
  28. package/.env.prod +0 -1
  29. package/apiclaw-README.md +0 -494
  30. package/convex/_generated/api.d.ts +0 -137
  31. package/convex/_generated/api.js +0 -23
  32. package/convex/_generated/dataModel.d.ts +0 -60
  33. package/convex/_generated/server.d.ts +0 -143
  34. package/convex/_generated/server.js +0 -93
  35. package/convex/adminActivate.ts +0 -53
  36. package/convex/adminStats.ts +0 -306
  37. package/convex/agents.ts +0 -939
  38. package/convex/analytics.ts +0 -187
  39. package/convex/apiKeys.ts +0 -220
  40. package/convex/backfillAnalytics.ts +0 -272
  41. package/convex/backfillSearchLogs.ts +0 -35
  42. package/convex/billing.ts +0 -834
  43. package/convex/capabilities.ts +0 -157
  44. package/convex/chains.ts +0 -1318
  45. package/convex/credits.ts +0 -211
  46. package/convex/crons.ts +0 -50
  47. package/convex/debugFilestackLogs.ts +0 -16
  48. package/convex/debugGetToken.ts +0 -18
  49. package/convex/directCall.ts +0 -713
  50. package/convex/earnProgress.ts +0 -753
  51. package/convex/email.ts +0 -329
  52. package/convex/feedback.ts +0 -265
  53. package/convex/http.ts +0 -3430
  54. package/convex/inbound.ts +0 -32
  55. package/convex/logs.ts +0 -701
  56. package/convex/migrateFilestack.ts +0 -81
  57. package/convex/migratePartnersProd.ts +0 -174
  58. package/convex/migratePratham.ts +0 -126
  59. package/convex/migrateProviderWorkspaces.ts +0 -175
  60. package/convex/mou.ts +0 -91
  61. package/convex/providerKeys.ts +0 -289
  62. package/convex/providers.ts +0 -1135
  63. package/convex/purchases.ts +0 -183
  64. package/convex/ratelimit.ts +0 -104
  65. package/convex/schema.ts +0 -869
  66. package/convex/searchLogs.ts +0 -265
  67. package/convex/seedAPILayerAPIs.ts +0 -191
  68. package/convex/seedDirectCallConfigs.ts +0 -336
  69. package/convex/seedPratham.ts +0 -149
  70. package/convex/spendAlerts.ts +0 -442
  71. package/convex/stripeActions.ts +0 -607
  72. package/convex/teams.ts +0 -243
  73. package/convex/telemetry.ts +0 -81
  74. package/convex/tsconfig.json +0 -25
  75. package/convex/updateAPIStatus.ts +0 -44
  76. package/convex/usage.ts +0 -260
  77. package/convex/usageReports.ts +0 -357
  78. package/convex/waitlist.ts +0 -55
  79. package/convex/webhooks.ts +0 -494
  80. package/convex/workspaceSettings.ts +0 -143
  81. package/convex/workspaces.ts +0 -1331
  82. package/convex.json +0 -3
  83. package/direct-test.mjs +0 -51
  84. package/email-templates/filestack-provider-outreach.html +0 -162
  85. package/email-templates/partnership-template.html +0 -116
  86. package/email-templates/pratham-draft-preview.txt +0 -57
  87. package/email-templates/pratham-partnership-draft.html +0 -141
  88. package/reports/APIClaw-Session-Report-2026-04-05.pdf +0 -0
  89. package/reports/pipeline/PIPELINE-REPORT.json +0 -153
  90. package/reports/pipeline/acquire_apisguru.json +0 -17
  91. package/reports/pipeline/capabilities.json +0 -38
  92. package/reports/pipeline/discover_azure_recursive.json +0 -1551
  93. package/reports/pipeline/discover_github.json +0 -25
  94. package/reports/pipeline/discover_github_repos.json +0 -49
  95. package/reports/pipeline/discover_swaggerhub.json +0 -24
  96. package/reports/pipeline/discover_well_known.json +0 -23
  97. package/reports/pipeline/fetch_specs.json +0 -19
  98. package/reports/pipeline/generate_providers.json +0 -14
  99. package/reports/pipeline/match_registry.json +0 -11
  100. package/reports/pipeline/parse_specs.json +0 -17
  101. package/reports/pipeline/promote_candidates.json +0 -34
  102. package/reports/pipeline/validate.json +0 -30
  103. package/reports/pipeline/validate_smoke_details.json +0 -3835
  104. package/reports/session-report-2026-04-05.html +0 -433
  105. package/seed-apis-direct.mjs +0 -106
  106. package/src/access-control.ts +0 -174
  107. package/src/adapters/base.ts +0 -364
  108. package/src/adapters/claude-desktop.ts +0 -41
  109. package/src/adapters/cline.ts +0 -88
  110. package/src/adapters/continue.ts +0 -91
  111. package/src/adapters/cursor.ts +0 -43
  112. package/src/adapters/custom.ts +0 -188
  113. package/src/adapters/detect.ts +0 -202
  114. package/src/adapters/index.ts +0 -47
  115. package/src/adapters/windsurf.ts +0 -44
  116. package/src/bin-http.ts +0 -45
  117. package/src/bin.ts +0 -34
  118. package/src/capability-router.ts +0 -331
  119. package/src/chainExecutor.ts +0 -730
  120. package/src/chainResolver.test.ts +0 -246
  121. package/src/chainResolver.ts +0 -658
  122. package/src/cli/commands/demo.ts +0 -109
  123. package/src/cli/commands/doctor.ts +0 -435
  124. package/src/cli/commands/index.ts +0 -9
  125. package/src/cli/commands/login.ts +0 -203
  126. package/src/cli/commands/mcp-install.ts +0 -373
  127. package/src/cli/commands/restore.ts +0 -333
  128. package/src/cli/commands/setup.ts +0 -297
  129. package/src/cli/commands/uninstall.ts +0 -240
  130. package/src/cli/index.ts +0 -148
  131. package/src/cli.ts +0 -370
  132. package/src/confirmation.ts +0 -296
  133. package/src/credentials.ts +0 -455
  134. package/src/credits.ts +0 -329
  135. package/src/crypto.ts +0 -75
  136. package/src/discovery.ts +0 -568
  137. package/src/enterprise/env.ts +0 -156
  138. package/src/enterprise/index.ts +0 -7
  139. package/src/enterprise/script-generator.ts +0 -481
  140. package/src/execute-dynamic.ts +0 -617
  141. package/src/execute.ts +0 -2386
  142. package/src/gateway-client.ts +0 -192
  143. package/src/hivr-whitelist.ts +0 -110
  144. package/src/http-api.ts +0 -286
  145. package/src/http-server-minimal.ts +0 -154
  146. package/src/index.ts +0 -2611
  147. package/src/intelligent-gateway.ts +0 -339
  148. package/src/mcp-analytics.ts +0 -156
  149. package/src/metered.ts +0 -149
  150. package/src/open-apis-generated.ts +0 -157
  151. package/src/open-apis.ts +0 -558
  152. package/src/postinstall.ts +0 -18
  153. package/src/product-whitelist.ts +0 -246
  154. package/src/proxy.ts +0 -36
  155. package/src/session.ts +0 -129
  156. package/src/stripe.ts +0 -497
  157. package/src/telemetry.ts +0 -71
  158. package/src/test.ts +0 -135
  159. package/src/types/convex-api.d.ts +0 -20
  160. package/src/types/convex-api.ts +0 -21
  161. package/src/types.ts +0 -109
  162. package/src/ui/colors.ts +0 -219
  163. package/src/ui/errors.ts +0 -394
  164. package/src/ui/index.ts +0 -17
  165. package/src/ui/prompts.ts +0 -390
  166. package/src/ui/spinner.ts +0 -325
  167. package/src/utils/backup.ts +0 -224
  168. package/src/utils/config.ts +0 -318
  169. package/src/utils/os.ts +0 -124
  170. package/src/utils/paths.ts +0 -203
  171. package/src/webhook.ts +0 -107
  172. package/test-10-working.cjs +0 -97
  173. package/test-14-final.cjs +0 -96
  174. package/test-actual-handlers.ts +0 -92
  175. package/test-apilayer-all-14.ts +0 -249
  176. package/test-apilayer-fixed.ts +0 -248
  177. package/test-direct-endpoints.ts +0 -174
  178. package/test-exact-endpoints.ts +0 -144
  179. package/test-final.ts +0 -83
  180. package/test-full-routing.ts +0 -100
  181. package/test-handlers-correct.ts +0 -217
  182. package/test-numverify-key.ts +0 -41
  183. package/test-via-handlers.ts +0 -92
  184. package/test-worldnews.mjs +0 -26
  185. package/tsconfig.json +0 -20
package/src/discovery.ts DELETED
@@ -1,568 +0,0 @@
1
- // Discovery engine for APIvault
2
- // MVP: Keyword matching. Future: Embeddings + semantic search
3
-
4
- import { APIProvider, SearchResult, APIDetailsResponse } from './types.js';
5
- import { readFileSync } from 'fs';
6
- import { fileURLToPath } from 'url';
7
- import { dirname, join } from 'path';
8
- import { getConnectedProviders } from './execute.js';
9
- import { openAPIs, isOpenAPI } from './open-apis.js';
10
-
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = dirname(__filename);
13
-
14
- const apisData = JSON.parse(
15
- readFileSync(join(__dirname, 'registry', 'apis.json'), 'utf-8')
16
- );
17
- const apis: APIProvider[] = apisData.apis;
18
-
19
- // Direct Call provider specs (hardcoded handlers with params)
20
- // Ordered: AI-first (models, LLM routing, audio), then infrastructure (code, web, search, email, SMS)
21
- const DIRECT_CALL_SPECS: Record<string, {
22
- description: string;
23
- auth: string;
24
- docs: string;
25
- actions: Record<string, { params: { name: string; required: boolean; desc: string }[]; desc: string }>;
26
- }> = {
27
- openrouter: {
28
- description: 'LLM routing (100+ models)',
29
- auth: 'bearer',
30
- docs: 'https://openrouter.ai/docs',
31
- actions: {
32
- chat: {
33
- desc: 'Chat completion',
34
- params: [
35
- { name: 'messages', required: true, desc: 'Array of {role, content}' },
36
- { name: 'model', required: false, desc: 'Model ID (default: claude-3-haiku)' },
37
- { name: 'max_tokens', required: false, desc: 'Max response tokens (default: 1000)' },
38
- ],
39
- },
40
- },
41
- },
42
- replicate: {
43
- description: 'Run any AI model (images, video, audio)',
44
- auth: 'bearer',
45
- docs: 'https://replicate.com/docs',
46
- actions: {
47
- run: {
48
- desc: 'Run a model',
49
- params: [
50
- { name: 'model', required: true, desc: 'Model ID (e.g., stability-ai/sdxl:...)' },
51
- { name: 'input', required: true, desc: 'Model input parameters' },
52
- ],
53
- },
54
- list_models: {
55
- desc: 'List available models',
56
- params: [],
57
- },
58
- },
59
- },
60
- elevenlabs: {
61
- description: 'Text-to-speech',
62
- auth: 'api_key',
63
- docs: 'https://elevenlabs.io/docs',
64
- actions: {
65
- text_to_speech: {
66
- desc: 'Generate audio from text',
67
- params: [
68
- { name: 'text', required: true, desc: 'Text to speak' },
69
- { name: 'voice_id', required: false, desc: 'Voice ID (default: Rachel)' },
70
- { name: 'model_id', required: false, desc: 'Model ID' },
71
- ],
72
- },
73
- },
74
- },
75
- e2b: {
76
- description: 'Code sandbox for AI agents',
77
- auth: 'api_key',
78
- docs: 'https://e2b.dev/docs',
79
- actions: {
80
- run_code: {
81
- desc: 'Execute code in sandbox',
82
- params: [
83
- { name: 'code', required: true, desc: 'Code to run' },
84
- { name: 'language', required: false, desc: 'Language (default: python)' },
85
- ],
86
- },
87
- run_shell: {
88
- desc: 'Execute shell command',
89
- params: [
90
- { name: 'command', required: true, desc: 'Shell command' },
91
- ],
92
- },
93
- },
94
- },
95
- firecrawl: {
96
- description: 'Web scraping and crawling',
97
- auth: 'bearer',
98
- docs: 'https://firecrawl.dev/docs',
99
- actions: {
100
- scrape: {
101
- desc: 'Scrape a URL',
102
- params: [
103
- { name: 'url', required: true, desc: 'URL to scrape' },
104
- { name: 'formats', required: false, desc: 'Output formats (default: ["markdown"])' },
105
- ],
106
- },
107
- crawl: {
108
- desc: 'Start a crawl job',
109
- params: [
110
- { name: 'url', required: true, desc: 'Starting URL' },
111
- { name: 'limit', required: false, desc: 'Max pages (default: 10)' },
112
- ],
113
- },
114
- map: {
115
- desc: 'Map site structure',
116
- params: [
117
- { name: 'url', required: true, desc: 'URL to map' },
118
- ],
119
- },
120
- },
121
- },
122
- github: {
123
- description: 'Code repos and developer data',
124
- auth: 'bearer',
125
- docs: 'https://docs.github.com/rest',
126
- actions: {
127
- search_repos: {
128
- desc: 'Search repositories',
129
- params: [
130
- { name: 'query', required: true, desc: 'Search query' },
131
- { name: 'sort', required: false, desc: 'Sort by (default: stars)' },
132
- { name: 'limit', required: false, desc: 'Max results (default: 10)' },
133
- ],
134
- },
135
- get_repo: {
136
- desc: 'Get repo details',
137
- params: [
138
- { name: 'owner', required: true, desc: 'Repo owner' },
139
- { name: 'repo', required: true, desc: 'Repo name' },
140
- ],
141
- },
142
- list_issues: {
143
- desc: 'List issues',
144
- params: [
145
- { name: 'owner', required: true, desc: 'Repo owner' },
146
- { name: 'repo', required: true, desc: 'Repo name' },
147
- { name: 'state', required: false, desc: 'State filter (default: open)' },
148
- ],
149
- },
150
- create_issue: {
151
- desc: 'Create issue',
152
- params: [
153
- { name: 'owner', required: true, desc: 'Repo owner' },
154
- { name: 'repo', required: true, desc: 'Repo name' },
155
- { name: 'title', required: true, desc: 'Issue title' },
156
- { name: 'body', required: false, desc: 'Issue body' },
157
- ],
158
- },
159
- get_file: {
160
- desc: 'Get file contents',
161
- params: [
162
- { name: 'owner', required: true, desc: 'Repo owner' },
163
- { name: 'repo', required: true, desc: 'Repo name' },
164
- { name: 'path', required: true, desc: 'File path' },
165
- ],
166
- },
167
- },
168
- },
169
- brave_search: {
170
- description: 'Web search API',
171
- auth: 'api_key',
172
- docs: 'https://api.search.brave.com/docs',
173
- actions: {
174
- search: {
175
- desc: 'Search the web',
176
- params: [
177
- { name: 'query', required: true, desc: 'Search query' },
178
- { name: 'count', required: false, desc: 'Number of results (default: 5)' },
179
- ],
180
- },
181
- },
182
- },
183
- resend: {
184
- description: 'Email API',
185
- auth: 'bearer',
186
- docs: 'https://resend.com/docs',
187
- actions: {
188
- send_email: {
189
- desc: 'Send email',
190
- params: [
191
- { name: 'to', required: true, desc: 'Recipient email' },
192
- { name: 'subject', required: true, desc: 'Email subject' },
193
- { name: 'html', required: false, desc: 'HTML body' },
194
- { name: 'text', required: false, desc: 'Plain text body' },
195
- { name: 'from', required: false, desc: 'Sender (default: noreply@apiclaw.cloud)' },
196
- ],
197
- },
198
- },
199
- },
200
- '46elks': {
201
- description: 'Swedish SMS and voice API',
202
- auth: 'basic',
203
- docs: 'https://46elks.com/docs',
204
- actions: {
205
- send_sms: {
206
- desc: 'Send SMS message',
207
- params: [
208
- { name: 'to', required: true, desc: 'Phone number (+46...)' },
209
- { name: 'message', required: true, desc: 'SMS text (max 160 chars for 1 segment)' },
210
- { name: 'from', required: false, desc: 'Sender ID (default: APIClaw)' },
211
- ],
212
- },
213
- },
214
- },
215
- twilio: {
216
- description: 'Global SMS and voice API',
217
- auth: 'basic',
218
- docs: 'https://www.twilio.com/docs',
219
- actions: {
220
- send_sms: {
221
- desc: 'Send SMS message',
222
- params: [
223
- { name: 'to', required: true, desc: 'Phone number (E.164 format)' },
224
- { name: 'message', required: true, desc: 'SMS text' },
225
- { name: 'from', required: false, desc: 'Sender phone number' },
226
- ],
227
- },
228
- },
229
- },
230
- apilayer: {
231
- description: 'APILayer marketplace — currency, news, scraping, PDFs, verification & more',
232
- auth: 'api_key',
233
- docs: 'https://apilayer.com',
234
- actions: {
235
- exchange_rates: {
236
- desc: 'Get live or historical currency exchange rates',
237
- params: [
238
- { name: 'base', required: false, desc: 'Base currency (default: USD)' },
239
- { name: 'symbols', required: false, desc: 'Comma-separated target currencies' },
240
- { name: 'date', required: false, desc: 'Historical date YYYY-MM-DD (omit for live)' },
241
- ],
242
- },
243
- market_data: {
244
- desc: 'End-of-day stock market data',
245
- params: [
246
- { name: 'symbols', required: true, desc: 'Stock ticker(s), comma-separated e.g. AAPL,MSFT' },
247
- { name: 'date_from', required: false, desc: 'Start date YYYY-MM-DD' },
248
- { name: 'date_to', required: false, desc: 'End date YYYY-MM-DD' },
249
- ],
250
- },
251
- aviation: {
252
- desc: 'Real-time flight data and tracking',
253
- params: [
254
- { name: 'flight_iata', required: false, desc: 'IATA flight number e.g. AA100' },
255
- { name: 'dep_iata', required: false, desc: 'Departure airport IATA code' },
256
- { name: 'arr_iata', required: false, desc: 'Arrival airport IATA code' },
257
- ],
258
- },
259
- pdf_generate: {
260
- desc: 'Generate PDF from URL or HTML',
261
- params: [
262
- { name: 'document_url', required: false, desc: 'URL to convert to PDF' },
263
- { name: 'document_html', required: false, desc: 'HTML string to convert (alternative to URL)' },
264
- { name: 'page_size', required: false, desc: 'Page size: A4, Letter, etc (default: A4)' },
265
- ],
266
- },
267
- screenshot: {
268
- desc: 'Capture full-page screenshot of any URL',
269
- params: [
270
- { name: 'url', required: true, desc: 'URL to screenshot' },
271
- { name: 'viewport', required: false, desc: 'Viewport size e.g. 1440x900 (default)' },
272
- { name: 'fullpage', required: false, desc: '1 for full page, 0 for viewport only (default: 0)' },
273
- ],
274
- },
275
- verify_email: {
276
- desc: 'Validate email address format and deliverability',
277
- params: [
278
- { name: 'email', required: true, desc: 'Email address to verify' },
279
- ],
280
- },
281
- verify_number: {
282
- desc: 'Validate and lookup phone number details',
283
- params: [
284
- { name: 'number', required: true, desc: 'Phone number in E.164 format e.g. +46701234567' },
285
- ],
286
- },
287
- vat_check: {
288
- desc: 'Validate EU VAT number',
289
- params: [
290
- { name: 'vat_number', required: true, desc: 'EU VAT number e.g. SE556012345601' },
291
- ],
292
- },
293
- world_news: {
294
- desc: 'Extract and analyze news articles from a URL',
295
- params: [
296
- { name: 'url', required: true, desc: 'URL of the news article to analyze' },
297
- { name: 'analyze', required: false, desc: 'Whether to analyze the news (default: true)' },
298
- ],
299
- },
300
- finance_news: {
301
- desc: 'Latest financial and stock market news',
302
- params: [
303
- { name: 'tickers', required: false, desc: 'Stock tickers comma-separated e.g. AAPL,TSLA' },
304
- { name: 'text', required: false, desc: 'Keyword filter' },
305
- { name: 'number', required: false, desc: 'Number of results (default: 5)' },
306
- ],
307
- },
308
- scrape: {
309
- desc: 'Advanced web scraper — returns clean page content',
310
- params: [
311
- { name: 'url', required: true, desc: 'URL to scrape' },
312
- ],
313
- },
314
- image_crop: {
315
- desc: 'Smart crop an image to specified dimensions',
316
- params: [
317
- { name: 'url', required: true, desc: 'Image URL to crop' },
318
- { name: 'width', required: false, desc: 'Target width in pixels' },
319
- { name: 'height', required: false, desc: 'Target height in pixels' },
320
- ],
321
- },
322
- skills: {
323
- desc: 'Search 7000+ professional skills database',
324
- params: [
325
- { name: 'q', required: true, desc: 'Skill search query e.g. "machine learning"' },
326
- { name: 'count', required: false, desc: 'Number of results (default: 10)' },
327
- ],
328
- },
329
- form_submit: {
330
- desc: 'Submit form data to a FormAPI endpoint',
331
- params: [
332
- { name: 'endpoint', required: true, desc: 'FormAPI endpoint path' },
333
- { name: 'data', required: false, desc: 'Form data object to submit' },
334
- ],
335
- },
336
- },
337
- },
338
- };
339
-
340
- /**
341
- * Discover APIs based on a natural language query
342
- * MVP uses keyword matching; production would use embeddings
343
- */
344
- export function discoverAPIs(
345
- query: string,
346
- options: {
347
- category?: string;
348
- maxResults?: number;
349
- maxPrice?: number;
350
- region?: string;
351
- } = {}
352
- ): SearchResult[] {
353
- const { category, maxResults = 5, maxPrice, region } = options;
354
-
355
- const queryLower = query.toLowerCase();
356
- const queryWords = queryLower.split(/\s+/).filter(w => w.length > 2);
357
-
358
- const results: SearchResult[] = [];
359
-
360
- for (const api of apis) {
361
- // Category filter
362
- if (category && api.category !== category) continue;
363
-
364
- // Region filter
365
- if (region && api.regions && !api.regions.includes(region) && !api.regions.includes('global')) continue;
366
-
367
- // Calculate relevance score
368
- let score = 0;
369
- const matchReasons: string[] = [];
370
-
371
- // Check keywords
372
- for (const word of queryWords) {
373
- // Direct keyword match
374
- if (api.keywords?.some(k => k.includes(word))) {
375
- score += 10;
376
- matchReasons.push(`keyword: ${word}`);
377
- }
378
-
379
- // Capability match
380
- if (api.capabilities?.some(c => c.includes(word))) {
381
- score += 15;
382
- matchReasons.push(`capability: ${word}`);
383
- }
384
-
385
- // Name match
386
- if (api.name.toLowerCase().includes(word)) {
387
- score += 20;
388
- matchReasons.push(`name: ${word}`);
389
- }
390
-
391
- // Description match
392
- if (api.description.toLowerCase().includes(word)) {
393
- score += 5;
394
- matchReasons.push(`description: ${word}`);
395
- }
396
-
397
- // Feature match
398
- if (api.features?.some(f => f.toLowerCase().includes(word))) {
399
- score += 8;
400
- matchReasons.push(`feature: ${word}`);
401
- }
402
- }
403
-
404
- // Boost for high success rate (default to 0.8 if not set)
405
- score += (api.agent_success_rate ?? 0.8) * 10;
406
-
407
- // Boost for low latency (default to 500ms if not set)
408
- score += Math.max(0, (1000 - (api.avg_latency_ms ?? 500)) / 100);
409
-
410
- // Boost for free tier
411
- if (api.pricing?.free_tier) {
412
- score += 5;
413
- matchReasons.push('has free tier');
414
- }
415
-
416
- if (score > 0) {
417
- results.push({
418
- provider: api,
419
- relevance_score: Math.round(score * 100) / 100,
420
- match_reasons: [...new Set(matchReasons)]
421
- });
422
- }
423
- }
424
-
425
- // Sort by relevance
426
- results.sort((a, b) => b.relevance_score - a.relevance_score);
427
-
428
- return results.slice(0, maxResults);
429
- }
430
-
431
- /**
432
- * Get detailed information about a specific API
433
- * @param apiId - The API provider ID
434
- * @param options.compact - If true, returns minified spec (saves ~60% tokens)
435
- */
436
- export function getAPIDetails(
437
- apiId: string,
438
- options: { compact?: boolean } = {}
439
- ): APIDetailsResponse | null {
440
- const { compact = false } = options;
441
-
442
- // Check if it's a Direct Call provider (hardcoded handlers)
443
- const directSpec = DIRECT_CALL_SPECS[apiId];
444
- if (directSpec) {
445
- if (compact) {
446
- // Minified format: ~60% smaller
447
- return {
448
- id: apiId,
449
- type: 'direct_call',
450
- desc: directSpec.description,
451
- auth: directSpec.auth,
452
- actions: Object.fromEntries(
453
- Object.entries(directSpec.actions).map(([action, info]) => [
454
- action,
455
- {
456
- params: info.params.map(p =>
457
- p.required ? p.name : `${p.name}?`
458
- ),
459
- },
460
- ])
461
- ),
462
- } as APIDetailsResponse;
463
- }
464
-
465
- return {
466
- id: apiId,
467
- type: 'direct_call',
468
- name: apiId,
469
- description: directSpec.description,
470
- auth_type: directSpec.auth,
471
- docs_url: directSpec.docs,
472
- direct_call: true,
473
- actions: Object.fromEntries(
474
- Object.entries(directSpec.actions).map(([action, info]) => [
475
- action,
476
- {
477
- description: info.desc,
478
- params: info.params,
479
- },
480
- ])
481
- ),
482
- } as APIDetailsResponse;
483
- }
484
-
485
- // Check if it's an Open API (free, no auth)
486
- if (isOpenAPI(apiId)) {
487
- const openApi = openAPIs[apiId];
488
- const actions = Object.keys(openApi.actions);
489
-
490
- if (compact) {
491
- return {
492
- id: apiId,
493
- type: 'open',
494
- desc: openApi.description,
495
- auth: 'none',
496
- actions: Object.fromEntries(
497
- actions.map(a => [a, { params: [] }])
498
- ),
499
- } as APIDetailsResponse;
500
- }
501
-
502
- return {
503
- id: apiId,
504
- type: 'open',
505
- name: openApi.name,
506
- description: openApi.description,
507
- auth_type: 'none',
508
- free: true,
509
- actions: Object.fromEntries(
510
- actions.map(a => [a, { description: `Execute ${a}`, params: [] }])
511
- ),
512
- } as APIDetailsResponse;
513
- }
514
-
515
- // Fall back to registry (19,000+ APIs - basic info only)
516
- const registryApi = apis.find(api =>
517
- api.id === apiId ||
518
- api.name?.toLowerCase() === apiId.toLowerCase()
519
- );
520
-
521
- if (!registryApi) {
522
- return null;
523
- }
524
-
525
- if (compact) {
526
- return {
527
- id: registryApi.id || registryApi.name,
528
- type: 'registry',
529
- desc: registryApi.description?.slice(0, 80),
530
- auth: registryApi.auth_type || (registryApi as any).auth || 'unknown',
531
- url: registryApi.base_url || (registryApi as any).baseUrl,
532
- } as APIDetailsResponse;
533
- }
534
-
535
- return {
536
- id: registryApi.id || registryApi.name,
537
- type: 'registry',
538
- name: registryApi.name,
539
- description: registryApi.description,
540
- category: registryApi.category,
541
- auth_type: registryApi.auth_type || (registryApi as any).auth,
542
- base_url: registryApi.base_url || (registryApi as any).baseUrl,
543
- docs_url: registryApi.docs_url || (registryApi as any).docsUrl,
544
- pricing: registryApi.pricing || (registryApi as any).pricing,
545
- note: 'Registry API - use call_api with customer_key or check docs for integration',
546
- } as APIDetailsResponse;
547
- }
548
-
549
- /**
550
- * List all APIs in a category
551
- */
552
- export function listByCategory(category: string): APIProvider[] {
553
- return apis.filter(api => api.category === category);
554
- }
555
-
556
- /**
557
- * Get all available categories
558
- */
559
- export function getCategories(): string[] {
560
- return [...new Set(apis.map(api => api.category))];
561
- }
562
-
563
- /**
564
- * Get all APIs
565
- */
566
- export function getAllAPIs(): APIProvider[] {
567
- return apis;
568
- }