@layer-ai/core 0.9.2 → 2.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.
Files changed (38) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/routes/v1/gates.js +2 -2
  5. package/dist/routes/v2/complete.d.ts.map +1 -1
  6. package/dist/routes/v2/complete.js +127 -56
  7. package/dist/routes/v2/tests/test-byok-completion.js +1 -1
  8. package/dist/routes/v2/tests/test-complete-anthropic.js +4 -4
  9. package/dist/routes/v2/tests/test-complete-openai.js +7 -7
  10. package/dist/routes/v2/tests/test-complete-routing.js +5 -5
  11. package/dist/routes/v3/chat.d.ts +4 -0
  12. package/dist/routes/v3/chat.d.ts.map +1 -0
  13. package/dist/routes/v3/chat.js +203 -0
  14. package/dist/routes/v3/completions/chat.d.ts +4 -0
  15. package/dist/routes/v3/completions/chat.d.ts.map +1 -0
  16. package/dist/routes/v3/completions/chat.js +178 -0
  17. package/dist/routes/v3/completions/embed.d.ts +4 -0
  18. package/dist/routes/v3/completions/embed.d.ts.map +1 -0
  19. package/dist/routes/v3/completions/embed.js +94 -0
  20. package/dist/routes/v3/completions/image.d.ts +4 -0
  21. package/dist/routes/v3/completions/image.d.ts.map +1 -0
  22. package/dist/routes/v3/completions/image.js +155 -0
  23. package/dist/routes/v3/completions/ocr.d.ts +4 -0
  24. package/dist/routes/v3/completions/ocr.d.ts.map +1 -0
  25. package/dist/routes/v3/completions/ocr.js +94 -0
  26. package/dist/routes/v3/completions/tts.d.ts +4 -0
  27. package/dist/routes/v3/completions/tts.d.ts.map +1 -0
  28. package/dist/routes/v3/completions/tts.js +94 -0
  29. package/dist/routes/v3/completions/video.d.ts +4 -0
  30. package/dist/routes/v3/completions/video.d.ts.map +1 -0
  31. package/dist/routes/v3/completions/video.js +94 -0
  32. package/dist/services/providers/base-adapter.d.ts.map +1 -1
  33. package/dist/services/providers/base-adapter.js +5 -2
  34. package/dist/services/providers/tests/test-anthropic-adapter.js +4 -4
  35. package/dist/services/providers/tests/test-google-adapter.js +9 -9
  36. package/dist/services/providers/tests/test-mistral-adapter.js +11 -11
  37. package/dist/services/providers/tests/test-openai-adapter.js +8 -8
  38. package/package.json +2 -2
