@nordsym/apiclaw 1.0.0 → 1.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.
Files changed (154) hide show
  1. package/AGENTS.md +74 -0
  2. package/HEARTBEAT.md +4 -0
  3. package/IDENTITY.md +22 -0
  4. package/README.md +197 -202
  5. package/SOUL.md +36 -0
  6. package/STATUS.md +237 -0
  7. package/TOOLS.md +36 -0
  8. package/USER.md +17 -0
  9. package/{backend/convex → convex}/_generated/api.d.ts +6 -6
  10. package/convex/credits.ts +211 -0
  11. package/convex/http.ts +490 -0
  12. package/convex/providers.ts +516 -0
  13. package/convex/purchases.ts +183 -0
  14. package/convex/schema.ts +180 -0
  15. package/convex.json +3 -0
  16. package/dist/credentials.d.ts +19 -0
  17. package/dist/credentials.d.ts.map +1 -0
  18. package/dist/credentials.js +158 -0
  19. package/dist/credentials.js.map +1 -0
  20. package/dist/credits.d.ts +14 -11
  21. package/dist/credits.d.ts.map +1 -1
  22. package/dist/credits.js +151 -99
  23. package/dist/credits.js.map +1 -1
  24. package/dist/discovery.d.ts +7 -16
  25. package/dist/discovery.d.ts.map +1 -1
  26. package/dist/discovery.js +33 -40
  27. package/dist/discovery.js.map +1 -1
  28. package/dist/execute.d.ts +19 -0
  29. package/dist/execute.d.ts.map +1 -0
  30. package/dist/execute.js +285 -0
  31. package/dist/execute.js.map +1 -0
  32. package/dist/index.js +106 -30
  33. package/dist/index.js.map +1 -1
  34. package/dist/proxy.d.ts +6 -0
  35. package/dist/proxy.d.ts.map +1 -0
  36. package/dist/proxy.js +19 -0
  37. package/dist/proxy.js.map +1 -0
  38. package/dist/registry/apis.json +95362 -202
  39. package/dist/registry/apis_expanded.json +100853 -0
  40. package/dist/stripe.d.ts +68 -0
  41. package/dist/stripe.d.ts.map +1 -0
  42. package/dist/stripe.js +196 -0
  43. package/dist/stripe.js.map +1 -0
  44. package/dist/test.d.ts +3 -2
  45. package/dist/test.d.ts.map +1 -1
  46. package/dist/test.js +105 -75
  47. package/dist/test.js.map +1 -1
  48. package/dist/types.d.ts +0 -28
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/webhook.d.ts +2 -0
  51. package/dist/webhook.d.ts.map +1 -0
  52. package/dist/webhook.js +90 -0
  53. package/dist/webhook.js.map +1 -0
  54. package/landing/DESIGN.md +343 -0
  55. package/landing/package-lock.json +1190 -40
  56. package/landing/package.json +5 -2
  57. package/landing/public/android-chrome-192x192.png +0 -0
  58. package/landing/public/android-chrome-512x512.png +0 -0
  59. package/landing/public/apple-touch-icon.png +0 -0
  60. package/landing/public/demo.gif +0 -0
  61. package/landing/public/demo.mp4 +0 -0
  62. package/landing/public/favicon-16x16.png +0 -0
  63. package/landing/public/favicon-32x32.png +0 -0
  64. package/landing/public/favicon.ico +0 -0
  65. package/landing/public/favicon.svg +3 -0
  66. package/landing/public/icon.svg +47 -0
  67. package/landing/public/logo-mono.svg +37 -0
  68. package/landing/public/logo-simple.svg +45 -0
  69. package/landing/public/logo.svg +84 -0
  70. package/landing/public/og-image.png +0 -0
  71. package/landing/public/og-template.html +184 -0
  72. package/landing/public/site.webmanifest +31 -0
  73. package/landing/scripts/generate-assets.js +284 -0
  74. package/landing/scripts/generate-pngs.js +48 -0
  75. package/landing/scripts/generate-stats.js +42 -0
  76. package/landing/src/app/admin/page.tsx +348 -0
  77. package/landing/src/app/api/auth/magic-link/route.ts +73 -0
  78. package/landing/src/app/api/auth/session/route.ts +38 -0
  79. package/landing/src/app/api/auth/verify/route.ts +43 -0
  80. package/landing/src/app/api/og/route.tsx +74 -0
  81. package/landing/src/app/globals.css +439 -100
  82. package/landing/src/app/layout.tsx +37 -9
  83. package/landing/src/app/page.tsx +640 -552
  84. package/landing/src/app/providers/dashboard/login/page.tsx +176 -0
  85. package/landing/src/app/providers/dashboard/page.tsx +589 -0
  86. package/landing/src/app/providers/dashboard/verify/page.tsx +106 -0
  87. package/landing/src/app/providers/layout.tsx +14 -0
  88. package/landing/src/app/providers/page.tsx +402 -0
  89. package/landing/src/app/providers/register/page.tsx +670 -0
  90. package/landing/src/components/ProviderDashboard.tsx +794 -0
  91. package/landing/src/hooks/useDashboardData.ts +99 -0
  92. package/landing/src/lib/apis.json +116054 -0
  93. package/landing/src/lib/convex-client.ts +106 -0
  94. package/landing/src/lib/mock-data.ts +285 -0
  95. package/landing/src/lib/stats.json +6 -0
  96. package/landing/tailwind.config.ts +12 -11
  97. package/landing/tsconfig.tsbuildinfo +1 -0
  98. package/package.json +21 -20
  99. package/scripts/SYMBOT-FIX.md +238 -0
  100. package/scripts/demo-simulation.py +177 -0
  101. package/scripts/expand-more.py +502 -0
  102. package/scripts/expand-registry.py +434 -0
  103. package/scripts/history-sanitizer.ts +272 -0
  104. package/scripts/mass-scrape.py +1308 -0
  105. package/scripts/sync-and-deploy.sh +36 -0
  106. package/src/credentials.ts +177 -0
  107. package/src/credits.ts +190 -122
  108. package/src/discovery.ts +45 -58
  109. package/src/execute.ts +350 -0
  110. package/src/index.ts +113 -31
  111. package/src/proxy.ts +24 -0
  112. package/src/registry/apis.json +95362 -202
  113. package/src/registry/apis_expanded.json +100853 -0
  114. package/src/stripe.ts +243 -0
  115. package/src/test.ts +127 -89
  116. package/src/types.ts +0 -34
  117. package/src/webhook.ts +107 -0
  118. package/.github/ISSUE_TEMPLATE/add-api.yml +0 -123
  119. package/BRIEFING.md +0 -30
  120. package/backend/convex/apiKeys.ts +0 -75
  121. package/backend/convex/purchases.ts +0 -74
  122. package/backend/convex/schema.ts +0 -45
  123. package/backend/convex/transactions.ts +0 -57
  124. package/backend/convex/users.ts +0 -94
  125. package/backend/package-lock.json +0 -521
  126. package/backend/package.json +0 -15
  127. package/dist/registry/parse_apis.py +0 -146
  128. package/dist/revenuecat.d.ts +0 -61
  129. package/dist/revenuecat.d.ts.map +0 -1
  130. package/dist/revenuecat.js +0 -166
  131. package/dist/revenuecat.js.map +0 -1
  132. package/dist/webhooks/revenuecat.d.ts +0 -48
  133. package/dist/webhooks/revenuecat.d.ts.map +0 -1
  134. package/dist/webhooks/revenuecat.js +0 -119
  135. package/dist/webhooks/revenuecat.js.map +0 -1
  136. package/docs/revenuecat-setup.md +0 -89
  137. package/landing/src/app/api/keys/route.ts +0 -71
  138. package/landing/src/app/api/log/route.ts +0 -37
  139. package/landing/src/app/api/stats/route.ts +0 -37
  140. package/landing/src/app/page.tsx.bak +0 -567
  141. package/landing/src/components/AddKeyModal.tsx +0 -159
  142. package/newsletter-template.html +0 -71
  143. package/outreach/OUTREACH-SYSTEM.md +0 -211
  144. package/outreach/email-template.html +0 -179
  145. package/outreach/targets.md +0 -133
  146. package/src/registry/parse_apis.py +0 -146
  147. package/src/revenuecat.ts +0 -239
  148. package/src/webhooks/revenuecat.ts +0 -187
  149. /package/{backend/convex → convex}/README.md +0 -0
  150. /package/{backend/convex → convex}/_generated/api.js +0 -0
  151. /package/{backend/convex → convex}/_generated/dataModel.d.ts +0 -0
  152. /package/{backend/convex → convex}/_generated/server.d.ts +0 -0
  153. /package/{backend/convex → convex}/_generated/server.js +0 -0
  154. /package/{backend/convex → convex}/tsconfig.json +0 -0
