@nordsym/apiclaw 1.7.7 → 1.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nordsym/apiclaw",
3
- "version": "1.7.7",
3
+ "version": "1.7.8",
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",
@@ -7,7 +7,7 @@ import { executeAPICall } from './execute.js';
7
7
  import { logAPICall } from './mcp-analytics.js';
8
8
 
9
9
  // Convex HTTP API for capability queries
10
- const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || 'https://adventurous-avocet-799.convex.cloud';
10
+ const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || 'https://brilliant-puffin-712.eu-west-1.convex.cloud';
11
11
 
12
12
  interface ProviderMapping {
13
13
  providerId: string;
package/src/cli.ts CHANGED
@@ -10,7 +10,7 @@ import { discoverAPIs, getAPIDetails, getCategories } from './discovery.js';
10
10
  import { executeAPICall, getConnectedProviders } from './execute.js';
11
11
  import { readSession, writeSession, clearSession, getMachineFingerprint } from './session.js';
12
12
 
13
- const CONVEX_URL = process.env.CONVEX_URL || 'https://adventurous-avocet-799.convex.cloud';
13
+ const CONVEX_URL = process.env.CONVEX_URL || 'https://brilliant-puffin-712.eu-west-1.convex.cloud';
14
14
  const convex = new ConvexHttpClient(CONVEX_URL);
15
15
 
16
16
  // Colors for terminal
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  // Hivr PROD Convex deployment
8
- const HIVR_CONVEX_URL = "https://sensible-quail-275.convex.cloud";
8
+ const HIVR_CONVEX_URL = "https://brilliant-puffin-712.eu-west-1.convex.cloud";
9
9
 
10
10
  // Fallback static whitelist (in case Convex is down)
11
11
  const STATIC_WHITELIST = [
package/src/index.ts CHANGED
@@ -77,6 +77,7 @@ interface WorkspaceContext {
77
77
  email: string;
78
78
  tier: string;
79
79
  usageRemaining: number;
80
+ usageCount: number;
80
81
  status: string;
81
82
  }
82
83
 
@@ -221,6 +222,7 @@ async function validateSession(): Promise<boolean> {
221
222
  email: result.email ?? '',
222
223
  tier: result.tier ?? 'free',
223
224
  usageRemaining: result.usageRemaining ?? 0,
225
+ usageCount: result.usageCount ?? 0,
224
226
  status: result.status ?? 'unknown',
225
227
  };
226
228
 
@@ -274,6 +276,9 @@ interface RateLimitState {
274
276
 
275
277
  const rateLimitStore = new Map<string, RateLimitState>();
276
278
 
279
+ // Unregistered (auto-provisioned, no email) users get this many calls before signup required
280
+ const UNREGISTERED_CALL_LIMIT = 5;
281
+
277
282
  /**
278
283
  * For proxy providers, allow anonymous usage with rate limiting
279
284
  */
@@ -308,12 +313,25 @@ function checkWorkspaceAccess(providerId?: string): { allowed: boolean; error?:
308
313
  }
309
314
 
310
315
  if (workspaceContext.status !== 'active') {
311
- return {
312
- allowed: false,
313
- error: `Workspace status: ${workspaceContext.status}. Please verify your email.`
316
+ return {
317
+ allowed: false,
318
+ error: `Workspace status: ${workspaceContext.status}. Please verify your email.`
314
319
  };
315
320
  }
316
-
321
+
322
+ // Unregistered workspaces (auto-provisioned, no email) get limited calls then must register
323
+ if (!workspaceContext.email && workspaceContext.usageCount >= UNREGISTERED_CALL_LIMIT) {
324
+ return {
325
+ allowed: false,
326
+ error: JSON.stringify({
327
+ success: false,
328
+ error: `Register to continue. You've used ${UNREGISTERED_CALL_LIMIT} free calls.`,
329
+ hint: "Run register_owner with your email to unlock 50 calls/week.",
330
+ action: "register_owner"
331
+ }, null, 2)
332
+ };
333
+ }
334
+
317
335
  if (workspaceContext.usageRemaining === 0) {
318
336
  // Free tier hit weekly limit
319
337
  if (workspaceContext.tier === 'free') {
@@ -1532,6 +1550,7 @@ Docs: https://apiclaw.nordsym.com
1532
1550
  }) as { success: boolean; remaining?: number };
1533
1551
  if (usageResult.success) {
1534
1552
  workspaceContext.usageRemaining = usageResult.remaining ?? -1;
1553
+ workspaceContext.usageCount = (workspaceContext.usageCount || 0) + 1;
1535
1554
  }
1536
1555
 
1537
1556
  // Track earn progress (first direct call + unique APIs)
@@ -1541,18 +1560,29 @@ Docs: https://apiclaw.nordsym.com
1541
1560
  }
1542
1561
  }
1543
1562
 
1563
+ // Build response with signup nudge for unregistered users
1564
+ const responseData: Record<string, unknown> = {
1565
+ status: result.success ? 'success' : 'error',
1566
+ provider: result.provider,
1567
+ action: result.action,
1568
+ type: apiType,
1569
+ ...(result.success ? { data: result.data } : { error: result.error }),
1570
+ ...(result.cost !== undefined ? { cost_sek: result.cost } : {})
1571
+ };
1572
+
1573
+ // Nudge unregistered users
1574
+ if (result.success && workspaceContext && !workspaceContext.email) {
1575
+ const remaining = UNREGISTERED_CALL_LIMIT - (workspaceContext.usageCount || 0);
1576
+ if (remaining > 0 && remaining <= 3) {
1577
+ responseData._notice = `${remaining} free calls remaining. Run register_owner to unlock 50/week.`;
1578
+ }
1579
+ }
1580
+
1544
1581
  return {
1545
1582
  content: [
1546
1583
  {
1547
1584
  type: 'text',
1548
- text: JSON.stringify({
1549
- status: result.success ? 'success' : 'error',
1550
- provider: result.provider,
1551
- action: result.action,
1552
- type: apiType,
1553
- ...(result.success ? { data: result.data } : { error: result.error }),
1554
- ...(result.cost !== undefined ? { cost_sek: result.cost } : {})
1555
- }, null, 2)
1585
+ text: JSON.stringify(responseData, null, 2)
1556
1586
  }
1557
1587
  ],
1558
1588
  isError: !result.success
@@ -1729,6 +1759,7 @@ Docs: https://apiclaw.nordsym.com
1729
1759
  email,
1730
1760
  tier: existing.tier,
1731
1761
  usageRemaining: existing.usageLimit - existing.usageCount,
1762
+ usageCount: existing.usageCount,
1732
1763
  status: existing.status,
1733
1764
  };
1734
1765
 
@@ -1770,7 +1801,7 @@ Docs: https://apiclaw.nordsym.com
1770
1801
  }) as { token: string; expiresAt: number };
