@layer-ai/core 0.5.5 → 0.5.7
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/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/lib/provider-constants.d.ts +24 -0
- package/dist/lib/provider-constants.d.ts.map +1 -0
- package/dist/lib/provider-constants.js +24 -0
- package/dist/lib/provider-factory.d.ts +25 -0
- package/dist/lib/provider-factory.d.ts.map +1 -0
- package/dist/lib/provider-factory.js +71 -0
- package/dist/routes/v1/auth.d.ts +4 -0
- package/dist/routes/v1/auth.d.ts.map +1 -0
- package/dist/routes/v1/auth.js +82 -0
- package/dist/routes/v1/gates.d.ts +4 -0
- package/dist/routes/v1/gates.d.ts.map +1 -0
- package/dist/routes/v1/gates.js +275 -0
- package/dist/routes/v1/keys.d.ts +4 -0
- package/dist/routes/v1/keys.d.ts.map +1 -0
- package/dist/routes/v1/keys.js +70 -0
- package/dist/routes/v1/logs.d.ts +4 -0
- package/dist/routes/v1/logs.d.ts.map +1 -0
- package/dist/routes/v1/logs.js +151 -0
- package/dist/routes/v2/complete.d.ts.map +1 -1
- package/dist/routes/v2/complete.js +6 -45
- package/dist/services/provider-service.d.ts +11 -0
- package/dist/services/provider-service.d.ts.map +1 -0
- package/dist/services/provider-service.js +49 -0
- package/dist/services/providers/anthropic-adapter.d.ts +2 -1
- package/dist/services/providers/anthropic-adapter.d.ts.map +1 -1
- package/dist/services/providers/anthropic-adapter.js +2 -1
- package/dist/services/providers/base-adapter.d.ts +2 -1
- package/dist/services/providers/base-adapter.d.ts.map +1 -1
- package/dist/services/providers/google-adapter.d.ts +2 -1
- package/dist/services/providers/google-adapter.d.ts.map +1 -1
- package/dist/services/providers/google-adapter.js +2 -1
- package/dist/services/providers/mistral-adapter.d.ts +2 -1
- package/dist/services/providers/mistral-adapter.d.ts.map +1 -1
- package/dist/services/providers/mistral-adapter.js +2 -1
- package/dist/services/providers/openai-adapter.d.ts +2 -1
- package/dist/services/providers/openai-adapter.d.ts.map +1 -1
- package/dist/services/providers/openai-adapter.js +2 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { default as authRouter } from './routes/auth.js';
|
|
2
|
-
export { default as gatesRouter } from './routes/gates.js';
|
|
3
|
-
export { default as keysRouter } from './routes/keys.js';
|
|
4
|
-
export { default as logsRouter } from './routes/logs.js';
|
|
1
|
+
export { default as authRouter } from './routes/v1/auth.js';
|
|
2
|
+
export { default as gatesRouter } from './routes/v1/gates.js';
|
|
3
|
+
export { default as keysRouter } from './routes/v1/keys.js';
|
|
4
|
+
export { default as logsRouter } from './routes/v1/logs.js';
|
|
5
5
|
export { default as completeRouter } from './routes/v2/complete.js';
|
|
6
6
|
export { authenticate } from './middleware/auth.js';
|
|
7
7
|
export type {} from './middleware/auth.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG3C,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAG3E,CAAC;AAGF,cAAc,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Routes
|
|
2
|
-
export { default as authRouter } from './routes/auth.js';
|
|
3
|
-
export { default as gatesRouter } from './routes/gates.js';
|
|
4
|
-
export { default as keysRouter } from './routes/keys.js';
|
|
5
|
-
export { default as logsRouter } from './routes/logs.js';
|
|
2
|
+
export { default as authRouter } from './routes/v1/auth.js';
|
|
3
|
+
export { default as gatesRouter } from './routes/v1/gates.js';
|
|
4
|
+
export { default as keysRouter } from './routes/v1/keys.js';
|
|
5
|
+
export { default as logsRouter } from './routes/v1/logs.js';
|
|
6
6
|
export { default as completeRouter } from './routes/v2/complete.js';
|
|
7
7
|
// Middleware
|
|
8
8
|
export { authenticate } from './middleware/auth.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Constants
|
|
3
|
+
*
|
|
4
|
+
* Central location for provider-related types and constants.
|
|
5
|
+
* Separated from provider-factory to avoid circular dependencies.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Provider type - maps to adapter implementations
|
|
9
|
+
*/
|
|
10
|
+
export type Provider = 'openai' | 'anthropic' | 'google' | 'mistral';
|
|
11
|
+
/**
|
|
12
|
+
* Provider constants - use these instead of string literals
|
|
13
|
+
*/
|
|
14
|
+
export declare const PROVIDER: {
|
|
15
|
+
readonly OPENAI: "openai";
|
|
16
|
+
readonly ANTHROPIC: "anthropic";
|
|
17
|
+
readonly GOOGLE: "google";
|
|
18
|
+
readonly MISTRAL: "mistral";
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* List of all providers
|
|
22
|
+
*/
|
|
23
|
+
export declare const PROVIDERS: Provider[];
|
|
24
|
+
//# sourceMappingURL=provider-constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-constants.d.ts","sourceRoot":"","sources":["../../src/lib/provider-constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAErE;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;CAKwB,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,QAAQ,EAK/B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Constants
|
|
3
|
+
*
|
|
4
|
+
* Central location for provider-related types and constants.
|
|
5
|
+
* Separated from provider-factory to avoid circular dependencies.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Provider constants - use these instead of string literals
|
|
9
|
+
*/
|
|
10
|
+
export const PROVIDER = {
|
|
11
|
+
OPENAI: 'openai',
|
|
12
|
+
ANTHROPIC: 'anthropic',
|
|
13
|
+
GOOGLE: 'google',
|
|
14
|
+
MISTRAL: 'mistral',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* List of all providers
|
|
18
|
+
*/
|
|
19
|
+
export const PROVIDERS = [
|
|
20
|
+
PROVIDER.OPENAI,
|
|
21
|
+
PROVIDER.ANTHROPIC,
|
|
22
|
+
PROVIDER.GOOGLE,
|
|
23
|
+
PROVIDER.MISTRAL
|
|
24
|
+
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Factory
|
|
3
|
+
*
|
|
4
|
+
* Centralized module for managing and calling provider adapters.
|
|
5
|
+
* Acts as a factory that routes requests to the appropriate provider adapter
|
|
6
|
+
* based on the model's provider type.
|
|
7
|
+
*/
|
|
8
|
+
import type { LayerRequest, LayerResponse, SupportedModel } from '@layer-ai/sdk';
|
|
9
|
+
import { PROVIDER, PROVIDERS, type Provider } from './provider-constants.js';
|
|
10
|
+
export { PROVIDER, PROVIDERS, type Provider };
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes a model ID to its full registry format.
|
|
13
|
+
* Supports both full IDs (e.g., "openai/gpt-4") and short IDs (e.g., "gpt-4").
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeModelId(modelId: string): SupportedModel;
|
|
16
|
+
/**
|
|
17
|
+
* Gets the provider type for a given model
|
|
18
|
+
*/
|
|
19
|
+
export declare function getProviderForModel(model: SupportedModel): Provider;
|
|
20
|
+
/**
|
|
21
|
+
* Calls the appropriate provider adapter for the given request.
|
|
22
|
+
* This is the main entry point for executing AI model requests.
|
|
23
|
+
*/
|
|
24
|
+
export declare function callAdapter(request: LayerRequest): Promise<LayerResponse>;
|
|
25
|
+
//# sourceMappingURL=provider-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-factory.d.ts","sourceRoot":"","sources":["../../src/lib/provider-factory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG7E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,CAAC;AAa9C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAmBhE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,QAAQ,CAMnE;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAW/E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Factory
|
|
3
|
+
*
|
|
4
|
+
* Centralized module for managing and calling provider adapters.
|
|
5
|
+
* Acts as a factory that routes requests to the appropriate provider adapter
|
|
6
|
+
* based on the model's provider type.
|
|
7
|
+
*/
|
|
8
|
+
import { OpenAIAdapter } from '../services/providers/openai-adapter.js';
|
|
9
|
+
import { AnthropicAdapter } from '../services/providers/anthropic-adapter.js';
|
|
10
|
+
import { GoogleAdapter } from '../services/providers/google-adapter.js';
|
|
11
|
+
import { MistralAdapter } from '../services/providers/mistral-adapter.js';
|
|
12
|
+
import { MODEL_REGISTRY } from '@layer-ai/sdk';
|
|
13
|
+
import { PROVIDER, PROVIDERS } from './provider-constants.js';
|
|
14
|
+
// Re-export for convenience
|
|
15
|
+
export { PROVIDER, PROVIDERS };
|
|
16
|
+
/**
|
|
17
|
+
* Provider adapter registry
|
|
18
|
+
* Maps provider names to their adapter classes
|
|
19
|
+
*/
|
|
20
|
+
const PROVIDER_ADAPTERS = {
|
|
21
|
+
[PROVIDER.OPENAI]: OpenAIAdapter,
|
|
22
|
+
[PROVIDER.ANTHROPIC]: AnthropicAdapter,
|
|
23
|
+
[PROVIDER.GOOGLE]: GoogleAdapter,
|
|
24
|
+
[PROVIDER.MISTRAL]: MistralAdapter,
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Normalizes a model ID to its full registry format.
|
|
28
|
+
* Supports both full IDs (e.g., "openai/gpt-4") and short IDs (e.g., "gpt-4").
|
|
29
|
+
*/
|
|
30
|
+
export function normalizeModelId(modelId) {
|
|
31
|
+
if (MODEL_REGISTRY[modelId]) {
|
|
32
|
+
return modelId;
|
|
33
|
+
}
|
|
34
|
+
const providers = [
|
|
35
|
+
PROVIDER.OPENAI,
|
|
36
|
+
PROVIDER.ANTHROPIC,
|
|
37
|
+
PROVIDER.GOOGLE,
|
|
38
|
+
PROVIDER.MISTRAL
|
|
39
|
+
];
|
|
40
|
+
for (const provider of providers) {
|
|
41
|
+
const fullId = `${provider}/${modelId}`;
|
|
42
|
+
if (MODEL_REGISTRY[fullId]) {
|
|
43
|
+
return fullId;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`invalid model ID: "${modelId}" not found in registry`);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Gets the provider type for a given model
|
|
50
|
+
*/
|
|
51
|
+
export function getProviderForModel(model) {
|
|
52
|
+
const modelInfo = MODEL_REGISTRY[model];
|
|
53
|
+
if (!modelInfo) {
|
|
54
|
+
throw new Error(`Model "${model}" not found in registry`);
|
|
55
|
+
}
|
|
56
|
+
return modelInfo.provider;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Calls the appropriate provider adapter for the given request.
|
|
60
|
+
* This is the main entry point for executing AI model requests.
|
|
61
|
+
*/
|
|
62
|
+
export async function callAdapter(request) {
|
|
63
|
+
const normalizedModel = normalizeModelId(request.model);
|
|
64
|
+
const provider = getProviderForModel(normalizedModel);
|
|
65
|
+
const AdapterClass = PROVIDER_ADAPTERS[provider];
|
|
66
|
+
if (!AdapterClass) {
|
|
67
|
+
throw new Error(`No adapter found for provider: ${provider}`);
|
|
68
|
+
}
|
|
69
|
+
const adapter = new AdapterClass();
|
|
70
|
+
return await adapter.call(request);
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/routes/v1/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAKpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA4FpC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import bcrypt from 'bcryptjs';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import { db } from '../../lib/db/postgres.js';
|
|
5
|
+
const router = Router();
|
|
6
|
+
// POST /auth/signup
|
|
7
|
+
router.post('/signup', async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const { email, password } = req.body;
|
|
10
|
+
if (!email || !password) {
|
|
11
|
+
res.status(400).json({ error: 'bad_request', message: 'Email and password required' });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const existing = await db.getUserByEmail(email);
|
|
15
|
+
if (existing) {
|
|
16
|
+
res.status(409).json({ error: 'conflict', message: 'Email already registered' });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const passwordHash = await bcrypt.hash(password, 10);
|
|
20
|
+
const user = await db.createUser(email, passwordHash);
|
|
21
|
+
res.status(201).json({ id: user.id, email: user.email });
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error('Signup error:', error);
|
|
25
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to create account ' });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// POST /auth/login
|
|
29
|
+
router.post('/login', async (req, res) => {
|
|
30
|
+
try {
|
|
31
|
+
const { email, password } = req.body;
|
|
32
|
+
if (!email || !password) {
|
|
33
|
+
res.status(400).json({ error: 'bad_request', message: 'Email and password required' });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const user = await db.getUserByEmail(email);
|
|
37
|
+
if (!user) {
|
|
38
|
+
res.status(401).json({ error: 'unauthorized', message: 'Invalid credentials' });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const valid = await bcrypt.compare(password, user.passwordHash);
|
|
42
|
+
if (!valid) {
|
|
43
|
+
res.status(401).json({ error: 'unauthorized', message: 'Invalid credentials' });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
res.json({ id: user.id, email: user.email });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error('Login error', error);
|
|
50
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to login' });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// POST /auth/token
|
|
54
|
+
router.post('/token', async (req, res) => {
|
|
55
|
+
try {
|
|
56
|
+
const { email, password } = req.body;
|
|
57
|
+
if (!email || !password) {
|
|
58
|
+
res.status(400).json({ error: 'bad_request', message: 'Email and password required' });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const user = await db.getUserByEmail(email);
|
|
62
|
+
if (!user) {
|
|
63
|
+
res.status(401).json({ error: 'unauthorized', message: 'Invalid credentials' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const valid = await bcrypt.compare(password, user.passwordHash);
|
|
67
|
+
if (!valid) {
|
|
68
|
+
res.status(401).json({ error: 'unauthorized', message: 'Invalid credentials' });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const rawKey = `layer_${crypto.randomBytes(32).toString('hex')}`;
|
|
72
|
+
const keyHash = crypto.createHash('sha256').update(rawKey).digest('hex');
|
|
73
|
+
const keyPrefix = rawKey.substring(0, 12); // "layer_xxxxxx"
|
|
74
|
+
await db.createApiKey(user.id, keyHash, keyPrefix, 'CLI');
|
|
75
|
+
res.status(201).json({ apiKey: rawKey });
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.error('api key creation error', error);
|
|
79
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to create api key' });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
export default router;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../../../src/routes/v1/gates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA0TpC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { db } from '../../lib/db/postgres.js';
|
|
3
|
+
import { cache } from '../../lib/db/redis.js';
|
|
4
|
+
import { authenticate } from '../../middleware/auth.js';
|
|
5
|
+
import { MODEL_REGISTRY } from '@layer-ai/sdk';
|
|
6
|
+
const router = Router();
|
|
7
|
+
// All routes require authentication (SDK auth with Bearer token)
|
|
8
|
+
router.use(authenticate);
|
|
9
|
+
// POST / - Create a new gate
|
|
10
|
+
router.post('/', async (req, res) => {
|
|
11
|
+
if (!req.userId) {
|
|
12
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const { name, description, taskType, model, systemPrompt, allowOverrides, temperature, maxTokens, topP, tags, routingStrategy, fallbackModels, costWeight, latencyWeight, qualityWeight, reanalysisPeriod, taskAnalysis } = req.body;
|
|
17
|
+
if (!name || !model) {
|
|
18
|
+
res.status(400).json({ error: 'bad_request', message: 'Missing required fields: name and model' });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!MODEL_REGISTRY[model]) {
|
|
22
|
+
res.status(400).json({ error: 'bad_request', message: `Unsupported model: ${model}` });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const existing = await db.getGateByUserAndName(req.userId, name);
|
|
26
|
+
if (existing) {
|
|
27
|
+
res.status(409).json({ error: 'conflict', message: `Gate "${name}" already exists` });
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const gate = await db.createGate(req.userId, {
|
|
31
|
+
name,
|
|
32
|
+
description,
|
|
33
|
+
taskType,
|
|
34
|
+
model,
|
|
35
|
+
systemPrompt,
|
|
36
|
+
allowOverrides,
|
|
37
|
+
temperature,
|
|
38
|
+
maxTokens,
|
|
39
|
+
topP,
|
|
40
|
+
tags,
|
|
41
|
+
routingStrategy,
|
|
42
|
+
fallbackModels,
|
|
43
|
+
costWeight,
|
|
44
|
+
latencyWeight,
|
|
45
|
+
qualityWeight,
|
|
46
|
+
reanalysisPeriod,
|
|
47
|
+
taskAnalysis,
|
|
48
|
+
});
|
|
49
|
+
res.status(201).json(gate);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('Create gate error:', error);
|
|
53
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to create gate' });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// GET / - List all the gates for user
|
|
57
|
+
router.get('/', async (req, res) => {
|
|
58
|
+
if (!req.userId) {
|
|
59
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const gates = await db.getGatesForUser(req.userId);
|
|
64
|
+
res.json(gates);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error('List gates error:', error);
|
|
68
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to list gates' });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// GET /name/:name - Get a single gate by name
|
|
72
|
+
router.get('/name/:name', async (req, res) => {
|
|
73
|
+
if (!req.userId) {
|
|
74
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const gate = await db.getGateByUserAndName(req.userId, req.params.name);
|
|
79
|
+
if (!gate) {
|
|
80
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
res.json(gate);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error('Get gate by name error:', error);
|
|
87
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to get gate' });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
// GET /:id - Get a single gate by ID
|
|
91
|
+
router.get('/:id', async (req, res) => {
|
|
92
|
+
if (!req.userId) {
|
|
93
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const gate = await db.getGateById(req.params.id);
|
|
98
|
+
if (!gate) {
|
|
99
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (gate.userId !== req.userId) {
|
|
103
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
res.json(gate);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error('Get gate error:', error);
|
|
110
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to get gate' });
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
// PATCH /name/:name - Update a gate by name
|
|
114
|
+
router.patch('/name/:name', async (req, res) => {
|
|
115
|
+
if (!req.userId) {
|
|
116
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const { description, taskType, model, systemPrompt, allowOverrides, temperature, maxTokens, topP, tags, routingStrategy, fallbackModels, costWeight, latencyWeight, qualityWeight, reanalysisPeriod, taskAnalysis } = req.body;
|
|
121
|
+
const existing = await db.getGateByUserAndName(req.userId, req.params.name);
|
|
122
|
+
if (!existing) {
|
|
123
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (model && !MODEL_REGISTRY[model]) {
|
|
127
|
+
res.status(400).json({ error: 'bad_request', message: `Unsupported model: ${model}` });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const updated = await db.updateGate(existing.id, {
|
|
131
|
+
description,
|
|
132
|
+
taskType,
|
|
133
|
+
model,
|
|
134
|
+
systemPrompt,
|
|
135
|
+
allowOverrides,
|
|
136
|
+
temperature,
|
|
137
|
+
maxTokens,
|
|
138
|
+
topP,
|
|
139
|
+
tags,
|
|
140
|
+
routingStrategy,
|
|
141
|
+
fallbackModels,
|
|
142
|
+
costWeight,
|
|
143
|
+
latencyWeight,
|
|
144
|
+
qualityWeight,
|
|
145
|
+
reanalysisPeriod,
|
|
146
|
+
taskAnalysis,
|
|
147
|
+
});
|
|
148
|
+
await cache.invalidateGate(req.userId, existing.name);
|
|
149
|
+
res.json(updated);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.error('Update gate by name error:', error);
|
|
153
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to update gate' });
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
// PATCH /:id - Update a gate by ID
|
|
157
|
+
router.patch('/:id', async (req, res) => {
|
|
158
|
+
if (!req.userId) {
|
|
159
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const { description, taskType, model, systemPrompt, allowOverrides, temperature, maxTokens, topP, tags, routingStrategy, fallbackModels, costWeight, latencyWeight, qualityWeight, reanalysisPeriod, taskAnalysis } = req.body;
|
|
164
|
+
const existing = await db.getGateById(req.params.id);
|
|
165
|
+
if (!existing) {
|
|
166
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (existing.userId !== req.userId) {
|
|
170
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (model && !MODEL_REGISTRY[model]) {
|
|
174
|
+
res.status(400).json({ error: 'bad_request', message: `Unsupported model: ${model}` });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const updated = await db.updateGate(req.params.id, {
|
|
178
|
+
description,
|
|
179
|
+
taskType,
|
|
180
|
+
model,
|
|
181
|
+
systemPrompt,
|
|
182
|
+
allowOverrides,
|
|
183
|
+
temperature,
|
|
184
|
+
maxTokens,
|
|
185
|
+
topP,
|
|
186
|
+
tags,
|
|
187
|
+
routingStrategy,
|
|
188
|
+
fallbackModels,
|
|
189
|
+
costWeight,
|
|
190
|
+
latencyWeight,
|
|
191
|
+
qualityWeight,
|
|
192
|
+
reanalysisPeriod,
|
|
193
|
+
taskAnalysis,
|
|
194
|
+
});
|
|
195
|
+
await cache.invalidateGate(req.userId, existing.name);
|
|
196
|
+
res.json(updated);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
console.error('Update gate error:', error);
|
|
200
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to update gate' });
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
// DELETE /name/:name - Delete a gate by name
|
|
204
|
+
router.delete('/name/:name', async (req, res) => {
|
|
205
|
+
if (!req.userId) {
|
|
206
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
const existing = await db.getGateByUserAndName(req.userId, req.params.name);
|
|
211
|
+
if (!existing) {
|
|
212
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
await db.deleteGate(existing.id);
|
|
216
|
+
await cache.invalidateGate(req.userId, existing.name);
|
|
217
|
+
res.status(204).send();
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
console.error('Delete gate by name error:', error);
|
|
221
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to delete gate' });
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
// DELETE /:id - Delete a gate by ID
|
|
225
|
+
router.delete('/:id', async (req, res) => {
|
|
226
|
+
if (!req.userId) {
|
|
227
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const existing = await db.getGateById(req.params.id);
|
|
232
|
+
if (!existing) {
|
|
233
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (existing.userId !== req.userId) {
|
|
237
|
+
res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
await db.deleteGate(req.params.id);
|
|
241
|
+
await cache.invalidateGate(req.userId, existing.name);
|
|
242
|
+
res.status(204).send();
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error('Delete gate error:', error);
|
|
246
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to delete gate' });
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
// POST /suggestions - Get AI-powered model suggestions for a gate
|
|
250
|
+
router.post('/suggestions', async (req, res) => {
|
|
251
|
+
if (!req.userId) {
|
|
252
|
+
res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
const { description, costWeight, latencyWeight, qualityWeight } = req.body;
|
|
257
|
+
if (!description) {
|
|
258
|
+
res.status(400).json({ error: 'bad_request', message: 'Gate must have a description for AI recommendations' });
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const userPreferences = {
|
|
262
|
+
costWeight: parseFloat(costWeight ?? '0.33'),
|
|
263
|
+
latencyWeight: parseFloat(latencyWeight ?? '0.33'),
|
|
264
|
+
qualityWeight: parseFloat(qualityWeight ?? '0.34'),
|
|
265
|
+
};
|
|
266
|
+
const { analyzeTask } = await import('../../services/task-analysis.js');
|
|
267
|
+
const suggestions = await analyzeTask(description, userPreferences);
|
|
268
|
+
res.json(suggestions);
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
console.error('Get suggestions error:', error);
|
|
272
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to fetch suggestions' });
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
export default router;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/routes/v1/keys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAKpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA4EpC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { db } from '../../lib/db/postgres.js';
|
|
4
|
+
import { authenticate } from '../../middleware/auth.js';
|
|
5
|
+
const router = Router();
|
|
6
|
+
// All routes require sdk authentication
|
|
7
|
+
router.use(authenticate);
|
|
8
|
+
// Generate a random API key
|
|
9
|
+
function generateApiKey() {
|
|
10
|
+
const randomBytes = crypto.randomBytes(32).toString('hex');
|
|
11
|
+
return `layer_${randomBytes}`;
|
|
12
|
+
}
|
|
13
|
+
// Hash an API key for storage
|
|
14
|
+
function hashApiKey(key) {
|
|
15
|
+
return crypto.createHash('sha256').update(key).digest('hex');
|
|
16
|
+
}
|
|
17
|
+
// GET /api/keys - List user's API keys
|
|
18
|
+
router.get('/', async (req, res) => {
|
|
19
|
+
try {
|
|
20
|
+
const keys = await db.getApiKeysForUser(req.userId);
|
|
21
|
+
res.json(keys);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error('Get keys error:', error);
|
|
25
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to get API keys' });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// POST /api/keys - Generate new API key
|
|
29
|
+
router.post('/', async (req, res) => {
|
|
30
|
+
try {
|
|
31
|
+
const { name } = req.body;
|
|
32
|
+
if (!name) {
|
|
33
|
+
res.status(400).json({ error: 'bad_request', message: 'Key name required' });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const key = generateApiKey();
|
|
37
|
+
const keyHash = hashApiKey(key);
|
|
38
|
+
const keyPrefix = key.substring(0, 12);
|
|
39
|
+
const apiKey = await db.createApiKey(req.userId, keyHash, keyPrefix, name);
|
|
40
|
+
// Return full key only once
|
|
41
|
+
res.status(201).json({
|
|
42
|
+
id: apiKey.id,
|
|
43
|
+
name: apiKey.name,
|
|
44
|
+
key: key,
|
|
45
|
+
keyPrefix: apiKey.keyPrefix,
|
|
46
|
+
createdAt: apiKey.createdAt,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error('Create key error:', error);
|
|
51
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to create API key' });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// DELETE /api/keys/:id - Delete an API key
|
|
55
|
+
router.delete('/:id', async (req, res) => {
|
|
56
|
+
try {
|
|
57
|
+
const { id } = req.params;
|
|
58
|
+
const deleted = await db.deleteApiKey(id, req.userId);
|
|
59
|
+
if (!deleted) {
|
|
60
|
+
res.status(404).json({ error: 'not_found', message: 'API key not found' });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
res.status(204).send();
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('Delete key error:', error);
|
|
67
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to delete API key' });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
export default router;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/routes/v1/logs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAIpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AAsLpC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { db } from '../../lib/db/postgres.js';
|
|
3
|
+
import { authenticate } from '../../middleware/auth.js';
|
|
4
|
+
const router = Router();
|
|
5
|
+
// All routes require SDK authentication
|
|
6
|
+
router.use(authenticate);
|
|
7
|
+
// GET /v1/logs - List request logs
|
|
8
|
+
router.get('/', async (req, res) => {
|
|
9
|
+
try {
|
|
10
|
+
const userId = req.userId;
|
|
11
|
+
const limit = parseInt(req.query.limit) || 50;
|
|
12
|
+
const offset = parseInt(req.query.offset) || 0;
|
|
13
|
+
const gate = req.query.gate;
|
|
14
|
+
let query = `
|
|
15
|
+
SELECT
|
|
16
|
+
id,
|
|
17
|
+
user_id,
|
|
18
|
+
gate_id,
|
|
19
|
+
gate_name,
|
|
20
|
+
model_requested,
|
|
21
|
+
model_used,
|
|
22
|
+
prompt_tokens,
|
|
23
|
+
completion_tokens,
|
|
24
|
+
cost_usd,
|
|
25
|
+
latency_ms,
|
|
26
|
+
success,
|
|
27
|
+
error_message,
|
|
28
|
+
created_at as logged_at
|
|
29
|
+
FROM requests
|
|
30
|
+
WHERE user_id = $1
|
|
31
|
+
`;
|
|
32
|
+
const params = [userId];
|
|
33
|
+
if (gate) {
|
|
34
|
+
query += ` AND gate_name = $2`;
|
|
35
|
+
params.push(gate);
|
|
36
|
+
}
|
|
37
|
+
query += ` ORDER BY created_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`;
|
|
38
|
+
params.push(limit, offset);
|
|
39
|
+
const result = await db.query(query, params);
|
|
40
|
+
const logs = result.rows.map((row) => ({
|
|
41
|
+
id: row.id,
|
|
42
|
+
userId: row.user_id,
|
|
43
|
+
gateId: row.gate_id,
|
|
44
|
+
gateName: row.gate_name,
|
|
45
|
+
modelRequested: row.model_requested,
|
|
46
|
+
modelUsed: row.model_used,
|
|
47
|
+
promptTokens: row.prompt_tokens,
|
|
48
|
+
completionTokens: row.completion_tokens,
|
|
49
|
+
costUsd: parseFloat(row.cost_usd),
|
|
50
|
+
latencyMs: row.latency_ms,
|
|
51
|
+
success: row.success,
|
|
52
|
+
errorMessage: row.error_message,
|
|
53
|
+
loggedAt: row.logged_at,
|
|
54
|
+
}));
|
|
55
|
+
res.json(logs);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error('Logs list error:', error);
|
|
59
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to fetch logs' });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// GET /v1/logs/overview - Get logs for api calls
|
|
63
|
+
router.get('/overview', async (req, res) => {
|
|
64
|
+
try {
|
|
65
|
+
const userId = req.userId;
|
|
66
|
+
const [statsResult, gatesResult, recentRequestsResult] = await Promise.all([
|
|
67
|
+
// Get aggregate stats
|
|
68
|
+
db.query(`SELECT
|
|
69
|
+
COUNT(*) as total_requests,
|
|
70
|
+
COALESCE(SUM(cost_usd), 0) as total_cost,
|
|
71
|
+
COALESCE(AVG(latency_ms), 0) as avg_latency
|
|
72
|
+
FROM requests
|
|
73
|
+
WHERE user_id = $1`, [userId]),
|
|
74
|
+
// Get gates count
|
|
75
|
+
db.query(`SELECT COUNT(*) as active_gates FROM gates WHERE user_id = $1`, [userId]),
|
|
76
|
+
// Get recent requests
|
|
77
|
+
db.query(`SELECT
|
|
78
|
+
id,
|
|
79
|
+
gate_name,
|
|
80
|
+
model_used,
|
|
81
|
+
prompt_tokens,
|
|
82
|
+
completion_tokens,
|
|
83
|
+
total_tokens,
|
|
84
|
+
cost_usd,
|
|
85
|
+
latency_ms,
|
|
86
|
+
success,
|
|
87
|
+
created_at
|
|
88
|
+
FROM requests
|
|
89
|
+
WHERE user_id = $1
|
|
90
|
+
ORDER BY created_at DESC
|
|
91
|
+
LIMIT 20`, [userId]),
|
|
92
|
+
]);
|
|
93
|
+
const stats = statsResult.rows[0];
|
|
94
|
+
const gatesCount = gatesResult.rows[0];
|
|
95
|
+
const recentRequests = recentRequestsResult.rows;
|
|
96
|
+
res.json({
|
|
97
|
+
totalRequests: parseInt(stats.total_requests),
|
|
98
|
+
totalCost: parseFloat(stats.total_cost),
|
|
99
|
+
avgLatency: Math.round(parseFloat(stats.avg_latency)),
|
|
100
|
+
activeGates: parseInt(gatesCount.active_gates),
|
|
101
|
+
recentRequests: recentRequests.map((req) => ({
|
|
102
|
+
id: req.id,
|
|
103
|
+
gateName: req.gate_name,
|
|
104
|
+
model: req.model_used,
|
|
105
|
+
promptTokens: req.prompt_tokens,
|
|
106
|
+
completionTokens: req.completion_tokens,
|
|
107
|
+
totalTokens: req.total_tokens,
|
|
108
|
+
cost: parseFloat(req.cost_usd),
|
|
109
|
+
latency: req.latency_ms,
|
|
110
|
+
success: req.success,
|
|
111
|
+
createdAt: req.created_at,
|
|
112
|
+
})),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('Analytics overview error:', error);
|
|
117
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to fetch analytics' });
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
// GET /v1/logs/gate/:gateId - Get metrics for a specific gate
|
|
121
|
+
router.get('/gate/:gateId', async (req, res) => {
|
|
122
|
+
try {
|
|
123
|
+
const userId = req.userId;
|
|
124
|
+
const { gateId } = req.params;
|
|
125
|
+
// Verify gate ownership
|
|
126
|
+
const gateCheck = await db.query('SELECT id FROM gates WHERE id = $1 AND user_id = $2', [gateId, userId]);
|
|
127
|
+
if (gateCheck.rows.length === 0) {
|
|
128
|
+
return res.status(404).json({ error: 'not_found', message: 'Gate not found' });
|
|
129
|
+
}
|
|
130
|
+
// Get gate metrics
|
|
131
|
+
const metricsResult = await db.query(`SELECT
|
|
132
|
+
COUNT(*) as requests,
|
|
133
|
+
COALESCE(SUM(cost_usd), 0) as cost,
|
|
134
|
+
COALESCE(AVG(latency_ms), 0) as latency,
|
|
135
|
+
MAX(created_at) as last_request
|
|
136
|
+
FROM requests
|
|
137
|
+
WHERE gate_id = $1`, [gateId]);
|
|
138
|
+
const metrics = metricsResult.rows[0];
|
|
139
|
+
res.json({
|
|
140
|
+
requests: parseInt(metrics.requests) || 0,
|
|
141
|
+
cost: parseFloat(metrics.cost) || 0,
|
|
142
|
+
latency: Math.round(parseFloat(metrics.latency)) || 0,
|
|
143
|
+
lastRequest: metrics.last_request,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.error('Gate metrics error:', error);
|
|
148
|
+
res.status(500).json({ error: 'internal_error', message: 'Failed to fetch gate metrics' });
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
export default router;
|
|
@@ -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;
|
|
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;AAgPpC,eAAe,MAAM,CAAC"}
|
|
@@ -2,26 +2,10 @@ import { Router } from 'express';
|
|
|
2
2
|
import { db } from '../../lib/db/postgres.js';
|
|
3
3
|
import { cache } from '../../lib/db/redis.js';
|
|
4
4
|
import { authenticate } from '../../middleware/auth.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { GoogleAdapter } from '../../services/providers/google-adapter.js';
|
|
8
|
-
import { MistralAdapter } from '../../services/providers/mistral-adapter.js';
|
|
9
|
-
import { MODEL_REGISTRY, OverrideField } from '@layer-ai/sdk';
|
|
5
|
+
import { callAdapter, normalizeModelId } from '../../lib/provider-factory.js';
|
|
6
|
+
import { OverrideField } from '@layer-ai/sdk';
|
|
10
7
|
const router = Router();
|
|
11
8
|
// MARK:- Helper Functions
|
|
12
|
-
function normalizeModelId(modelId) {
|
|
13
|
-
if (MODEL_REGISTRY[modelId]) {
|
|
14
|
-
return modelId;
|
|
15
|
-
}
|
|
16
|
-
const providers = ['openai', 'anthropic', 'google', 'mistral'];
|
|
17
|
-
for (const provider of providers) {
|
|
18
|
-
const fullId = `${provider}/${modelId}`;
|
|
19
|
-
if (MODEL_REGISTRY[fullId]) {
|
|
20
|
-
return fullId;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
throw new Error(`invalid model ID: "${modelId}" not found in registry`);
|
|
24
|
-
}
|
|
25
9
|
function isOverrideAllowed(allowOverrides, field) {
|
|
26
10
|
if (allowOverrides === undefined || allowOverrides === null || allowOverrides === true)
|
|
27
11
|
return true;
|
|
@@ -78,29 +62,6 @@ function resolveFinalRequest(gateConfig, request) {
|
|
|
78
62
|
}
|
|
79
63
|
return finalRequest;
|
|
80
64
|
}
|
|
81
|
-
async function callProvider(request) {
|
|
82
|
-
const normalizedModel = normalizeModelId(request.model);
|
|
83
|
-
const provider = MODEL_REGISTRY[normalizedModel].provider;
|
|
84
|
-
switch (provider) {
|
|
85
|
-
case 'openai': {
|
|
86
|
-
const adapter = new OpenAIAdapter();
|
|
87
|
-
return await adapter.call(request);
|
|
88
|
-
}
|
|
89
|
-
case 'anthropic': {
|
|
90
|
-
const adapter = new AnthropicAdapter();
|
|
91
|
-
return await adapter.call(request);
|
|
92
|
-
}
|
|
93
|
-
case 'google':
|
|
94
|
-
const adapter = new GoogleAdapter();
|
|
95
|
-
return await adapter.call(request);
|
|
96
|
-
case 'mistral': {
|
|
97
|
-
const adapter = new MistralAdapter();
|
|
98
|
-
return await adapter.call(request);
|
|
99
|
-
}
|
|
100
|
-
default:
|
|
101
|
-
throw new Error(`Unknown provider: ${provider}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
65
|
function getModelsToTry(gateConfig, primaryModel) {
|
|
105
66
|
const modelsToTry = [primaryModel];
|
|
106
67
|
if (gateConfig.routingStrategy === 'fallback' && gateConfig.fallbackModels?.length) {
|
|
@@ -115,7 +76,7 @@ async function executeWithFallback(request, modelsToTry) {
|
|
|
115
76
|
for (const modelToTry of modelsToTry) {
|
|
116
77
|
try {
|
|
117
78
|
const modelRequest = { ...request, model: modelToTry };
|
|
118
|
-
result = await
|
|
79
|
+
result = await callAdapter(modelRequest);
|
|
119
80
|
modelUsed = modelToTry;
|
|
120
81
|
break;
|
|
121
82
|
}
|
|
@@ -132,14 +93,14 @@ async function executeWithFallback(request, modelsToTry) {
|
|
|
132
93
|
}
|
|
133
94
|
async function executeWithRoundRobin(gateConfig, request) {
|
|
134
95
|
if (!gateConfig.fallbackModels?.length) {
|
|
135
|
-
const result = await
|
|
96
|
+
const result = await callAdapter(request);
|
|
136
97
|
return { result, modelUsed: request.model };
|
|
137
98
|
}
|
|
138
99
|
const allModels = [gateConfig.model, ...gateConfig.fallbackModels];
|
|
139
100
|
const modelIndex = Math.floor(Math.random() * allModels.length);
|
|
140
101
|
const selectedModel = allModels[modelIndex];
|
|
141
102
|
const modelRequest = { ...request, model: selectedModel };
|
|
142
|
-
const result = await
|
|
103
|
+
const result = await callAdapter(modelRequest);
|
|
143
104
|
return { result, modelUsed: selectedModel };
|
|
144
105
|
}
|
|
145
106
|
async function executeWithRouting(gateConfig, request) {
|
|
@@ -151,7 +112,7 @@ async function executeWithRouting(gateConfig, request) {
|
|
|
151
112
|
return await executeWithRoundRobin(gateConfig, request);
|
|
152
113
|
case 'single':
|
|
153
114
|
default:
|
|
154
|
-
const result = await
|
|
115
|
+
const result = await callAdapter(request);
|
|
155
116
|
return { result, modelUsed: request.model };
|
|
156
117
|
}
|
|
157
118
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LayerRequest, LayerResponse, SupportedModel } from '@layer-ai/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a model ID to its full registry format.
|
|
4
|
+
* Supports both full IDs (e.g., "openai/gpt-4") and short IDs (e.g., "gpt-4").
|
|
5
|
+
*/
|
|
6
|
+
export declare function normalizeModelId(modelId: string): SupportedModel;
|
|
7
|
+
/**
|
|
8
|
+
* Calls the appropriate provider adapter for the given request.
|
|
9
|
+
*/
|
|
10
|
+
export declare function callProvider(request: LayerRequest): Promise<LayerResponse>;
|
|
11
|
+
//# sourceMappingURL=provider-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-service.d.ts","sourceRoot":"","sources":["../../src/services/provider-service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGjF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAchE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAwBhF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { OpenAIAdapter } from './providers/openai-adapter.js';
|
|
2
|
+
import { AnthropicAdapter } from './providers/anthropic-adapter.js';
|
|
3
|
+
import { GoogleAdapter } from './providers/google-adapter.js';
|
|
4
|
+
import { MistralAdapter } from './providers/mistral-adapter.js';
|
|
5
|
+
import { MODEL_REGISTRY } from '@layer-ai/sdk';
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes a model ID to its full registry format.
|
|
8
|
+
* Supports both full IDs (e.g., "openai/gpt-4") and short IDs (e.g., "gpt-4").
|
|
9
|
+
*/
|
|
10
|
+
export function normalizeModelId(modelId) {
|
|
11
|
+
if (MODEL_REGISTRY[modelId]) {
|
|
12
|
+
return modelId;
|
|
13
|
+
}
|
|
14
|
+
const providers = ['openai', 'anthropic', 'google', 'mistral'];
|
|
15
|
+
for (const provider of providers) {
|
|
16
|
+
const fullId = `${provider}/${modelId}`;
|
|
17
|
+
if (MODEL_REGISTRY[fullId]) {
|
|
18
|
+
return fullId;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`invalid model ID: "${modelId}" not found in registry`);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Calls the appropriate provider adapter for the given request.
|
|
25
|
+
*/
|
|
26
|
+
export async function callProvider(request) {
|
|
27
|
+
const normalizedModel = normalizeModelId(request.model);
|
|
28
|
+
const provider = MODEL_REGISTRY[normalizedModel].provider;
|
|
29
|
+
switch (provider) {
|
|
30
|
+
case 'openai': {
|
|
31
|
+
const adapter = new OpenAIAdapter();
|
|
32
|
+
return await adapter.call(request);
|
|
33
|
+
}
|
|
34
|
+
case 'anthropic': {
|
|
35
|
+
const adapter = new AnthropicAdapter();
|
|
36
|
+
return await adapter.call(request);
|
|
37
|
+
}
|
|
38
|
+
case 'google': {
|
|
39
|
+
const adapter = new GoogleAdapter();
|
|
40
|
+
return await adapter.call(request);
|
|
41
|
+
}
|
|
42
|
+
case 'mistral': {
|
|
43
|
+
const adapter = new MistralAdapter();
|
|
44
|
+
return await adapter.call(request);
|
|
45
|
+
}
|
|
46
|
+
default:
|
|
47
|
+
throw new Error(`Unknown provider: ${provider}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
2
2
|
import { LayerRequest, LayerResponse, Role, FinishReason, ToolChoice } from '@layer-ai/sdk';
|
|
3
|
+
import { type Provider } from "../../lib/provider-constants.js";
|
|
3
4
|
export declare class AnthropicAdapter extends BaseProviderAdapter {
|
|
4
|
-
protected provider:
|
|
5
|
+
protected provider: Provider;
|
|
5
6
|
protected roleMappings: Record<Role, string>;
|
|
6
7
|
protected toolChoiceMappings: Record<string, string | object>;
|
|
7
8
|
protected finishReasonMappings: Record<string, FinishReason>;
|
|
@@ -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;
|
|
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;AAa1E,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,GAAG,OAAO,CAAC,aAAa,CAAC;YAiB3C,UAAU;CA4JzB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
2
|
import { BaseProviderAdapter, ADAPTER_HANDLED } from './base-adapter.js';
|
|
3
|
+
import { PROVIDER } from "../../lib/provider-constants.js";
|
|
3
4
|
let anthropic = null;
|
|
4
5
|
function getAnthropicClient() {
|
|
5
6
|
if (!anthropic) {
|
|
@@ -12,7 +13,7 @@ function getAnthropicClient() {
|
|
|
12
13
|
export class AnthropicAdapter extends BaseProviderAdapter {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
15
|
-
this.provider =
|
|
16
|
+
this.provider = PROVIDER.ANTHROPIC;
|
|
16
17
|
this.roleMappings = {
|
|
17
18
|
system: ADAPTER_HANDLED, // Handled via system parameter
|
|
18
19
|
user: 'user',
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { LayerRequest, LayerResponse, Role, ImageDetail, ImageSize, ImageQuality, ImageStyle, VideoSize, AudioFormat, AudioMimeType, ImageMimeType, FinishReason, ToolChoice, EncodingFormat, ADAPTER_HANDLED } from '@layer-ai/sdk';
|
|
2
|
+
import type { Provider } from "../../lib/provider-constants.js";
|
|
2
3
|
export { ADAPTER_HANDLED };
|
|
3
4
|
export declare abstract class BaseProviderAdapter {
|
|
4
|
-
protected abstract provider:
|
|
5
|
+
protected abstract provider: Provider;
|
|
5
6
|
protected roleMappings?: Record<Role, string>;
|
|
6
7
|
protected imageDetailMappings?: Record<ImageDetail, string>;
|
|
7
8
|
protected toolChoiceMappings?: Record<string, string | object>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/base-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,UAAU,EACV,cAAc,EACd,eAAe,EAGhB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"base-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/base-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,UAAU,EACV,cAAc,EACd,eAAe,EAGhB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,8BAAsB,mBAAmB;IACvC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAEtC,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9C,SAAS,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC5D,SAAS,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAC/D,SAAS,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9D,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACxD,SAAS,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9D,SAAS,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1D,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACxD,SAAS,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC5D,SAAS,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAChE,SAAS,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAChE,SAAS,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAElE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAE5D,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAcrC,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAQjE,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS;IAQ3D,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS;IAQpE,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS;IAQ9D,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS;IAQ3D,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAQjE,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS;IAQvE,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS;IAQvE,SAAS,CAAC,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS;IAQvE,SAAS,CAAC,eAAe,CAAC,oBAAoB,EAAE,MAAM,GAAG,YAAY;IAQrE,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS;IAYxE,SAAS,CAAC,aAAa,CACrB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,GACvB,MAAM;CAOV"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { FunctionCallingConfigMode } from '@google/genai';
|
|
2
2
|
import { LayerRequest, LayerResponse, Role, FinishReason, VideoSize } from '@layer-ai/sdk';
|
|
3
3
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
4
|
+
import { type Provider } from "../../lib/provider-constants.js";
|
|
4
5
|
export declare class GoogleAdapter extends BaseProviderAdapter {
|
|
5
|
-
protected provider:
|
|
6
|
+
protected provider: Provider;
|
|
6
7
|
protected roleMappings: Record<Role, string>;
|
|
7
8
|
protected finishReasonMappings: Record<string, FinishReason>;
|
|
8
9
|
protected toolChoiceMappings: Record<string, FunctionCallingConfigMode>;
|
|
@@ -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;
|
|
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;AAW1E,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,GAAG,OAAO,CAAC,aAAa,CAAC;YAiB3C,UAAU;YAqLV,qBAAqB;YAkCrB,gBAAgB;YAmChB,qBAAqB;YAmHrB,kBAAkB;IAwChC,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GoogleGenAI, FunctionCallingConfigMode, VideoGenerationReferenceType, } from '@google/genai';
|
|
2
2
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
3
3
|
import { ADAPTER_HANDLED } from './base-adapter.js';
|
|
4
|
+
import { PROVIDER } from "../../lib/provider-constants.js";
|
|
4
5
|
let client = null;
|
|
5
6
|
function getGoogleClient() {
|
|
6
7
|
if (!client) {
|
|
@@ -11,7 +12,7 @@ function getGoogleClient() {
|
|
|
11
12
|
export class GoogleAdapter extends BaseProviderAdapter {
|
|
12
13
|
constructor() {
|
|
13
14
|
super(...arguments);
|
|
14
|
-
this.provider =
|
|
15
|
+
this.provider = PROVIDER.GOOGLE;
|
|
15
16
|
this.roleMappings = {
|
|
16
17
|
system: ADAPTER_HANDLED,
|
|
17
18
|
user: 'user',
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
2
2
|
import { LayerRequest, LayerResponse, Role, FinishReason } from '@layer-ai/sdk';
|
|
3
|
+
import { type Provider } from "../../lib/provider-constants.js";
|
|
3
4
|
export declare class MistralAdapter extends BaseProviderAdapter {
|
|
4
|
-
protected provider:
|
|
5
|
+
protected provider: Provider;
|
|
5
6
|
protected roleMappings: Record<Role, string>;
|
|
6
7
|
protected finishReasonMappings: Record<string, FinishReason>;
|
|
7
8
|
protected toolChoiceMappings: Record<string, string>;
|
|
@@ -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;
|
|
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;AAa1E,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,GAAG,OAAO,CAAC,aAAa,CAAC;YAmB3C,UAAU;YA8LV,gBAAgB;YAuChB,SAAS;CA2ExB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Mistral } from '@mistralai/mistralai';
|
|
2
2
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
3
3
|
import { ADAPTER_HANDLED, } from '@layer-ai/sdk';
|
|
4
|
+
import { PROVIDER } from "../../lib/provider-constants.js";
|
|
4
5
|
let client = null;
|
|
5
6
|
function getMistralClient() {
|
|
6
7
|
if (!client) {
|
|
@@ -13,7 +14,7 @@ function getMistralClient() {
|
|
|
13
14
|
export class MistralAdapter extends BaseProviderAdapter {
|
|
14
15
|
constructor() {
|
|
15
16
|
super(...arguments);
|
|
16
|
-
this.provider =
|
|
17
|
+
this.provider = PROVIDER.MISTRAL;
|
|
17
18
|
this.roleMappings = {
|
|
18
19
|
system: ADAPTER_HANDLED,
|
|
19
20
|
user: 'user',
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
2
2
|
import { LayerRequest, LayerResponse, Role, ImageDetail, ImageSize, ImageQuality, ImageStyle, VideoSize, AudioFormat, FinishReason } from '@layer-ai/sdk';
|
|
3
|
+
import { type Provider } from "../../lib/provider-constants.js";
|
|
3
4
|
export declare class OpenAIAdapter extends BaseProviderAdapter {
|
|
4
|
-
protected provider:
|
|
5
|
+
protected provider: Provider;
|
|
5
6
|
protected roleMappings: Record<Role, string>;
|
|
6
7
|
protected imageDetailMappings: Record<ImageDetail, string>;
|
|
7
8
|
protected finishReasonMappings: Record<string, FinishReason>;
|
|
@@ -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;
|
|
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;AAa1E,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,GAAG,OAAO,CAAC,aAAa,CAAC;YAiB3C,UAAU;YA2GV,qBAAqB;YA6BrB,gBAAgB;YAiChB,kBAAkB;CA8BjC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
2
|
import { BaseProviderAdapter } from './base-adapter.js';
|
|
3
|
+
import { PROVIDER } from "../../lib/provider-constants.js";
|
|
3
4
|
let openai = null;
|
|
4
5
|
function getOpenAIClient() {
|
|
5
6
|
if (!openai) {
|
|
@@ -12,7 +13,7 @@ function getOpenAIClient() {
|
|
|
12
13
|
export class OpenAIAdapter extends BaseProviderAdapter {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
15
|
-
this.provider =
|
|
16
|
+
this.provider = PROVIDER.OPENAI;
|
|
16
17
|
this.roleMappings = {
|
|
17
18
|
system: 'system',
|
|
18
19
|
user: 'user',
|