@nordsym/apiclaw 1.5.18 → 1.6.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.
- package/CODEBASE.md +42 -0
- package/CONCEPT.md +9 -0
- package/DASHBOARD_FIX.md +9 -0
- package/EARN-CREDITS-SPEC.md +9 -0
- package/HIVR-INTEGRATION.md +9 -0
- package/HTTP-API.md +9 -0
- package/PRD-ANALYTICS-AGENTS-TEAMS.md +9 -0
- package/PRD-API-CHAINING.md +9 -0
- package/PRD-HARDEN-SHELL.md +9 -0
- package/PRD-LOGS-SUBAGENTS-V2.md +9 -0
- package/VISION.md +9 -0
- package/{AGENTS.md → apiclaw-AGENTS.md} +9 -0
- package/{CHANGELOG.md → apiclaw-CHANGELOG.md} +31 -0
- package/{CONTRIBUTING.md → apiclaw-CONTRIBUTING.md} +9 -0
- package/{HEARTBEAT.md → apiclaw-HEARTBEAT.md} +9 -0
- package/{IDENTITY.md → apiclaw-IDENTITY.md} +9 -0
- package/{README.md → apiclaw-README.md} +9 -0
- package/{SOUL.md → apiclaw-SOUL.md} +9 -0
- package/{TOOLS.md → apiclaw-TOOLS.md} +9 -0
- package/{USER.md → apiclaw-USER.md} +9 -0
- package/convex/_generated/api.d.ts +2 -0
- package/convex/{README.md → apiclaw-convex-README.md} +9 -0
- package/convex/http.ts +315 -0
- package/convex/seedPratham.ts +161 -0
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +136 -2
- package/dist/credentials.js.map +1 -1
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +289 -1
- package/dist/execute.js.map +1 -1
- package/docs/PRD-BILLING.md +9 -0
- package/docs/PRD-EARN-SYSTEM.md +9 -0
- package/docs/PRD-MCP-AUTO-SETUP.md +9 -0
- package/docs/PRD-ORGANIC-DISTRIBUTION.md +9 -0
- package/docs/PRD-agent-first-billing.md +9 -0
- package/docs/PRD-customer-key-passthrough.md +9 -0
- package/docs/PRD-final-polish.md +9 -0
- package/docs/PRD-mobile-responsive.md +9 -0
- package/docs/PRD-navigation-expansion.md +9 -0
- package/docs/PRD-stripe-billing.md +9 -0
- package/docs/PRD-workspace-cleanup.md +9 -0
- package/docs/PRD-workspace-fixes.md +9 -0
- package/docs/SUBAGENT-NAMING.md +9 -0
- package/docs/enterprise-deployment.md +6 -0
- package/email-templates/{README.md → email-templates-README.md} +9 -0
- package/landing/DESIGN.md +9 -0
- package/package.json +2 -2
- package/scripts/SYMBOT-FIX.md +9 -0
- package/src/credentials.ts +150 -2
- package/src/execute.ts +306 -1
- package/test-legacy-apis.sh +51 -0
- package/convex/adminActivate.d.ts +0 -3
- package/convex/adminActivate.js +0 -47
- package/convex/adminActivate.js.map +0 -1
- package/convex/adminStats.d.ts +0 -3
- package/convex/adminStats.js +0 -42
- package/convex/adminStats.js.map +0 -1
- package/convex/agents.d.ts +0 -54
- package/convex/agents.js +0 -499
- package/convex/agents.js.map +0 -1
- package/convex/analytics.d.ts +0 -5
- package/convex/analytics.js +0 -166
- package/convex/analytics.js.map +0 -1
- package/convex/billing.d.ts +0 -88
- package/convex/billing.js +0 -655
- package/convex/billing.js.map +0 -1
- package/convex/capabilities.d.ts +0 -9
- package/convex/capabilities.js +0 -145
- package/convex/capabilities.js.map +0 -1
- package/convex/chains.d.ts +0 -67
- package/convex/chains.js +0 -1042
- package/convex/chains.js.map +0 -1
- package/convex/credits.d.ts +0 -25
- package/convex/credits.js +0 -186
- package/convex/credits.js.map +0 -1
- package/convex/crons.d.ts +0 -3
- package/convex/crons.js +0 -17
- package/convex/crons.js.map +0 -1
- package/convex/directCall.d.ts +0 -72
- package/convex/directCall.js +0 -627
- package/convex/directCall.js.map +0 -1
- package/convex/earnProgress.d.ts +0 -58
- package/convex/earnProgress.js +0 -649
- package/convex/earnProgress.js.map +0 -1
- package/convex/email.d.ts +0 -14
- package/convex/email.js +0 -300
- package/convex/email.js.map +0 -1
- package/convex/feedback.d.ts +0 -7
- package/convex/feedback.js +0 -227
- package/convex/feedback.js.map +0 -1
- package/convex/http.d.ts +0 -3
- package/convex/http.js +0 -1106
- package/convex/http.js.map +0 -1
- package/convex/http.ts.bak +0 -934
- package/convex/logs.d.ts +0 -38
- package/convex/logs.js +0 -487
- package/convex/logs.js.map +0 -1
- package/convex/mou.d.ts +0 -6
- package/convex/mou.js +0 -82
- package/convex/mou.js.map +0 -1
- package/convex/providerKeys.d.ts +0 -31
- package/convex/providerKeys.js +0 -257
- package/convex/providerKeys.js.map +0 -1
- package/convex/providers.d.ts +0 -29
- package/convex/providers.js +0 -756
- package/convex/providers.js.map +0 -1
- package/convex/purchases.d.ts +0 -7
- package/convex/purchases.js +0 -157
- package/convex/purchases.js.map +0 -1
- package/convex/ratelimit.d.ts +0 -4
- package/convex/ratelimit.js +0 -91
- package/convex/ratelimit.js.map +0 -1
- package/convex/searchLogs.d.ts +0 -4
- package/convex/searchLogs.js +0 -129
- package/convex/searchLogs.js.map +0 -1
- package/convex/spendAlerts.d.ts +0 -36
- package/convex/spendAlerts.js +0 -380
- package/convex/spendAlerts.js.map +0 -1
- package/convex/stripeActions.d.ts +0 -19
- package/convex/stripeActions.js +0 -411
- package/convex/stripeActions.js.map +0 -1
- package/convex/teams.d.ts +0 -21
- package/convex/teams.js +0 -215
- package/convex/teams.js.map +0 -1
- package/convex/telemetry.d.ts +0 -4
- package/convex/telemetry.js +0 -74
- package/convex/telemetry.js.map +0 -1
- package/convex/usage.d.ts +0 -27
- package/convex/usage.js +0 -229
- package/convex/usage.js.map +0 -1
- package/convex/waitlist.d.ts +0 -4
- package/convex/waitlist.js +0 -49
- package/convex/waitlist.js.map +0 -1
- package/convex/webhooks.d.ts +0 -12
- package/convex/webhooks.js +0 -410
- package/convex/webhooks.js.map +0 -1
- package/convex/workspaces.d.ts +0 -29
- package/convex/workspaces.js +0 -880
- package/convex/workspaces.js.map +0 -1
- package/dist/registry/apis.json.bak +0 -248811
- package/src/registry/apis.json.bak +0 -248811
package/scripts/SYMBOT-FIX.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
nord_type: ENGINE
|
|
3
|
+
nord_owner: APIClaw
|
|
4
|
+
nord_status: LIVE
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Symbot/Clawdbot Fix — Message History Sanitizer
|
|
2
8
|
|
|
3
9
|
**Problem:** `unexpected tool_use_id found in tool_result blocks: toolu_012ogrVbszMVvQZF6Jpcbvar`
|
|
@@ -236,3 +242,6 @@ Om problem kvarstår:
|
|
|
236
242
|
|
|
237
243
|
*Created: 2026-02-21*
|
|
238
244
|
*Status: TESTED ✅*
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
*[[03 - Products/Apiclaw/Apiclaw|APIClaw]] · [[MOC|Production Line]]*
|
package/src/credentials.ts
CHANGED
|
@@ -172,17 +172,127 @@ const providers: Record<string, ProviderCredential> = {
|
|
|
172
172
|
type: 'api_key',
|
|
173
173
|
get(): APICredentials | null {
|
|
174
174
|
const env = loadEnvFile('apilayer.env');
|
|
175
|
-
|
|
175
|
+
const legacy = loadEnvFile('apilayer-legacy.env');
|
|
176
|
+
|
|
177
|
+
// Merge unified + legacy keys
|
|
176
178
|
const keys: Record<string, string> = {};
|
|
179
|
+
|
|
180
|
+
// Unified APILayer keys (APILAYER_*)
|
|
177
181
|
for (const [k, v] of Object.entries(env)) {
|
|
178
182
|
if (k.startsWith('APILAYER_') && v) {
|
|
179
183
|
keys[k] = v;
|
|
180
184
|
}
|
|
181
185
|
}
|
|
186
|
+
|
|
187
|
+
// Legacy keys (separate API domains)
|
|
188
|
+
for (const [k, v] of Object.entries(legacy)) {
|
|
189
|
+
if (v && k.endsWith('_API_KEY')) {
|
|
190
|
+
keys[k] = v;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
182
194
|
if (Object.keys(keys).length === 0) return null;
|
|
183
195
|
return { type: 'api_key', api_key: keys.APILAYER_EXCHANGERATE_KEY || '', ...keys } as any;
|
|
184
196
|
},
|
|
185
197
|
},
|
|
198
|
+
|
|
199
|
+
groq: {
|
|
200
|
+
type: 'bearer',
|
|
201
|
+
get(): APICredentials | null {
|
|
202
|
+
const env = loadEnvFile('groq.env');
|
|
203
|
+
const key = env.GROQ_API_KEY || process.env.GROQ_API_KEY;
|
|
204
|
+
if (key) {
|
|
205
|
+
return { type: 'bearer', api_key: key };
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
mistral: {
|
|
212
|
+
type: 'bearer',
|
|
213
|
+
get(): APICredentials | null {
|
|
214
|
+
const env = loadEnvFile('mistral.env');
|
|
215
|
+
const key = env.MISTRAL_API_KEY || process.env.MISTRAL_API_KEY;
|
|
216
|
+
if (key) {
|
|
217
|
+
return { type: 'bearer', api_key: key };
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
cohere: {
|
|
224
|
+
type: 'bearer',
|
|
225
|
+
get(): APICredentials | null {
|
|
226
|
+
const env = loadEnvFile('cohere.env');
|
|
227
|
+
const key = env.COHERE_API_KEY || process.env.COHERE_API_KEY;
|
|
228
|
+
if (key) {
|
|
229
|
+
return { type: 'bearer', api_key: key };
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
together: {
|
|
236
|
+
type: 'bearer',
|
|
237
|
+
get(): APICredentials | null {
|
|
238
|
+
const env = loadEnvFile('together.env');
|
|
239
|
+
const key = env.TOGETHER_API_KEY || process.env.TOGETHER_API_KEY;
|
|
240
|
+
if (key) {
|
|
241
|
+
return { type: 'bearer', api_key: key };
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
stability: {
|
|
248
|
+
type: 'api_key',
|
|
249
|
+
get(): APICredentials | null {
|
|
250
|
+
const env = loadEnvFile('stability.env');
|
|
251
|
+
const key = env.STABILITY_API_KEY || process.env.STABILITY_API_KEY;
|
|
252
|
+
if (key) {
|
|
253
|
+
return { type: 'api_key', api_key: key };
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
deepgram: {
|
|
260
|
+
type: 'api_key',
|
|
261
|
+
get(): APICredentials | null {
|
|
262
|
+
const env = loadEnvFile('deepgram.env');
|
|
263
|
+
const key = env.DEEPGRAM_API_KEY || process.env.DEEPGRAM_API_KEY;
|
|
264
|
+
if (key) {
|
|
265
|
+
return { type: 'api_key', api_key: key };
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
assemblyai: {
|
|
272
|
+
type: 'api_key',
|
|
273
|
+
get(): APICredentials | null {
|
|
274
|
+
const env = loadEnvFile('assemblyai.env');
|
|
275
|
+
const key = env.ASSEMBLYAI_API_KEY || process.env.ASSEMBLYAI_API_KEY;
|
|
276
|
+
if (key) {
|
|
277
|
+
return { type: 'api_key', api_key: key };
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
serper: {
|
|
284
|
+
type: 'api_key',
|
|
285
|
+
get(): APICredentials | null {
|
|
286
|
+
// Note: local file is serpapi.env for historical reasons
|
|
287
|
+
const env = loadEnvFile('serper.env');
|
|
288
|
+
const envAlt = loadEnvFile('serpapi.env');
|
|
289
|
+
const key = env.SERPER_API_KEY || envAlt.SERPAPI_API_KEY || envAlt.SERPER_API_KEY || process.env.SERPER_API_KEY;
|
|
290
|
+
if (key) {
|
|
291
|
+
return { type: 'api_key', api_key: key };
|
|
292
|
+
}
|
|
293
|
+
return null;
|
|
294
|
+
},
|
|
295
|
+
},
|
|
186
296
|
};
|
|
187
297
|
|
|
188
298
|
/**
|
|
@@ -233,7 +343,45 @@ export function hasRealCredentials(providerId: string): boolean {
|
|
|
233
343
|
}
|
|
234
344
|
if (providerId === 'apilayer') {
|
|
235
345
|
const env = loadEnvFile('apilayer.env');
|
|
236
|
-
|
|
346
|
+
const legacy = loadEnvFile('apilayer-legacy.env');
|
|
347
|
+
return !!(
|
|
348
|
+
env.APILAYER_EXCHANGERATE_KEY ||
|
|
349
|
+
process.env.APILAYER_EXCHANGERATE_KEY ||
|
|
350
|
+
Object.keys(legacy).length > 0
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
if (providerId === 'groq') {
|
|
354
|
+
const env = loadEnvFile('groq.env');
|
|
355
|
+
return !!(env.GROQ_API_KEY || process.env.GROQ_API_KEY);
|
|
356
|
+
}
|
|
357
|
+
if (providerId === 'mistral') {
|
|
358
|
+
const env = loadEnvFile('mistral.env');
|
|
359
|
+
return !!(env.MISTRAL_API_KEY || process.env.MISTRAL_API_KEY);
|
|
360
|
+
}
|
|
361
|
+
if (providerId === 'cohere') {
|
|
362
|
+
const env = loadEnvFile('cohere.env');
|
|
363
|
+
return !!(env.COHERE_API_KEY || process.env.COHERE_API_KEY);
|
|
364
|
+
}
|
|
365
|
+
if (providerId === 'together') {
|
|
366
|
+
const env = loadEnvFile('together.env');
|
|
367
|
+
return !!(env.TOGETHER_API_KEY || process.env.TOGETHER_API_KEY);
|
|
368
|
+
}
|
|
369
|
+
if (providerId === 'stability') {
|
|
370
|
+
const env = loadEnvFile('stability.env');
|
|
371
|
+
return !!(env.STABILITY_API_KEY || process.env.STABILITY_API_KEY);
|
|
372
|
+
}
|
|
373
|
+
if (providerId === 'deepgram') {
|
|
374
|
+
const env = loadEnvFile('deepgram.env');
|
|
375
|
+
return !!(env.DEEPGRAM_API_KEY || process.env.DEEPGRAM_API_KEY);
|
|
376
|
+
}
|
|
377
|
+
if (providerId === 'assemblyai') {
|
|
378
|
+
const env = loadEnvFile('assemblyai.env');
|
|
379
|
+
return !!(env.ASSEMBLYAI_API_KEY || process.env.ASSEMBLYAI_API_KEY);
|
|
380
|
+
}
|
|
381
|
+
if (providerId === 'serper') {
|
|
382
|
+
const env = loadEnvFile('serper.env');
|
|
383
|
+
const envAlt = loadEnvFile('serpapi.env');
|
|
384
|
+
return !!(env.SERPER_API_KEY || envAlt.SERPAPI_API_KEY || envAlt.SERPER_API_KEY || process.env.SERPER_API_KEY);
|
|
237
385
|
}
|
|
238
386
|
return false;
|
|
239
387
|
}
|
package/src/execute.ts
CHANGED
|
@@ -403,6 +403,7 @@ const apiEndpoints: Record<string, Record<string, { url: string; method: string;
|
|
|
403
403
|
run_shell: { url: 'https://api.e2b.dev/v1/sandboxes', method: 'POST' },
|
|
404
404
|
},
|
|
405
405
|
apilayer: {
|
|
406
|
+
// Unified APILayer APIs (apilayer.com)
|
|
406
407
|
exchange_rates: { url: 'https://api.apilayer.com/exchangerates_data/latest', method: 'GET' },
|
|
407
408
|
market_data: { url: 'http://api.marketstack.com/v1/eod', method: 'GET' },
|
|
408
409
|
aviation: { url: 'http://api.aviationstack.com/v1/flights', method: 'GET' },
|
|
@@ -417,6 +418,34 @@ const apiEndpoints: Record<string, Record<string, { url: string; method: string;
|
|
|
417
418
|
image_crop: { url: 'https://api.apilayer.com/smart_crop/url', method: 'POST' },
|
|
418
419
|
skills: { url: 'https://api.promptapi.com/skills', method: 'GET' },
|
|
419
420
|
form_submit: { url: 'https://api.apilayer.com/form_api/{endpoint}', method: 'POST' },
|
|
421
|
+
|
|
422
|
+
// Legacy APIs (separate domains, each with own key)
|
|
423
|
+
// FINANCE
|
|
424
|
+
fixer_convert: { url: 'http://data.fixer.io/api/convert', method: 'GET' },
|
|
425
|
+
fixer_latest: { url: 'http://data.fixer.io/api/latest', method: 'GET' },
|
|
426
|
+
currencylayer_live: { url: 'http://api.currencylayer.com/live', method: 'GET' },
|
|
427
|
+
currencylayer_convert: { url: 'http://api.currencylayer.com/convert', method: 'GET' },
|
|
428
|
+
coinlayer_live: { url: 'http://api.coinlayer.com/live', method: 'GET' },
|
|
429
|
+
exchangeratehost_latest: { url: 'https://api.exchangerate.host/latest', method: 'GET' },
|
|
430
|
+
|
|
431
|
+
// GEOLOCATION
|
|
432
|
+
weatherstack_current: { url: 'http://api.weatherstack.com/current', method: 'GET' },
|
|
433
|
+
weatherstack_forecast: { url: 'http://api.weatherstack.com/forecast', method: 'GET' },
|
|
434
|
+
ipstack_lookup: { url: 'http://api.ipstack.com/{ip}', method: 'GET' },
|
|
435
|
+
ipapi_lookup: { url: 'https://ipapi.co/{ip}/json/', method: 'GET' },
|
|
436
|
+
positionstack_forward: { url: 'http://api.positionstack.com/v1/forward', method: 'GET' },
|
|
437
|
+
positionstack_reverse: { url: 'http://api.positionstack.com/v1/reverse', method: 'GET' },
|
|
438
|
+
languagelayer_detect: { url: 'https://api.languagelayer.com/detect', method: 'POST' },
|
|
439
|
+
|
|
440
|
+
// SCRAPING
|
|
441
|
+
scrapestack_scrape: { url: 'http://api.scrapestack.com/scrape', method: 'GET' },
|
|
442
|
+
serpstack_search: { url: 'http://api.serpstack.com/search', method: 'GET' },
|
|
443
|
+
|
|
444
|
+
// NEWS
|
|
445
|
+
mediastack_news: { url: 'http://api.mediastack.com/v1/news', method: 'GET' },
|
|
446
|
+
|
|
447
|
+
// DEVTOOLS
|
|
448
|
+
userstack_detect: { url: 'http://api.userstack.com/detect', method: 'GET' },
|
|
420
449
|
},
|
|
421
450
|
};
|
|
422
451
|
|
|
@@ -1912,11 +1941,287 @@ const handlers: Record<string, Record<string, (params: any, creds: any) => Promi
|
|
|
1912
1941
|
'Content-Type': 'application/json',
|
|
1913
1942
|
},
|
|
1914
1943
|
body: JSON.stringify(formData || {}),
|
|
1915
|
-
}, { provider: 'apilayer', action: 'form_submit' });
|
|
1944
|
+
}, { provider: 'apilayer', 'action': 'form_submit' });
|
|
1916
1945
|
const data = await response.json() as Record<string, unknown>;
|
|
1917
1946
|
if (!response.ok) return createErrorResult('apilayer', 'form_submit', 'Request failed', statusToErrorCode(response.status));
|
|
1918
1947
|
return { success: true, provider: 'apilayer', action: 'form_submit', data };
|
|
1919
1948
|
},
|
|
1949
|
+
|
|
1950
|
+
// ========== LEGACY APIs (separate domains, each with own key) ==========
|
|
1951
|
+
|
|
1952
|
+
// FINANCE
|
|
1953
|
+
fixer_convert: async (params, creds) => {
|
|
1954
|
+
const key = creds.FIXER_API_KEY || creds.api_key;
|
|
1955
|
+
const { from, to, amount, date } = params;
|
|
1956
|
+
if (!from || !to || !amount) return createErrorResult('apilayer', 'fixer_convert', 'Missing required params: from, to, amount', ERROR_CODES.INVALID_PARAMS);
|
|
1957
|
+
|
|
1958
|
+
const url = new URL('http://data.fixer.io/api/convert');
|
|
1959
|
+
url.searchParams.set('access_key', key);
|
|
1960
|
+
url.searchParams.set('from', from);
|
|
1961
|
+
url.searchParams.set('to', to);
|
|
1962
|
+
url.searchParams.set('amount', amount.toString());
|
|
1963
|
+
if (date) url.searchParams.set('date', date);
|
|
1964
|
+
|
|
1965
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'fixer_convert' });
|
|
1966
|
+
const data = await response.json() as Record<string, unknown>;
|
|
1967
|
+
if (!response.ok) return createErrorResult('apilayer', 'fixer_convert', 'Request failed', statusToErrorCode(response.status));
|
|
1968
|
+
return { success: true, provider: 'apilayer', action: 'fixer_convert', data };
|
|
1969
|
+
},
|
|
1970
|
+
|
|
1971
|
+
fixer_latest: async (params, creds) => {
|
|
1972
|
+
const key = creds.FIXER_API_KEY || creds.api_key;
|
|
1973
|
+
const { base = 'EUR', symbols } = params;
|
|
1974
|
+
|
|
1975
|
+
const url = new URL('http://data.fixer.io/api/latest');
|
|
1976
|
+
url.searchParams.set('access_key', key);
|
|
1977
|
+
url.searchParams.set('base', base);
|
|
1978
|
+
if (symbols) url.searchParams.set('symbols', symbols);
|
|
1979
|
+
|
|
1980
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'fixer_latest' });
|
|
1981
|
+
const data = await response.json() as Record<string, unknown>;
|
|
1982
|
+
if (!response.ok) return createErrorResult('apilayer', 'fixer_latest', 'Request failed', statusToErrorCode(response.status));
|
|
1983
|
+
return { success: true, provider: 'apilayer', action: 'fixer_latest', data };
|
|
1984
|
+
},
|
|
1985
|
+
|
|
1986
|
+
currencylayer_live: async (params, creds) => {
|
|
1987
|
+
const key = creds.CURRENCYLAYER_API_KEY || creds.api_key;
|
|
1988
|
+
const { currencies, source = 'USD' } = params;
|
|
1989
|
+
|
|
1990
|
+
const url = new URL('http://api.currencylayer.com/live');
|
|
1991
|
+
url.searchParams.set('access_key', key);
|
|
1992
|
+
url.searchParams.set('source', source);
|
|
1993
|
+
if (currencies) url.searchParams.set('currencies', currencies);
|
|
1994
|
+
|
|
1995
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'currencylayer_live' });
|
|
1996
|
+
const data = await response.json() as Record<string, unknown>;
|
|
1997
|
+
if (!response.ok) return createErrorResult('apilayer', 'currencylayer_live', 'Request failed', statusToErrorCode(response.status));
|
|
1998
|
+
return { success: true, provider: 'apilayer', action: 'currencylayer_live', data };
|
|
1999
|
+
},
|
|
2000
|
+
|
|
2001
|
+
currencylayer_convert: async (params, creds) => {
|
|
2002
|
+
const key = creds.CURRENCYLAYER_API_KEY || creds.api_key;
|
|
2003
|
+
const { from, to, amount, date } = params;
|
|
2004
|
+
if (!from || !to || !amount) return createErrorResult('apilayer', 'currencylayer_convert', 'Missing required params: from, to, amount', ERROR_CODES.INVALID_PARAMS);
|
|
2005
|
+
|
|
2006
|
+
const url = new URL('http://api.currencylayer.com/convert');
|
|
2007
|
+
url.searchParams.set('access_key', key);
|
|
2008
|
+
url.searchParams.set('from', from);
|
|
2009
|
+
url.searchParams.set('to', to);
|
|
2010
|
+
url.searchParams.set('amount', amount.toString());
|
|
2011
|
+
if (date) url.searchParams.set('date', date);
|
|
2012
|
+
|
|
2013
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'currencylayer_convert' });
|
|
2014
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2015
|
+
if (!response.ok) return createErrorResult('apilayer', 'currencylayer_convert', 'Request failed', statusToErrorCode(response.status));
|
|
2016
|
+
return { success: true, provider: 'apilayer', action: 'currencylayer_convert', data };
|
|
2017
|
+
},
|
|
2018
|
+
|
|
2019
|
+
coinlayer_live: async (params, creds) => {
|
|
2020
|
+
const key = creds.COINLAYER_API_KEY || creds.api_key;
|
|
2021
|
+
const { symbols, target = 'USD' } = params;
|
|
2022
|
+
|
|
2023
|
+
const url = new URL('http://api.coinlayer.com/live');
|
|
2024
|
+
url.searchParams.set('access_key', key);
|
|
2025
|
+
url.searchParams.set('target', target);
|
|
2026
|
+
if (symbols) url.searchParams.set('symbols', symbols);
|
|
2027
|
+
|
|
2028
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'coinlayer_live' });
|
|
2029
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2030
|
+
if (!response.ok) return createErrorResult('apilayer', 'coinlayer_live', 'Request failed', statusToErrorCode(response.status));
|
|
2031
|
+
return { success: true, provider: 'apilayer', action: 'coinlayer_live', data };
|
|
2032
|
+
},
|
|
2033
|
+
|
|
2034
|
+
exchangeratehost_latest: async (params, creds) => {
|
|
2035
|
+
const key = creds.EXCHANGERATEHOST_API_KEY || creds.api_key;
|
|
2036
|
+
const { base = 'EUR', symbols } = params;
|
|
2037
|
+
|
|
2038
|
+
const url = new URL('https://api.exchangerate.host/latest');
|
|
2039
|
+
url.searchParams.set('access_key', key);
|
|
2040
|
+
url.searchParams.set('base', base);
|
|
2041
|
+
if (symbols) url.searchParams.set('symbols', symbols);
|
|
2042
|
+
|
|
2043
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'exchangeratehost_latest' });
|
|
2044
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2045
|
+
if (!response.ok) return createErrorResult('apilayer', 'exchangeratehost_latest', 'Request failed', statusToErrorCode(response.status));
|
|
2046
|
+
return { success: true, provider: 'apilayer', action: 'exchangeratehost_latest', data };
|
|
2047
|
+
},
|
|
2048
|
+
|
|
2049
|
+
// GEOLOCATION
|
|
2050
|
+
weatherstack_current: async (params, creds) => {
|
|
2051
|
+
const key = creds.WEATHERSTACK_API_KEY || creds.api_key;
|
|
2052
|
+
const { query, units = 'm' } = params;
|
|
2053
|
+
if (!query) return createErrorResult('apilayer', 'weatherstack_current', 'Missing required param: query (city name or coordinates)', ERROR_CODES.INVALID_PARAMS);
|
|
2054
|
+
|
|
2055
|
+
const url = new URL('http://api.weatherstack.com/current');
|
|
2056
|
+
url.searchParams.set('access_key', key);
|
|
2057
|
+
url.searchParams.set('query', query);
|
|
2058
|
+
url.searchParams.set('units', units);
|
|
2059
|
+
|
|
2060
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'weatherstack_current' });
|
|
2061
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2062
|
+
if (!response.ok) return createErrorResult('apilayer', 'weatherstack_current', 'Request failed', statusToErrorCode(response.status));
|
|
2063
|
+
return { success: true, provider: 'apilayer', action: 'weatherstack_current', data };
|
|
2064
|
+
},
|
|
2065
|
+
|
|
2066
|
+
weatherstack_forecast: async (params, creds) => {
|
|
2067
|
+
const key = creds.WEATHERSTACK_API_KEY || creds.api_key;
|
|
2068
|
+
const { query, forecast_days = 1, units = 'm' } = params;
|
|
2069
|
+
if (!query) return createErrorResult('apilayer', 'weatherstack_forecast', 'Missing required param: query', ERROR_CODES.INVALID_PARAMS);
|
|
2070
|
+
|
|
2071
|
+
const url = new URL('http://api.weatherstack.com/forecast');
|
|
2072
|
+
url.searchParams.set('access_key', key);
|
|
2073
|
+
url.searchParams.set('query', query);
|
|
2074
|
+
url.searchParams.set('forecast_days', forecast_days.toString());
|
|
2075
|
+
url.searchParams.set('units', units);
|
|
2076
|
+
|
|
2077
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'weatherstack_forecast' });
|
|
2078
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2079
|
+
if (!response.ok) return createErrorResult('apilayer', 'weatherstack_forecast', 'Request failed', statusToErrorCode(response.status));
|
|
2080
|
+
return { success: true, provider: 'apilayer', action: 'weatherstack_forecast', data };
|
|
2081
|
+
},
|
|
2082
|
+
|
|
2083
|
+
ipstack_lookup: async (params, creds) => {
|
|
2084
|
+
const key = creds.IPSTACK_API_KEY || creds.api_key;
|
|
2085
|
+
const { ip } = params;
|
|
2086
|
+
if (!ip) return createErrorResult('apilayer', 'ipstack_lookup', 'Missing required param: ip', ERROR_CODES.INVALID_PARAMS);
|
|
2087
|
+
|
|
2088
|
+
const url = new URL(`http://api.ipstack.com/${ip}`);
|
|
2089
|
+
url.searchParams.set('access_key', key);
|
|
2090
|
+
|
|
2091
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'ipstack_lookup' });
|
|
2092
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2093
|
+
if (!response.ok) return createErrorResult('apilayer', 'ipstack_lookup', 'Request failed', statusToErrorCode(response.status));
|
|
2094
|
+
return { success: true, provider: 'apilayer', action: 'ipstack_lookup', data };
|
|
2095
|
+
},
|
|
2096
|
+
|
|
2097
|
+
ipapi_lookup: async (params, creds) => {
|
|
2098
|
+
const key = creds.IPAPI_API_KEY || creds.api_key;
|
|
2099
|
+
const { ip } = params;
|
|
2100
|
+
if (!ip) return createErrorResult('apilayer', 'ipapi_lookup', 'Missing required param: ip', ERROR_CODES.INVALID_PARAMS);
|
|
2101
|
+
|
|
2102
|
+
const url = `https://ipapi.co/${ip}/json/?key=${key}`;
|
|
2103
|
+
|
|
2104
|
+
const response = await fetchWithRetry(url, {}, { provider: 'apilayer', action: 'ipapi_lookup' });
|
|
2105
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2106
|
+
if (!response.ok) return createErrorResult('apilayer', 'ipapi_lookup', 'Request failed', statusToErrorCode(response.status));
|
|
2107
|
+
return { success: true, provider: 'apilayer', action: 'ipapi_lookup', data };
|
|
2108
|
+
},
|
|
2109
|
+
|
|
2110
|
+
positionstack_forward: async (params, creds) => {
|
|
2111
|
+
const key = creds.POSITIONSTACK_API_KEY || creds.api_key;
|
|
2112
|
+
const { query, limit = 1 } = params;
|
|
2113
|
+
if (!query) return createErrorResult('apilayer', 'positionstack_forward', 'Missing required param: query (address)', ERROR_CODES.INVALID_PARAMS);
|
|
2114
|
+
|
|
2115
|
+
const url = new URL('http://api.positionstack.com/v1/forward');
|
|
2116
|
+
url.searchParams.set('access_key', key);
|
|
2117
|
+
url.searchParams.set('query', query);
|
|
2118
|
+
url.searchParams.set('limit', limit.toString());
|
|
2119
|
+
|
|
2120
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'positionstack_forward' });
|
|
2121
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2122
|
+
if (!response.ok) return createErrorResult('apilayer', 'positionstack_forward', 'Request failed', statusToErrorCode(response.status));
|
|
2123
|
+
return { success: true, provider: 'apilayer', action: 'positionstack_forward', data };
|
|
2124
|
+
},
|
|
2125
|
+
|
|
2126
|
+
positionstack_reverse: async (params, creds) => {
|
|
2127
|
+
const key = creds.POSITIONSTACK_API_KEY || creds.api_key;
|
|
2128
|
+
const { query, limit = 1 } = params;
|
|
2129
|
+
if (!query) return createErrorResult('apilayer', 'positionstack_reverse', 'Missing required param: query (lat,lng)', ERROR_CODES.INVALID_PARAMS);
|
|
2130
|
+
|
|
2131
|
+
const url = new URL('http://api.positionstack.com/v1/reverse');
|
|
2132
|
+
url.searchParams.set('access_key', key);
|
|
2133
|
+
url.searchParams.set('query', query);
|
|
2134
|
+
url.searchParams.set('limit', limit.toString());
|
|
2135
|
+
|
|
2136
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'positionstack_reverse' });
|
|
2137
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2138
|
+
if (!response.ok) return createErrorResult('apilayer', 'positionstack_reverse', 'Request failed', statusToErrorCode(response.status));
|
|
2139
|
+
return { success: true, provider: 'apilayer', action: 'positionstack_reverse', data };
|
|
2140
|
+
},
|
|
2141
|
+
|
|
2142
|
+
languagelayer_detect: async (params, creds) => {
|
|
2143
|
+
const key = creds.LANGUAGELAYER_API_KEY || creds.api_key;
|
|
2144
|
+
const { query } = params;
|
|
2145
|
+
if (!query) return createErrorResult('apilayer', 'languagelayer_detect', 'Missing required param: query (text to analyze)', ERROR_CODES.INVALID_PARAMS);
|
|
2146
|
+
|
|
2147
|
+
const response = await fetchWithRetry('https://api.languagelayer.com/detect', {
|
|
2148
|
+
method: 'POST',
|
|
2149
|
+
headers: {
|
|
2150
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
2151
|
+
},
|
|
2152
|
+
body: new URLSearchParams({ access_key: key, query }).toString(),
|
|
2153
|
+
}, { provider: 'apilayer', action: 'languagelayer_detect' });
|
|
2154
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2155
|
+
if (!response.ok) return createErrorResult('apilayer', 'languagelayer_detect', 'Request failed', statusToErrorCode(response.status));
|
|
2156
|
+
return { success: true, provider: 'apilayer', action: 'languagelayer_detect', data };
|
|
2157
|
+
},
|
|
2158
|
+
|
|
2159
|
+
// SCRAPING
|
|
2160
|
+
scrapestack_scrape: async (params, creds) => {
|
|
2161
|
+
const key = creds.SCRAPESTACK_API_KEY || creds.api_key;
|
|
2162
|
+
const { url: targetUrl } = params;
|
|
2163
|
+
if (!targetUrl) return createErrorResult('apilayer', 'scrapestack_scrape', 'Missing required param: url', ERROR_CODES.INVALID_PARAMS);
|
|
2164
|
+
|
|
2165
|
+
const url = new URL('http://api.scrapestack.com/scrape');
|
|
2166
|
+
url.searchParams.set('access_key', key);
|
|
2167
|
+
url.searchParams.set('url', targetUrl);
|
|
2168
|
+
|
|
2169
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'scrapestack_scrape' });
|
|
2170
|
+
const data = await response.text();
|
|
2171
|
+
if (!response.ok) return createErrorResult('apilayer', 'scrapestack_scrape', 'Request failed', statusToErrorCode(response.status));
|
|
2172
|
+
return { success: true, provider: 'apilayer', action: 'scrapestack_scrape', data: { html: data } };
|
|
2173
|
+
},
|
|
2174
|
+
|
|
2175
|
+
serpstack_search: async (params, creds) => {
|
|
2176
|
+
const key = creds.SERPSTACK_API_KEY || creds.api_key;
|
|
2177
|
+
const { query, num = 10 } = params;
|
|
2178
|
+
if (!query) return createErrorResult('apilayer', 'serpstack_search', 'Missing required param: query', ERROR_CODES.INVALID_PARAMS);
|
|
2179
|
+
|
|
2180
|
+
const url = new URL('http://api.serpstack.com/search');
|
|
2181
|
+
url.searchParams.set('access_key', key);
|
|
2182
|
+
url.searchParams.set('query', query);
|
|
2183
|
+
url.searchParams.set('num', num.toString());
|
|
2184
|
+
|
|
2185
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'serpstack_search' });
|
|
2186
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2187
|
+
if (!response.ok) return createErrorResult('apilayer', 'serpstack_search', 'Request failed', statusToErrorCode(response.status));
|
|
2188
|
+
return { success: true, provider: 'apilayer', action: 'serpstack_search', data };
|
|
2189
|
+
},
|
|
2190
|
+
|
|
2191
|
+
// NEWS
|
|
2192
|
+
mediastack_news: async (params, creds) => {
|
|
2193
|
+
const key = creds.MEDIASTACK_API_KEY || creds.api_key;
|
|
2194
|
+
const { keywords, categories, countries, languages, limit = 25 } = params;
|
|
2195
|
+
|
|
2196
|
+
const url = new URL('http://api.mediastack.com/v1/news');
|
|
2197
|
+
url.searchParams.set('access_key', key);
|
|
2198
|
+
if (keywords) url.searchParams.set('keywords', keywords);
|
|
2199
|
+
if (categories) url.searchParams.set('categories', categories);
|
|
2200
|
+
if (countries) url.searchParams.set('countries', countries);
|
|
2201
|
+
if (languages) url.searchParams.set('languages', languages);
|
|
2202
|
+
url.searchParams.set('limit', limit.toString());
|
|
2203
|
+
|
|
2204
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'mediastack_news' });
|
|
2205
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2206
|
+
if (!response.ok) return createErrorResult('apilayer', 'mediastack_news', 'Request failed', statusToErrorCode(response.status));
|
|
2207
|
+
return { success: true, provider: 'apilayer', action: 'mediastack_news', data };
|
|
2208
|
+
},
|
|
2209
|
+
|
|
2210
|
+
// DEVTOOLS
|
|
2211
|
+
userstack_detect: async (params, creds) => {
|
|
2212
|
+
const key = creds.USERSTACK_API_KEY || creds.api_key;
|
|
2213
|
+
const { ua } = params;
|
|
2214
|
+
if (!ua) return createErrorResult('apilayer', 'userstack_detect', 'Missing required param: ua (user agent string)', ERROR_CODES.INVALID_PARAMS);
|
|
2215
|
+
|
|
2216
|
+
const url = new URL('http://api.userstack.com/detect');
|
|
2217
|
+
url.searchParams.set('access_key', key);
|
|
2218
|
+
url.searchParams.set('ua', ua);
|
|
2219
|
+
|
|
2220
|
+
const response = await fetchWithRetry(url.toString(), {}, { provider: 'apilayer', action: 'userstack_detect' });
|
|
2221
|
+
const data = await response.json() as Record<string, unknown>;
|
|
2222
|
+
if (!response.ok) return createErrorResult('apilayer', 'userstack_detect', 'Request failed', statusToErrorCode(response.status));
|
|
2223
|
+
return { success: true, provider: 'apilayer', action: 'userstack_detect', data };
|
|
2224
|
+
},
|
|
1920
2225
|
},
|
|
1921
2226
|
};
|
|
1922
2227
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Test APILayer Legacy APIs
|
|
4
|
+
# Quick smoke test to verify keys work
|
|
5
|
+
|
|
6
|
+
echo "🧪 Testing APILayer Legacy APIs..."
|
|
7
|
+
echo ""
|
|
8
|
+
|
|
9
|
+
# Load keys
|
|
10
|
+
source ~/.secrets/apilayer-legacy.env
|
|
11
|
+
|
|
12
|
+
# Finance
|
|
13
|
+
echo "1. Testing Fixer API..."
|
|
14
|
+
curl -s "http://data.fixer.io/api/latest?access_key=$FIXER_API_KEY&base=USD&symbols=EUR" | jq -r '.success' 2>/dev/null && echo " ✓ Fixer working" || echo " ✗ Fixer failed"
|
|
15
|
+
|
|
16
|
+
echo "2. Testing Currencylayer..."
|
|
17
|
+
curl -s "http://api.currencylayer.com/live?access_key=$CURRENCYLAYER_API_KEY&source=USD¤cies=EUR" | jq -r '.success' 2>/dev/null && echo " ✓ Currencylayer working" || echo " ✗ Currencylayer failed"
|
|
18
|
+
|
|
19
|
+
echo "3. Testing Coinlayer..."
|
|
20
|
+
curl -s "http://api.coinlayer.com/live?access_key=$COINLAYER_API_KEY&target=USD&symbols=BTC" | jq -r '.success' 2>/dev/null && echo " ✓ Coinlayer working" || echo " ✗ Coinlayer failed"
|
|
21
|
+
|
|
22
|
+
# Geolocation
|
|
23
|
+
echo "4. Testing Weatherstack..."
|
|
24
|
+
curl -s "http://api.weatherstack.com/current?access_key=$WEATHERSTACK_API_KEY&query=Stockholm" | jq -r '.current.temperature' 2>/dev/null && echo " ✓ Weatherstack working" || echo " ✗ Weatherstack failed"
|
|
25
|
+
|
|
26
|
+
echo "5. Testing IPstack..."
|
|
27
|
+
curl -s "http://api.ipstack.com/8.8.8.8?access_key=$IPSTACK_API_KEY" | jq -r '.country_name' 2>/dev/null && echo " ✓ IPstack working" || echo " ✗ IPstack failed"
|
|
28
|
+
|
|
29
|
+
echo "6. Testing IPapi..."
|
|
30
|
+
curl -s "https://ipapi.co/8.8.8.8/json/?key=$IPAPI_API_KEY" | jq -r '.country_name' 2>/dev/null && echo " ✓ IPapi working" || echo " ✗ IPapi failed"
|
|
31
|
+
|
|
32
|
+
echo "7. Testing Positionstack..."
|
|
33
|
+
curl -s "http://api.positionstack.com/v1/forward?access_key=$POSITIONSTACK_API_KEY&query=Stockholm&limit=1" | jq -r '.data[0].label' 2>/dev/null && echo " ✓ Positionstack working" || echo " ✗ Positionstack failed"
|
|
34
|
+
|
|
35
|
+
# Scraping
|
|
36
|
+
echo "8. Testing Scrapestack..."
|
|
37
|
+
curl -s "http://api.scrapestack.com/scrape?access_key=$SCRAPESTACK_API_KEY&url=https://example.com" | head -c 100 2>/dev/null && echo " ✓ Scrapestack working" || echo " ✗ Scrapestack failed"
|
|
38
|
+
|
|
39
|
+
echo "9. Testing Serpstack..."
|
|
40
|
+
curl -s "http://api.serpstack.com/search?access_key=$SERPSTACK_API_KEY&query=OpenAI" | jq -r '.organic_results[0].title' 2>/dev/null && echo " ✓ Serpstack working" || echo " ✗ Serpstack failed"
|
|
41
|
+
|
|
42
|
+
# News
|
|
43
|
+
echo "10. Testing Mediastack..."
|
|
44
|
+
curl -s "http://api.mediastack.com/v1/news?access_key=$MEDIASTACK_API_KEY&keywords=AI&limit=1" | jq -r '.data[0].title' 2>/dev/null && echo " ✓ Mediastack working" || echo " ✗ Mediastack failed"
|
|
45
|
+
|
|
46
|
+
# DevTools
|
|
47
|
+
echo "11. Testing Userstack..."
|
|
48
|
+
curl -s "http://api.userstack.com/detect?access_key=$USERSTACK_API_KEY&ua=Mozilla/5.0" | jq -r '.device.type' 2>/dev/null && echo " ✓ Userstack working" || echo " ✗ Userstack failed"
|
|
49
|
+
|
|
50
|
+
echo ""
|
|
51
|
+
echo "✅ Test complete!"
|
package/convex/adminActivate.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { mutation } from "./_generated/server";
|
|
2
|
-
import { v } from "convex/values";
|
|
3
|
-
export const activateWorkspace = mutation({
|
|
4
|
-
args: { workspaceId: v.id("workspaces") },
|
|
5
|
-
handler: async (ctx, { workspaceId }) => {
|
|
6
|
-
const workspace = await ctx.db.get(workspaceId);
|
|
7
|
-
if (!workspace) {
|
|
8
|
-
return { success: false, error: "not_found" };
|
|
9
|
-
}
|
|
10
|
-
await ctx.db.patch(workspaceId, {
|
|
11
|
-
status: "active",
|
|
12
|
-
tier: "backer", // Give Hivr bees backer status
|
|
13
|
-
weeklyUsageLimit: 999999,
|
|
14
|
-
usageLimit: 999999,
|
|
15
|
-
backerUntil: new Date("2026-12-31T23:59:59Z").getTime(), // Founding Backer until end of 2026
|
|
16
|
-
updatedAt: Date.now(),
|
|
17
|
-
});
|
|
18
|
-
return { success: true };
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
function generateToken() {
|
|
22
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
23
|
-
let result = '';
|
|
24
|
-
for (let i = 0; i < 32; i++) {
|
|
25
|
-
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
26
|
-
}
|
|
27
|
-
return result;
|
|
28
|
-
}
|
|
29
|
-
export const createSessionForWorkspace = mutation({
|
|
30
|
-
args: { workspaceId: v.id("workspaces") },
|
|
31
|
-
handler: async (ctx, { workspaceId }) => {
|
|
32
|
-
const workspace = await ctx.db.get(workspaceId);
|
|
33
|
-
if (!workspace || workspace.status !== "active") {
|
|
34
|
-
return { success: false, error: "workspace_not_active" };
|
|
35
|
-
}
|
|
36
|
-
const sessionToken = "apiclaw_" + generateToken();
|
|
37
|
-
await ctx.db.insert("agentSessions", {
|
|
38
|
-
workspaceId,
|
|
39
|
-
sessionToken,
|
|
40
|
-
fingerprint: "hivr-bees",
|
|
41
|
-
lastUsedAt: Date.now(),
|
|
42
|
-
createdAt: Date.now(),
|
|
43
|
-
});
|
|
44
|
-
return { success: true, sessionToken };
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
//# sourceMappingURL=adminActivate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adminActivate.js","sourceRoot":"","sources":["adminActivate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACxC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;IACzC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;QACtC,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QAChD,CAAC;QAED,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,QAAQ,EAAE,+BAA+B;YAC/C,gBAAgB,EAAE,MAAM;YACxB,UAAU,EAAE,MAAM;YAClB,WAAW,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC,CAAC,OAAO,EAAE,EAAE,oCAAoC;YAC7F,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,aAAa;IACpB,MAAM,KAAK,GAAG,gEAAgE,CAAC;IAC/E,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;IACzC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;QACtC,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAChD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC;QAC3D,CAAC;QAED,MAAM,YAAY,GAAG,UAAU,GAAG,aAAa,EAAE,CAAC;QAElD,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE;YACnC,WAAW;YACX,YAAY;YACZ,WAAW,EAAE,WAAW;YACxB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;YACtB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACzC,CAAC;CACF,CAAC,CAAC"}
|
package/convex/adminStats.d.ts
DELETED