@nordsym/apiclaw 1.5.8 → 1.5.10

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 (80) hide show
  1. package/CHANGELOG-WHITELIST-V2.md +269 -0
  2. package/HIVR-INTEGRATION.md +281 -0
  3. package/HIVR-WHITELIST-STATUS.md +205 -0
  4. package/HIVR-WHITELIST.md +148 -0
  5. package/HTTP-API.md +306 -0
  6. package/WHITELIST-ARCHITECTURE.md +379 -0
  7. package/api/discover.ts +71 -0
  8. package/api/health.ts +20 -0
  9. package/convex/http.d.ts.map +1 -1
  10. package/convex/http.js +8 -0
  11. package/convex/http.js.map +1 -1
  12. package/convex/http.ts +8 -0
  13. package/dist/access-control.d.ts +45 -0
  14. package/dist/access-control.d.ts.map +1 -0
  15. package/dist/access-control.js +142 -0
  16. package/dist/access-control.js.map +1 -0
  17. package/dist/analytics.d.ts +4 -0
  18. package/dist/analytics.d.ts.map +1 -1
  19. package/dist/analytics.js +1 -0
  20. package/dist/analytics.js.map +1 -1
  21. package/dist/bin-http.d.ts +7 -0
  22. package/dist/bin-http.d.ts.map +1 -0
  23. package/dist/bin-http.js +43 -0
  24. package/dist/bin-http.js.map +1 -0
  25. package/dist/credentials.d.ts.map +1 -1
  26. package/dist/credentials.js +20 -0
  27. package/dist/credentials.js.map +1 -1
  28. package/dist/execute.d.ts.map +1 -1
  29. package/dist/execute.js +245 -0
  30. package/dist/execute.js.map +1 -1
  31. package/dist/hivr-whitelist.d.ts +18 -0
  32. package/dist/hivr-whitelist.d.ts.map +1 -0
  33. package/dist/hivr-whitelist.js +95 -0
  34. package/dist/hivr-whitelist.js.map +1 -0
  35. package/dist/http-api.d.ts +16 -0
  36. package/dist/http-api.d.ts.map +1 -0
  37. package/dist/http-api.js +253 -0
  38. package/dist/http-api.js.map +1 -0
  39. package/dist/http-server-minimal.d.ts +7 -0
  40. package/dist/http-server-minimal.d.ts.map +1 -0
  41. package/dist/http-server-minimal.js +126 -0
  42. package/dist/http-server-minimal.js.map +1 -0
  43. package/dist/product-whitelist.d.ts +37 -0
  44. package/dist/product-whitelist.d.ts.map +1 -0
  45. package/dist/product-whitelist.js +203 -0
  46. package/dist/product-whitelist.js.map +1 -0
  47. package/dist/proxy.d.ts.map +1 -1
  48. package/dist/proxy.js +1 -1
  49. package/dist/proxy.js.map +1 -1
  50. package/landing/next-env.d.ts +1 -0
  51. package/landing/pages/api/discover.ts +43 -0
  52. package/landing/pages/api/health.ts +20 -0
  53. package/landing/src/app/auth/verify/page.tsx +6 -0
  54. package/landing/src/app/dashboard/verify/page.tsx +6 -0
  55. package/landing/src/app/join/page.tsx +6 -0
  56. package/landing/src/app/layout.tsx +5 -5
  57. package/landing/src/app/mou/[partnerId]/page.tsx +6 -0
  58. package/landing/src/app/providers/dashboard/[apiId]/actions/[actionId]/edit/page.tsx +6 -0
  59. package/landing/src/app/providers/dashboard/[apiId]/actions/new/page.tsx +5 -0
  60. package/landing/src/app/providers/dashboard/[apiId]/actions/page.tsx +5 -0
  61. package/landing/src/app/providers/dashboard/[apiId]/direct-call/page.tsx +5 -0
  62. package/landing/src/app/providers/dashboard/[apiId]/page.tsx +5 -0
  63. package/landing/src/app/providers/dashboard/[apiId]/test/page.tsx +5 -0
  64. package/landing/src/app/providers/dashboard/layout.tsx +6 -6
  65. package/landing/src/app/providers/dashboard/verify/page.tsx +6 -0
  66. package/landing/src/app/upgrade/page.tsx +6 -0
  67. package/landing/src/app/workspace/page.tsx +6 -0
  68. package/landing/src/lib/stats.json +1 -1
  69. package/package.json +6 -3
  70. package/scripts/test-whitelist-v2.sh +128 -0
  71. package/src/access-control.ts +174 -0
  72. package/src/analytics.ts +5 -0
  73. package/src/bin-http.ts +45 -0
  74. package/src/credentials.ts +20 -0
  75. package/src/execute.ts +247 -0
  76. package/src/hivr-whitelist.ts +110 -0
  77. package/src/http-api.ts +286 -0
  78. package/src/http-server-minimal.ts +154 -0
  79. package/src/product-whitelist.ts +246 -0
  80. package/src/proxy.ts +1 -1
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Multi-Product Whitelist System
3
+ * Supports multiple products (Hivr, NordSym, partners) with namespaced agentIds
4
+ *
5
+ * Format: product:agentId
6
+ * Examples: hivr:bytebee, nordsym:mollebot, partner_x:agent1
7
+ */
8
+ // Product sources configuration
9
+ const PRODUCT_SOURCES = [
10
+ {
11
+ name: 'hivr',
12
+ convexUrl: 'https://sensible-quail-275.convex.cloud',
13
+ queryPath: 'agents:list',
14
+ agentIdField: 'handle', // ✅ Fixed: Hivr agents use 'handle', not 'agentId'
15
+ },
16
+ // Add more products here as needed
17
+ // {
18
+ // name: 'nordsym',
19
+ // convexUrl: 'https://nordsym-deployment.convex.cloud',
20
+ // queryPath: 'team:listAgents',
21
+ // agentIdField: 'memberId',
22
+ // },
23
+ ];
24
+ // Fallback static whitelist (emergency only)
25
+ const STATIC_WHITELIST = [
26
+ 'hivr:bytebee',
27
+ 'hivr:analyzerbee',
28
+ 'hivr:buildbee',
29
+ 'hivr:buzzwriter',
30
+ 'hivr:hivemind',
31
+ 'hivr:hivesage',
32
+ 'hivr:symbot',
33
+ 'hivr:hivrqueen',
34
+ 'hivr:marketmaven',
35
+ 'hivr:reconbee',
36
+ 'hivr:sprintbee',
37
+ 'hivr:quillbee',
38
+ ];
39
+ const cache = new Map();
40
+ const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
41
+ /**
42
+ * Fetch agents from a single product source
43
+ */
44
+ async function fetchFromProduct(source) {
45
+ try {
46
+ const headers = {
47
+ 'Content-Type': 'application/json',
48
+ };
49
+ if (source.authToken) {
50
+ headers['Authorization'] = `Bearer ${source.authToken}`;
51
+ }
52
+ const response = await fetch(`${source.convexUrl}/api/query`, {
53
+ method: 'POST',
54
+ headers,
55
+ body: JSON.stringify({
56
+ path: source.queryPath,
57
+ args: {},
58
+ }),
59
+ });
60
+ if (!response.ok) {
61
+ console.warn(`[Whitelist] ${source.name}: HTTP ${response.status}`);
62
+ return [];
63
+ }
64
+ const result = await response.json();
65
+ // Convex HTTP API returns { status: "success", value: [...] }
66
+ const data = result.value || result;
67
+ if (!Array.isArray(data)) {
68
+ console.warn(`[Whitelist] ${source.name}: Invalid response format`, typeof data);
69
+ return [];
70
+ }
71
+ // Extract agentIds and add namespace
72
+ const agents = data
73
+ .map((item) => {
74
+ const agentId = item[source.agentIdField];
75
+ if (!agentId)
76
+ return null;
77
+ return `${source.name}:${String(agentId).toLowerCase().trim()}`;
78
+ })
79
+ .filter((id) => id !== null && id.length > 0);
80
+ console.log(`[Whitelist] ${source.name}: Fetched ${agents.length} agents`);
81
+ return agents;
82
+ }
83
+ catch (error) {
84
+ console.error(`[Whitelist] ${source.name}: Fetch failed`, error);
85
+ return [];
86
+ }
87
+ }
88
+ /**
89
+ * Fetch and merge agents from all product sources
90
+ */
91
+ async function fetchAllProducts() {
92
+ const results = await Promise.allSettled(PRODUCT_SOURCES.map(source => fetchFromProduct(source)));
93
+ const allAgents = [];
94
+ for (const result of results) {
95
+ if (result.status === 'fulfilled') {
96
+ allAgents.push(...result.value);
97
+ }
98
+ }
99
+ // If no products returned data, use static fallback
100
+ if (allAgents.length === 0) {
101
+ console.warn('[Whitelist] All sources failed, using static fallback');
102
+ return STATIC_WHITELIST;
103
+ }
104
+ return allAgents;
105
+ }
106
+ /**
107
+ * Get current whitelist (cached or fresh)
108
+ */
109
+ export async function getWhitelist() {
110
+ const now = Date.now();
111
+ // Check if any cache entry is still valid
112
+ const validCaches = [];
113
+ for (const [product, cached] of cache.entries()) {
114
+ if (now < cached.expiresAt) {
115
+ validCaches.push(...cached.agents);
116
+ }
117
+ }
118
+ // If all caches valid, return merged
119
+ if (validCaches.length > 0 && cache.size === PRODUCT_SOURCES.length) {
120
+ return validCaches;
121
+ }
122
+ // Fetch fresh data
123
+ const agents = await fetchAllProducts();
124
+ // Update cache per product
125
+ const agentsByProduct = new Map();
126
+ for (const agent of agents) {
127
+ const [product] = agent.split(':');
128
+ if (!agentsByProduct.has(product)) {
129
+ agentsByProduct.set(product, []);
130
+ }
131
+ agentsByProduct.get(product).push(agent);
132
+ }
133
+ for (const [product, productAgents] of agentsByProduct.entries()) {
134
+ cache.set(product, {
135
+ agents: productAgents,
136
+ expiresAt: now + CACHE_TTL,
137
+ });
138
+ }
139
+ return agents;
140
+ }
141
+ /**
142
+ * Check if agentId is authorized
143
+ * Supports both namespaced (product:agent) and legacy (agent) formats
144
+ */
145
+ export async function isAuthorized(agentId) {
146
+ if (!agentId)
147
+ return false;
148
+ const normalized = agentId.toLowerCase().trim();
149
+ const whitelist = await getWhitelist();
150
+ // Check exact match (namespaced)
151
+ if (whitelist.includes(normalized)) {
152
+ return true;
153
+ }
154
+ // Legacy support: check if agentId matches any product's agent (without namespace)
155
+ // e.g., "bytebee" matches "hivr:bytebee"
156
+ if (!normalized.includes(':')) {
157
+ const legacyMatch = whitelist.some(entry => {
158
+ const [, agent] = entry.split(':');
159
+ return agent === normalized;
160
+ });
161
+ if (legacyMatch) {
162
+ console.log(`[Whitelist] Legacy match for ${normalized}`);
163
+ return true;
164
+ }
165
+ }
166
+ return false;
167
+ }
168
+ /**
169
+ * Extract product name from agentId
170
+ */
171
+ export function getProduct(agentId) {
172
+ const [product] = agentId.split(':');
173
+ return product || null;
174
+ }
175
+ /**
176
+ * Force refresh whitelist (call after adding new agent)
177
+ */
178
+ export function invalidateCache(product) {
179
+ if (product) {
180
+ cache.delete(product);
181
+ console.log(`[Whitelist] Cache invalidated for ${product}`);
182
+ }
183
+ else {
184
+ cache.clear();
185
+ console.log('[Whitelist] All caches invalidated');
186
+ }
187
+ }
188
+ /**
189
+ * Add new product source dynamically
190
+ */
191
+ export function addProductSource(source) {
192
+ const existing = PRODUCT_SOURCES.find(s => s.name === source.name);
193
+ if (existing) {
194
+ console.warn(`[Whitelist] Product ${source.name} already exists, updating`);
195
+ Object.assign(existing, source);
196
+ }
197
+ else {
198
+ PRODUCT_SOURCES.push(source);
199
+ console.log(`[Whitelist] Added product source: ${source.name}`);
200
+ }
201
+ invalidateCache(source.name);
202
+ }
203
+ //# sourceMappingURL=product-whitelist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-whitelist.js","sourceRoot":"","sources":["../src/product-whitelist.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAyB3E;AAED,eAAO,MAAM,eAAe,UAAkN,CAAC"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAyB3E;AAED,eAAO,MAAM,eAAe,UAA8N,CAAC"}
package/dist/proxy.js CHANGED
@@ -25,5 +25,5 @@ export async function callProxy(provider, params) {
25
25
  }
