@layer-ai/core 0.8.7 → 0.8.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.
@@ -45,6 +45,7 @@ export declare const db: {
45
45
  getGateHistoryById(id: string): Promise<any | null>;
46
46
  createActivityLog(gateId: string, userId: string | null, action: "manual_update" | "auto_update" | "reanalysis" | "rollback", details: any): Promise<void>;
47
47
  getActivityLog(gateId: string, limit?: number): Promise<any[]>;
48
+ rollbackGate(gateId: string, historyId: string, userId: string): Promise<Gate | null>;
48
49
  };
49
50
  export default getPool;
50
51
  //# sourceMappingURL=postgres.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"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"}
@@ -301,5 +301,70 @@ export const db = {
301
301
  LIMIT $2`, [gateId, limit]);
302
302
  return result.rows.map(toCamelCase);
303
303
  },
304
+ async rollbackGate(gateId, historyId, userId) {
305
+ // Get the historical configuration
306
+ const historyEntry = await this.getGateHistoryById(historyId);
307
+ if (!historyEntry || historyEntry.gateId !== gateId) {
308
+ return null;
309
+ }
310
+ // Get the current gate state before rollback for history snapshot
311
+ const currentGate = await this.getGateById(gateId);
312
+ if (!currentGate) {
313
+ return null;
314
+ }
315
+ // Create a snapshot of the current state before rolling back
316
+ await this.createGateHistory(gateId, currentGate, 'user');
317
+ // Update the gate with the historical configuration
318
+ const result = await getPool().query(`UPDATE gates SET
319
+ name = $2,
320
+ description = $3,
321
+ model = $4,
322
+ fallback_models = $5,
323
+ routing_strategy = $6,
324
+ temperature = $7,
325
+ max_tokens = $8,
326
+ top_p = $9,
327
+ cost_weight = $10,
328
+ latency_weight = $11,
329
+ quality_weight = $12,
330
+ analysis_method = $13,
331
+ task_type = $14,
332
+ task_analysis = $15,
333
+ system_prompt = $16,
334
+ reanalysis_period = $17,
335
+ auto_apply_recommendations = $18,
336
+ updated_at = NOW()
337
+ WHERE id = $1 RETURNING *`, [
338
+ gateId,
339
+ historyEntry.name,
340
+ historyEntry.description,
341
+ historyEntry.model,
342
+ typeof historyEntry.fallbackModels === 'string' ? historyEntry.fallbackModels : JSON.stringify(historyEntry.fallbackModels || []),
343
+ historyEntry.routingStrategy,
344
+ historyEntry.temperature,
345
+ historyEntry.maxTokens,
346
+ historyEntry.topP,
347
+ historyEntry.costWeight ?? 0.33,
348
+ historyEntry.latencyWeight ?? 0.33,
349
+ historyEntry.qualityWeight ?? 0.34,
350
+ historyEntry.analysisMethod ?? 'balanced',
351
+ historyEntry.taskType,
352
+ typeof historyEntry.taskAnalysis === 'string' ? historyEntry.taskAnalysis : (historyEntry.taskAnalysis ? JSON.stringify(historyEntry.taskAnalysis) : null),
353
+ historyEntry.systemPrompt,
354
+ historyEntry.reanalysisPeriod ?? 'never',
355
+ historyEntry.autoApplyRecommendations ?? false
356
+ ]);
357
+ const rolledBackGate = result.rows[0] ? toCamelCase(result.rows[0]) : null;
358
+ if (rolledBackGate) {
359
+ // Log the rollback activity
360
+ await this.createActivityLog(gateId, userId, 'rollback', {
361
+ historyId: historyId,
362
+ rolledBackTo: historyEntry.createdAt,
363
+ previousModel: currentGate.model,
364
+ newModel: historyEntry.model
365
+ });
366
+ }
367
+ return rolledBackGate;
368
+ },
304
369
  };
305
370
  export default getPool;
@@ -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;AAQpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AA6cpC,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;AA6fpC,eAAe,MAAM,CAAC"}
@@ -128,8 +128,6 @@ router.patch('/name/:name', async (req, res) => {
128
128
  res.status(400).json({ error: 'bad_request', message: `Unsupported model: ${model}` });
129
129
  return;
130
130
  }
131
- // Create history snapshot before update
132
- await db.createGateHistory(existing.id, existing, 'user');
133
131
  const updated = await db.updateGate(existing.id, {
134
132
  description,
135
133
  taskType,
@@ -149,6 +147,10 @@ router.patch('/name/:name', async (req, res) => {
149
147
  reanalysisPeriod,
150
148
  taskAnalysis,
151
149
  });
150
+ // Create history snapshot after update with the updated values
151
+ if (updated) {
152
+ await db.createGateHistory(existing.id, updated, 'user');
153
+ }
152
154
  // Log manual update activity
153
155
  await db.createActivityLog(existing.id, req.userId, 'manual_update', {
154
156
  changedFields: Object.keys(req.body)
@@ -182,8 +184,6 @@ router.patch('/:id', async (req, res) => {
182
184
  res.status(400).json({ error: 'bad_request', message: `Unsupported model: ${model}` });
183
185
  return;
184
186
  }
185
- // Create history snapshot before update
186
- await db.createGateHistory(req.params.id, existing, 'user');
187
187
  const updated = await db.updateGate(req.params.id, {
188
188
  name,
189
189
  description,
@@ -204,6 +204,10 @@ router.patch('/:id', async (req, res) => {
204
204
  reanalysisPeriod,
205
205
  taskAnalysis,
206
206
  });
207
+ // Create history snapshot after update with the updated values
208
+ if (updated) {
209
+ await db.createGateHistory(req.params.id, updated, 'user');
210
+ }
207
211
  // Log manual update activity
208
212
  await db.createActivityLog(req.params.id, req.userId, 'manual_update', {
209
213
  changedFields: Object.keys(req.body)
@@ -400,4 +404,39 @@ router.post('/suggestions', async (req, res) => {
400
404
  res.status(500).json({ error: 'internal_error', message: 'Failed to fetch suggestions' });
401
405
  }
402
406
  });
407
+ // POST /:id/rollback - Rollback gate to a previous configuration from history
408
+ router.post('/:id/rollback', async (req, res) => {
409
+ if (!req.userId) {
410
+ res.status(401).json({ error: 'unauthorized', message: 'Missing user ID' });
411
+ return;
412
+ }
413
+ try {
414
+ const { historyId } = req.body;
415
+ if (!historyId) {
416
+ res.status(400).json({ error: 'bad_request', message: 'Missing required field: historyId' });
417
+ return;
418
+ }
419
+ const gate = await db.getGateById(req.params.id);
420
+ if (!gate) {
421
+ res.status(404).json({ error: 'not_found', message: 'Gate not found' });
422
+ return;
423
+ }
424
+ if (gate.userId !== req.userId) {
425
+ res.status(404).json({ error: 'not_found', message: 'Gate not found' });
426
+ return;
427
+ }
428
+ // Rollback the gate to the historical configuration
429
+ const updated = await db.rollbackGate(req.params.id, historyId, req.userId);
430
+ if (!updated) {
431
+ res.status(404).json({ error: 'not_found', message: 'History entry not found' });
432
+ return;
433
+ }
434
+ await cache.invalidateGate(req.userId, gate.name);
435
+ res.json(updated);
436
+ }
437
+ catch (error) {
438
+ console.error('Rollback gate error:', error);
439
+ res.status(500).json({ error: 'internal_error', message: 'Failed to rollback gate' });
440
+ }
441
+ });
403
442
  export default router;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layer-ai/core",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
4
4
  "description": "Core API routes and services for Layer AI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",