import { test } from "node:test"; import assert from "node:assert/strict"; import type { ApiKeyEntry, UsageResponse } from "../src/client.js"; import { FAILED_NOTE, summarizeUsage, usageWindow } from "../src/tools/billing.js"; import { KEYS_TOOL_DESCRIPTION, presentKeys } from "../src/tools/keys.js"; import { fixture } from "./helpers.js"; test("usageWindow: to = сейчас, from = сейчас − days, без миллисекунд", () => { const w = usageWindow(7, new Date("2026-10-24T03:39:57.123Z")); assert.deepEqual(w, { from: "2026-10-17T03:39:57Z", to: "2026-10-24T03:39:57Z" }); }); test("summarizeUsage: total по всем строкам до обрезки, decimal-сложение", () => { const resp = fixture("api-usage"); const s = summarizeUsage(resp, 2); // 0.8124417 + 0.18412076 + 0.24310558 + 0.05120934 + 0.00371284 = 1.29459022 assert.equal(s.total_rub, "1.29459022"); assert.equal((s.items as unknown[]).length, 2); assert.equal(s.truncated, true); assert.equal(s.failed_note, null); const failed = summarizeUsage({ ...resp, failed_events: 3 }, 50); assert.equal(failed.failed_note, FAILED_NOTE); assert.equal(failed.truncated, false); }); test("presentKeys: ключ не выводится, текущий отмечен по префиксу, отозванные скрыты", () => { const { keys } = fixture<{ keys: ApiKeyEntry[] }>("api-keys"); const current = "orr_live_Gh5iJkSECRETSECRETSECRETSECRET1"; const withRevoked = [...keys, { ...(keys[0] as ApiKeyEntry), id: "rev", revoked_at: "2026-10-01T00:00:00Z" }]; const out = presentKeys(withRevoked, current, false); assert.equal(out.length, 3); assert.deepEqual(out.map((k) => k.is_current_key), [false, true, false]); assert.ok(!JSON.stringify(out).includes(current)); assert.equal(out[0]?.all_models_allowed, true); assert.equal(out[0]?.allowed_models, null); assert.deepEqual(out[1]?.allowed_models, ["openai/gpt-4o-mini"]); assert.equal(out[1]?.all_models_allowed, false); assert.equal(out[0]?.spend_used_rub, "12.5784961"); assert.equal(out[0]?.key_prefix, "orr_live_Ab3dEf"); assert.equal(presentKeys(withRevoked, current, true).length, 4); }); test("описание list_api_keys дословно говорит о запрете управления ключами", () => { assert.ok( KEYS_TOOL_DESCRIPTION.includes( "Создать, отозвать или изменить ключ через MCP нельзя — такие действия требуют браузерной сессии на openrusrouter.ru. " + "Это сознательное ограничение безопасности: ключ, которым пользуется MCP, не должен уметь управлять другими ключами или собой", ), ); });