26
26
  return response.json();
27
27
  }
28
- export const PROXY_PROVIDERS = ["openrouter", "brave_search", "resend", "elevenlabs", "46elks", "twilio", "replicate", "firecrawl", "e2b", "groq", "deepgram", "serper", "mistral", "cohere", "together", "stability", "assemblyai", "github"];
28
+ export const PROXY_PROVIDERS = ["openrouter", "brave_search", "resend", "elevenlabs", "46elks", "twilio", "replicate", "firecrawl", "e2b", "groq", "deepgram", "serper", "mistral", "cohere", "together", "stability", "assemblyai", "github", "apilayer"];
29
29
  //# sourceMappingURL=proxy.js.map
package/dist/proxy.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,UAAU,GAAG,0DAA0D,CAAC;AAE9E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,MAAW;IAC3D,MAAM,GAAG,GAAG,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;IAExC,2CAA2C;IAC3C,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,EAAE,WAAW,IAAI,QAAQ,WAAW,EAAE,CAAC;IAEjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,sBAAsB,EAAE,UAAU;YAClC,oBAAoB,EAAE,QAAQ;YAC9B,kBAAkB,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM;SAC5C;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;KAC7B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAuB,CAAC;QAC/G,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,gBAAgB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,UAAU,GAAG,0DAA0D,CAAC;AAE9E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,MAAW;IAC3D,MAAM,GAAG,GAAG,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;IAExC,2CAA2C;IAC3C,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,EAAE,WAAW,IAAI,QAAQ,WAAW,EAAE,CAAC;IAEjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,sBAAsB,EAAE,UAAU;YAClC,oBAAoB,EAAE,QAAQ;YAC9B,kBAAkB,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM;SAC5C;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;KAC7B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAuB,CAAC;QAC/G,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,gBAAgB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
+ /// <reference types="next/navigation-types/compat/navigation" />
3
4
 
