mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 03:15:46 -06:00
efe5d8d76e
* longcat: align baseUrl with docs, fix cacheWrite pricing, add brand icon - Point baseUrl at the documented https://api.longcat.chat/openai/v1 path instead of the undocumented unversioned alias route. - Fix cacheWrite pricing to 0: the LongCat pricing page has no separate cache-write charge (matches deepseek/moonshot/zai catalog conventions). - Update the pricing page link to the current docs path. - Add the official LongCat brand icon (provenance recorded in ATTRIBUTION.md) and display-name mapping so the Control UI shows proper branding instead of the letter-badge fallback. - Migrate the persisted legacy default baseUrl via a plugin-owned doctor configRepair contract: onboarding persists models.providers.longcat.baseUrl and the runtime reads the stored value, so the contract rewrites exactly the former default to /openai/v1, preserves custom endpoints, and warns via a legacy-config rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(longcat): correct provider metadata * fix(longcat): migrate persisted stock pricing * style(longcat): format doctor repair * fix(longcat): preserve doctor migration after compat cleanup * fix(longcat): avoid map spread in doctor repair --------- Co-authored-by: yuzehui02 <yuzehui02@meituan.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
// LongCat doctor contract repairs the historical stock model price persisted
|
|
// by onboarding. Match the complete stock row so operator-customized models
|
|
// and prices are never rewritten when the vendor catalog changes.
|
|
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
|
import { asObjectRecord } from "openclaw/plugin-sdk/runtime-doctor-migrations";
|
|
|
|
const MODELS_PATH = ["models", "providers", "longcat", "models"];
|
|
const LEGACY_CACHE_WRITE_PRICE = 0.75;
|
|
|
|
function isStringArray(value: unknown, expected: readonly string[]): boolean {
|
|
return (
|
|
Array.isArray(value) &&
|
|
value.length === expected.length &&
|
|
value.every((entry, index) => entry === expected[index])
|
|
);
|
|
}
|
|
|
|
function isLegacyStockLongCatModel(value: unknown): boolean {
|
|
const model = asObjectRecord(value);
|
|
const cost = asObjectRecord(model?.cost);
|
|
const compatValue = model?.compat;
|
|
const compat = asObjectRecord(compatValue);
|
|
// Core Doctor removes catalog-owned compat fields before plugin repairs run.
|
|
// Accept that normalized shape, but preserve rows with any divergent compat override.
|
|
const hasHistoricalCompat =
|
|
compatValue === undefined ||
|
|
Boolean(
|
|
compat &&
|
|
compat.supportsStore === false &&
|
|
compat.supportsDeveloperRole === false &&
|
|
compat.supportsReasoningEffort === false &&
|
|
compat.supportsUsageInStreaming === false &&
|
|
compat.supportsStrictMode === false &&
|
|
compat.maxTokensField === "max_tokens" &&
|
|
compat.requiresReasoningContentOnAssistantMessages === true &&
|
|
compat.thinkingFormat === "deepseek" &&
|
|
Object.keys(compat).length === 8,
|
|
);
|
|
return Boolean(
|
|
model &&
|
|
model.id === "LongCat-2.0" &&
|
|
model.name === "LongCat 2.0" &&
|
|
model.reasoning === true &&
|
|
isStringArray(model.input, ["text"]) &&
|
|
model.contextWindow === 1_048_576 &&
|
|
model.maxTokens === 131_072 &&
|
|
cost?.input === 0.75 &&
|
|
cost.output === 2.95 &&
|
|
cost.cacheRead === 0.015 &&
|
|
cost.cacheWrite === LEGACY_CACHE_WRITE_PRICE &&
|
|
hasHistoricalCompat,
|
|
);
|
|
}
|
|
|
|
function hasLegacyStockLongCatModel(value: unknown): boolean {
|
|
return Array.isArray(value) && value.some(isLegacyStockLongCatModel);
|
|
}
|
|
|
|
export const legacyConfigRules = [
|
|
{
|
|
path: MODELS_PATH,
|
|
message:
|
|
'models.providers.longcat.models contains the historical stock LongCat-2.0 cache-write price; run "openclaw doctor --fix" to update it without changing customized rows.',
|
|
match: hasLegacyStockLongCatModel,
|
|
},
|
|
];
|
|
|
|
export function normalizeCompatibilityConfig({ cfg }: { cfg: OpenClawConfig }): {
|
|
config: OpenClawConfig;
|
|
changes: string[];
|
|
} {
|
|
const models = asObjectRecord(cfg.models);
|
|
const providers = asObjectRecord(models?.providers);
|
|
const provider = asObjectRecord(providers?.longcat);
|
|
const configuredModels = provider?.models;
|
|
if (!hasLegacyStockLongCatModel(configuredModels) || !Array.isArray(configuredModels)) {
|
|
return { config: cfg, changes: [] };
|
|
}
|
|
|
|
const nextModels = configuredModels.map((model) => {
|
|
if (!isLegacyStockLongCatModel(model)) {
|
|
return model;
|
|
}
|
|
const row = asObjectRecord(model) ?? {};
|
|
const cost = asObjectRecord(row.cost) ?? {};
|
|
return Object.assign({}, row, {
|
|
cost: Object.assign({}, cost, { cacheWrite: 0 }),
|
|
});
|
|
});
|
|
|
|
return {
|
|
config: {
|
|
...cfg,
|
|
models: {
|
|
...models,
|
|
providers: {
|
|
...providers,
|
|
longcat: { ...provider, models: nextModels },
|
|
},
|
|
} as unknown as OpenClawConfig["models"],
|
|
},
|
|
changes: ["Updated the historical stock LongCat-2.0 cache-write price from $0.75 to $0."],
|
|
};
|
|
}
|