@nordsym/apiclaw 1.7.1 → 1.7.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nordsym/apiclaw",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "description": "The API layer for AI agents. Dashboard + 22K APIs + 18 Direct Call providers. MCP native.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { executeAPICall } from './execute.js';
7
- import { logAPICall } from './analytics.js';
7
+ import { logAPICall } from './mcp-analytics.js';
8
8
 
9
9
  // Convex HTTP API for capability queries
10
10
  const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || 'https://adventurous-avocet-799.convex.cloud';
package/src/execute.ts CHANGED
@@ -2256,11 +2256,26 @@ export async function getProviderActionsAsync(providerId: string): Promise<strin
2256
2256
  }
2257
2257
 
2258
2258
  // Get all connected providers with their actions (static handlers only)
2259
- export function getConnectedProviders(): { provider: string; actions: string[] }[] {
2260
- return Object.entries(handlers).map(([provider, actions]) => ({
2261
- provider,
2262
- actions: Object.keys(actions),
2263
- }));
2259
+ // APILayer actions blocked by subscription tier
2260
+ const BLOCKED_ACTIONS = ['verify_number', 'world_news', 'image_crop', 'form_submit'];
2261
+ const RATE_LIMITED_ACTIONS = ['pdf_generate'];
2262
+
2263
+ export function getConnectedProviders(): { provider: string; actions: string[]; blocked?: string[]; rate_limited?: string[] }[] {
2264
+ return Object.entries(handlers).map(([provider, actions]) => {
2265
+ const allActions = Object.keys(actions);
2266
+ if (provider === 'apilayer') {
2267
+ const live = allActions.filter(a => !BLOCKED_ACTIONS.includes(a) && !RATE_LIMITED_ACTIONS.includes(a));
2268
+ const blocked = allActions.filter(a => BLOCKED_ACTIONS.includes(a));
2269
+ const rateLimited = allActions.filter(a => RATE_LIMITED_ACTIONS.includes(a));
2270
+ return {
2271
+ provider,
2272
+ actions: live,
2273
+ ...(blocked.length > 0 ? { blocked } : {}),
2274
+ ...(rateLimited.length > 0 ? { rate_limited: rateLimited } : {}),
2275
+ };
2276
+ }
2277
+ return { provider, actions: allActions };
2278
+ });
2264
2279
  }
2265
2280
 
2266
2281
  // Execute an API call
package/src/http-api.ts CHANGED
@@ -15,7 +15,7 @@ import { URL } from 'url';
15
15
  import { discoverAPIs } from './discovery.js';
16
16
  import { isOpenAPI, executeOpenAPI } from './open-apis.js';
17
17
  import { executeMetered } from './metered.js';
18
- import { logAPICall } from './analytics.js';
18
+ import { logAPICall } from './mcp-analytics.js';
19
19
  import { getMachineFingerprint } from './session.js';
20
20
  import { isAuthorized, getProduct } from './product-whitelist.js';
21
21
 
package/src/index.ts CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  import { hasRealCredentials } from './credentials.js';
32
32
  import { getConnectedProviders } from './execute.js';
33
33
  import { executeMetered } from './metered.js';
34
- import { logAPICall } from './analytics.js';
34
+ import { logAPICall } from './mcp-analytics.js';
35
35
  import { isOpenAPI, executeOpenAPI, listOpenAPIs, getOpenAPIActions } from './open-apis.js';
36
36
  import { PROXY_PROVIDERS } from './proxy.js';
37
37
  import {
@@ -1,32 +0,0 @@
1
- /**
2
- * APIClaw Analytics - Track all API usage
3
- * Both Direct Call and Open API calls are logged here
4
- */
5
- export interface APICallLog {
6
- timestamp: string;
7
- provider: string;
8
- action: string;
9
- type: 'direct' | 'open';
10
- userId?: string;
11
- success: boolean;
12
- latencyMs?: number;
13
- error?: string;
14
- metadata?: {
15
- product?: string;
16
- [key: string]: any;
17
- };
18
- }
19
- /**
20
- * Log an API call to local file AND Convex
21
- */
22
- export declare function logAPICall(log: APICallLog): void;
23
- /**
24
- * Webhook for real-time analytics (optional)
25
- * Set APICLAW_ANALYTICS_WEBHOOK env var to enable
26
- */
27
- export declare function sendToWebhook(log: APICallLog): Promise<void>;
28
- /**
29
- * Track API call with timing
30
- */
31
- export declare function trackAPICall<T>(provider: string, action: string, type: 'direct' | 'open', userId: string | undefined, fn: () => Promise<T>): Promise<T>;
32
- //# sourceMappingURL=analytics.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AA+BD;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAYhD;AA+BD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAalE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,GAAG,MAAM,EACvB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CA0BZ"}
package/dist/analytics.js DELETED
@@ -1,130 +0,0 @@
1
- /**
2
- * APIClaw Analytics - Track all API usage
3
- * Both Direct Call and Open API calls are logged here
4
- */
5
- import { appendFileSync, existsSync, mkdirSync } from 'fs';
6
- import { homedir } from 'os';
7
- import { join } from 'path';
8
- import { ConvexHttpClient } from 'convex/browser';
9
- import { api } from '../convex/_generated/api.js';
10
- // Log directory
11
- const LOG_DIR = join(homedir(), '.apiclaw', 'logs');
12
- const LOG_FILE = join(LOG_DIR, 'api-calls.jsonl');
13
- // Convex client (lazy init)
14
- let convexClient = null;
15
- function getConvexClient() {
16
- if (convexClient)
17
- return convexClient;
18
- const convexUrl = process.env.APICLAW_CONVEX_URL || process.env.NEXT_PUBLIC_CONVEX_URL;
19
- if (!convexUrl)
20
- return null;
21
- try {
22
- convexClient = new ConvexHttpClient(convexUrl);
23
- return convexClient;
24
- }
25
- catch (e) {
26
- console.error('[APIClaw Analytics] Failed to init Convex client:', e);
27
- return null;
28
- }
29
- }
30
- // Ensure log directory exists
31
- function ensureLogDir() {
32
- if (!existsSync(LOG_DIR)) {
33
- mkdirSync(LOG_DIR, { recursive: true });
34
- }
35
- }
36
- /**
37
- * Log an API call to local file AND Convex
38
- */
39
- export function logAPICall(log) {
40
- // 1. Local file (existing behavior)
41
- try {
42
- ensureLogDir();
43
- const line = JSON.stringify(log) + '\n';
44
- appendFileSync(LOG_FILE, line);
45
- }
46
- catch (e) {
47
- console.error('[APIClaw Analytics] Failed to log to file:', e);
48
- }
49
- // 2. Send to Convex (new - includes anonymous usage)
50
- sendToConvex(log).catch(() => { }); // Fire and forget
51
- }
52
- /**
53
- * Send analytics event to Convex
54
- * Works for both authenticated and anonymous users
55
- */
56
- async function sendToConvex(log) {
57
- const client = getConvexClient();
58
- if (!client)
59
- return;
60
- try {
61
- await client.mutation(api.analytics.log, {
62
- event: 'api_call',
63
- provider: log.provider,
64
- query: log.action, // Store action as query field
65
- identifier: log.userId || 'anonymous',
66
- metadata: {
67
- type: log.type,
68
- success: log.success,
69
- latencyMs: log.latencyMs,
70
- error: log.error,
71
- timestamp: log.timestamp,
72
- ...log.metadata, // Include product and any other metadata
73
- },
74
- });
75
- }
76
- catch (e) {
77
- // Silent fail - don't break API calls for logging errors
78
- console.error('[APIClaw Analytics] Failed to send to Convex:', e);
79
- }
80
- }
81
- /**
82
- * Webhook for real-time analytics (optional)
83
- * Set APICLAW_ANALYTICS_WEBHOOK env var to enable
84
- */
85
- export async function sendToWebhook(log) {
86
- const webhookUrl = process.env.APICLAW_ANALYTICS_WEBHOOK;
87
- if (!webhookUrl)
88
- return;
89
- try {
90
- await fetch(webhookUrl, {
91
- method: 'POST',
92
- headers: { 'Content-Type': 'application/json' },
93
- body: JSON.stringify(log),
94
- });
95
- }
96
- catch (e) {
97
- // Silent fail
98
- }
99
- }
100
- /**
101
- * Track API call with timing
102
- */
103
- export async function trackAPICall(provider, action, type, userId, fn) {
104
- const start = Date.now();
105
- let success = true;
106
- let error;
107
- try {
108
- return await fn();
109
- }
110
- catch (e) {
111
- success = false;
112
- error = e.message;
113
- throw e;
114
- }
115
- finally {
116
- const log = {
117
- timestamp: new Date().toISOString(),
118
- provider,
119
- action,
120
- type,
121
- userId,
122
- success,
123
- latencyMs: Date.now() - start,
124
- error,
125
- };
126
- logAPICall(log);
127
- sendToWebhook(log).catch(() => { }); // Fire and forget
128
- }
129
- }
130
- //# sourceMappingURL=analytics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"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"}
@@ -1,129 +0,0 @@
1
- /**
2
- * APIClaw Analytics - Track all API usage
3
- * Both Direct Call and Open API calls are logged here
4
- */
5
- import { appendFileSync, existsSync, mkdirSync } from 'fs';
6
- import { homedir } from 'os';
7
- import { join } from 'path';
8
- import { ConvexHttpClient } from 'convex/browser';
9
- import { api } from '../convex/_generated/api.js';
10
- // Log directory
11
- const LOG_DIR = join(homedir(), '.apiclaw', 'logs');
12
- const LOG_FILE = join(LOG_DIR, 'api-calls.jsonl');
13
- // Convex client (lazy init)
14
- let convexClient = null;
15
- function getConvexClient() {
16
- if (convexClient)
17
- return convexClient;
18
- const convexUrl = process.env.APICLAW_CONVEX_URL || process.env.NEXT_PUBLIC_CONVEX_URL;
19
- if (!convexUrl)
20
- return null;
21
- try {
22
- convexClient = new ConvexHttpClient(convexUrl);
23
- return convexClient;
24
- }
25
- catch (e) {
26
- console.error('[APIClaw Analytics] Failed to init Convex client:', e);
27
- return null;
28
- }
29
- }
30
- // Ensure log directory exists
31
- function ensureLogDir() {
32
- if (!existsSync(LOG_DIR)) {
33
- mkdirSync(LOG_DIR, { recursive: true });
34
- }
35
- }
36
- /**
37
- * Log an API call to local file AND Convex
38
- */
39
- export function logAPICall(log) {
40
- // 1. Local file (existing behavior)
41
- try {
42
- ensureLogDir();
43
- const line = JSON.stringify(log) + '\n';
44
- appendFileSync(LOG_FILE, line);
45
- }
46
- catch (e) {
47
- console.error('[APIClaw Analytics] Failed to log to file:', e);
48
- }
49
- // 2. Send to Convex (new - includes anonymous usage)
50
- sendToConvex(log).catch(() => { }); // Fire and forget
51
- }
52
- /**
53
- * Send analytics event to Convex
54
- * Works for both authenticated and anonymous users
55
- */
56
- async function sendToConvex(log) {
57
- const client = getConvexClient();
58
- if (!client)
59
- return;
60
- try {
61
- await client.mutation(api.analytics.log, {
62
- event: 'api_call',
63
- provider: log.provider,
64
- query: log.action, // Store action as query field
65
- identifier: log.userId || 'anonymous',
66
- metadata: {
67
- type: log.type,
68
- success: log.success,
69
- latencyMs: log.latencyMs,
70
- error: log.error,
71
- timestamp: log.timestamp,
72
- ...log.metadata, // Include product and any other metadata
73
- },
74
- });
75
- }
76
- catch (e) {
77
- // Silent fail - don't break API calls for logging errors
78
- console.error('[APIClaw Analytics] Failed to send to Convex:', e);
79
- }
80
- }
81
- /**
82
- * Webhook for real-time analytics (optional)
83
- * Set APICLAW_ANALYTICS_WEBHOOK env var to enable
84
- */
85
- export async function sendToWebhook(log) {
86
- const webhookUrl = process.env.APICLAW_ANALYTICS_WEBHOOK;
87
- if (!webhookUrl)
88
- return;
89
- try {
90
- await fetch(webhookUrl, {
91
- method: 'POST',
92
- headers: { 'Content-Type': 'application/json' },
93
- body: JSON.stringify(log),
94
- });
95
- }
96
- catch (e) {
97
- // Silent fail
98
- }
99
- }
100
- /**
101
- * Track API call with timing
102
- */
103
- export async function trackAPICall(provider, action, type, userId, fn) {
104
- const start = Date.now();
105
- let success = true;
106
- let error;
107
- try {
108
- return await fn();
109
- }
110
- catch (e) {
111
- success = false;
112
- error = e.message;
113
- throw e;
114
- }
115
- finally {
116
- const log = {
117
- timestamp: new Date().toISOString(),
118
- provider,
119
- action,
120
- type,
121
- userId,
122
- success,
123
- latencyMs: Date.now() - start,
124
- error,
125
- };
126
- logAPICall(log);
127
- sendToWebhook(log).catch(() => { }); // Fire and forget
128
- }
129
- }
File without changes