package/src/index.ts CHANGED
@@ -18,14 +18,17 @@ import {
18
18
  Tool,
19
19
  } from '@modelcontextprotocol/sdk/types.js';
20
20
 
21
- import { discoverAPIs, getAPIDetails, getCategories, getAllAPIs, getAPICount } from './discovery.js';
21
+ import { discoverAPIs, getAPIDetails, getCategories, getAllAPIs } from './discovery.js';
22
22
  import {
23
23
  getAgentCredits,
24
24
  addCredits,
25
25
  purchaseAPIAccess,
26
26
  getBalanceSummary,
27
- getAgentPurchases
27
+ getAgentPurchases,
28
+ getProvidersWithRealCredentials
28
29
  } from './credits.js';
30
+ import { hasRealCredentials } from './credentials.js';
31
+ import { executeAPICall, getConnectedProviders } from './execute.js';
29
32
 
30
33
  // Default agent ID for MVP (in production, this would come from auth)
31
34
  const DEFAULT_AGENT_ID = 'agent_default';
@@ -34,22 +37,27 @@ const DEFAULT_AGENT_ID = 'agent_default';
34
37
  const tools: Tool[] = [
35
38
  {
36
39
  name: 'discover_apis',
37
- description: 'Search 1400+ APIs based on what you need to do. Describe your use case naturally.',
40
+ description: 'Search for APIs based on what you need to do. Describe your use case naturally.',
38
41
  inputSchema: {
39
42
  type: 'object',
40
43
  properties: {
41
44
  query: {
42
45
  type: 'string',
43
- description: 'Natural language query describing what you need (e.g., "send SMS", "weather data", "payment processing", "text to speech")'
46
+ description: 'Natural language query describing what you need (e.g., "send SMS to Sweden", "search the web", "generate speech from text")'
44
47
  },
45
48
  category: {
46
49
  type: 'string',
47
- description: 'Filter by category (use list_categories to see all)'
50
+ description: 'Filter by category: communication, search, ai',
51
+ enum: ['communication', 'search', 'ai']
48
52
  },
49
53
  max_results: {
50
54
  type: 'number',
51
- description: 'Maximum number of results to return (default: 10)',
52
- default: 10
55
+ description: 'Maximum number of results to return (default: 5)',
56
+ default: 5
57
+ },
58
+ region: {
59
+ type: 'string',
60
+ description: 'Filter by region (e.g., "SE", "EU", "global")'
53
61
  }
54
62
  },
55
63
  required: ['query']
@@ -129,6 +137,36 @@ const tools: Tool[] = [
129
137
  type: 'object',
130
138
  properties: {}
131
139
  }
140
+ },
141
+ {
142
+ name: 'call_api',
143
+ description: 'Execute an API call through APIClaw Instant Connect. No API keys needed - we handle authentication.',
144
+ inputSchema: {
145
+ type: 'object',
146
+ properties: {
147
+ provider: {
148
+ type: 'string',
149
+ description: 'Provider ID (e.g., "46elks", "brave_search", "resend", "openrouter", "elevenlabs", "twilio")'
150
+ },
151
+ action: {
152
+ type: 'string',
153
+ description: 'Action to perform (e.g., "send_sms", "search", "send_email", "chat", "text_to_speech")'
154
+ },
155
+ params: {
156
+ type: 'object',
157
+ description: 'Parameters for the action. Varies by provider/action.'
158
+ }
159
+ },
160
+ required: ['provider', 'action', 'params']
161
+ }
162
+ },
163
+ {
164
+ name: 'list_connected',
165
+ description: 'List all APIs available for Instant Connect (no API key needed).',
166
+ inputSchema: {
167
+ type: 'object',
168
+ properties: {}
169
+ }
132
170
  }
133
171
  ];
134
172
 
@@ -159,9 +197,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
159
197
  case 'discover_apis': {
160
198
  const query = args?.query as string;
161
199
  const category = args?.category as string | undefined;
162
- const maxResults = (args?.max_results as number) || 10;
200
+ const maxResults = (args?.max_results as number) || 5;
201
+ const region = args?.region as string | undefined;
163
202
 
164
- const results = discoverAPIs(query, { category, maxResults });
203
+ const results = discoverAPIs(query, { category, maxResults, region });
165
204
 
166
205
  if (results.length === 0) {
167
206
  return {
@@ -171,8 +210,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
171
210
  text: JSON.stringify({
172
211
  status: 'no_results',
173
212
  message: `No APIs found matching "${query}". Try broader terms or check available categories with list_categories.`,
174
- total_apis: getAPICount(),
175
- available_categories: getCategories().slice(0, 20)
213
+ available_categories: getCategories()
176
214
  }, null, 2)
177
215
  }
178
216
  ]
@@ -187,17 +225,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
187
225
  status: 'success',
188
226
  query,
189
227
  results_count: results.length,
190
- total_apis: getAPICount(),
191
228
  results: results.map(r => ({
192
- id: r.api.id,
193
- name: r.api.name,
194
- description: r.api.description,
195
- category: r.api.category,
196
- auth: r.api.auth,
197
- https: r.api.https,
198
- link: r.api.link,
199
- pricing: r.api.pricing,
200
- keywords: r.api.keywords,
229
+ id: r.provider.id,
230
+ name: r.provider.name,
231
+ description: r.provider.description,
232
+ category: r.provider.category,
233
+ capabilities: r.provider.capabilities,
234
+ pricing_model: r.provider.pricing.model,
235
+ has_free_tier: r.provider.pricing.free_tier,
236
+ agent_success_rate: r.provider.agent_success_rate,
201
237
  relevance_score: r.relevance_score,
202
238
  match_reasons: r.match_reasons
203
239
  }))
@@ -274,12 +310,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
274
310
  provider: apiId,
275
311
  amount_paid_usd: amountUsd,
276
312
  credits_received: result.purchase!.credits_purchased,
277
- status: result.purchase!.status
313
+ status: result.purchase!.status,
314
+ real_credentials: hasRealCredentials(apiId)
278
315
  },
279
316
  credentials: result.purchase!.credentials,
280
317
  access: {
281
- link: api?.link,
282
- auth: api?.auth
318
+ base_url: api?.base_url,
319
+ docs_url: api?.docs_url,
320
+ auth_type: api?.auth_type
283
321
  }
284
322
  }, null, 2)
