fix(web): 模型价格 - 合并 PR #372 并修复零积分展示
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
import { defaultConfig, type AiConfig } from "../src/stores/use-config-store";
|
||||
import { createModelChannel, defaultConfig } from "../src/stores/use-config-store";
|
||||
import { runBackendGenerationTask, runBackendGenerationTaskBatch } from "../src/services/api/generation-task";
|
||||
import { deleteGenerationTask, formatTaskLog, listGenerationTasks, projectBackendSafeTaskLog, splitGenerationTaskObservationIds, type GenerationTask } from "../src/services/api/task-center";
|
||||
import { isLocalDreaminaBackgroundTask, localDreaminaCancellationCopy, localDreaminaDetachOutcome, projectLocalDreaminaTask } from "../src/services/local-dreamina-task-projection";
|
||||
@@ -24,24 +24,25 @@ function sourceSection(source: string, startMarker: string, endMarker: string) {
|
||||
return compactSource(source.slice(start, end));
|
||||
}
|
||||
|
||||
function remoteBackendConfig(model: string, overrides: Partial<AiConfig> = {}): AiConfig {
|
||||
const modelName = model.includes("::") ? model.slice(model.indexOf("::") + 2) : model;
|
||||
function backendModelConfig(model: string) {
|
||||
const channel = createModelChannel({
|
||||
id: "system-test-channel",
|
||||
name: "系统测试渠道",
|
||||
baseUrl: "/api/system-test-channel",
|
||||
apiKey: "system",
|
||||
apiFormat: "openai",
|
||||
scope: "system",
|
||||
models: [model],
|
||||
});
|
||||
const selectedModel = `${channel.id}::${model}`;
|
||||
return {
|
||||
...defaultConfig,
|
||||
...overrides,
|
||||
model,
|
||||
channels: [
|
||||
{
|
||||
id: "default",
|
||||
name: "Backend test channel",
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "test-key",
|
||||
apiFormat: "openai",
|
||||
interfaceType: "newapi-channel-2",
|
||||
models: [modelName],
|
||||
scope: "user",
|
||||
},
|
||||
],
|
||||
channelMode: "remote" as const,
|
||||
channels: [channel],
|
||||
model: selectedModel,
|
||||
imageModel: selectedModel,
|
||||
videoModel: selectedModel,
|
||||
audioModel: selectedModel,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1307,7 +1308,7 @@ test("remote provider keeps Create resolution semantics and still creates one Ba
|
||||
{
|
||||
mode: "video",
|
||||
prompt: "A remote test clip",
|
||||
config: remoteBackendConfig("default::grok-imagine-video", { vquality: "720", quality: "auto" }),
|
||||
config: { ...backendModelConfig("grok-imagine-video"), vquality: "720", quality: "auto" },
|
||||
},
|
||||
{
|
||||
createTask: async (input) => {
|
||||
@@ -1375,7 +1376,7 @@ test("remote image video and audio references keep Backend parity without Dreami
|
||||
{
|
||||
mode: item.mode,
|
||||
prompt: "Remote parity fixture",
|
||||
config: remoteBackendConfig("default::provider-neutral-model"),
|
||||
config: backendModelConfig("provider-neutral-model"),
|
||||
...item.references,
|
||||
},
|
||||
{
|
||||
@@ -1694,7 +1695,7 @@ test("Create audio upload converts, previews, removes, and submits through the s
|
||||
projectId: running.projectId,
|
||||
mode: "video",
|
||||
prompt: running.prompt,
|
||||
config: remoteBackendConfig("remote-video-audio-fixture", { videoModel: "remote-video-audio-fixture" }),
|
||||
config: backendModelConfig("remote-video-audio-fixture"),
|
||||
...references,
|
||||
} as Parameters<typeof runBackendGenerationTask>[0],
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
import { modelQuoteRequest, normalizeTierResolution, priceTiersForCurrentSelection, requestCreditCost } from "../src/lib/model-pricing";
|
||||
import { modelQuoteRequest, normalizeTierResolution, priceTierSummaryLabel, priceTiersForCurrentSelection, requestCreditCost } from "../src/lib/model-pricing";
|
||||
import type { ModelRequirements } from "../src/lib/model-selection";
|
||||
import { createModelChannel, defaultConfig, normalizeConfigSnapshot, resolveModelChannel, type AiConfig } from "../src/stores/use-config-store";
|
||||
|
||||
@@ -86,6 +86,19 @@ describe("model request pricing", () => {
|
||||
).toBe(0.125);
|
||||
});
|
||||
|
||||
test("displays zero-price system tiers as configured free pricing", () => {
|
||||
const fixedConfig = systemConfig({
|
||||
capability: "image",
|
||||
tiers: [{ selector: {}, billingMode: "fixed_request", unitPriceMicrocredits: 0 }],
|
||||
});
|
||||
const perSecondConfig = systemConfig({
|
||||
tiers: [{ selector: {}, billingMode: "per_second", unitPriceMicrocredits: 0 }],
|
||||
});
|
||||
|
||||
expect(priceTierSummaryLabel(resolveModelChannel(fixedConfig, fixedConfig.model).modelCosts![0]!.logicalPriceTiers!)).toBe("0 积分");
|
||||
expect(priceTierSummaryLabel(resolveModelChannel(perSecondConfig, perSecondConfig.model).modelCosts![0]!.logicalPriceTiers!)).toBe("0 积分/秒");
|
||||
});
|
||||
|
||||
test("uses reference count and operation to avoid a text-video price tier", () => {
|
||||
const config = systemConfig({
|
||||
tiers: [
|
||||
|
||||
Reference in New Issue
Block a user