4
5
  // NOTE: This file should not be edited
5
6
  // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
@@ -0,0 +1,43 @@
1
+ /**
2
+ * APIClaw Discovery API - Next.js API Route
3
+ * GET /api/discover?query=...&agentId=...
4
+ */
5
+
6
+ import type { NextApiRequest, NextApiResponse } from 'next';
7
+
8
+ // Import from built dist (since we can't easily import TS from parent)
9
+ // For now, return a simple response - we'll implement full logic after verifying deployment
10
+
11
+ export default async function handler(
12
+ req: NextApiRequest,
13
+ res: NextApiResponse
14
+ ) {
15
+ // CORS
16
+ res.setHeader('Access-Control-Allow-Origin', '*');
17
+ res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
18
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Agent-Id');
19
+
20
+ if (req.method === 'OPTIONS') {
21
+ return res.status(200).end();
22
+ }
23
+
24
+ if (req.method !== 'GET') {
25
+ return res.status(405).json({ error: 'Method not allowed' });
26
+ }
27
+
28
+ const { query, agentId, category, maxResults } = req.query;
29
+
30
+ if (!query || typeof query !== 'string') {
31
+ return res.status(400).json({ error: 'Missing query parameter' });
32
+ }
33
+
34
+ // TODO: Import actual whitelist + discovery logic
35
+ // For now, simple passthrough
36
+ return res.status(200).json({
37
+ success: true,
38
+ query,
39
+ agentId: typeof agentId === 'string' ? agentId : undefined,
40
+ message: 'APIClaw Discovery API - implementation pending',
41
+ timestamp: new Date().toISOString(),
42
+ });
43
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * APIClaw Health Check - Next.js API Route
3
+ * GET /api/health
4
+ */
5
+
6
+ import type { NextApiRequest, NextApiResponse } from 'next';
7
+
8
+ export default async function handler(
9
+ req: NextApiRequest,
10
+ res: NextApiResponse
11
+ ) {
12
+ res.setHeader('Access-Control-Allow-Origin', '*');
13
+
14
+ return res.status(200).json({
15
+ status: 'ok',
16
+ service: 'apiclaw-http-api',
17
+ version: '2.0.0',
18
+ timestamp: new Date().toISOString(),
19
+ });
20
+ }
@@ -22,6 +22,12 @@ interface VerifyResult {
22
22
 
23
23
  function VerifyContent() {
24
24
  const searchParams = useSearchParams();
25
+
26
+ // Handle null searchParams (shouldn't happen in client component, but TypeScript requires it)
27
+ if (!searchParams) {
28
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
29
+ }
30
+
25
31
  const token = searchParams.get("token");
26
32
  const referralCode = searchParams.get("ref"); // Referral code from signup URL
27
33
 
@@ -8,6 +8,12 @@ import Link from "next/link";
8
8
  function VerifyContent() {
9
9
  const router = useRouter();
10
10
  const searchParams = useSearchParams();
11
+
12
+ // Handle null searchParams
13
+ if (!searchParams) {
14
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
15
+ }
16
+
11
17
  const token = searchParams.get("token");
12
18
 
13
19
  const [status, setStatus] = useState<"verifying" | "success" | "error">("verifying");
@@ -7,6 +7,12 @@ import { Suspense } from "react";
7
7
  function JoinContent() {
8
8
  const searchParams = useSearchParams();
9
9
  const router = useRouter();
10
+
11
+ // Handle null searchParams
12
+ if (!searchParams) {
13
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
14
+ }
15
+
10
16
  const refCode = searchParams.get("ref");
11
17
 
12
18
  useEffect(() => {
@@ -5,7 +5,7 @@ import statsData from "@/lib/stats.json";
5
5
 
6
6
  export const metadata: Metadata = {
7
7
  title: "APIClaw | The API Layer for AI Agents",
8
- description: `Agents discover and evaluate APIs via MCP. Structured data. Ranked results. ${statsData.apiCount.toLocaleString()}+ APIs across ${statsData.categoryCount}+ categories.`,
8
+ description: `Your agent's API encyclopedia. Search by capability, call instantly. ${statsData.apiCount.toLocaleString()} APIs indexed • ${statsData.openApiCount.toLocaleString()} Open APIs ${statsData.directCallCount} Direct Call • MCP native`,
9
9
  metadataBase: new URL("https://apiclaw.nordsym.com"),
10
10
  icons: {
11
11
  icon: [
@@ -18,7 +18,7 @@ export const metadata: Metadata = {
18
18
  },
19
19
  openGraph: {
20
20
  title: "APIClaw | The API Layer for AI Agents",
21
- description: `${statsData.apiCount.toLocaleString()}+ APIs. MCP native. Direct Call: providers self-serve their APIs for AI agents.`,
21
+ description: `Your agent's API encyclopedia. Search by capability, call instantly. ${statsData.apiCount.toLocaleString()} APIs indexed • ${statsData.openApiCount.toLocaleString()} Open APIs ${statsData.directCallCount} Direct Call MCP native`,
22
22
  type: "website",
23
23
  siteName: "APIClaw",
24
24
  locale: "en_US",
@@ -34,7 +34,7 @@ export const metadata: Metadata = {
34
34
  twitter: {
35
35
  card: "summary_large_image",
36
36
  title: "APIClaw | The API Layer for AI Agents",
37
- description: `Agents discover and evaluate APIs via MCP. ${statsData.apiCount.toLocaleString()}+ APIs. MCP native.`,
37
+ description: `Your agent's API encyclopedia. Search by capability, call instantly. ${statsData.apiCount.toLocaleString()} APIs indexed • ${statsData.openApiCount.toLocaleString()} Open APIs • ${statsData.directCallCount} Direct Call • MCP native`,
38
38
  images: ["/api/og"],
39
39
  creator: "@nordsym",
40
40
  },
@@ -51,7 +51,7 @@ const schemaOrg = {
51
51
  "@type": "WebSite",
52
52
  "name": "APIClaw",
53
53
  "url": "https://apiclaw.nordsym.com",
54
- "description": "The API layer for AI agents. Discover and call APIs via MCP with structured data and ranked results."
54
+ "description": "Your agent's API encyclopedia. Search by capability, call instantly. 22,392 APIs indexed • 1,636 Open APIs 18 Direct Call MCP native"
55
55
  },
56
56
  {
57
57
  "@type": "Organization",
@@ -63,7 +63,7 @@ const schemaOrg = {
63
63
  "name": "APIClaw",
64
64
  "applicationCategory": "DeveloperApplication",
65
65
  "operatingSystem": "Web",
66
- "description": "API discovery and execution layer for AI agents. 22,000+ APIs indexed. MCP native. Direct Call providers.",
66
+ "description": "The API layer for AI agents. 22,392 APIs indexed, 1,636 Open APIs, 18 Direct Call providers. MCP native.",
67
67
  "offers": {
68
68
  "@type": "Offer",
69
69
  "price": "0",
@@ -126,6 +126,12 @@ const mouContent: Record<string, MOUPartner> = {
126
126
 
127
127
  export default function MOUPage() {
128
128
  const params = useParams();
129
+
130
+ // Handle null params
131
+ if (!params || !params.partnerId) {
132
+ return <div className="min-h-screen flex items-center justify-center">Invalid partner ID</div>;
133
+ }
134
+
129
135
  const partnerId = params.partnerId as string;
130
136
  const canvasRef = useRef<HTMLCanvasElement>(null);
131
137
  const [isDrawing, setIsDrawing] = useState(false);
@@ -47,6 +47,12 @@ const PARAM_LOCATIONS = ["body", "query", "path"] as const;
47
47
  export default function EditActionPage() {
48
48
  const params = useParams();
49
49
  const router = useRouter();
50
+
51
+ // Handle null params
52
+ if (!params || !params.apiId || !params.actionId) {
53
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
54
+ }
55
+
50
56
  const apiId = params.apiId as string;
51
57
  const actionId = params.actionId as string;
52
58
 
@@ -45,6 +45,11 @@ const PARAM_LOCATIONS = ["body", "query", "path"] as const;
45
45
 
46
46
  export default function NewActionPage() {
47
47
  const params = useParams();
48
+
49
+ // Handle null params
50
+ if (!params || !params.apiId) {
51
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
52
+ }
48
53
  const router = useRouter();
49
54
  const apiId = params.apiId as string;
50
55
 
@@ -41,6 +41,11 @@ const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || 'https://brilliant-puff
41
41
 
42
42
  export default function ActionsPage() {
43
43
  const params = useParams();
44
+
45
+ // Handle null params
46
+ if (!params || !params.apiId) {
47
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
48
+ }
44
49
  const router = useRouter();
45
50
  const apiId = params.apiId as string;
46
51
 
@@ -50,6 +50,11 @@ const authTypes = [
50
50
 
51
51
  export default function DirectCallSetupPage() {
52
52
  const params = useParams();
53
+
54
+ // Handle null params
55
+ if (!params || !params.apiId) {
56
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
57
+ }
53
58
  const router = useRouter();
54
59
  const apiId = params.apiId as string;
55
60
 
@@ -32,6 +32,11 @@ interface DirectCallConfig {
32
32
 
33
33
  export default function ApiOverviewPage() {
34
34
  const params = useParams();
35
+
36
+ // Handle null params
37
+ if (!params || !params.apiId) {
38
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
39
+ }
35
40
  const router = useRouter();
36
41
  const apiId = params.apiId as string;
37
42
 
@@ -61,6 +61,11 @@ const methodColors: Record<string, string> = {
61
61
 
62
62
  export default function TestConsolePage() {
63
63
  const params = useParams();
64
+
65
+ // Handle null params
66
+ if (!params || !params.apiId) {
67
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
68
+ }
64
69
  const router = useRouter();
65
70
  const apiId = params.apiId as string;
66
71
 
@@ -80,12 +80,12 @@ export default function DashboardLayout({
80
80
  };
81
81
 
82
82
  // Check if current route is API detail page
83
- const apiIdMatch = pathname.match(/\/providers\/dashboard\/([^/]+)/);
83
+ const apiIdMatch = pathname?.match(/\/providers\/dashboard\/([^/]+)/);
84
84
  const currentApiId = apiIdMatch ? apiIdMatch[1] : null;
85
85
  const isApiDetailPage = currentApiId && currentApiId !== "login" && currentApiId !== "verify";
86
86
 
87
87
  // Don't show layout for login/verify pages
88
- if (pathname.includes("/login") || pathname.includes("/verify")) {
88
+ if (pathname?.includes("/login") || pathname?.includes("/verify")) {
89
89
  return <>{children}</>;
90
90
  }
91
91
 
@@ -167,7 +167,7 @@ export default function DashboardLayout({
167
167
  key={item.label}
168
168
  href={item.href}
169
169
  className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
170
- (item.exact ? pathname === item.href : pathname.startsWith(item.href.split('?')[0])) && !isApiDetailPage
170
+ (item.exact ? pathname === item.href : pathname?.startsWith(item.href.split('?')[0])) && !isApiDetailPage
171
171
  ? "bg-accent text-white"
172
172
  : "text-text-secondary hover:bg-surface hover:text-text-primary"
173
173
  }`}
@@ -200,7 +200,7 @@ export default function DashboardLayout({
200
200
  <Link
201
201
  href={`/providers/dashboard/${currentApiId}/direct-call`}
202
202
  className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
203
- pathname.includes("/direct-call")
203
+ pathname?.includes("/direct-call")
204
204
  ? "bg-accent text-white"
205
205
  : "text-text-secondary hover:bg-surface hover:text-text-primary"
206
206
  }`}
@@ -212,7 +212,7 @@ export default function DashboardLayout({
212
212
  <Link
213
213
  href={`/providers/dashboard/${currentApiId}/actions`}
214
214
  className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
215
- pathname.includes("/actions")
215
+ pathname?.includes("/actions")
216
216
  ? "bg-accent text-white"
217
217
  : "text-text-secondary hover:bg-surface hover:text-text-primary"
218
218
  }`}
@@ -224,7 +224,7 @@ export default function DashboardLayout({
224
224
  <Link
225
225
  href={`/providers/dashboard/${currentApiId}/test`}
226
226
  className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
227
- pathname.includes("/test")
227
+ pathname?.includes("/test")
228
228
  ? "bg-accent text-white"
229
229
  : "text-text-secondary hover:bg-surface hover:text-text-primary"
230
230
  }`}
@@ -8,6 +8,12 @@ import Link from "next/link";
8
8
  function VerifyContent() {
9
9
  const router = useRouter();
10
10
  const searchParams = useSearchParams();
11
+
12
+ // Handle null searchParams
13
+ if (!searchParams) {
14
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
15
+ }
16
+
11
17
  const token = searchParams.get("token");
12
18
 
13
19
  const [status, setStatus] = useState<"verifying" | "success" | "error">("verifying");
@@ -40,6 +40,12 @@ async function actionConvex<T>(path: string, args: Record<string, unknown>): Pro
40
40
  function UpgradeContent() {
41
41
  const searchParams = useSearchParams();
42
42
  const router = useRouter();
43
+
44
+ // Handle null searchParams
45
+ if (!searchParams) {
46
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
47
+ }
48
+
43
49
  const workspaceId = searchParams.get("ws");
44
50
  const success = searchParams.get("success");
45
51
 
@@ -184,6 +184,12 @@ function generatePreviewAnalytics(): ProviderAnalytics {
184
184
  export default function WorkspacePage() {
185
185
  const router = useRouter();
186
186
  const searchParams = useSearchParams();
187
+
188
+ // Handle null searchParams
189
+ if (!searchParams) {
190
+ return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
191
+ }
192
+
187
193
  const tabFromUrl = searchParams.get("tab") as TabType | null;
188
194
  const subFromUrl = searchParams.get("sub") as AnalyticsSubtab | null;
189
195
 
@@ -4,7 +4,7 @@
4
4
  "directCallCount": 18,
5
5
  "npmDownloads": 4232,
6
6
  "categoryCount": 13,
7
- "generatedAt": "2026-03-18T12:30:05.958Z",
7
+ "generatedAt": "2026-03-19T12:16:00.022Z",
8
8
  "categoryBreakdown": {
9
9
  "Finance": 1179,
10
10
  "Auth & Security": 491,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nordsym/apiclaw",
3
- "version": "1.5.8",
3
+ "version": "1.5.10",
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",
@@ -16,6 +16,7 @@
16
16
  "build": "tsc && cp -r src/registry dist/",
17
17
  "dev": "tsx watch src/index.ts",
18
18
  "start": "node dist/index.js",
19
+ "start:http": "tsx src/http-server-minimal.ts",
19
20
  "test": "tsx src/test.ts",
20
21
  "test:e2e": "tsx src/test.ts",
21
22
  "webhook": "tsx src/webhook.ts",
@@ -66,7 +67,7 @@
66
67
  "@types/inquirer": "^9.0.9",
67
68
  "chalk": "^5.6.2",
68
69
  "commander": "^14.0.3",
69
- "convex": "^1.32.0",
70
+ "convex": "^1.33.1",
70
71
  "dotenv": "^17.3.1",
71
72
  "fs-extra": "^11.3.3",
72
73
  "hono": "^4.0.0",
@@ -77,10 +78,12 @@
77
78
  "devDependencies": {
78
79
  "@types/fs-extra": "^11.0.4",
79
80
  "@types/node": "^20.10.0",
81
+ "@vercel/node": "^5.6.16",
80
82
  "tsx": "^4.7.0",
81
83
  "typescript": "^5.3.0"
82
84
  },
83
85
  "bin": {
84
- "apiclaw": "./dist/bin.js"
86
+ "apiclaw": "./dist/bin.js",
87
+ "apiclaw-http": "./dist/bin-http.js"
85
88
  }
86
89
  }