@nordsym/apiclaw 1.0.0 → 1.1.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.
- package/AGENTS.md +74 -0
- package/HEARTBEAT.md +4 -0
- package/IDENTITY.md +22 -0
- package/README.md +193 -202
- package/SOUL.md +36 -0
- package/STATUS.md +237 -0
- package/TOOLS.md +36 -0
- package/USER.md +17 -0
- package/{backend/convex → convex}/_generated/api.d.ts +12 -6
- package/convex/analytics.ts +90 -0
- package/convex/credits.ts +211 -0
- package/convex/http.ts +578 -0
- package/convex/providers.ts +516 -0
- package/convex/purchases.ts +183 -0
- package/convex/ratelimit.ts +104 -0
- package/convex/schema.ts +220 -0
- package/convex/telemetry.ts +81 -0
- package/convex.json +3 -0
- package/dist/credentials.d.ts +19 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +158 -0
- package/dist/credentials.js.map +1 -0
- package/dist/credits.d.ts +14 -11
- package/dist/credits.d.ts.map +1 -1
- package/dist/credits.js +151 -99
- package/dist/credits.js.map +1 -1
- package/dist/discovery.d.ts +7 -16
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +33 -40
- package/dist/discovery.js.map +1 -1
- package/dist/execute.d.ts +19 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +285 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.js +175 -31
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +6 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +19 -0
- package/dist/proxy.js.map +1 -0
- package/dist/registry/apis.json +95362 -202
- package/dist/registry/apis_expanded.json +100853 -0
- package/dist/stripe.d.ts +68 -0
- package/dist/stripe.d.ts.map +1 -0
- package/dist/stripe.js +196 -0
- package/dist/stripe.js.map +1 -0
- package/dist/telemetry.d.ts +28 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +50 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/test.d.ts +3 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +105 -75
- package/dist/test.js.map +1 -1
- package/dist/types.d.ts +0 -28
- package/dist/types.d.ts.map +1 -1
- package/dist/webhook.d.ts +2 -0
- package/dist/webhook.d.ts.map +1 -0
- package/dist/webhook.js +90 -0
- package/dist/webhook.js.map +1 -0
- package/landing/DESIGN.md +343 -0
- package/landing/package-lock.json +1196 -7
- package/landing/package.json +5 -1
- package/landing/public/android-chrome-192x192.png +0 -0
- package/landing/public/android-chrome-512x512.png +0 -0
- package/landing/public/apple-touch-icon.png +0 -0
- package/landing/public/demo.gif +0 -0
- package/landing/public/demo.mp4 +0 -0
- package/landing/public/favicon-16x16.png +0 -0
- package/landing/public/favicon-32x32.png +0 -0
- package/landing/public/favicon.ico +0 -0
- package/landing/public/favicon.svg +3 -0
- package/landing/public/icon.svg +47 -0
- package/landing/public/logo-mono.svg +37 -0
- package/landing/public/logo-simple.svg +45 -0
- package/landing/public/logo.svg +84 -0
- package/landing/public/og-template.html +184 -0
- package/landing/public/site.webmanifest +31 -0
- package/landing/scripts/generate-assets.js +284 -0
- package/landing/scripts/generate-pngs.js +48 -0
- package/landing/scripts/generate-stats.js +42 -0
- package/landing/src/app/admin/page.tsx +348 -0
- package/landing/src/app/api/auth/magic-link/route.ts +73 -0
- package/landing/src/app/api/auth/session/route.ts +38 -0
- package/landing/src/app/api/auth/verify/route.ts +43 -0
- package/landing/src/app/api/og/route.tsx +84 -0
- package/landing/src/app/globals.css +439 -100
- package/landing/src/app/layout.tsx +37 -7
- package/landing/src/app/page.tsx +627 -552
- package/landing/src/app/providers/dashboard/login/page.tsx +176 -0
- package/landing/src/app/providers/dashboard/page.tsx +589 -0
- package/landing/src/app/providers/dashboard/verify/page.tsx +106 -0
- package/landing/src/app/providers/layout.tsx +14 -0
- package/landing/src/app/providers/page.tsx +402 -0
- package/landing/src/app/providers/register/page.tsx +670 -0
- package/landing/src/components/ProviderDashboard.tsx +794 -0
- package/landing/src/hooks/useDashboardData.ts +99 -0
- package/landing/src/lib/apis.json +116054 -0
- package/landing/src/lib/convex-client.ts +106 -0
- package/landing/src/lib/mock-data.ts +285 -0
- package/landing/src/lib/stats.json +6 -0
- package/landing/tailwind.config.ts +12 -11
- package/landing/tsconfig.tsbuildinfo +1 -0
- package/package.json +21 -20
- package/scripts/SYMBOT-FIX.md +238 -0
- package/scripts/demo-simulation.py +177 -0
- package/scripts/expand-more.py +502 -0
- package/scripts/expand-registry.py +434 -0
- package/scripts/history-sanitizer.ts +272 -0
- package/scripts/mass-scrape.py +1308 -0
- package/scripts/sync-and-deploy.sh +36 -0
- package/src/credentials.ts +177 -0
- package/src/credits.ts +190 -122
- package/src/discovery.ts +45 -58
- package/src/execute.ts +350 -0
- package/src/index.ts +184 -32
- package/src/proxy.ts +24 -0
- package/src/registry/apis.json +95362 -202
- package/src/registry/apis_expanded.json +100853 -0
- package/src/stripe.ts +243 -0
- package/src/telemetry.ts +71 -0
- package/src/test.ts +127 -89
- package/src/types.ts +0 -34
- package/src/webhook.ts +107 -0
- package/.github/ISSUE_TEMPLATE/add-api.yml +0 -123
- package/BRIEFING.md +0 -30
- package/backend/convex/apiKeys.ts +0 -75
- package/backend/convex/purchases.ts +0 -74
- package/backend/convex/schema.ts +0 -45
- package/backend/convex/transactions.ts +0 -57
- package/backend/convex/users.ts +0 -94
- package/backend/package-lock.json +0 -521
- package/backend/package.json +0 -15
- package/dist/registry/parse_apis.py +0 -146
- package/dist/revenuecat.d.ts +0 -61
- package/dist/revenuecat.d.ts.map +0 -1
- package/dist/revenuecat.js +0 -166
- package/dist/revenuecat.js.map +0 -1
- package/dist/webhooks/revenuecat.d.ts +0 -48
- package/dist/webhooks/revenuecat.d.ts.map +0 -1
- package/dist/webhooks/revenuecat.js +0 -119
- package/dist/webhooks/revenuecat.js.map +0 -1
- package/docs/revenuecat-setup.md +0 -89
- package/landing/src/app/api/keys/route.ts +0 -71
- package/landing/src/app/api/log/route.ts +0 -37
- package/landing/src/app/api/stats/route.ts +0 -37
- package/landing/src/app/page.tsx.bak +0 -567
- package/landing/src/components/AddKeyModal.tsx +0 -159
- package/newsletter-template.html +0 -71
- package/outreach/OUTREACH-SYSTEM.md +0 -211
- package/outreach/email-template.html +0 -179
- package/outreach/targets.md +0 -133
- package/src/registry/parse_apis.py +0 -146
- package/src/revenuecat.ts +0 -239
- package/src/webhooks/revenuecat.ts +0 -187
- /package/{backend/convex → convex}/README.md +0 -0
- /package/{backend/convex → convex}/_generated/api.js +0 -0
- /package/{backend/convex → convex}/_generated/dataModel.d.ts +0 -0
- /package/{backend/convex → convex}/_generated/server.d.ts +0 -0
- /package/{backend/convex → convex}/_generated/server.js +0 -0
- /package/{backend/convex → convex}/tsconfig.json +0 -0
package/src/index.ts
CHANGED
|
@@ -18,38 +18,56 @@ import {
|
|
|
18
18
|
Tool,
|
|
19
19
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
20
20
|
|
|
21
|
-
import { discoverAPIs, getAPIDetails, getCategories, getAllAPIs
|
|
21
|
+
import { discoverAPIs, getAPIDetails, getCategories, getAllAPIs } from './discovery.js';
|
|
22
|
+
import { trackStartup, trackSearch, trackExecute, trackDiscovery } from './telemetry.js';
|
|
22
23
|
import {
|
|
23
24
|
getAgentCredits,
|
|
24
25
|
addCredits,
|
|
25
26
|
purchaseAPIAccess,
|
|
26
27
|
getBalanceSummary,
|
|
27
|
-
getAgentPurchases
|
|
28
|
+
getAgentPurchases,
|
|
29
|
+
getProvidersWithRealCredentials
|
|
28
30
|
} from './credits.js';
|
|
31
|
+
import { hasRealCredentials } from './credentials.js';
|
|
32
|
+
import { executeAPICall, getConnectedProviders } from './execute.js';
|
|
29
33
|
|
|
30
34
|
// Default agent ID for MVP (in production, this would come from auth)
|
|
31
35
|
const DEFAULT_AGENT_ID = 'agent_default';
|
|
32
36
|
|
|
33
37
|
// Tool definitions
|
|
34
38
|
const tools: Tool[] = [
|
|
39
|
+
{
|
|
40
|
+
name: 'apiclaw_help',
|
|
41
|
+
description: 'Get help and see available commands. Start here if you are new to APIClaw.',
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {},
|
|
45
|
+
required: []
|
|
46
|
+
}
|
|
47
|
+
},
|
|
35
48
|
{
|
|
36
49
|
name: 'discover_apis',
|
|
37
|
-
description: 'Search
|
|
50
|
+
description: 'Search for APIs based on what you need to do. Describe your use case naturally.',
|
|
38
51
|
inputSchema: {
|
|
39
52
|
type: 'object',
|
|
40
53
|
properties: {
|
|
41
54
|
query: {
|
|
42
55
|
type: 'string',
|
|
43
|
-
description: 'Natural language query describing what you need (e.g., "send SMS
|
|
56
|
+
description: 'Natural language query describing what you need (e.g., "send SMS to Sweden", "search the web", "generate speech from text")'
|
|
44
57
|
},
|
|
45
58
|
category: {
|
|
46
59
|
type: 'string',
|
|
47
|
-
description: 'Filter by category
|
|
60
|
+
description: 'Filter by category: communication, search, ai',
|
|
61
|
+
enum: ['communication', 'search', 'ai']
|
|
48
62
|
},
|
|
49
63
|
max_results: {
|
|
50
64
|
type: 'number',
|
|
51
|
-
description: 'Maximum number of results to return (default:
|
|
52
|
-
default:
|
|
65
|
+
description: 'Maximum number of results to return (default: 5)',
|
|
66
|
+
default: 5
|
|
67
|
+
},
|
|
68
|
+
region: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
description: 'Filter by region (e.g., "SE", "EU", "global")'
|
|
53
71
|
}
|
|
54
72
|
},
|
|
55
73
|
required: ['query']
|
|
@@ -129,6 +147,36 @@ const tools: Tool[] = [
|
|
|
129
147
|
type: 'object',
|
|
130
148
|
properties: {}
|
|
131
149
|
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: 'call_api',
|
|
153
|
+
description: 'Execute an API call through APIClaw Instant Connect. No API keys needed - we handle authentication.',
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
properties: {
|
|
157
|
+
provider: {
|
|
158
|
+
type: 'string',
|
|
159
|
+
description: 'Provider ID (e.g., "46elks", "brave_search", "resend", "openrouter", "elevenlabs", "twilio")'
|
|
160
|
+
},
|
|
161
|
+
action: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
description: 'Action to perform (e.g., "send_sms", "search", "send_email", "chat", "text_to_speech")'
|
|
164
|
+
},
|
|
165
|
+
params: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
description: 'Parameters for the action. Varies by provider/action.'
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
required: ['provider', 'action', 'params']
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: 'list_connected',
|
|
175
|
+
description: 'List all APIs available for Instant Connect (no API key needed).',
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
properties: {}
|
|
179
|
+
}
|
|
132
180
|
}
|
|
133
181
|
];
|
|
134
182
|
|
|
@@ -156,12 +204,51 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
156
204
|
|
|
157
205
|
try {
|
|
158
206
|
switch (name) {
|
|
207
|
+
case 'apiclaw_help': {
|
|
208
|
+
const helpText = `
|
|
209
|
+
🦞 APIClaw — The API Layer for AI Agents
|
|
210
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
211
|
+
|
|
212
|
+
DISCOVER APIs:
|
|
213
|
+
discover_apis({ query: "send SMS to Sweden" })
|
|
214
|
+
discover_apis({ query: "search the web", max_results: 10 })
|
|
215
|
+
discover_apis({ query: "text to speech", category: "ai" })
|
|
216
|
+
|
|
217
|
+
GET DETAILS:
|
|
218
|
+
get_api_details({ api_id: "46elks" })
|
|
219
|
+
|
|
220
|
+
INSTANT CONNECT (6 APIs, no key needed):
|
|
221
|
+
get_connected_providers()
|
|
222
|
+
call_api({ provider: "brave_search", endpoint: "search", params: { q: "AI agents" } })
|
|
223
|
+
|
|
224
|
+
Available instant-connect providers:
|
|
225
|
+
• brave_search — Web search
|
|
226
|
+
• 46elks — SMS (Sweden)
|
|
227
|
+
• twilio — SMS (Global)
|
|
228
|
+
• resend — Email
|
|
229
|
+
• openrouter — LLM routing
|
|
230
|
+
• elevenlabs — Text-to-speech
|
|
231
|
+
|
|
232
|
+
BROWSE:
|
|
233
|
+
list_categories()
|
|
234
|
+
list_all_apis({ category: "communication", limit: 20 })
|
|
235
|
+
|
|
236
|
+
Docs: https://apiclaw.nordsym.com
|
|
237
|
+
`;
|
|
238
|
+
return {
|
|
239
|
+
content: [{ type: 'text', text: helpText }]
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
159
243
|
case 'discover_apis': {
|
|
160
244
|
const query = args?.query as string;
|
|
161
245
|
const category = args?.category as string | undefined;
|
|
162
|
-
const maxResults = (args?.max_results as number) ||
|
|
246
|
+
const maxResults = (args?.max_results as number) || 5;
|
|
247
|
+
const region = args?.region as string | undefined;
|
|
163
248
|
|
|
164
|
-
const
|
|
249
|
+
const startTime = Date.now();
|
|
250
|
+
const results = discoverAPIs(query, { category, maxResults, region });
|
|
251
|
+
trackSearch(query, results.length, Date.now() - startTime);
|
|
165
252
|
|
|
166
253
|
if (results.length === 0) {
|
|
167
254
|
return {
|
|
@@ -171,8 +258,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
171
258
|
text: JSON.stringify({
|
|
172
259
|
status: 'no_results',
|
|
173
260
|
message: `No APIs found matching "${query}". Try broader terms or check available categories with list_categories.`,
|
|
174
|
-
|
|
175
|
-
available_categories: getCategories().slice(0, 20)
|
|
261
|
+
available_categories: getCategories()
|
|
176
262
|
}, null, 2)
|
|
177
263
|
}
|
|
178
264
|
]
|
|
@@ -187,17 +273,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
187
273
|
status: 'success',
|
|
188
274
|
query,
|
|
189
275
|
results_count: results.length,
|
|
190
|
-
total_apis: getAPICount(),
|
|
191
276
|
results: results.map(r => ({
|
|
192
|
-
id: r.
|
|
193
|
-
name: r.
|
|
194
|
-
description: r.
|
|
195
|
-
category: r.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
keywords: r.api.keywords,
|
|
277
|
+
id: r.provider.id,
|
|
278
|
+
name: r.provider.name,
|
|
279
|
+
description: r.provider.description,
|
|
280
|
+
category: r.provider.category,
|
|
281
|
+
capabilities: r.provider.capabilities,
|
|
282
|
+
pricing_model: r.provider.pricing.model,
|
|
283
|
+
has_free_tier: r.provider.pricing.free_tier,
|
|
284
|
+
agent_success_rate: r.provider.agent_success_rate,
|
|
201
285
|
relevance_score: r.relevance_score,
|
|
202
286
|
match_reasons: r.match_reasons
|
|
203
287
|
}))
|
|
@@ -274,12 +358,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
274
358
|
provider: apiId,
|
|
275
359
|
amount_paid_usd: amountUsd,
|
|
276
360
|
credits_received: result.purchase!.credits_purchased,
|
|
277
|
-
status: result.purchase!.status
|
|
361
|
+
status: result.purchase!.status,
|
|
362
|
+
real_credentials: hasRealCredentials(apiId)
|
|
278
363
|
},
|
|
279
364
|
credentials: result.purchase!.credentials,
|
|
280
365
|
access: {
|
|
281
|
-
|
|
282
|
-
|
|
366
|
+
base_url: api?.base_url,
|
|
367
|
+
docs_url: api?.docs_url,
|
|
368
|
+
auth_type: api?.auth_type
|
|
283
369
|
}
|
|
284
370
|
}, null, 2)
|
|
285
371
|
}
|
|
@@ -301,11 +387,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
301
387
|
balance_usd: summary.credits.balance_usd,
|
|
302
388
|
currency: summary.credits.currency,
|
|
303
389
|
total_spent_usd: summary.total_spent_usd,
|
|
390
|
+
real_credential_providers: summary.real_credentials_available,
|
|
304
391
|
active_purchases: summary.active_purchases.map(p => ({
|
|
305
392
|
id: p.id,
|
|
306
393
|
provider: p.provider_id,
|
|
307
|
-
credits_remaining: p.credits_purchased,
|
|
308
|
-
status: p.status
|
|
394
|
+
credits_remaining: p.credits_purchased,
|
|
395
|
+
status: p.status,
|
|
396
|
+
real_credentials: hasRealCredentials(p.provider_id)
|
|
309
397
|
}))
|
|
310
398
|
}, null, 2)
|
|
311
399
|
}
|
|
@@ -335,10 +423,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
335
423
|
|
|
336
424
|
case 'list_categories': {
|
|
337
425
|
const categories = getCategories();
|
|
338
|
-
const
|
|
426
|
+
const apisByCategory: Record<string, string[]> = {};
|
|
339
427
|
|
|
340
428
|
for (const cat of categories) {
|
|
341
|
-
|
|
429
|
+
apisByCategory[cat] = getAllAPIs()
|
|
430
|
+
.filter(a => a.category === cat)
|
|
431
|
+
.map(a => a.id);
|
|
342
432
|
}
|
|
343
433
|
|
|
344
434
|
return {
|
|
@@ -347,9 +437,49 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
347
437
|
type: 'text',
|
|
348
438
|
text: JSON.stringify({
|
|
349
439
|
status: 'success',
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
440
|
+
categories: apisByCategory
|
|
441
|
+
}, null, 2)
|
|
442
|
+
}
|
|
443
|
+
]
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
case 'call_api': {
|
|
448
|
+
const provider = args?.provider as string;
|
|
449
|
+
const action = args?.action as string;
|
|
450
|
+
const params = (args?.params as Record<string, any>) || {};
|
|
451
|
+
|
|
452
|
+
const result = await executeAPICall(provider, action, params);
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
content: [
|
|
456
|
+
{
|
|
457
|
+
type: 'text',
|
|
458
|
+
text: JSON.stringify({
|
|
459
|
+
status: result.success ? 'success' : 'error',
|
|
460
|
+
provider: result.provider,
|
|
461
|
+
action: result.action,
|
|
462
|
+
...(result.success ? { data: result.data } : { error: result.error }),
|
|
463
|
+
...(result.cost !== undefined ? { cost_sek: result.cost } : {})
|
|
464
|
+
}, null, 2)
|
|
465
|
+
}
|
|
466
|
+
],
|
|
467
|
+
isError: !result.success
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
case 'list_connected': {
|
|
472
|
+
const connected = getConnectedProviders();
|
|
473
|
+
|
|
474
|
+
return {
|
|
475
|
+
content: [
|
|
476
|
+
{
|
|
477
|
+
type: 'text',
|
|
478
|
+
text: JSON.stringify({
|
|
479
|
+
status: 'success',
|
|
480
|
+
message: 'These APIs are available for Instant Connect - no API key needed!',
|
|
481
|
+
connected_providers: connected,
|
|
482
|
+
usage: 'Use call_api with provider, action, and params to execute calls.'
|
|
353
483
|
}, null, 2)
|
|
354
484
|
}
|
|
355
485
|
]
|
|
@@ -390,7 +520,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
390
520
|
async function main() {
|
|
391
521
|
const transport = new StdioServerTransport();
|
|
392
522
|
await server.connect(transport);
|
|
393
|
-
|
|
523
|
+
trackStartup();
|
|
524
|
+
|
|
525
|
+
// Welcome message with onboarding
|
|
526
|
+
console.error(`
|
|
527
|
+
🦞 APIClaw v1.1.1 — The API Layer for AI Agents
|
|
528
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
529
|
+
|
|
530
|
+
✓ 10,001 APIs indexed
|
|
531
|
+
✓ 446 categories
|
|
532
|
+
✓ 6 instant-connect providers ready
|
|
533
|
+
|
|
534
|
+
Quick Start:
|
|
535
|
+
discover_apis("send SMS to Sweden")
|
|
536
|
+
discover_apis("search the web")
|
|
537
|
+
discover_apis("generate speech from text")
|
|
538
|
+
|
|
539
|
+
Instant Connect (no API key needed):
|
|
540
|
+
get_connected_providers()
|
|
541
|
+
call_api({ provider: "brave_search", ... })
|
|
542
|
+
|
|
543
|
+
Docs: https://apiclaw.nordsym.com
|
|
544
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
545
|
+
`);
|
|
394
546
|
}
|
|
395
547
|
|
|
396
548
|
main().catch(console.error);
|
package/src/proxy.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APIClaw Proxy - Fallback to hosted API when no local credentials
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const PROXY_BASE = "https://adventurous-avocet-799.convex.site/proxy";
|
|
6
|
+
|
|
7
|
+
export async function callProxy(provider: string, params: any): Promise<any> {
|
|
8
|
+
const url = `${PROXY_BASE}/${provider}`;
|
|
9
|
+
|
|
10
|
+
const response = await fetch(url, {
|
|
11
|
+
method: "POST",
|
|
12
|
+
headers: { "Content-Type": "application/json" },
|
|
13
|
+
body: JSON.stringify(params),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
const errorData = await response.json().catch(() => ({ error: "Proxy request failed" })) as { error?: string };
|
|
18
|
+
throw new Error(errorData.error || `Proxy error: ${response.status}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return response.json();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const PROXY_PROVIDERS = ["openrouter", "brave_search", "resend", "elevenlabs", "46elks", "twilio"];
|