285
323
  }
@@ -301,11 +339,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
301
339
  balance_usd: summary.credits.balance_usd,
302
340
  currency: summary.credits.currency,
303
341
  total_spent_usd: summary.total_spent_usd,
342
+ real_credential_providers: summary.real_credentials_available,
304
343
  active_purchases: summary.active_purchases.map(p => ({
305
344
  id: p.id,
306
345
  provider: p.provider_id,
307
- credits_remaining: p.credits_purchased, // Would track actual usage in production
308
- status: p.status
346
+ credits_remaining: p.credits_purchased,
347
+ status: p.status,
348
+ real_credentials: hasRealCredentials(p.provider_id)
309
349
  }))
310
350
  }, null, 2)
311
351
  }
@@ -335,10 +375,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
335
375
 
336
376
  case 'list_categories': {
337
377
  const categories = getCategories();
338
- const categoryCounts: Record<string, number> = {};
378
+ const apisByCategory: Record<string, string[]> = {};
339
379
 
340
380
  for (const cat of categories) {
341
- categoryCounts[cat] = getAllAPIs().filter(a => a.category === cat).length;
381
+ apisByCategory[cat] = getAllAPIs()
382
+ .filter(a => a.category === cat)
383
+ .map(a => a.id);
342
384
  }
343
385
 
344
386
  return {
@@ -347,9 +389,49 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
347
389
  type: 'text',
348
390
  text: JSON.stringify({
349
391
  status: 'success',
350
- total_apis: getAPICount(),
351
- category_count: categories.length,
352
- categories: categoryCounts
392
+ categories: apisByCategory
393
+ }, null, 2)
394
+ }
395
+ ]
396
+ };
397
+ }
398
+
399
+ case 'call_api': {
400
+ const provider = args?.provider as string;
401
+ const action = args?.action as string;
402
+ const params = (args?.params as Record<string, any>) || {};
403
+
404
+ const result = await executeAPICall(provider, action, params);
405
+
406
+ return {
407
+ content: [
408
+ {
409
+ type: 'text',
410
+ text: JSON.stringify({
411
+ status: result.success ? 'success' : 'error',
412
+ provider: result.provider,
413
+ action: result.action,
414
+ ...(result.success ? { data: result.data } : { error: result.error }),
415
+ ...(result.cost !== undefined ? { cost_sek: result.cost } : {})
416
+ }, null, 2)
417
+ }
418
+ ],
419
+ isError: !result.success
420
+ };
421
+ }
422
+
423
+ case 'list_connected': {
424
+ const connected = getConnectedProviders();
425
+
426
+ return {
427
+ content: [
428
+ {
429
+ type: 'text',
430
+ text: JSON.stringify({
431
+ status: 'success',
432
+ message: 'These APIs are available for Instant Connect - no API key needed!',
433
+ connected_providers: connected,
434
+ usage: 'Use call_api with provider, action, and params to execute calls.'
353
435
  }, null, 2)
354
436
  }
355
437
  ]
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"];