@nordsym/apiclaw 1.5.9 → 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 (72) 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/WHITELIST-ARCHITECTURE.md +379 -0
  6. package/api/discover.ts +71 -0
  7. package/api/health.ts +20 -0
  8. package/convex/http.d.ts.map +1 -1
  9. package/convex/http.js +8 -0
  10. package/convex/http.js.map +1 -1
  11. package/convex/http.ts +8 -0
  12. package/dist/access-control.d.ts +45 -0
  13. package/dist/access-control.d.ts.map +1 -0
  14. package/dist/access-control.js +142 -0
  15. package/dist/access-control.js.map +1 -0
  16. package/dist/analytics.d.ts +4 -0
  17. package/dist/analytics.d.ts.map +1 -1
  18. package/dist/analytics.js +1 -0
  19. package/dist/analytics.js.map +1 -1
  20. package/dist/credentials.d.ts.map +1 -1
  21. package/dist/credentials.js +20 -0
  22. package/dist/credentials.js.map +1 -1
  23. package/dist/execute.d.ts.map +1 -1
  24. package/dist/execute.js +245 -0
  25. package/dist/execute.js.map +1 -1
  26. package/dist/hivr-whitelist.d.ts +18 -0
  27. package/dist/hivr-whitelist.d.ts.map +1 -0
  28. package/dist/hivr-whitelist.js +95 -0
  29. package/dist/hivr-whitelist.js.map +1 -0
  30. package/dist/http-api.d.ts.map +1 -1
  31. package/dist/http-api.js +17 -33
  32. package/dist/http-api.js.map +1 -1
  33. package/dist/http-server-minimal.d.ts +7 -0
  34. package/dist/http-server-minimal.d.ts.map +1 -0
  35. package/dist/http-server-minimal.js +126 -0
  36. package/dist/http-server-minimal.js.map +1 -0
  37. package/dist/product-whitelist.d.ts +37 -0
  38. package/dist/product-whitelist.d.ts.map +1 -0
  39. package/dist/product-whitelist.js +203 -0
  40. package/dist/product-whitelist.js.map +1 -0
  41. package/dist/proxy.d.ts.map +1 -1
  42. package/dist/proxy.js +1 -1
  43. package/dist/proxy.js.map +1 -1
  44. package/landing/next-env.d.ts +1 -0
  45. package/landing/pages/api/discover.ts +43 -0
  46. package/landing/pages/api/health.ts +20 -0
  47. package/landing/src/app/auth/verify/page.tsx +6 -0
  48. package/landing/src/app/dashboard/verify/page.tsx +6 -0
  49. package/landing/src/app/join/page.tsx +6 -0
  50. package/landing/src/app/mou/[partnerId]/page.tsx +6 -0
  51. package/landing/src/app/providers/dashboard/[apiId]/actions/[actionId]/edit/page.tsx +6 -0
  52. package/landing/src/app/providers/dashboard/[apiId]/actions/new/page.tsx +5 -0
  53. package/landing/src/app/providers/dashboard/[apiId]/actions/page.tsx +5 -0
  54. package/landing/src/app/providers/dashboard/[apiId]/direct-call/page.tsx +5 -0
  55. package/landing/src/app/providers/dashboard/[apiId]/page.tsx +5 -0
  56. package/landing/src/app/providers/dashboard/[apiId]/test/page.tsx +5 -0
  57. package/landing/src/app/providers/dashboard/layout.tsx +6 -6
  58. package/landing/src/app/providers/dashboard/verify/page.tsx +6 -0
  59. package/landing/src/app/upgrade/page.tsx +6 -0
  60. package/landing/src/app/workspace/page.tsx +6 -0
  61. package/landing/src/lib/stats.json +1 -1
  62. package/package.json +4 -2
  63. package/scripts/test-whitelist-v2.sh +128 -0
  64. package/src/access-control.ts +174 -0
  65. package/src/analytics.ts +5 -0
  66. package/src/credentials.ts +20 -0
  67. package/src/execute.ts +247 -0
  68. package/src/hivr-whitelist.ts +110 -0
  69. package/src/http-api.ts +18 -34
  70. package/src/http-server-minimal.ts +154 -0
  71. package/src/product-whitelist.ts +246 -0
  72. package/src/proxy.ts +1 -1
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Minimal HTTP API Server for APIClaw
4
+ * Bypasses chain executor imports
5
+ */
6
+ import { createServer } from 'http';
7
+ import { URL } from 'url';
8
+ const PORT = parseInt(process.env.PORT || '3001');
9
+ // Import whitelist directly
10
+ import { isAuthorized, getProduct } from './product-whitelist.js';
11
+ function sendJSON(res, status, data) {
12
+ res.writeHead(status, {
13
+ 'Content-Type': 'application/json',
14
+ 'Access-Control-Allow-Origin': '*',
15
+ });
16
+ res.end(JSON.stringify(data));
17
+ }
18
+ async function parseBody(req) {
19
+ return new Promise((resolve, reject) => {
20
+ let body = '';
21
+ req.on('data', (chunk) => body += chunk.toString());
22
+ req.on('end', () => {
23
+ try {
24
+ resolve(JSON.parse(body));
25
+ }
26
+ catch (e) {
27
+ reject(new Error('Invalid JSON'));
28
+ }
29
+ });
30
+ });
31
+ }
32
+ const server = createServer(async (req, res) => {
33
+ const url = new URL(req.url || '/', `http://${req.headers.host}`);
34
+ console.log(`[APIClaw] ${req.method} ${url.pathname}`);
35
+ // CORS
36
+ if (req.method === 'OPTIONS') {
37
+ res.writeHead(204, {
38
+ 'Access-Control-Allow-Origin': '*',
39
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
40
+ 'Access-Control-Allow-Headers': 'Content-Type',
41
+ });
42
+ res.end();
43
+ return;
44
+ }
45
+ // Health check
46
+ if (url.pathname === '/health') {
47
+ sendJSON(res, 200, {
48
+ status: 'ok',
49
+ service: 'apiclaw-http-api',
50
+ version: '2.0.0',
51
+ whitelist: 'multi-product',
52
+ });
53
+ return;
54
+ }
55
+ // Discovery endpoint
56
+ if (url.pathname === '/api/discover' && req.method === 'GET') {
57
+ const query = url.searchParams.get('query');
58
+ const agentId = url.searchParams.get('agentId');
59
+ if (!query) {
60
+ sendJSON(res, 400, { error: 'Missing query parameter' });
61
+ return;
62
+ }
63
+ const authorized = await isAuthorized(agentId || undefined);
64
+ if (!authorized) {
65
+ sendJSON(res, 403, {
66
+ error: 'Unauthorized',
67
+ message: 'This endpoint is restricted. Contact admin@nordsym.com',
68
+ });
69
+ return;
70
+ }
71
+ const product = agentId ? getProduct(agentId) : null;
72
+ sendJSON(res, 200, {
73
+ success: true,
74
+ query,
75
+ agentId,
76
+ product,
77
+ message: 'Whitelist v2.0 active - discovery endpoint placeholder',
78
+ });
79
+ return;
80
+ }
81
+ // Call API endpoint
82
+ if (url.pathname === '/api/call_api' && req.method === 'POST') {
83
+ try {
84
+ const body = await parseBody(req);
85
+ const { provider, action, params, agentId } = body;
86
+ if (!provider || !action || !agentId) {
87
+ sendJSON(res, 400, {
88
+ error: 'Missing required fields',
89
+ required: ['provider', 'action', 'agentId', 'params'],
90
+ });
91
+ return;
92
+ }
93
+ const authorized = await isAuthorized(agentId);
94
+ if (!authorized) {
95
+ sendJSON(res, 403, {
96
+ error: 'Unauthorized',
97
+ message: 'Agent not whitelisted',
98
+ });
99
+ return;
100
+ }
101
+ const product = getProduct(agentId);
102
+ sendJSON(res, 200, {
103
+ success: true,
104
+ agentId,
105
+ provider,
106
+ action,
107
+ product,
108
+ message: 'Whitelist v2.0 active - execution placeholder',
109
+ });
110
+ }
111
+ catch (e) {
112
+ sendJSON(res, 400, { error: e.message });
113
+ }
114
+ return;
115
+ }
116
+ // 404
117
+ sendJSON(res, 404, { error: 'Not found' });
118
+ });
119
+ server.listen(PORT, () => {
120
+ console.log(`\n🦞 APIClaw HTTP API (Whitelist v2.0)`);
121
+ console.log(` Running on http://localhost:${PORT}`);
122
+ console.log(` GET /health`);
123
+ console.log(` GET /api/discover?query=...&agentId=...`);
124
+ console.log(` POST /api/call_api\n`);
125
+ });
126
+ //# sourceMappingURL=http-server-minimal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server-minimal.js","sourceRoot":"","sources":["../src/http-server-minimal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
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
+ interface ProductSource {
9
+ name: string;
10
+ convexUrl: string;
11
+ queryPath: string;
12
+ agentIdField: string;
13
+ authToken?: string;
14
+ }
15
+ /**
16
+ * Get current whitelist (cached or fresh)
17
+ */
18
+ export declare function getWhitelist(): Promise<string[]>;
19
+ /**
20
+ * Check if agentId is authorized
21
+ * Supports both namespaced (product:agent) and legacy (agent) formats
22
+ */
23
+ export declare function isAuthorized(agentId: string | undefined): Promise<boolean>;
24
+ /**
25
+ * Extract product name from agentId
26
+ */
27
+ export declare function getProduct(agentId: string): string | null;
28
+ /**
29
+ * Force refresh whitelist (call after adding new agent)
30
+ */
31
+ export declare function invalidateCache(product?: string): void;
32
+ /**
33
+ * Add new product source dynamically
34
+ */
35
+ export declare function addProductSource(source: ProductSource): void;
36
+ export {};
37
+ //# sourceMappingURL=product-whitelist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-whitelist.d.ts","sourceRoot":"","sources":["../src/product-whitelist.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4HD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAqCtD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAyBhF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAQtD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAU5D"}
@@ -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(() => {
@@ -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