Laimiao agent v2 service: agent orchestration, sessions, billing, gateway client, skills catalog, auth, config, plus tests.
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { PricingError, quoteSkill, repriceForQuantity } from "../src/billing/pricing.js";
|
|
import type { SkillDefinition } from "../src/types.js";
|
|
|
|
const skill: SkillDefinition = {
|
|
key: "demo",
|
|
name: "demo",
|
|
displayName: "Demo Skill",
|
|
description: "demo",
|
|
content: "# demo",
|
|
triggerKeywords: "demo",
|
|
usesDefaults: false,
|
|
manifest: {
|
|
key: "demo",
|
|
version: "1.0.0",
|
|
industry: "test",
|
|
model: "seedream@5.0",
|
|
defaults: { size: "1024x1536", n: 1 },
|
|
price: { currency: "credits", per_image: 30, size_multipliers: { "2048x3072": 2 } },
|
|
capabilities: [],
|
|
tags: [],
|
|
max_images: 4,
|
|
enabled: true,
|
|
},
|
|
};
|
|
|
|
describe("pricing", () => {
|
|
it("quotes one image using defaults", () => {
|
|
expect(quoteSkill(skill, { size: "1024x1536", quantity: 1 }, {}, "dry_run")).toEqual({
|
|
skill_id: "demo",
|
|
skill_name: "Demo Skill",
|
|
model: "seedream@5.0",
|
|
size: "1024x1536",
|
|
quantity: 1,
|
|
unit_credits: 30,
|
|
size_multiplier: 1,
|
|
total_credits: 30,
|
|
currency: "credits",
|
|
billing_mode: "dry_run",
|
|
});
|
|
});
|
|
|
|
it("applies size multipliers and quantity", () => {
|
|
const quote = quoteSkill(
|
|
skill,
|
|
{ size: "1024x1536", quantity: 1 },
|
|
{ size: "2048x3072", quantity: 3 },
|
|
"off",
|
|
);
|
|
expect(quote.size_multiplier).toBe(2);
|
|
expect(quote.total_credits).toBe(180);
|
|
expect(quote.billing_mode).toBe("off");
|
|
});
|
|
|
|
it("rejects over-limit, non-integer, and malformed sizes", () => {
|
|
expect(() => quoteSkill(skill, { size: "1024x1536", quantity: 1 }, { quantity: 5 }, "dry_run")).toThrow(
|
|
PricingError,
|
|
);
|
|
expect(() => quoteSkill(skill, { size: "1024x1536", quantity: 1 }, { quantity: 1.5 }, "dry_run")).toThrow(
|
|
/integer/,
|
|
);
|
|
expect(() => quoteSkill(skill, { size: "1024x1536", quantity: 1 }, { size: "large" }, "dry_run")).toThrow(
|
|
/size/,
|
|
);
|
|
});
|
|
|
|
it("reprices to the actually returned image count", () => {
|
|
const quote = quoteSkill(skill, { size: "1024x1536", quantity: 1 }, { quantity: 3 }, "dry_run");
|
|
const repriced = repriceForQuantity(quote, 1);
|
|
expect(repriced.quantity).toBe(1);
|
|
expect(repriced.total_credits).toBe(30);
|
|
expect(() => repriceForQuantity(quote, -1)).toThrow(PricingError);
|
|
});
|
|
});
|