@layer-ai/core 2.0.9 → 2.0.11
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/db/migrations/006_add_response_format_to_gates.sql +17 -0
- package/dist/lib/db/postgres.d.ts.map +1 -1
- package/dist/lib/db/postgres.js +12 -3
- package/dist/lib/gate-utils.d.ts.map +1 -1
- package/dist/lib/gate-utils.js +3 -0
- package/dist/routes/v3/chat.d.ts.map +1 -1
- package/dist/routes/v3/chat.js +59 -1
- package/dist/routes/v3/embeddings.d.ts.map +1 -1
- package/dist/routes/v3/embeddings.js +21 -0
- package/dist/routes/v3/image.d.ts.map +1 -1
- package/dist/routes/v3/image.js +21 -0
- package/dist/routes/v3/ocr.d.ts.map +1 -1
- package/dist/routes/v3/ocr.js +21 -0
- package/dist/routes/v3/tts.d.ts.map +1 -1
- package/dist/routes/v3/tts.js +21 -0
- package/dist/routes/v3/video.d.ts.map +1 -1
- package/dist/routes/v3/video.js +21 -0
- package/dist/services/providers/openai-adapter.d.ts.map +1 -1
- package/dist/services/providers/openai-adapter.js +6 -0
- package/dist/services/task-analysis.d.ts.map +1 -1
- package/dist/services/task-analysis.js +11 -2
- package/package.json +2 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Migration: 006_add_response_format_to_gates
|
|
2
|
+
-- Description: Add structured output support fields to gates table (OpenAI response_format feature)
|
|
3
|
+
|
|
4
|
+
ALTER TABLE gates
|
|
5
|
+
ADD COLUMN response_format_enabled BOOLEAN DEFAULT FALSE,
|
|
6
|
+
ADD COLUMN response_format_type VARCHAR(20),
|
|
7
|
+
ADD COLUMN response_format_schema JSONB;
|
|
8
|
+
|
|
9
|
+
-- Add index for querying gates with structured output enabled
|
|
10
|
+
CREATE INDEX idx_gates_response_format_enabled
|
|
11
|
+
ON gates(response_format_enabled)
|
|
12
|
+
WHERE response_format_enabled = TRUE;
|
|
13
|
+
|
|
14
|
+
-- Add comments for documentation
|
|
15
|
+
COMMENT ON COLUMN gates.response_format_enabled IS 'Whether structured output is enabled for this gate';
|
|
16
|
+
COMMENT ON COLUMN gates.response_format_type IS 'Response format type: text, json_object, or json_schema';
|
|
17
|
+
COMMENT ON COLUMN gates.response_format_schema IS 'JSON schema for json_schema response format type';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAyB,WAAW,EAAE,MAAM,eAAe,CAAC;AAO5F,iBAAS,OAAO,IAAI,EAAE,CAAC,IAAI,CAqB1B;AA0BD,eAAO,MAAM,EAAE;gBAEK,MAAM,WAAW,GAAG,EAAE;0BASZ,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;oBAQnC,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;sBAQ3B,MAAM,gBAAgB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;0BAQxC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;6BAS5B,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;yBAQnC,MAAM,WAAW,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;kCAQjE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;8BAO1B,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;qBAQnC,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;iCAS7B,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;+BAQjD,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;4BAQhD,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;uBAQ7B,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/db/postgres.js
CHANGED
|
@@ -102,8 +102,8 @@ export const db = {
|
|
|
102
102
|
return result.rows.map(toCamelCase);
|
|
103
103
|
},
|
|
104
104
|
async createGate(userId, data) {
|
|
105
|
-
const result = await getPool().query(`INSERT INTO gates (user_id, name, description, task_type, model, system_prompt, allow_overrides, temperature, max_tokens, top_p, tags, routing_strategy, fallback_models, cost_weight, latency_weight, quality_weight, analysis_method, reanalysis_period, auto_apply_recommendations, task_analysis)
|
|
106
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20) RETURNING *`, [
|
|
105
|
+
const result = await getPool().query(`INSERT INTO gates (user_id, name, description, task_type, model, system_prompt, allow_overrides, temperature, max_tokens, top_p, tags, routing_strategy, fallback_models, cost_weight, latency_weight, quality_weight, analysis_method, reanalysis_period, auto_apply_recommendations, task_analysis, response_format_enabled, response_format_type, response_format_schema)
|
|
106
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23) RETURNING *`, [
|
|
107
107
|
userId,
|
|
108
108
|
data.name,
|
|
109
109
|
data.description,
|
|
@@ -123,7 +123,10 @@ export const db = {
|
|
|
123
123
|
data.analysisMethod || 'balanced',
|
|
124
124
|
data.reanalysisPeriod || 'never',
|
|
125
125
|
data.autoApplyRecommendations ?? false,
|
|
126
|
-
data.taskAnalysis ? JSON.stringify(data.taskAnalysis) : null
|
|
126
|
+
data.taskAnalysis ? JSON.stringify(data.taskAnalysis) : null,
|
|
127
|
+
data.responseFormatEnabled ?? false,
|
|
128
|
+
data.responseFormatType || null,
|
|
129
|
+
data.responseFormatSchema ? JSON.stringify(data.responseFormatSchema) : null
|
|
127
130
|
]);
|
|
128
131
|
return toCamelCase(result.rows[0]);
|
|
129
132
|
},
|
|
@@ -152,6 +155,9 @@ export const db = {
|
|
|
152
155
|
reanalysis_period = COALESCE($18, reanalysis_period),
|
|
153
156
|
auto_apply_recommendations = COALESCE($19, auto_apply_recommendations),
|
|
154
157
|
task_analysis = COALESCE($20, task_analysis),
|
|
158
|
+
response_format_enabled = COALESCE($21, response_format_enabled),
|
|
159
|
+
response_format_type = COALESCE($22, response_format_type),
|
|
160
|
+
response_format_schema = COALESCE($23, response_format_schema),
|
|
155
161
|
updated_at = NOW()
|
|
156
162
|
WHERE id = $1 RETURNING *`, [
|
|
157
163
|
id,
|
|
@@ -174,6 +180,9 @@ export const db = {
|
|
|
174
180
|
data.reanalysisPeriod,
|
|
175
181
|
data.autoApplyRecommendations,
|
|
176
182
|
data.taskAnalysis ? JSON.stringify(data.taskAnalysis) : null,
|
|
183
|
+
data.responseFormatEnabled,
|
|
184
|
+
data.responseFormatType,
|
|
185
|
+
data.responseFormatSchema ? JSON.stringify(data.responseFormatSchema) : null,
|
|
177
186
|
]);
|
|
178
187
|
return result.rows[0] ? toCamelCase(result.rows[0]) : null;
|
|
179
188
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-utils.d.ts","sourceRoot":"","sources":["../../src/lib/gate-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"gate-utils.d.ts","sourceRoot":"","sources":["../../src/lib/gate-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,CA0D9E"}
|
package/dist/lib/gate-utils.js
CHANGED
|
@@ -45,6 +45,9 @@ export function detectSignificantChanges(existing, updates) {
|
|
|
45
45
|
systemPrompt: 'systemPrompt',
|
|
46
46
|
reanalysisPeriod: 'reanalysisPeriod',
|
|
47
47
|
autoApplyRecommendations: 'autoApplyRecommendations',
|
|
48
|
+
responseFormatEnabled: 'responseFormatEnabled',
|
|
49
|
+
responseFormatType: 'responseFormatType',
|
|
50
|
+
responseFormatSchema: 'responseFormatSchema',
|
|
48
51
|
};
|
|
49
52
|
for (const [field, displayName] of Object.entries(significantFields)) {
|
|
50
53
|
if (hasChanged(field, existing[field], updates[field])) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AAmTpC,eAAe,MAAM,CAAC"}
|
package/dist/routes/v3/chat.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { db } from '../../lib/db/postgres.js';
|
|
3
3
|
import { authenticate } from '../../middleware/auth.js';
|
|
4
|
-
import { callAdapter, normalizeModelId } from '../../lib/provider-factory.js';
|
|
4
|
+
import { callAdapter, normalizeModelId, getProviderForModel, PROVIDER } from '../../lib/provider-factory.js';
|
|
5
5
|
import { OverrideField } from '@layer-ai/sdk';
|
|
6
6
|
const router = Router();
|
|
7
7
|
// MARK:- Helper Functions
|
|
@@ -45,6 +45,42 @@ function resolveFinalRequest(gateConfig, request) {
|
|
|
45
45
|
else if (chatData.topP !== undefined && !isOverrideAllowed(gateConfig.allowOverrides, OverrideField.TopP)) {
|
|
46
46
|
chatData.topP = gateConfig.topP;
|
|
47
47
|
}
|
|
48
|
+
// Apply structured output (response format) from gate config if enabled
|
|
49
|
+
if (gateConfig.responseFormatEnabled && gateConfig.responseFormatType) {
|
|
50
|
+
const modelProvider = getProviderForModel(finalModel);
|
|
51
|
+
if (modelProvider === PROVIDER.OPENAI) {
|
|
52
|
+
// OpenAI: Use native response_format support
|
|
53
|
+
if (gateConfig.responseFormatType === 'json_schema' && gateConfig.responseFormatSchema) {
|
|
54
|
+
chatData.responseFormat = {
|
|
55
|
+
type: 'json_schema',
|
|
56
|
+
json_schema: gateConfig.responseFormatSchema,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
chatData.responseFormat = gateConfig.responseFormatType; // 'text' or 'json_object'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Non-OpenAI providers: Beta mode - inject instructions into system prompt
|
|
65
|
+
if (gateConfig.responseFormatType !== 'text') {
|
|
66
|
+
let schemaInstructions = '';
|
|
67
|
+
if (gateConfig.responseFormatType === 'json_schema' && gateConfig.responseFormatSchema) {
|
|
68
|
+
// For json_schema mode, include the actual schema
|
|
69
|
+
schemaInstructions = `\n\n[STRUCTURED OUTPUT - BETA] You MUST respond with valid JSON matching this exact schema:\n${JSON.stringify(gateConfig.responseFormatSchema, null, 2)}\n\nIMPORTANT: Output ONLY the JSON object. Do not include any explanatory text, markdown formatting, or code blocks. Just the raw JSON.`;
|
|
70
|
+
}
|
|
71
|
+
else if (gateConfig.responseFormatType === 'json_object') {
|
|
72
|
+
// For json_object mode, just require valid JSON
|
|
73
|
+
schemaInstructions = `\n\n[STRUCTURED OUTPUT - BETA] You MUST respond with valid JSON only. Do not include any explanatory text, markdown formatting, or code blocks. Output should be a raw JSON object.`;
|
|
74
|
+
}
|
|
75
|
+
// Append to existing system prompt or create new one
|
|
76
|
+
chatData.systemPrompt = (chatData.systemPrompt || '') + schemaInstructions;
|
|
77
|
+
// Log info message about beta mode
|
|
78
|
+
console.log(`[Layer AI - Structured Output Beta] Gate "${gateConfig.name}" (ID: ${gateConfig.id}) ` +
|
|
79
|
+
`is using structured output with provider "${modelProvider}". This is a beta feature that relies on ` +
|
|
80
|
+
`prompt engineering and may not be as reliable as OpenAI's native support.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
48
84
|
return {
|
|
49
85
|
...request,
|
|
50
86
|
type: 'chat',
|
|
@@ -168,6 +204,20 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
168
204
|
errorMessage: null,
|
|
169
205
|
userAgent: req.headers['user-agent'] || null,
|
|
170
206
|
ipAddress: req.ip || null,
|
|
207
|
+
requestPayload: {
|
|
208
|
+
gateId: request.gateId,
|
|
209
|
+
type: request.type,
|
|
210
|
+
model: request.model,
|
|
211
|
+
data: request.data,
|
|
212
|
+
metadata: request.metadata,
|
|
213
|
+
},
|
|
214
|
+
responsePayload: {
|
|
215
|
+
content: result.content,
|
|
216
|
+
model: result.model,
|
|
217
|
+
usage: result.usage,
|
|
218
|
+
cost: result.cost,
|
|
219
|
+
finishReason: result.finishReason,
|
|
220
|
+
},
|
|
171
221
|
}).catch(err => console.error('Failed to log request:', err));
|
|
172
222
|
// Return LayerResponse with additional metadata
|
|
173
223
|
const response = {
|
|
@@ -195,6 +245,14 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
195
245
|
errorMessage,
|
|
196
246
|
userAgent: req.headers['user-agent'] || null,
|
|
197
247
|
ipAddress: req.ip || null,
|
|
248
|
+
requestPayload: request ? {
|
|
249
|
+
gateId: request.gateId,
|
|
250
|
+
type: request.type,
|
|
251
|
+
model: request.model,
|
|
252
|
+
data: request.data,
|
|
253
|
+
metadata: request.metadata,
|
|
254
|
+
} : null,
|
|
255
|
+
responsePayload: null,
|
|
198
256
|
}).catch(err => console.error('Failed to log request:', err));
|
|
199
257
|
console.error('Chat completion error:', error);
|
|
200
258
|
res.status(500).json({ error: 'internal_error', message: errorMessage });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/embeddings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/embeddings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AAmQpC,eAAe,MAAM,CAAC"}
|
|
@@ -161,6 +161,19 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
161
161
|
errorMessage: null,
|
|
162
162
|
userAgent: req.headers['user-agent'] || null,
|
|
163
163
|
ipAddress: req.ip || null,
|
|
164
|
+
requestPayload: {
|
|
165
|
+
gateId: request.gateId,
|
|
166
|
+
type: request.type,
|
|
167
|
+
model: request.model,
|
|
168
|
+
data: request.data,
|
|
169
|
+
metadata: request.metadata,
|
|
170
|
+
},
|
|
171
|
+
responsePayload: {
|
|
172
|
+
embeddings: result.embeddings,
|
|
173
|
+
model: result.model,
|
|
174
|
+
usage: result.usage,
|
|
175
|
+
cost: result.cost,
|
|
176
|
+
},
|
|
164
177
|
}).catch(err => console.error('Failed to log request:', err));
|
|
165
178
|
// Return LayerResponse with additional metadata
|
|
166
179
|
const response = {
|
|
@@ -188,6 +201,14 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
188
201
|
errorMessage,
|
|
189
202
|
userAgent: req.headers['user-agent'] || null,
|
|
190
203
|
ipAddress: req.ip || null,
|
|
204
|
+
requestPayload: request ? {
|
|
205
|
+
gateId: request.gateId,
|
|
206
|
+
type: request.type,
|
|
207
|
+
model: request.model,
|
|
208
|
+
data: request.data,
|
|
209
|
+
metadata: request.metadata,
|
|
210
|
+
} : null,
|
|
211
|
+
responsePayload: null,
|
|
191
212
|
}).catch(err => console.error('Failed to log request:', err));
|
|
192
213
|
console.error('Embeddings error:', error);
|
|
193
214
|
res.status(500).json({ error: 'internal_error', message: errorMessage });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA4PpC,eAAe,MAAM,CAAC"}
|
package/dist/routes/v3/image.js
CHANGED
|
@@ -155,6 +155,19 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
155
155
|
errorMessage: null,
|
|
156
156
|
userAgent: req.headers['user-agent'] || null,
|
|
157
157
|
ipAddress: req.ip || null,
|
|
158
|
+
requestPayload: {
|
|
159
|
+
gateId: request.gateId,
|
|
160
|
+
type: request.type,
|
|
161
|
+
model: request.model,
|
|
162
|
+
data: request.data,
|
|
163
|
+
metadata: request.metadata,
|
|
164
|
+
},
|
|
165
|
+
responsePayload: {
|
|
166
|
+
images: result.images,
|
|
167
|
+
model: result.model,
|
|
168
|
+
usage: result.usage,
|
|
169
|
+
cost: result.cost,
|
|
170
|
+
},
|
|
158
171
|
}).catch(err => console.error('Failed to log request:', err));
|
|
159
172
|
// Return LayerResponse with additional metadata
|
|
160
173
|
const response = {
|
|
@@ -182,6 +195,14 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
182
195
|
errorMessage,
|
|
183
196
|
userAgent: req.headers['user-agent'] || null,
|
|
184
197
|
ipAddress: req.ip || null,
|
|
198
|
+
requestPayload: request ? {
|
|
199
|
+
gateId: request.gateId,
|
|
200
|
+
type: request.type,
|
|
201
|
+
model: request.model,
|
|
202
|
+
data: request.data,
|
|
203
|
+
metadata: request.metadata,
|
|
204
|
+
} : null,
|
|
205
|
+
responsePayload: null,
|
|
185
206
|
}).catch(err => console.error('Failed to log request:', err));
|
|
186
207
|
console.error('Image generation error:', error);
|
|
187
208
|
res.status(500).json({ error: 'internal_error', message: errorMessage });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ocr.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/ocr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ocr.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/ocr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AAqPpC,eAAe,MAAM,CAAC"}
|
package/dist/routes/v3/ocr.js
CHANGED
|
@@ -149,6 +149,19 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
149
149
|
errorMessage: null,
|
|
150
150
|
userAgent: req.headers['user-agent'] || null,
|
|
151
151
|
ipAddress: req.ip || null,
|
|
152
|
+
requestPayload: {
|
|
153
|
+
gateId: request.gateId,
|
|
154
|
+
type: request.type,
|
|
155
|
+
model: request.model,
|
|
156
|
+
data: request.data,
|
|
157
|
+
metadata: request.metadata,
|
|
158
|
+
},
|
|
159
|
+
responsePayload: {
|
|
160
|
+
ocr: result.ocr,
|
|
161
|
+
model: result.model,
|
|
162
|
+
usage: result.usage,
|
|
163
|
+
cost: result.cost,
|
|
164
|
+
},
|
|
152
165
|
}).catch(err => console.error('Failed to log request:', err));
|
|
153
166
|
// Return LayerResponse with additional metadata
|
|
154
167
|
const response = {
|
|
@@ -176,6 +189,14 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
176
189
|
errorMessage,
|
|
177
190
|
userAgent: req.headers['user-agent'] || null,
|
|
178
191
|
ipAddress: req.ip || null,
|
|
192
|
+
requestPayload: request ? {
|
|
193
|
+
gateId: request.gateId,
|
|
194
|
+
type: request.type,
|
|
195
|
+
model: request.model,
|
|
196
|
+
data: request.data,
|
|
197
|
+
metadata: request.metadata,
|
|
198
|
+
} : null,
|
|
199
|
+
responsePayload: null,
|
|
179
200
|
}).catch(err => console.error('Failed to log request:', err));
|
|
180
201
|
console.error('OCR error:', error);
|
|
181
202
|
res.status(500).json({ error: 'internal_error', message: errorMessage });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tts.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/tts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"tts.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/tts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AAiPpC,eAAe,MAAM,CAAC"}
|
package/dist/routes/v3/tts.js
CHANGED
|
@@ -145,6 +145,19 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
145
145
|
errorMessage: null,
|
|
146
146
|
userAgent: req.headers['user-agent'] || null,
|
|
147
147
|
ipAddress: req.ip || null,
|
|
148
|
+
requestPayload: {
|
|
149
|
+
gateId: request.gateId,
|
|
150
|
+
type: request.type,
|
|
151
|
+
model: request.model,
|
|
152
|
+
data: request.data,
|
|
153
|
+
metadata: request.metadata,
|
|
154
|
+
},
|
|
155
|
+
responsePayload: {
|
|
156
|
+
audio: result.audio,
|
|
157
|
+
model: result.model,
|
|
158
|
+
usage: result.usage,
|
|
159
|
+
cost: result.cost,
|
|
160
|
+
},
|
|
148
161
|
}).catch(err => console.error('Failed to log request:', err));
|
|
149
162
|
// Return LayerResponse with additional metadata
|
|
150
163
|
const response = {
|
|
@@ -172,6 +185,14 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
172
185
|
errorMessage,
|
|
173
186
|
userAgent: req.headers['user-agent'] || null,
|
|
174
187
|
ipAddress: req.ip || null,
|
|
188
|
+
requestPayload: request ? {
|
|
189
|
+
gateId: request.gateId,
|
|
190
|
+
type: request.type,
|
|
191
|
+
model: request.model,
|
|
192
|
+
data: request.data,
|
|
193
|
+
metadata: request.metadata,
|
|
194
|
+
} : null,
|
|
195
|
+
responsePayload: null,
|
|
175
196
|
}).catch(err => console.error('Failed to log request:', err));
|
|
176
197
|
console.error('TTS error:', error);
|
|
177
198
|
res.status(500).json({ error: 'internal_error', message: errorMessage });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/video.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/video.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA4PpC,eAAe,MAAM,CAAC"}
|
package/dist/routes/v3/video.js
CHANGED
|
@@ -155,6 +155,19 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
155
155
|
errorMessage: null,
|
|
156
156
|
userAgent: req.headers['user-agent'] || null,
|
|
157
157
|
ipAddress: req.ip || null,
|
|
158
|
+
requestPayload: {
|
|
159
|
+
gateId: request.gateId,
|
|
160
|
+
type: request.type,
|
|
161
|
+
model: request.model,
|
|
162
|
+
data: request.data,
|
|
163
|
+
metadata: request.metadata,
|
|
164
|
+
},
|
|
165
|
+
responsePayload: {
|
|
166
|
+
videos: result.videos,
|
|
167
|
+
model: result.model,
|
|
168
|
+
usage: result.usage,
|
|
169
|
+
cost: result.cost,
|
|
170
|
+
},
|
|
158
171
|
}).catch(err => console.error('Failed to log request:', err));
|
|
159
172
|
// Return LayerResponse with additional metadata
|
|
160
173
|
const response = {
|
|
@@ -182,6 +195,14 @@ router.post('/', authenticate, async (req, res) => {
|
|
|
182
195
|
errorMessage,
|
|
183
196
|
userAgent: req.headers['user-agent'] || null,
|
|
184
197
|
ipAddress: req.ip || null,
|
|
198
|
+
requestPayload: request ? {
|
|
199
|
+
gateId: request.gateId,
|
|
200
|
+
type: request.type,
|
|
201
|
+
model: request.model,
|
|
202
|
+
data: request.data,
|
|
203
|
+
metadata: request.metadata,
|
|
204
|
+
} : null,
|
|
205
|
+
responsePayload: null,
|
|
185
206
|
}).catch(err => console.error('Failed to log request:', err));
|
|
186
207
|
console.error('Video generation error:', error);
|
|
187
208
|
res.status(500).json({ error: 'internal_error', message: errorMessage });
|
|
@@ -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;YAoHV,qBAAqB;YAuCrB,gBAAgB;YAkChB,kBAAkB;CA+BjC"}
|
|
@@ -161,6 +161,12 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
161
161
|
tools: chat.tools,
|
|
162
162
|
...(chat.toolChoice && { tool_choice: chat.toolChoice }),
|
|
163
163
|
}),
|
|
164
|
+
// Structured output support: convert camelCase to snake_case
|
|
165
|
+
...(chat.responseFormat && {
|
|
166
|
+
response_format: (typeof chat.responseFormat === 'string'
|
|
167
|
+
? { type: chat.responseFormat }
|
|
168
|
+
: chat.responseFormat),
|
|
169
|
+
}),
|
|
164
170
|
};
|
|
165
171
|
const response = await client.chat.completions.create(openaiRequest);
|
|
166
172
|
const choice = response.choices[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-analysis.d.ts","sourceRoot":"","sources":["../../src/services/task-analysis.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,YAAY,EAAmC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"task-analysis.d.ts","sourceRoot":"","sources":["../../src/services/task-analysis.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,YAAY,EAAmC,MAAM,eAAe,CAAC;AA2D9F,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,OAAO,CAAC,YAAY,CAAC,CAkHvB"}
|
|
@@ -20,8 +20,13 @@ AVAILABLE TASK TYPES:
|
|
|
20
20
|
|
|
21
21
|
Return ONLY the task type as a single word, nothing else.`;
|
|
22
22
|
try {
|
|
23
|
+
// Smart routing model - upgraded to Sonnet 4.5 for better recommendations
|
|
24
|
+
// Can be overridden via SMART_ROUTING_MODEL environment variable
|
|
25
|
+
// Default: claude-sonnet-4-5-20250929 (~$3/1M tokens vs Haiku ~$0.25/1M)
|
|
26
|
+
// Cost impact is minimal since smart routing is infrequent (gate creation/reanalysis)
|
|
27
|
+
const smartRoutingModel = process.env.SMART_ROUTING_MODEL || 'claude-sonnet-4-5-20250929';
|
|
23
28
|
const response = await anthropic.messages.create({
|
|
24
|
-
model:
|
|
29
|
+
model: smartRoutingModel,
|
|
25
30
|
max_tokens: 50,
|
|
26
31
|
temperature: 0.0,
|
|
27
32
|
messages: [{
|
|
@@ -101,8 +106,12 @@ Return JSON with:
|
|
|
101
106
|
"reasoning": "why these models work for this task and user preferences"
|
|
102
107
|
}`;
|
|
103
108
|
try {
|
|
109
|
+
// Smart routing model - upgraded to Sonnet 4.5 for superior analysis quality
|
|
110
|
+
// Can be overridden via SMART_ROUTING_MODEL environment variable
|
|
111
|
+
// Default: claude-sonnet-4-5-20250929 for more nuanced model recommendations
|
|
112
|
+
const smartRoutingModel = process.env.SMART_ROUTING_MODEL || 'claude-sonnet-4-5-20250929';
|
|
104
113
|
const response = await anthropic.messages.create({
|
|
105
|
-
model:
|
|
114
|
+
model: smartRoutingModel,
|
|
106
115
|
max_tokens: 2000,
|
|
107
116
|
temperature: 0.0,
|
|
108
117
|
messages: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layer-ai/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.11",
|
|
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": "^2.5.
|
|
39
|
+
"@layer-ai/sdk": "^2.5.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bcryptjs": "^2.4.6",
|