UNPKG

manifest

Version:

Self-hosted Manifest LLM router with embedded server, SQLite database, and dashboard

156 lines 7.37 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NotificationRulesService = void 0; const common_1 = require("@nestjs/common"); const typeorm_1 = require("typeorm"); const uuid_1 = require("uuid"); const sql_dialect_1 = require("../../common/utils/sql-dialect"); let NotificationRulesService = class NotificationRulesService { ds; dialect; constructor(ds) { this.ds = ds; this.dialect = (0, sql_dialect_1.detectDialect)(ds.options.type); } sql(query) { return (0, sql_dialect_1.portableSql)(query, this.dialect); } async listRules(userId, agentName) { return this.ds.query(this.sql(`SELECT nr.*, COALESCE(nl.trigger_count, 0) AS trigger_count FROM notification_rules nr LEFT JOIN ( SELECT rule_id, COUNT(*) AS trigger_count FROM notification_logs WHERE rule_id IN (SELECT id FROM notification_rules WHERE user_id = $1 AND agent_name = $2) GROUP BY rule_id ) nl ON nl.rule_id = nr.id WHERE nr.user_id = $3 AND nr.agent_name = $4 ORDER BY nr.created_at DESC`), [userId, agentName, userId, agentName]); } async createRule(userId, dto) { const agent = await this.resolveAgent(userId, dto.agent_name); const id = (0, uuid_1.v4)(); const now = new Date().toISOString().replace('T', ' ').replace('Z', '').slice(0, 19); await this.ds.query(this.sql(`INSERT INTO notification_rules (id, tenant_id, agent_id, agent_name, user_id, metric_type, threshold, period, action, is_active, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`), [ id, agent.tenant_id, agent.id, dto.agent_name, userId, dto.metric_type, dto.threshold, dto.period, dto.action ?? 'notify', this.dialect === 'sqlite' ? 1 : true, now, now, ]); const rows = await this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE id = $1`), [ id, ]); return rows[0]; } async updateRule(userId, ruleId, dto) { await this.verifyOwnership(userId, ruleId); const sets = []; const params = []; let paramIdx = 1; if (dto.metric_type !== undefined) { sets.push(`metric_type = $${paramIdx++}`); params.push(dto.metric_type); } if (dto.threshold !== undefined) { sets.push(`threshold = $${paramIdx++}`); params.push(dto.threshold); } if (dto.period !== undefined) { sets.push(`period = $${paramIdx++}`); params.push(dto.period); } if (dto.action !== undefined) { sets.push(`action = $${paramIdx++}`); params.push(dto.action); } if (dto.is_active !== undefined) { sets.push(`is_active = $${paramIdx++}`); params.push(this.dialect === 'sqlite' ? (dto.is_active ? 1 : 0) : dto.is_active); } if (sets.length === 0) return this.getRule(ruleId); const now = new Date().toISOString().replace('T', ' ').replace('Z', '').slice(0, 19); sets.push(`updated_at = $${paramIdx++}`); params.push(now); params.push(ruleId); await this.ds.query(this.sql(`UPDATE notification_rules SET ${sets.join(', ')} WHERE id = $${paramIdx}`), params); const rows = await this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE id = $1`), [ ruleId, ]); return rows[0]; } async deleteRule(userId, ruleId) { await this.verifyOwnership(userId, ruleId); await this.ds.query(this.sql(`DELETE FROM notification_rules WHERE id = $1`), [ruleId]); } async getConsumption(tenantId, agentName, metric, periodStart, periodEnd) { const expr = metric === 'tokens' ? 'COALESCE(SUM(input_tokens + output_tokens), 0)' : 'COALESCE(SUM(cost_usd), 0)'; const rows = await this.ds.query(this.sql(`SELECT ${expr} as total FROM agent_messages WHERE tenant_id = $1 AND agent_name = $2 AND timestamp >= $3 AND timestamp < $4`), [tenantId, agentName, periodStart, periodEnd]); return Number(rows[0]?.total ?? 0); } async getAllActiveRules() { return this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE is_active = $1 AND action IN ($2, $3)`), [this.dialect === 'sqlite' ? 1 : true, 'notify', 'both']); } async getActiveRulesForUser(userId) { return this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE user_id = $1 AND is_active = $2 AND action IN ($3, $4)`), [userId, this.dialect === 'sqlite' ? 1 : true, 'notify', 'both']); } async getActiveBlockRules(tenantId, agentName) { return this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE tenant_id = $1 AND agent_name = $2 AND is_active = $3 AND action IN ($4, $5)`), [tenantId, agentName, this.dialect === 'sqlite' ? 1 : true, 'block', 'both']); } async resolveAgent(userId, agentName) { const rows = await this.ds.query(this.sql(`SELECT a.id, a.tenant_id FROM agents a JOIN tenants t ON t.id = a.tenant_id WHERE t.name = $1 AND a.name = $2`), [userId, agentName]); if (!rows.length) { throw new common_1.BadRequestException(`Agent "${agentName}" not found`); } return rows[0]; } async verifyOwnership(userId, ruleId) { const rows = await this.ds.query(this.sql(`SELECT id FROM notification_rules WHERE id = $1 AND user_id = $2`), [ruleId, userId]); if (!rows.length) { throw new common_1.NotFoundException('Notification rule not found'); } } async getRule(ruleId) { const rows = await this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE id = $1`), [ ruleId, ]); return rows[0]; } async getOwnedRule(userId, ruleId) { const rows = await this.ds.query(this.sql(`SELECT * FROM notification_rules WHERE id = $1 AND user_id = $2`), [ruleId, userId]); return rows[0]; } }; exports.NotificationRulesService = NotificationRulesService; exports.NotificationRulesService = NotificationRulesService = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [typeorm_1.DataSource]) ], NotificationRulesService); //# sourceMappingURL=notification-rules.service.js.map