@@ -0,0 +1,94 @@
1
+ import { Router } from 'express';
2
+ import { db } from '../../../lib/db/postgres.js';
3
+ import { authenticate } from '../../../middleware/auth.js';
4
+ import { callAdapter, normalizeModelId } from '../../../lib/provider-factory.js';
5
+ import { OverrideField } from '@layer-ai/sdk';
6
+ const router = Router();
7
+ function isOverrideAllowed(allowOverrides, field) {
8
+ if (allowOverrides === undefined || allowOverrides === null || allowOverrides === true)
9
+ return true;
10
+ if (allowOverrides === false)
11
+ return false;
12
+ return allowOverrides[field] ?? false;
13
+ }
14
+ function resolveFinalRequest(gateConfig, request) {
15
+ let finalModel = gateConfig.model;
16
+ if (request.model && isOverrideAllowed(gateConfig.allowOverrides, OverrideField.Model)) {
17
+ try {
18
+ finalModel = normalizeModelId(request.model);
19
+ }
20
+ catch {
21
+ finalModel = gateConfig.model;
22
+ }
23
+ }
24
+ return { ...request, model: normalizeModelId(finalModel) };
25
+ }
26
+ function getModelsToTry(gateConfig, primaryModel) {
27
+ const modelsToTry = [primaryModel];
28
+ if (gateConfig.fallback1) {
29
+ try {
30
+ modelsToTry.push(normalizeModelId(gateConfig.fallback1));
31
+ }
32
+ catch (error) { }
33
+ }
34
+ if (gateConfig.fallback2) {
35
+ try {
36
+ modelsToTry.push(normalizeModelId(gateConfig.fallback2));
37
+ }
38
+ catch (error) { }
39
+ }
40
+ return modelsToTry;
41
+ }
42
+ async function executeWithRouting(gateConfig, request, userId) {
43
+ const modelsToTry = getModelsToTry(gateConfig, request.model);
44
+ let lastError = null;
45
+ for (let i = 0; i < modelsToTry.length; i++) {
46
+ const model = modelsToTry[i];
47
+ try {
48
+ const result = await callAdapter({ ...request, model }, userId);
49
+ return { result, modelUsed: model };
50
+ }
51
+ catch (error) {
52
+ lastError = error;
53
+ }
54
+ }
55
+ throw lastError || new Error('All models failed');
56
+ }
57
+ router.post('/', authenticate, async (req, res) => {
58
+ const startTime = Date.now();
59
+ if (!req.userId) {
60
+ res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
61
+ return;
62
+ }
63
+ const userId = req.userId;
64
+ let gateConfig = null;
65
+ try {
66
+ const rawRequest = req.body;
67
+ if (!rawRequest.gateId || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(rawRequest.gateId)) {
68
+ res.status(400).json({ error: 'bad_request', message: 'Valid gateId (UUID) is required' });
69
+ return;
70
+ }
71
+ if (!rawRequest.data?.prompt || typeof rawRequest.data.prompt !== 'string' || !rawRequest.data.prompt.trim()) {
72
+ res.status(400).json({ error: 'bad_request', message: 'data.prompt is required' });
73
+ return;
74
+ }
75
+ gateConfig = await db.getGateByUserAndId(userId, rawRequest.gateId);
76
+ if (!gateConfig) {
77
+ res.status(404).json({ error: 'not_found', message: `Gate not found` });
78
+ return;
79
+ }
80
+ const request = { gateId: rawRequest.gateId, type: 'video', data: rawRequest.data, model: rawRequest.model, metadata: rawRequest.metadata };
81
+ const finalRequest = resolveFinalRequest(gateConfig, request);
82
+ const { result, modelUsed } = await executeWithRouting(gateConfig, finalRequest, userId);
83
+ db.logRequest({ userId, gateId: gateConfig.id, model: modelUsed, promptTokens: result.usage?.promptTokens || 0, completionTokens: result.usage?.completionTokens || 0, totalTokens: result.usage?.totalTokens || 0, cost: result.cost || 0, latencyMs: Date.now() - startTime, success: true }).catch(() => { });
84
+ res.status(200).json(result);
85
+ }
86
+ catch (error) {
87
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
88
+ if (gateConfig) {
89
+ db.logRequest({ userId, gateId: gateConfig.id, model: gateConfig.model, promptTokens: 0, completionTokens: 0, totalTokens: 0, cost: 0, latencyMs: Date.now() - startTime, success: false, errorMessage }).catch(() => { });
90
+ }
91
+ res.status(500).json({ error: 'internal_server_error', message: errorMessage });
92
+ }
93
+ });
94
+ export default router;
@@ -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;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;IACtC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAE1B,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,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAE7E,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
+ {"version":3,"file":"base-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/base-adapter.ts"],"names":[],"mappings":"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"}
@@ -82,9 +82,12 @@ export class BaseProviderAdapter {
82
82
  }
83
83
  calculateCost(model, promptTokens, completionTokens) {
84
84
  const modelInfo = MODEL_REGISTRY[model];
85
- if (!modelInfo || !('pricing' in modelInfo) || !modelInfo.pricing?.input || !modelInfo.pricing?.output) {
85
+ if (!modelInfo || !('pricing' in modelInfo) || !modelInfo.pricing?.input) {
86
86
  return 0;
87
87
  }
88
- return (promptTokens / 1000000 * modelInfo.pricing.input) + (completionTokens / 1000000 * modelInfo.pricing.output);
88
+ const pricing = modelInfo.pricing;
89
+ const inputCost = promptTokens / 1000000 * pricing.input;
90
+ const outputCost = ('output' in pricing && pricing.output) ? (completionTokens / 1000000 * pricing.output) : 0;
91
+ return inputCost + outputCost;
89
92
  }
90
93
  }
@@ -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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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
- gate: 'test-gate',
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.9.2",
3
+ "version": "2.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": "^1.0.3"
39
+ "@layer-ai/sdk": "^2.1.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/bcryptjs": "^2.4.6",