1771
1802
 
1772
1803
  // Send magic link via email
1773
- const verifyUrl = `https://apiclaw.nordsym.com/verify?token=${magicLinkResult.token}`;
1804
+ const verifyUrl = `https://apiclaw.nordsym.com/auth/verify?token=${magicLinkResult.token}`;
1774
1805
 
1775
1806
  const emailResponse = await fetch('https://api.resend.com/emails', {
1776
1807
  method: 'POST',
@@ -1860,6 +1891,7 @@ Docs: https://apiclaw.nordsym.com
1860
1891
  email: result.email ?? '',
1861
1892
  tier: result.tier ?? 'free',
1862
1893
  usageRemaining: result.usageRemaining ?? 0,
1894
+ usageCount: result.usageCount ?? 0,
1863
1895
  status: result.status ?? 'unknown',
1864
1896
  };
1865
1897
 
@@ -1940,7 +1972,7 @@ Docs: https://apiclaw.nordsym.com
1940
1972
  }) as { token: string; expiresAt: number };
1941
1973
 
1942
1974
  // TODO: Agent 2 will implement actual email sending
1943
- const verifyUrl = `https://apiclaw.nordsym.com/verify?token=${magicLinkResult.token}`;
1975
+ const verifyUrl = `https://apiclaw.nordsym.com/auth/verify?token=${magicLinkResult.token}`;
1944
1976
 
1945
1977
  return {
1946
1978
  content: [{
@@ -18,7 +18,7 @@ interface ProductSource {
18
18
  const PRODUCT_SOURCES: ProductSource[] = [
19
19
  {
20
20
  name: 'hivr',
21
- convexUrl: 'https://sensible-quail-275.convex.cloud',
21
+ convexUrl: 'https://brilliant-puffin-712.eu-west-1.convex.cloud',
22
22
  queryPath: 'agents:list',
23
23
  agentIdField: 'handle', // ✅ Fixed: Hivr agents use 'handle', not 'agentId'
24
24
  },
package/src/proxy.ts CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { readSession, getMachineFingerprint } from './session.js';
6
6
 
7
- const PROXY_BASE = "https://adventurous-avocet-799.convex.site/proxy";
7
+ const PROXY_BASE = "https://brilliant-puffin-712.eu-west-1.convex.site/proxy";
8
8
 
9
9
  export async function callProxy(provider: string, params: any): Promise<any> {
10
10
  const url = `${PROXY_BASE}/${provider}`;
package/src/telemetry.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * Disable with APICLAW_TELEMETRY=false
11
11
  */
12
12
 
13
- const TELEMETRY_ENDPOINT = 'https://agile-crane-840.convex.cloud/api/mutation';
13
+ const TELEMETRY_ENDPOINT = 'https://brilliant-puffin-712.eu-west-1.convex.cloud/api/mutation';
14
14
 
15
15
  interface TelemetryEvent {
16
16
  type: 'startup' | 'search' | 'execute' | 'discovery';