manifest
Version:
Self-hosted Manifest LLM router with embedded server, SQLite database, and dashboard
125 lines • 6.64 kB
JavaScript
;
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);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentAnalyticsService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const agent_message_entity_1 = require("../../entities/agent-message.entity");
const range_util_1 = require("../../common/utils/range.util");
const query_helpers_1 = require("./query-helpers");
const sql_dialect_1 = require("../../common/utils/sql-dialect");
let AgentAnalyticsService = class AgentAnalyticsService {
turnRepo;
constructor(turnRepo) {
this.turnRepo = turnRepo;
}
async getUsage(range, scope) {
const interval = (0, range_util_1.rangeToInterval)(range);
const prevInterval = (0, range_util_1.rangeToPreviousInterval)(range);
const cutoff = (0, sql_dialect_1.computeCutoff)(interval);
const prevCutoff = (0, sql_dialect_1.computeCutoff)(prevInterval);
const [currentRows, prevRows] = await Promise.all([
this.turnRepo
.createQueryBuilder('at')
.select('COALESCE(SUM(at.input_tokens), 0)', 'input')
.addSelect('COALESCE(SUM(at.output_tokens), 0)', 'output')
.addSelect('COALESCE(SUM(at.cache_read_tokens), 0)', 'cache_read')
.addSelect('COUNT(*)', 'messages')
.where('at.timestamp >= :cutoff', { cutoff })
.andWhere('at.tenant_id = :tenantId', { tenantId: scope.tenantId })
.andWhere('at.agent_id = :agentId', { agentId: scope.agentId })
.getRawOne(),
this.turnRepo
.createQueryBuilder('at')
.select('COALESCE(SUM(at.input_tokens + at.output_tokens), 0)', 'total')
.where('at.timestamp >= :prevCutoff', { prevCutoff })
.andWhere('at.timestamp < :cutoff', { cutoff })
.andWhere('at.tenant_id = :tenantId', { tenantId: scope.tenantId })
.andWhere('at.agent_id = :agentId', { agentId: scope.agentId })
.getRawOne(),
]);
const input = Number(currentRows?.input ?? 0);
const output = Number(currentRows?.output ?? 0);
const cacheRead = Number(currentRows?.cache_read ?? 0);
const messages = Number(currentRows?.messages ?? 0);
const currentTotal = input + output;
const previousTotal = Number(prevRows?.total ?? 0);
return {
range,
total_tokens: currentTotal,
input_tokens: input,
output_tokens: output,
cache_read_tokens: cacheRead,
message_count: messages,
trend_pct: (0, query_helpers_1.computeTrend)(currentTotal, previousTotal),
};
}
async getCosts(range, scope) {
const interval = (0, range_util_1.rangeToInterval)(range);
const prevInterval = (0, range_util_1.rangeToPreviousInterval)(range);
const cutoff = (0, sql_dialect_1.computeCutoff)(interval);
const prevCutoff = (0, sql_dialect_1.computeCutoff)(prevInterval);
const [currentRows, prevRows, modelRows] = await Promise.all([
this.turnRepo
.createQueryBuilder('at')
.select('COALESCE(SUM(at.cost_usd), 0)', 'total')
.where('at.timestamp >= :cutoff', { cutoff })
.andWhere('at.tenant_id = :tenantId', { tenantId: scope.tenantId })
.andWhere('at.agent_id = :agentId', { agentId: scope.agentId })
.getRawOne(),
this.turnRepo
.createQueryBuilder('at')
.select('COALESCE(SUM(at.cost_usd), 0)', 'total')
.where('at.timestamp >= :prevCutoff', { prevCutoff })
.andWhere('at.timestamp < :cutoff', { cutoff })
.andWhere('at.tenant_id = :tenantId', { tenantId: scope.tenantId })
.andWhere('at.agent_id = :agentId', { agentId: scope.agentId })
.getRawOne(),
this.turnRepo
.createQueryBuilder('at')
.select('at.model', 'model')
.addSelect('COALESCE(SUM(at.cost_usd), 0)', 'cost_usd')
.addSelect('COALESCE(SUM(at.input_tokens), 0)', 'input_tokens')
.addSelect('COALESCE(SUM(at.output_tokens), 0)', 'output_tokens')
.where('at.timestamp >= :cutoff', { cutoff })
.andWhere('at.tenant_id = :tenantId', { tenantId: scope.tenantId })
.andWhere('at.agent_id = :agentId', { agentId: scope.agentId })
.andWhere('at.model IS NOT NULL')
.groupBy('at.model')
.orderBy('cost_usd', 'DESC')
.getRawMany(),
]);
const currentCost = Number(currentRows?.total ?? 0);
const previousCost = Number(prevRows?.total ?? 0);
return {
range,
total_cost_usd: currentCost,
trend_pct: (0, query_helpers_1.computeTrend)(currentCost, previousCost),
by_model: modelRows.map((r) => ({
model: String(r['model']),
cost_usd: Number(r['cost_usd']),
input_tokens: Number(r['input_tokens']),
output_tokens: Number(r['output_tokens']),
})),
};
}
};
exports.AgentAnalyticsService = AgentAnalyticsService;
exports.AgentAnalyticsService = AgentAnalyticsService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(agent_message_entity_1.AgentMessage)),
__metadata("design:paramtypes", [typeorm_2.Repository])
], AgentAnalyticsService);
//# sourceMappingURL=agent-analytics.service.js.map