@layer-ai/core 0.9.1 → 1.0.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/dist/lib/key-resolver.d.ts +6 -2
- package/dist/lib/key-resolver.d.ts.map +1 -1
- package/dist/lib/key-resolver.js +3 -3
- package/dist/routes/v1/gates.js +2 -2
- package/dist/routes/v2/complete.d.ts.map +1 -1
- package/dist/routes/v2/complete.js +11 -30
- package/dist/routes/v2/tests/test-byok-completion.js +1 -1
- package/dist/routes/v2/tests/test-complete-anthropic.js +4 -4
- package/dist/routes/v2/tests/test-complete-openai.js +7 -7
- package/dist/routes/v2/tests/test-complete-routing.js +5 -5
- package/dist/services/providers/anthropic-adapter.d.ts.map +1 -1
- package/dist/services/providers/anthropic-adapter.js +4 -3
- package/dist/services/providers/google-adapter.d.ts.map +1 -1
- package/dist/services/providers/google-adapter.js +16 -11
- package/dist/services/providers/mistral-adapter.d.ts.map +1 -1
- package/dist/services/providers/mistral-adapter.js +10 -7
- package/dist/services/providers/openai-adapter.d.ts.map +1 -1
- package/dist/services/providers/openai-adapter.js +13 -9
- package/dist/services/providers/tests/test-anthropic-adapter.js +4 -4
- package/dist/services/providers/tests/test-google-adapter.js +9 -9
- package/dist/services/providers/tests/test-mistral-adapter.js +11 -11
- package/dist/services/providers/tests/test-openai-adapter.js +8 -8
- package/package.json +2 -2
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
* Priority: User's BYOK key → Platform key → Error
|
|
6
6
|
*/
|
|
7
7
|
import type { Provider } from './provider-constants.js';
|
|
8
|
+
export interface ResolvedKey {
|
|
9
|
+
key: string;
|
|
10
|
+
usedPlatformKey: boolean;
|
|
11
|
+
}
|
|
8
12
|
/**
|
|
9
13
|
* Resolves the API key to use for a provider
|
|
10
14
|
* @param provider - The provider name
|
|
11
15
|
* @param userId - Optional user ID for BYOK lookup
|
|
12
16
|
* @param platformKey - The platform's API key (fallback)
|
|
13
|
-
* @returns The API key to use
|
|
17
|
+
* @returns The API key to use and whether platform key was used
|
|
14
18
|
*/
|
|
15
|
-
export declare function resolveApiKey(provider: Provider, userId: string | undefined, platformKey: string | undefined): Promise<
|
|
19
|
+
export declare function resolveApiKey(provider: Provider, userId: string | undefined, platformKey: string | undefined): Promise<ResolvedKey>;
|
|
16
20
|
//# sourceMappingURL=key-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/key-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGxD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"key-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/key-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGxD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,OAAO,CAAC,WAAW,CAAC,CAoBtB"}
|
package/dist/lib/key-resolver.js
CHANGED
|
@@ -10,7 +10,7 @@ import { decrypt } from './encryption.js';
|
|
|
10
10
|
* @param provider - The provider name
|
|
11
11
|
* @param userId - Optional user ID for BYOK lookup
|
|
12
12
|
* @param platformKey - The platform's API key (fallback)
|
|
13
|
-
* @returns The API key to use
|
|
13
|
+
* @returns The API key to use and whether platform key was used
|
|
14
14
|
*/
|
|
15
15
|
export async function resolveApiKey(provider, userId, platformKey) {
|
|
16
16
|
// If userId is provided, check for BYOK key
|
|
@@ -18,7 +18,7 @@ export async function resolveApiKey(provider, userId, platformKey) {
|
|
|
18
18
|
try {
|
|
19
19
|
const byokKey = await getUserProviderKey(userId, provider);
|
|
20
20
|
if (byokKey) {
|
|
21
|
-
return byokKey;
|
|
21
|
+
return { key: byokKey, usedPlatformKey: false };
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
catch (error) {
|
|
@@ -28,7 +28,7 @@ export async function resolveApiKey(provider, userId, platformKey) {
|
|
|
28
28
|
}
|
|
29
29
|
// Fallback to platform key
|
|
30
30
|
if (platformKey) {
|
|
31
|
-
return platformKey;
|
|
31
|
+
return { key: platformKey, usedPlatformKey: true };
|
|
32
32
|
}
|
|
33
33
|
throw new Error(`No API key available for provider: ${provider}`);
|
|
34
34
|
}
|
package/dist/routes/v1/gates.js
CHANGED
|
@@ -327,7 +327,7 @@ router.post('/test', async (req, res) => {
|
|
|
327
327
|
try {
|
|
328
328
|
const request = {
|
|
329
329
|
type: 'chat',
|
|
330
|
-
|
|
330
|
+
gateId: finalGate.id,
|
|
331
331
|
model: finalGate.model,
|
|
332
332
|
data: {
|
|
333
333
|
messages,
|
|
@@ -363,7 +363,7 @@ router.post('/test', async (req, res) => {
|
|
|
363
363
|
try {
|
|
364
364
|
const request = {
|
|
365
365
|
type: 'chat',
|
|
366
|
-
|
|
366
|
+
gateId: finalGate.id,
|
|
367
367
|
model: fallbackModel,
|
|
368
368
|
data: {
|
|
369
369
|
messages,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/routes/v2/complete.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AASpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/routes/v2/complete.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AASpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA+OpC,eAAe,MAAM,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { db } from '../../lib/db/postgres.js';
|
|
3
|
-
import { cache } from '../../lib/db/redis.js';
|
|
4
3
|
import { authenticate } from '../../middleware/auth.js';
|
|
5
4
|
import { callAdapter, normalizeModelId } from '../../lib/provider-factory.js';
|
|
6
5
|
import { OverrideField } from '@layer-ai/sdk';
|
|
@@ -13,29 +12,6 @@ function isOverrideAllowed(allowOverrides, field) {
|
|
|
13
12
|
return false;
|
|
14
13
|
return allowOverrides[field] ?? false;
|
|
15
14
|
}
|
|
16
|
-
async function getGateConfig(userId, gateIdentifier) {
|
|
17
|
-
const isUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(gateIdentifier);
|
|
18
|
-
let gateConfig = null;
|
|
19
|
-
if (isUUID) {
|
|
20
|
-
gateConfig = await cache.getGateById(userId, gateIdentifier);
|
|
21
|
-
if (!gateConfig) {
|
|
22
|
-
gateConfig = await db.getGateByUserAndId(userId, gateIdentifier);
|
|
23
|
-
if (gateConfig) {
|
|
24
|
-
await cache.setGate(userId, gateConfig.name, gateConfig);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
gateConfig = await cache.getGate(userId, gateIdentifier);
|
|
30
|
-
if (!gateConfig) {
|
|
31
|
-
gateConfig = await db.getGateByUserAndName(userId, gateIdentifier);
|
|
32
|
-
if (gateConfig) {
|
|
33
|
-
await cache.setGate(userId, gateIdentifier, gateConfig);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return gateConfig;
|
|
38
|
-
}
|
|
39
15
|
function resolveFinalRequest(gateConfig, request) {
|
|
40
16
|
const finalRequest = { ...request };
|
|
41
17
|
let finalModel = gateConfig.model;
|
|
@@ -141,18 +117,23 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
141
117
|
let request = null;
|
|
142
118
|
try {
|
|
143
119
|
const rawRequest = req.body;
|
|
144
|
-
if (!rawRequest.
|
|
145
|
-
res.status(400).json({ error: 'bad_request', message: 'Missing required field:
|
|
120
|
+
if (!rawRequest.gateId) {
|
|
121
|
+
res.status(400).json({ error: 'bad_request', message: 'Missing required field: gateId' });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const isUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(rawRequest.gateId);
|
|
125
|
+
if (!isUUID) {
|
|
126
|
+
res.status(400).json({ error: 'bad_request', message: 'gateId must be a valid UUID. Gate names are no longer supported.' });
|
|
146
127
|
return;
|
|
147
128
|
}
|
|
148
|
-
gateConfig = await
|
|
129
|
+
gateConfig = await db.getGateByUserAndId(userId, rawRequest.gateId);
|
|
149
130
|
if (!gateConfig) {
|
|
150
|
-
res.status(404).json({ error: 'not_found', message: `Gate "${rawRequest.
|
|
131
|
+
res.status(404).json({ error: 'not_found', message: `Gate with ID "${rawRequest.gateId}" not found` });
|
|
151
132
|
return;
|
|
152
133
|
}
|
|
153
134
|
const requestType = rawRequest.type || gateConfig.taskType || 'chat';
|
|
154
135
|
request = {
|
|
155
|
-
|
|
136
|
+
gateId: rawRequest.gateId,
|
|
156
137
|
type: requestType,
|
|
157
138
|
data: rawRequest.data,
|
|
158
139
|
model: rawRequest.model,
|
|
@@ -171,7 +152,7 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
171
152
|
db.logRequest({
|
|
172
153
|
userId,
|
|
173
154
|
gateId: gateConfig.id,
|
|
174
|
-
gateName:
|
|
155
|
+
gateName: gateConfig.name,
|
|
175
156
|
modelRequested: request.model || gateConfig.model,
|
|
176
157
|
modelUsed: modelUsed,
|
|
177
158
|
promptTokens: result.usage?.promptTokens || 0,
|
|
@@ -12,7 +12,7 @@ import { GoogleAdapter } from '../../../services/providers/google-adapter.js';
|
|
|
12
12
|
// Test user ID from the database
|
|
13
13
|
const TEST_USER_ID = 'ebd64998-465d-4211-ad67-87b4e01ad0da';
|
|
14
14
|
const SIMPLE_REQUEST = {
|
|
15
|
-
|
|
15
|
+
gateId: 'byok-test',
|
|
16
16
|
model: 'gpt-4o-mini',
|
|
17
17
|
type: 'chat',
|
|
18
18
|
data: {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
async function testBasicChat() {
|
|
4
4
|
console.log('Test 1: Basic chat completion with Anthropic\n');
|
|
5
5
|
const request = {
|
|
6
|
-
|
|
6
|
+
gateId: 'test-gate',
|
|
7
7
|
model: 'claude-sonnet-4-5-20250929',
|
|
8
8
|
type: 'chat',
|
|
9
9
|
data: {
|
|
@@ -27,7 +27,7 @@ async function testBasicChat() {
|
|
|
27
27
|
async function testVision() {
|
|
28
28
|
console.log('\n\nTest 2: Vision with Anthropic (not supported in v1)\n');
|
|
29
29
|
const request = {
|
|
30
|
-
|
|
30
|
+
gateId: 'test-gate',
|
|
31
31
|
model: 'claude-sonnet-4-5-20250929',
|
|
32
32
|
type: 'chat',
|
|
33
33
|
data: {
|
|
@@ -49,7 +49,7 @@ async function testVision() {
|
|
|
49
49
|
async function testToolCalls() {
|
|
50
50
|
console.log('\n\nTest 3: Tool calls with Anthropic (not supported in v1)\n');
|
|
51
51
|
const request = {
|
|
52
|
-
|
|
52
|
+
gateId: 'test-gate',
|
|
53
53
|
model: 'claude-sonnet-4-5-20250929',
|
|
54
54
|
type: 'chat',
|
|
55
55
|
data: {
|
|
@@ -86,7 +86,7 @@ async function testToolCalls() {
|
|
|
86
86
|
async function testSystemPrompt() {
|
|
87
87
|
console.log('\n\nTest 4: System prompt and advanced params\n');
|
|
88
88
|
const request = {
|
|
89
|
-
|
|
89
|
+
gateId: 'test-gate',
|
|
90
90
|
model: 'claude-sonnet-4-5-20250929',
|
|
91
91
|
type: 'chat',
|
|
92
92
|
data: {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
async function testBasicChat() {
|
|
4
4
|
console.log('Test 1: Basic chat completion with OpenAI\n');
|
|
5
5
|
const request = {
|
|
6
|
-
|
|
6
|
+
gateId: 'test-gate',
|
|
7
7
|
model: 'gpt-4o-mini',
|
|
8
8
|
type: 'chat',
|
|
9
9
|
data: {
|
|
@@ -26,7 +26,7 @@ async function testBasicChat() {
|
|
|
26
26
|
async function testVision() {
|
|
27
27
|
console.log('\n\nTest 2: Vision with GPT-4o\n');
|
|
28
28
|
const request = {
|
|
29
|
-
|
|
29
|
+
gateId: 'test-gate',
|
|
30
30
|
model: 'gpt-4o',
|
|
31
31
|
type: 'chat',
|
|
32
32
|
data: {
|
|
@@ -49,7 +49,7 @@ async function testVision() {
|
|
|
49
49
|
async function testToolCalls() {
|
|
50
50
|
console.log('\n\nTest 3: Tool calls with GPT-4\n');
|
|
51
51
|
const request = {
|
|
52
|
-
|
|
52
|
+
gateId: 'test-gate',
|
|
53
53
|
model: 'gpt-4o-mini',
|
|
54
54
|
type: 'chat',
|
|
55
55
|
data: {
|
|
@@ -85,7 +85,7 @@ async function testToolCalls() {
|
|
|
85
85
|
async function testImageGeneration() {
|
|
86
86
|
console.log('\n\nTest 4: Image generation with DALL-E\n');
|
|
87
87
|
const request = {
|
|
88
|
-
|
|
88
|
+
gateId: 'test-gate',
|
|
89
89
|
model: 'dall-e-3',
|
|
90
90
|
type: 'image',
|
|
91
91
|
data: {
|
|
@@ -102,7 +102,7 @@ async function testImageGeneration() {
|
|
|
102
102
|
async function testEmbeddings() {
|
|
103
103
|
console.log('\n\nTest 5: Text embeddings\n');
|
|
104
104
|
const request = {
|
|
105
|
-
|
|
105
|
+
gateId: 'test-gate',
|
|
106
106
|
model: 'text-embedding-3-small',
|
|
107
107
|
type: 'embeddings',
|
|
108
108
|
data: {
|
|
@@ -117,7 +117,7 @@ async function testEmbeddings() {
|
|
|
117
117
|
async function testTextToSpeech() {
|
|
118
118
|
console.log('\n\nTest 6: Text-to-speech\n');
|
|
119
119
|
const request = {
|
|
120
|
-
|
|
120
|
+
gateId: 'test-gate',
|
|
121
121
|
model: 'tts-1',
|
|
122
122
|
type: 'tts',
|
|
123
123
|
data: {
|
|
@@ -133,7 +133,7 @@ async function testTextToSpeech() {
|
|
|
133
133
|
async function testResponseFormat() {
|
|
134
134
|
console.log('\n\nTest 7: JSON response format\n');
|
|
135
135
|
const request = {
|
|
136
|
-
|
|
136
|
+
gateId: 'test-gate',
|
|
137
137
|
model: 'gpt-4o-mini',
|
|
138
138
|
type: 'chat',
|
|
139
139
|
data: {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
async function testFallbackRouting() {
|
|
4
4
|
console.log('Test 1: Fallback routing (Anthropic -> OpenAI)\n');
|
|
5
5
|
const request = {
|
|
6
|
-
|
|
6
|
+
gateId: 'test-gate-with-fallback',
|
|
7
7
|
model: 'claude-sonnet-4-5-20250929', // Primary model
|
|
8
8
|
type: 'chat',
|
|
9
9
|
data: {
|
|
@@ -27,7 +27,7 @@ async function testFallbackRouting() {
|
|
|
27
27
|
async function testRoundRobinRouting() {
|
|
28
28
|
console.log('\n\nTest 2: Round-robin routing across providers\n');
|
|
29
29
|
const request = {
|
|
30
|
-
|
|
30
|
+
gateId: 'test-gate-with-round-robin',
|
|
31
31
|
model: 'claude-sonnet-4-5-20250929',
|
|
32
32
|
type: 'chat',
|
|
33
33
|
data: {
|
|
@@ -50,7 +50,7 @@ async function testRoundRobinRouting() {
|
|
|
50
50
|
async function testCrossProviderFallback() {
|
|
51
51
|
console.log('\n\nTest 3: Cross-provider fallback with vision\n');
|
|
52
52
|
const request = {
|
|
53
|
-
|
|
53
|
+
gateId: 'test-gate-vision-fallback',
|
|
54
54
|
model: 'claude-sonnet-4-5-20250929',
|
|
55
55
|
type: 'chat',
|
|
56
56
|
data: {
|
|
@@ -78,7 +78,7 @@ async function testCrossProviderFallback() {
|
|
|
78
78
|
async function testToolCallsFallback() {
|
|
79
79
|
console.log('\n\nTest 4: Fallback routing with tool calls\n');
|
|
80
80
|
const request = {
|
|
81
|
-
|
|
81
|
+
gateId: 'test-gate-tools-fallback',
|
|
82
82
|
model: 'gpt-4o-mini',
|
|
83
83
|
type: 'chat',
|
|
84
84
|
data: {
|
|
@@ -117,7 +117,7 @@ async function testToolCallsFallback() {
|
|
|
117
117
|
async function testCostOptimization() {
|
|
118
118
|
console.log('\n\nTest 5: Cost optimization with round-robin\n');
|
|
119
119
|
const request = {
|
|
120
|
-
|
|
120
|
+
gateId: 'test-gate-cost-optimization',
|
|
121
121
|
model: 'gpt-4o-mini',
|
|
122
122
|
type: 'chat',
|
|
123
123
|
data: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/anthropic-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAmB,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAsB;IAElD,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAI3D;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAM1D;IAEF,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS;IAalE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;
|
|
1
|
+
{"version":3,"file":"anthropic-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/anthropic-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAmB,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAsB;IAElD,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAI3D;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAM1D;IAEF,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS;IAalE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;CA6JzB"}
|
|
@@ -55,10 +55,10 @@ export class AnthropicAdapter extends BaseProviderAdapter {
|
|
|
55
55
|
}
|
|
56
56
|
async call(request, userId) {
|
|
57
57
|
// Resolve API key (BYOK → Platform key)
|
|
58
|
-
const
|
|
58
|
+
const resolved = await resolveApiKey(this.provider, userId, process.env.ANTHROPIC_API_KEY);
|
|
59
59
|
switch (request.type) {
|
|
60
60
|
case 'chat':
|
|
61
|
-
return this.handleChat(request,
|
|
61
|
+
return this.handleChat(request, resolved.key, resolved.usedPlatformKey);
|
|
62
62
|
case 'image':
|
|
63
63
|
throw new Error('Image generation not yet supported by Anthropic');
|
|
64
64
|
case 'embeddings':
|
|
@@ -71,7 +71,7 @@ export class AnthropicAdapter extends BaseProviderAdapter {
|
|
|
71
71
|
throw new Error(`Unknown modality: ${request.type}`);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
async handleChat(request, apiKey) {
|
|
74
|
+
async handleChat(request, apiKey, usedPlatformKey) {
|
|
75
75
|
const startTime = Date.now();
|
|
76
76
|
const client = getAnthropicClient(apiKey);
|
|
77
77
|
const { data: chat, model } = request;
|
|
@@ -211,6 +211,7 @@ export class AnthropicAdapter extends BaseProviderAdapter {
|
|
|
211
211
|
},
|
|
212
212
|
cost,
|
|
213
213
|
latencyMs: Date.now() - startTime,
|
|
214
|
+
usedPlatformKey,
|
|
214
215
|
raw: response,
|
|
215
216
|
};
|
|
216
217
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/google-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,yBAAyB,EAI1B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAkB1E,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAmB;IAE/C,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAGF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAO1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAIrE;IAGF,SAAS,CAAC,eAAe,EAAE,MAAM,CAC/B,SAAS,EACT;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAC5C,CAKC;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;
|
|
1
|
+
{"version":3,"file":"google-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/google-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,yBAAyB,EAI1B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAkB1E,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAmB;IAE/C,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAGF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAO1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAIrE;IAGF,SAAS,CAAC,eAAe,EAAE,MAAM,CAC/B,SAAS,EACT;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAC5C,CAKC;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;YAwLV,qBAAqB;YAqCrB,gBAAgB;YAsChB,qBAAqB;YAsHrB,kBAAkB;IA2ChC,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -52,23 +52,23 @@ export class GoogleAdapter extends BaseProviderAdapter {
|
|
|
52
52
|
}
|
|
53
53
|
async call(request, userId) {
|
|
54
54
|
// Resolve API key (BYOK → Platform key)
|
|
55
|
-
const
|
|
55
|
+
const resolved = await resolveApiKey(this.provider, userId, process.env.GOOGLE_API_KEY);
|
|
56
56
|
switch (request.type) {
|
|
57
57
|
case 'chat':
|
|
58
|
-
return this.handleChat(request,
|
|
58
|
+
return this.handleChat(request, resolved.key, resolved.usedPlatformKey);
|
|
59
59
|
case 'image':
|
|
60
|
-
return this.handleImageGeneration(request,
|
|
60
|
+
return this.handleImageGeneration(request, resolved.key, resolved.usedPlatformKey);
|
|
61
61
|
case 'embeddings':
|
|
62
|
-
return this.handleEmbeddings(request,
|
|
62
|
+
return this.handleEmbeddings(request, resolved.key, resolved.usedPlatformKey);
|
|
63
63
|
case 'tts':
|
|
64
|
-
return this.handleTextToSpeech(request,
|
|
64
|
+
return this.handleTextToSpeech(request, resolved.key, resolved.usedPlatformKey);
|
|
65
65
|
case 'video':
|
|
66
|
-
return this.handleVideoGeneration(request,
|
|
66
|
+
return this.handleVideoGeneration(request, resolved.key, resolved.usedPlatformKey);
|
|
67
67
|
default:
|
|
68
68
|
throw new Error(`Unknown modality: ${request.type}`);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
async handleChat(request, apiKey) {
|
|
71
|
+
async handleChat(request, apiKey, usedPlatformKey) {
|
|
72
72
|
const startTime = Date.now();
|
|
73
73
|
const client = getGoogleClient(apiKey);
|
|
74
74
|
const { data: chat, model } = request;
|
|
@@ -220,10 +220,11 @@ export class GoogleAdapter extends BaseProviderAdapter {
|
|
|
220
220
|
},
|
|
221
221
|
cost,
|
|
222
222
|
latencyMs: Date.now() - startTime,
|
|
223
|
+
usedPlatformKey,
|
|
223
224
|
raw: response,
|
|
224
225
|
};
|
|
225
226
|
}
|
|
226
|
-
async handleImageGeneration(request, apiKey) {
|
|
227
|
+
async handleImageGeneration(request, apiKey, usedPlatformKey) {
|
|
227
228
|
const startTime = Date.now();
|
|
228
229
|
const client = getGoogleClient(apiKey);
|
|
229
230
|
const { data: image, model } = request;
|
|
@@ -246,10 +247,11 @@ export class GoogleAdapter extends BaseProviderAdapter {
|
|
|
246
247
|
images,
|
|
247
248
|
model: model,
|
|
248
249
|
latencyMs: Date.now() - startTime,
|
|
250
|
+
usedPlatformKey,
|
|
249
251
|
raw: response,
|
|
250
252
|
};
|
|
251
253
|
}
|
|
252
|
-
async handleEmbeddings(request, apiKey) {
|
|
254
|
+
async handleEmbeddings(request, apiKey, usedPlatformKey) {
|
|
253
255
|
const startTime = Date.now();
|
|
254
256
|
const client = getGoogleClient(apiKey);
|
|
255
257
|
const { data: embedding, model } = request;
|
|
@@ -273,10 +275,11 @@ export class GoogleAdapter extends BaseProviderAdapter {
|
|
|
273
275
|
totalTokens: 0,
|
|
274
276
|
},
|
|
275
277
|
latencyMs: Date.now() - startTime,
|
|
278
|
+
usedPlatformKey,
|
|
276
279
|
raw: response,
|
|
277
280
|
};
|
|
278
281
|
}
|
|
279
|
-
async handleVideoGeneration(request, apiKey) {
|
|
282
|
+
async handleVideoGeneration(request, apiKey, usedPlatformKey) {
|
|
280
283
|
const startTime = Date.now();
|
|
281
284
|
const client = getGoogleClient(apiKey);
|
|
282
285
|
const { data: video, model } = request;
|
|
@@ -376,10 +379,11 @@ export class GoogleAdapter extends BaseProviderAdapter {
|
|
|
376
379
|
videos: videos.filter((v) => v.url),
|
|
377
380
|
model: model,
|
|
378
381
|
latencyMs: Date.now() - startTime,
|
|
382
|
+
usedPlatformKey,
|
|
379
383
|
raw: operation.response,
|
|
380
384
|
};
|
|
381
385
|
}
|
|
382
|
-
async handleTextToSpeech(request, apiKey) {
|
|
386
|
+
async handleTextToSpeech(request, apiKey, usedPlatformKey) {
|
|
383
387
|
const startTime = Date.now();
|
|
384
388
|
const client = getGoogleClient(apiKey);
|
|
385
389
|
const { data: tts, model } = request;
|
|
@@ -408,6 +412,7 @@ export class GoogleAdapter extends BaseProviderAdapter {
|
|
|
408
412
|
},
|
|
409
413
|
model: model,
|
|
410
414
|
latencyMs: Date.now() - startTime,
|
|
415
|
+
usedPlatformKey,
|
|
411
416
|
raw: response,
|
|
412
417
|
};
|
|
413
418
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mistral-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/mistral-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,YAAY,EAEb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,cAAe,SAAQ,mBAAmB;IACrD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAoB;IAEhD,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAGF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAM1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIlD;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAsB5D,UAAU;
|
|
1
|
+
{"version":3,"file":"mistral-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/mistral-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,YAAY,EAEb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,cAAe,SAAQ,mBAAmB;IACrD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAoB;IAEhD,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAGF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAM1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIlD;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAsB5D,UAAU;YAiMV,gBAAgB;YA0ChB,SAAS;CA8ExB"}
|
|
@@ -46,14 +46,14 @@ export class MistralAdapter extends BaseProviderAdapter {
|
|
|
46
46
|
}
|
|
47
47
|
async call(request, userId) {
|
|
48
48
|
// Resolve API key (BYOK → Platform key)
|
|
49
|
-
const
|
|
49
|
+
const resolved = await resolveApiKey(this.provider, userId, process.env.MISTRAL_API_KEY);
|
|
50
50
|
switch (request.type) {
|
|
51
51
|
case 'chat':
|
|
52
|
-
return this.handleChat(request,
|
|
52
|
+
return this.handleChat(request, resolved.key, resolved.usedPlatformKey);
|
|
53
53
|
case 'embeddings':
|
|
54
|
-
return this.handleEmbeddings(request,
|
|
54
|
+
return this.handleEmbeddings(request, resolved.key, resolved.usedPlatformKey);
|
|
55
55
|
case 'ocr':
|
|
56
|
-
return this.handleOCR(request,
|
|
56
|
+
return this.handleOCR(request, resolved.key, resolved.usedPlatformKey);
|
|
57
57
|
case 'image':
|
|
58
58
|
throw new Error('Image generation not supported by Mistral');
|
|
59
59
|
case 'tts':
|
|
@@ -64,7 +64,7 @@ export class MistralAdapter extends BaseProviderAdapter {
|
|
|
64
64
|
throw new Error(`Unknown modality: ${request.type}`);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
async handleChat(request, apiKey) {
|
|
67
|
+
async handleChat(request, apiKey, usedPlatformKey) {
|
|
68
68
|
const startTime = Date.now();
|
|
69
69
|
const mistral = getMistralClient(apiKey);
|
|
70
70
|
const { data: chat, model } = request;
|
|
@@ -214,10 +214,11 @@ export class MistralAdapter extends BaseProviderAdapter {
|
|
|
214
214
|
},
|
|
215
215
|
cost,
|
|
216
216
|
latencyMs: Date.now() - startTime,
|
|
217
|
+
usedPlatformKey,
|
|
217
218
|
raw: response,
|
|
218
219
|
};
|
|
219
220
|
}
|
|
220
|
-
async handleEmbeddings(request, apiKey) {
|
|
221
|
+
async handleEmbeddings(request, apiKey, usedPlatformKey) {
|
|
221
222
|
const startTime = Date.now();
|
|
222
223
|
const mistral = getMistralClient(apiKey);
|
|
223
224
|
const { data: embedding, model } = request;
|
|
@@ -244,10 +245,11 @@ export class MistralAdapter extends BaseProviderAdapter {
|
|
|
244
245
|
},
|
|
245
246
|
cost,
|
|
246
247
|
latencyMs: Date.now() - startTime,
|
|
248
|
+
usedPlatformKey,
|
|
247
249
|
raw: response,
|
|
248
250
|
};
|
|
249
251
|
}
|
|
250
|
-
async handleOCR(request, apiKey) {
|
|
252
|
+
async handleOCR(request, apiKey, usedPlatformKey) {
|
|
251
253
|
const startTime = Date.now();
|
|
252
254
|
const mistral = getMistralClient(apiKey);
|
|
253
255
|
const { data: ocr, model } = request;
|
|
@@ -313,6 +315,7 @@ export class MistralAdapter extends BaseProviderAdapter {
|
|
|
313
315
|
},
|
|
314
316
|
model: response.model || ocrModel,
|
|
315
317
|
latencyMs: Date.now() - startTime,
|
|
318
|
+
usedPlatformKey,
|
|
316
319
|
raw: response,
|
|
317
320
|
};
|
|
318
321
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/openai-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAmB;IAE/C,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAIxD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK1D;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAQpD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAG1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAGtD;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAKpD;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAOxD;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;
|
|
1
|
+
{"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/openai-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAmB;IAE/C,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAIxD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK1D;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAQpD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAG1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAGtD;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAKpD;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAOxD;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;YA4GV,qBAAqB;YA8BrB,gBAAgB;YAkChB,kBAAkB;CA+BjC"}
|
|
@@ -74,23 +74,23 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
74
74
|
}
|
|
75
75
|
async call(request, userId) {
|
|
76
76
|
// Resolve API key (BYOK → Platform key)
|
|
77
|
-
const
|
|
77
|
+
const resolved = await resolveApiKey(this.provider, userId, process.env.OPENAI_API_KEY);
|
|
78
78
|
switch (request.type) {
|
|
79
79
|
case 'chat':
|
|
80
|
-
return this.handleChat(request,
|
|
80
|
+
return this.handleChat(request, resolved.key, resolved.usedPlatformKey);
|
|
81
81
|
case 'image':
|
|
82
|
-
return this.handleImageGeneration(request,
|
|
82
|
+
return this.handleImageGeneration(request, resolved.key, resolved.usedPlatformKey);
|
|
83
83
|
case 'embeddings':
|
|
84
|
-
return this.handleEmbeddings(request,
|
|
84
|
+
return this.handleEmbeddings(request, resolved.key, resolved.usedPlatformKey);
|
|
85
85
|
case 'tts':
|
|
86
|
-
return this.handleTextToSpeech(request,
|
|
86
|
+
return this.handleTextToSpeech(request, resolved.key, resolved.usedPlatformKey);
|
|
87
87
|
case 'video':
|
|
88
88
|
throw new Error('Video generation not yet supported by OpenAI');
|
|
89
89
|
default:
|
|
90
90
|
throw new Error(`Unknown modality: ${request.type}`);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
async handleChat(request, apiKey) {
|
|
93
|
+
async handleChat(request, apiKey, usedPlatformKey) {
|
|
94
94
|
const startTime = Date.now();
|
|
95
95
|
const client = getOpenAIClient(apiKey);
|
|
96
96
|
const { data: chat, model } = request;
|
|
@@ -181,10 +181,11 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
181
181
|
},
|
|
182
182
|
cost,
|
|
183
183
|
latencyMs: Date.now() - startTime,
|
|
184
|
+
usedPlatformKey,
|
|
184
185
|
raw: response,
|
|
185
186
|
};
|
|
186
187
|
}
|
|
187
|
-
async handleImageGeneration(request, apiKey) {
|
|
188
|
+
async handleImageGeneration(request, apiKey, usedPlatformKey) {
|
|
188
189
|
const startTime = Date.now();
|
|
189
190
|
const client = getOpenAIClient(apiKey);
|
|
190
191
|
const { data: image, model } = request;
|
|
@@ -206,10 +207,11 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
206
207
|
})),
|
|
207
208
|
model: model,
|
|
208
209
|
latencyMs: Date.now() - startTime,
|
|
210
|
+
usedPlatformKey,
|
|
209
211
|
raw: response,
|
|
210
212
|
};
|
|
211
213
|
}
|
|
212
|
-
async handleEmbeddings(request, apiKey) {
|
|
214
|
+
async handleEmbeddings(request, apiKey, usedPlatformKey) {
|
|
213
215
|
const startTime = Date.now();
|
|
214
216
|
const client = getOpenAIClient(apiKey);
|
|
215
217
|
const { data: embedding, model } = request;
|
|
@@ -234,10 +236,11 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
234
236
|
},
|
|
235
237
|
cost,
|
|
236
238
|
latencyMs: Date.now() - startTime,
|
|
239
|
+
usedPlatformKey,
|
|
237
240
|
raw: response,
|
|
238
241
|
};
|
|
239
242
|
}
|
|
240
|
-
async handleTextToSpeech(request, apiKey) {
|
|
243
|
+
async handleTextToSpeech(request, apiKey, usedPlatformKey) {
|
|
241
244
|
const startTime = Date.now();
|
|
242
245
|
const client = getOpenAIClient(apiKey);
|
|
243
246
|
const { data: tts, model } = request;
|
|
@@ -260,6 +263,7 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
260
263
|
},
|
|
261
264
|
model: model,
|
|
262
265
|
latencyMs: Date.now() - startTime,
|
|
266
|
+
usedPlatformKey,
|
|
263
267
|
};
|
|
264
268
|
}
|
|
265
269
|
}
|
|
@@ -3,7 +3,7 @@ const adapter = new AnthropicAdapter();
|
|
|
3
3
|
async function testChatCompletion() {
|
|
4
4
|
console.log('Testing chat completion...');
|
|
5
5
|
const request = {
|
|
6
|
-
|
|
6
|
+
gateId: 'test-gate',
|
|
7
7
|
model: 'claude-sonnet-4-5-20250929',
|
|
8
8
|
type: 'chat',
|
|
9
9
|
data: {
|
|
@@ -25,7 +25,7 @@ async function testChatCompletion() {
|
|
|
25
25
|
async function testChatWithVision() {
|
|
26
26
|
console.log('Testing chat with vision...');
|
|
27
27
|
const request = {
|
|
28
|
-
|
|
28
|
+
gateId: 'test-gate',
|
|
29
29
|
model: 'claude-sonnet-4-5-20250929',
|
|
30
30
|
type: 'chat',
|
|
31
31
|
data: {
|
|
@@ -50,7 +50,7 @@ async function testToolCalls() {
|
|
|
50
50
|
console.log('Testing tool calls...');
|
|
51
51
|
// Step 1: Initial request with tool available
|
|
52
52
|
const request = {
|
|
53
|
-
|
|
53
|
+
gateId: 'test-gate',
|
|
54
54
|
model: 'claude-sonnet-4-5-20250929',
|
|
55
55
|
type: 'chat',
|
|
56
56
|
data: {
|
|
@@ -91,7 +91,7 @@ async function testToolCalls() {
|
|
|
91
91
|
console.log('Function arguments:', toolCall.function.arguments);
|
|
92
92
|
// Step 2: Send tool response back
|
|
93
93
|
const toolResponseRequest = {
|
|
94
|
-
|
|
94
|
+
gateId: 'test-gate',
|
|
95
95
|
model: 'claude-sonnet-4-5-20250929',
|
|
96
96
|
type: 'chat',
|
|
97
97
|
data: {
|
|
@@ -4,7 +4,7 @@ const adapter = new GoogleAdapter();
|
|
|
4
4
|
async function testChatCompletion() {
|
|
5
5
|
console.log('Testing chat completion...');
|
|
6
6
|
const request = {
|
|
7
|
-
|
|
7
|
+
gateId: 'test-gate',
|
|
8
8
|
model: 'gemini-2.5-flash',
|
|
9
9
|
type: 'chat',
|
|
10
10
|
data: {
|
|
@@ -26,7 +26,7 @@ async function testChatCompletion() {
|
|
|
26
26
|
async function testChatWithVision() {
|
|
27
27
|
console.log('Testing chat with vision...');
|
|
28
28
|
const request = {
|
|
29
|
-
|
|
29
|
+
gateId: 'test-gate',
|
|
30
30
|
model: 'gemini-2.5-flash',
|
|
31
31
|
type: 'chat',
|
|
32
32
|
data: {
|
|
@@ -52,7 +52,7 @@ async function testChatWithVision() {
|
|
|
52
52
|
async function testImageGeneration() {
|
|
53
53
|
console.log('Testing image generation...');
|
|
54
54
|
const request = {
|
|
55
|
-
|
|
55
|
+
gateId: 'test-gate',
|
|
56
56
|
model: 'imagen-4.0-generate-001',
|
|
57
57
|
type: 'image',
|
|
58
58
|
data: {
|
|
@@ -69,7 +69,7 @@ async function testImageGeneration() {
|
|
|
69
69
|
async function testEmbeddings() {
|
|
70
70
|
console.log('Testing embeddings...');
|
|
71
71
|
const request = {
|
|
72
|
-
|
|
72
|
+
gateId: 'test-gate',
|
|
73
73
|
model: 'text-embedding-004',
|
|
74
74
|
type: 'embeddings',
|
|
75
75
|
data: {
|
|
@@ -85,7 +85,7 @@ async function testToolCalling() {
|
|
|
85
85
|
console.log('Testing tool calling...');
|
|
86
86
|
// Step 1: Send message with tools available
|
|
87
87
|
const request = {
|
|
88
|
-
|
|
88
|
+
gateId: 'test-gate',
|
|
89
89
|
model: 'gemini-2.5-flash',
|
|
90
90
|
type: 'chat',
|
|
91
91
|
data: {
|
|
@@ -122,7 +122,7 @@ async function testToolCalling() {
|
|
|
122
122
|
console.log('Function arguments:', toolCall.function.arguments);
|
|
123
123
|
// Step 2: Send tool response back
|
|
124
124
|
const toolResponseRequest = {
|
|
125
|
-
|
|
125
|
+
gateId: 'test-gate',
|
|
126
126
|
model: 'gemini-2.5-flash',
|
|
127
127
|
type: 'chat',
|
|
128
128
|
data: {
|
|
@@ -149,7 +149,7 @@ async function testToolCalling() {
|
|
|
149
149
|
async function testEmbeddingsMultiple() {
|
|
150
150
|
console.log('Testing multiple embeddings...');
|
|
151
151
|
const request = {
|
|
152
|
-
|
|
152
|
+
gateId: 'test-gate',
|
|
153
153
|
model: 'text-embedding-004',
|
|
154
154
|
type: 'embeddings',
|
|
155
155
|
data: {
|
|
@@ -165,7 +165,7 @@ async function testEmbeddingsMultiple() {
|
|
|
165
165
|
async function testTextToSpeech() {
|
|
166
166
|
console.log('Testing text-to-speech...');
|
|
167
167
|
const request = {
|
|
168
|
-
|
|
168
|
+
gateId: 'test-gate',
|
|
169
169
|
model: 'gemini-2.5-flash-preview-tts',
|
|
170
170
|
type: 'tts',
|
|
171
171
|
data: {
|
|
@@ -182,7 +182,7 @@ async function testTextToSpeech() {
|
|
|
182
182
|
async function testVideoGeneration() {
|
|
183
183
|
console.log('Testing video generation (this may take a few minutes)...');
|
|
184
184
|
const request = {
|
|
185
|
-
|
|
185
|
+
gateId: 'test-gate',
|
|
186
186
|
model: 'veo-2.0-generate-001',
|
|
187
187
|
type: 'video',
|
|
188
188
|
data: {
|
|
@@ -6,7 +6,7 @@ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
6
6
|
async function testChatCompletion() {
|
|
7
7
|
console.log('--- Testing Chat Completion ---');
|
|
8
8
|
const request = {
|
|
9
|
-
|
|
9
|
+
gateId: 'test-gate',
|
|
10
10
|
type: 'chat',
|
|
11
11
|
model: 'mistral-small-latest',
|
|
12
12
|
data: {
|
|
@@ -31,7 +31,7 @@ async function testChatCompletion() {
|
|
|
31
31
|
async function testChatWithSystemPrompt() {
|
|
32
32
|
console.log('--- Testing Chat with System Prompt ---');
|
|
33
33
|
const request = {
|
|
34
|
-
|
|
34
|
+
gateId: 'test-gate',
|
|
35
35
|
type: 'chat',
|
|
36
36
|
model: 'mistral-small-latest',
|
|
37
37
|
data: {
|
|
@@ -54,7 +54,7 @@ async function testChatWithSystemPrompt() {
|
|
|
54
54
|
async function testChatWithTools() {
|
|
55
55
|
console.log('--- Testing Chat with Tools ---');
|
|
56
56
|
const request = {
|
|
57
|
-
|
|
57
|
+
gateId: 'test-gate',
|
|
58
58
|
type: 'chat',
|
|
59
59
|
model: 'mistral-small-latest',
|
|
60
60
|
data: {
|
|
@@ -102,7 +102,7 @@ async function testToolResponse() {
|
|
|
102
102
|
console.log('--- Testing Tool Response Flow ---');
|
|
103
103
|
// First, get the tool call
|
|
104
104
|
const initialRequest = {
|
|
105
|
-
|
|
105
|
+
gateId: 'test-gate',
|
|
106
106
|
type: 'chat',
|
|
107
107
|
model: 'mistral-small-latest',
|
|
108
108
|
data: {
|
|
@@ -143,7 +143,7 @@ async function testToolResponse() {
|
|
|
143
143
|
const toolCall = initialResponse.toolCalls[0];
|
|
144
144
|
await delay(2000);
|
|
145
145
|
const followUpRequest = {
|
|
146
|
-
|
|
146
|
+
gateId: 'test-gate',
|
|
147
147
|
type: 'chat',
|
|
148
148
|
model: 'mistral-small-latest',
|
|
149
149
|
data: {
|
|
@@ -175,7 +175,7 @@ async function testToolResponse() {
|
|
|
175
175
|
async function testEmbeddings() {
|
|
176
176
|
console.log('--- Testing Embeddings ---');
|
|
177
177
|
const request = {
|
|
178
|
-
|
|
178
|
+
gateId: 'test-gate',
|
|
179
179
|
type: 'embeddings',
|
|
180
180
|
model: 'mistral-embed',
|
|
181
181
|
data: {
|
|
@@ -193,7 +193,7 @@ async function testVisionCapability() {
|
|
|
193
193
|
console.log('--- Testing Vision Capability (Pixtral) ---');
|
|
194
194
|
// Use a public image URL for testing
|
|
195
195
|
const request = {
|
|
196
|
-
|
|
196
|
+
gateId: 'test-gate',
|
|
197
197
|
type: 'chat',
|
|
198
198
|
model: 'pixtral-large-2411',
|
|
199
199
|
data: {
|
|
@@ -224,7 +224,7 @@ async function testVisionCapability() {
|
|
|
224
224
|
async function testResponseFormat() {
|
|
225
225
|
console.log('--- Testing JSON Response Format ---');
|
|
226
226
|
const request = {
|
|
227
|
-
|
|
227
|
+
gateId: 'test-gate',
|
|
228
228
|
type: 'chat',
|
|
229
229
|
model: 'mistral-small-latest',
|
|
230
230
|
data: {
|
|
@@ -245,7 +245,7 @@ async function testResponseFormat() {
|
|
|
245
245
|
async function testMultiTurn() {
|
|
246
246
|
console.log('--- Testing Multi-turn Conversation ---');
|
|
247
247
|
const request = {
|
|
248
|
-
|
|
248
|
+
gateId: 'test-gate',
|
|
249
249
|
type: 'chat',
|
|
250
250
|
model: 'mistral-small-latest',
|
|
251
251
|
data: {
|
|
@@ -273,7 +273,7 @@ async function testMultiTurn() {
|
|
|
273
273
|
async function testOCR() {
|
|
274
274
|
console.log('--- Testing OCR Capability ---');
|
|
275
275
|
const request = {
|
|
276
|
-
|
|
276
|
+
gateId: 'test-gate',
|
|
277
277
|
type: 'ocr',
|
|
278
278
|
model: 'mistral-ocr-latest',
|
|
279
279
|
data: {
|
|
@@ -295,7 +295,7 @@ async function testOCR() {
|
|
|
295
295
|
async function testUnsupportedModality() {
|
|
296
296
|
console.log('--- Testing Unsupported Modality (Image Generation) ---');
|
|
297
297
|
const request = {
|
|
298
|
-
|
|
298
|
+
gateId: 'test-gate',
|
|
299
299
|
type: 'image',
|
|
300
300
|
model: 'mistral-large-latest',
|
|
301
301
|
data: {
|
|
@@ -3,7 +3,7 @@ const adapter = new OpenAIAdapter();
|
|
|
3
3
|
async function testChatCompletion() {
|
|
4
4
|
console.log('Testing chat completion...');
|
|
5
5
|
const request = {
|
|
6
|
-
|
|
6
|
+
gateId: 'test-gate',
|
|
7
7
|
model: 'gpt-4o-mini',
|
|
8
8
|
type: 'chat',
|
|
9
9
|
data: {
|
|
@@ -25,7 +25,7 @@ async function testChatCompletion() {
|
|
|
25
25
|
async function testChatWithVision() {
|
|
26
26
|
console.log('Testing chat with vision...');
|
|
27
27
|
const request = {
|
|
28
|
-
|
|
28
|
+
gateId: 'test-gate',
|
|
29
29
|
model: 'gpt-4o-mini',
|
|
30
30
|
type: 'chat',
|
|
31
31
|
data: {
|
|
@@ -50,7 +50,7 @@ async function testChatWithVision() {
|
|
|
50
50
|
async function testImageGeneration() {
|
|
51
51
|
console.log('Testing image generation...');
|
|
52
52
|
const request = {
|
|
53
|
-
|
|
53
|
+
gateId: 'test-gate',
|
|
54
54
|
model: 'dall-e-3',
|
|
55
55
|
type: 'image',
|
|
56
56
|
data: {
|
|
@@ -69,7 +69,7 @@ async function testImageGeneration() {
|
|
|
69
69
|
async function testEmbeddings() {
|
|
70
70
|
console.log('Testing embeddings...');
|
|
71
71
|
const request = {
|
|
72
|
-
|
|
72
|
+
gateId: 'test-gate',
|
|
73
73
|
model: 'text-embedding-3-small',
|
|
74
74
|
type: 'embeddings',
|
|
75
75
|
data: {
|
|
@@ -85,7 +85,7 @@ async function testEmbeddings() {
|
|
|
85
85
|
async function testTextToSpeech() {
|
|
86
86
|
console.log('Testing text-to-speech...');
|
|
87
87
|
const request = {
|
|
88
|
-
|
|
88
|
+
gateId: 'test-gate',
|
|
89
89
|
model: 'tts-1',
|
|
90
90
|
type: 'tts',
|
|
91
91
|
data: {
|
|
@@ -104,7 +104,7 @@ async function testToolCalling() {
|
|
|
104
104
|
console.log('Testing tool calling...');
|
|
105
105
|
// Step 1: Initial request with tool available
|
|
106
106
|
const request = {
|
|
107
|
-
|
|
107
|
+
gateId: 'test-gate',
|
|
108
108
|
model: 'gpt-4o-mini',
|
|
109
109
|
type: 'chat',
|
|
110
110
|
data: {
|
|
@@ -145,7 +145,7 @@ async function testToolCalling() {
|
|
|
145
145
|
console.log('Function arguments:', toolCall.function.arguments);
|
|
146
146
|
// Step 2: Send tool response back
|
|
147
147
|
const toolResponseRequest = {
|
|
148
|
-
|
|
148
|
+
gateId: 'test-gate',
|
|
149
149
|
model: 'gpt-4o-mini',
|
|
150
150
|
type: 'chat',
|
|
151
151
|
data: {
|
|
@@ -173,7 +173,7 @@ async function testContentAndToolCalls() {
|
|
|
173
173
|
console.log('Testing content + tool calls in same message...');
|
|
174
174
|
// This tests the fix we made - assistant messages can have BOTH content and toolCalls
|
|
175
175
|
const request = {
|
|
176
|
-
|
|
176
|
+
gateId: 'test-gate',
|
|
177
177
|
model: 'gpt-4o-mini',
|
|
178
178
|
type: 'chat',
|
|
179
179
|
data: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layer-ai/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Core API routes and services for Layer AI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"nanoid": "^5.0.4",
|
|
37
37
|
"openai": "^4.24.0",
|
|
38
38
|
"pg": "^8.11.3",
|
|
39
|
-
"@layer-ai/sdk": "^
|
|
39
|
+
"@layer-ai/sdk": "^2.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bcryptjs": "^2.4.6",
|