@layer-ai/core 0.5.7 → 0.5.9

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 CHANGED
@@ -10,4 +10,5 @@ export { default as redis } from './lib/db/redis.js';
10
10
  export declare const createSessionKey: (userId: string) => Promise<string>;
11
11
  export declare const deleteSessionKeysForUser: (userId: string) => Promise<void>;
12
12
  export * from './services/task-analysis.js';
13
+ export { PROVIDER, PROVIDERS, type Provider, callAdapter, normalizeModelId, getProviderForModel } from './lib/provider-factory.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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"}
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;AAG5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/index.js CHANGED
@@ -20,3 +20,5 @@ export const deleteSessionKeysForUser = async (userId) => {
20
20
  };
21
21
  // Services
22
22
  export * from './services/task-analysis.js';
23
+ // Provider Factory
24
+ export { PROVIDER, PROVIDERS, callAdapter, normalizeModelId, getProviderForModel } from './lib/provider-factory.js';
@@ -1 +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"}
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;AAQpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA0bpC,eAAe,MAAM,CAAC"}
@@ -2,6 +2,7 @@ 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 { callAdapter } from '../../lib/provider-factory.js';
5
6
  import { MODEL_REGISTRY } from '@layer-ai/sdk';
6
7
  const router = Router();
7
8
  // All routes require authentication (SDK auth with Bearer token)
@@ -246,6 +247,118 @@ router.delete('/:id', async (req, res) => {
246
247
  res.status(500).json({ error: 'internal_error', message: 'Failed to delete gate' });
247
248
  }
248
249
  });
250
+ // POST /test - Test a gate configuration with a sample request
251
+ // Can either test a saved gate (by providing gateId) or test an unsaved configuration (by providing gate config)
252
+ router.post('/test', async (req, res) => {
253
+ if (!req.userId) {
254
+ res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
255
+ return;
256
+ }
257
+ try {
258
+ const { gateId, gate: gateOverride, messages } = req.body;
259
+ if (!messages || !Array.isArray(messages) || messages.length === 0) {
260
+ res.status(400).json({ error: 'bad_request', message: 'Missing or invalid messages array' });
261
+ return;
262
+ }
263
+ // Get base gate config from database if gateId provided, otherwise use empty base
264
+ let baseGate = {};
265
+ if (gateId) {
266
+ const savedGate = await db.getGateById(gateId);
267
+ if (!savedGate) {
268
+ res.status(404).json({ error: 'not_found', message: 'Gate not found' });
269
+ return;
270
+ }
271
+ if (savedGate.userId !== req.userId) {
272
+ res.status(404).json({ error: 'not_found', message: 'Gate not found' });
273
+ return;
274
+ }
275
+ baseGate = savedGate;
276
+ }
277
+ // Merge base gate with overrides (overrides take precedence)
278
+ const finalGate = { ...baseGate, ...gateOverride };
279
+ if (!finalGate.model) {
280
+ res.status(400).json({ error: 'bad_request', message: 'Missing required field: model' });
281
+ return;
282
+ }
283
+ const results = {};
284
+ // Test primary model
285
+ const primaryStartTime = Date.now();
286
+ try {
287
+ const request = {
288
+ type: 'chat',
289
+ gate: finalGate.name || 'test-gate',
290
+ model: finalGate.model,
291
+ data: {
292
+ messages,
293
+ systemPrompt: finalGate.systemPrompt,
294
+ temperature: finalGate.temperature,
295
+ maxTokens: finalGate.maxTokens,
296
+ topP: finalGate.topP,
297
+ },
298
+ };
299
+ const response = await callAdapter(request);
300
+ const latency = Date.now() - primaryStartTime;
301
+ results.primary = {
302
+ model: finalGate.model,
303
+ success: true,
304
+ latency,
305
+ content: response.content || 'Test completed successfully',
306
+ };
307
+ }
308
+ catch (error) {
309
+ const latency = Date.now() - primaryStartTime;
310
+ results.primary = {
311
+ model: finalGate.model,
312
+ success: false,
313
+ latency,
314
+ error: error instanceof Error ? error.message : 'Unknown error',
315
+ };
316
+ }
317
+ // Test all fallback models
318
+ if (finalGate.fallbackModels && finalGate.fallbackModels.length > 0) {
319
+ results.fallback = [];
320
+ for (const fallbackModel of finalGate.fallbackModels) {
321
+ const fallbackStartTime = Date.now();
322
+ try {
323
+ const request = {
324
+ type: 'chat',
325
+ gate: finalGate.name || 'test-gate',
326
+ model: fallbackModel,
327
+ data: {
328
+ messages,
329
+ systemPrompt: finalGate.systemPrompt,
330
+ temperature: finalGate.temperature,
331
+ maxTokens: finalGate.maxTokens,
332
+ topP: finalGate.topP,
333
+ },
334
+ };
335
+ const response = await callAdapter(request);
336
+ const latency = Date.now() - fallbackStartTime;
337
+ results.fallback.push({
338
+ model: fallbackModel,
339
+ success: true,
340
+ latency,
341
+ content: response.content || 'Test completed successfully',
342
+ });
343
+ }
344
+ catch (error) {
345
+ const latency = Date.now() - fallbackStartTime;
346
+ results.fallback.push({
347
+ model: fallbackModel,
348
+ success: false,
349
+ latency,
350
+ error: error instanceof Error ? error.message : 'Unknown error',
351
+ });
352
+ }
353
+ }
354
+ }
355
+ res.json(results);
356
+ }
357
+ catch (error) {
358
+ console.error('Test gate error:', error);
359
+ res.status(500).json({ error: 'internal_error', message: 'Failed to test gate' });
360
+ }
361
+ });
249
362
  // POST /suggestions - Get AI-powered model suggestions for a gate
250
363
  router.post('/suggestions', async (req, res) => {
251
364
  if (!req.userId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layer-ai/core",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "description": "Core API routes and services for Layer AI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",