mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-09 03:22:40 +00:00
fix(fireworks): resolve catalog model params from manifest (#90326)
Resolve bundled Fireworks manifest models through core's static catalog so Kimi K2.6 keeps its 262,144-token context limit and nested model compatibility metadata. Keep the existing dynamic fallback for uncataloged Fireworks IDs and align bundled Kimi reasoning metadata with existing runtime behavior. Verified with focused tests, extension/core type checks, lint/format, full build, fresh autoreview, required CI, and a live Fireworks Kimi K2.6 embedded run using a real key. Co-authored-by: Evgeni Obuchowski <evgeni@obukhovski.com>
This commit is contained in:
committed by
GitHub
parent
6c88811b4b
commit
9d9389bc6b
@@ -144,19 +144,19 @@ describe("fireworks provider plugin", () => {
|
||||
expect(resolved?.reasoning).toBe(false);
|
||||
});
|
||||
|
||||
it("disables reasoning metadata for Fireworks Kimi k2.6 dynamic models", async () => {
|
||||
it("defers manifest catalog models to core static-catalog resolution", async () => {
|
||||
const provider = await registerSingleProviderPlugin(fireworksPlugin);
|
||||
const resolved = provider.resolveDynamicModel?.(
|
||||
createProviderDynamicModelContext({
|
||||
provider: "fireworks",
|
||||
modelId: "accounts/fireworks/models/kimi-k2p6",
|
||||
models: [createFireworksDefaultRuntimeModel({ reasoning: false })],
|
||||
}),
|
||||
);
|
||||
for (const modelId of [FIREWORKS_K2_6_MODEL_ID, FIREWORKS_DEFAULT_MODEL_ID]) {
|
||||
const resolved = provider.resolveDynamicModel?.(
|
||||
createProviderDynamicModelContext({
|
||||
provider: "fireworks",
|
||||
modelId,
|
||||
models: [createFireworksDefaultRuntimeModel({ reasoning: false })],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(resolved?.provider).toBe("fireworks");
|
||||
expect(resolved?.id).toBe("accounts/fireworks/models/kimi-k2p6");
|
||||
expect(resolved?.reasoning).toBe(false);
|
||||
expect(resolved).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it("exposes off-only thinking policy for Fireworks Kimi models", async () => {
|
||||
|
||||
@@ -15,11 +15,13 @@ import {
|
||||
FIREWORKS_DEFAULT_CONTEXT_WINDOW,
|
||||
FIREWORKS_DEFAULT_MAX_TOKENS,
|
||||
FIREWORKS_DEFAULT_MODEL_ID,
|
||||
isFireworksCatalogModelId,
|
||||
} from "./provider-catalog.js";
|
||||
import { wrapFireworksProviderStream } from "./stream.js";
|
||||
import { resolveFireworksThinkingProfile } from "./thinking-policy.js";
|
||||
|
||||
const PROVIDER_ID = "fireworks";
|
||||
|
||||
function isFireworksGlmModelId(modelId: string): boolean {
|
||||
const normalized = modelId.trim().toLowerCase();
|
||||
const lastSegment = normalized.split("/").pop() ?? normalized;
|
||||
@@ -35,6 +37,11 @@ function resolveFireworksDynamicModel(ctx: ProviderResolveDynamicModelContext) {
|
||||
if (!modelId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isFireworksCatalogModelId(modelId)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const isKimiModel = isFireworksKimiModelId(modelId);
|
||||
const input = resolveFireworksDynamicInput(modelId);
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
{
|
||||
"id": "accounts/fireworks/models/kimi-k2p6",
|
||||
"name": "Kimi K2.6",
|
||||
"reasoning": false,
|
||||
"input": ["text", "image"],
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 262144,
|
||||
@@ -50,6 +51,7 @@
|
||||
{
|
||||
"id": "accounts/fireworks/routers/kimi-k2p5-turbo",
|
||||
"name": "Kimi K2.5 Turbo (Fire Pass)",
|
||||
"reasoning": false,
|
||||
"input": ["text", "image"],
|
||||
"contextWindow": 256000,
|
||||
"maxTokens": 256000,
|
||||
|
||||
@@ -31,16 +31,12 @@ export const FIREWORKS_DEFAULT_MAX_TOKENS = FIREWORKS_DEFAULT_MODEL.maxTokens;
|
||||
export const FIREWORKS_K2_6_CONTEXT_WINDOW = FIREWORKS_K2_6_MODEL.contextWindow;
|
||||
export const FIREWORKS_K2_6_MAX_TOKENS = FIREWORKS_K2_6_MODEL.maxTokens;
|
||||
|
||||
function cloneFireworksCatalogModel(model: ModelDefinitionConfig): ModelDefinitionConfig {
|
||||
return {
|
||||
...model,
|
||||
input: [...model.input],
|
||||
cost: { ...model.cost },
|
||||
};
|
||||
export function isFireworksCatalogModelId(modelId: string): boolean {
|
||||
return FIREWORKS_MANIFEST_PROVIDER.models.some((model) => model.id === modelId);
|
||||
}
|
||||
|
||||
export function buildFireworksCatalogModels(): ModelDefinitionConfig[] {
|
||||
return FIREWORKS_MANIFEST_PROVIDER.models.map(cloneFireworksCatalogModel);
|
||||
return FIREWORKS_MANIFEST_PROVIDER.models.map((model) => structuredClone(model));
|
||||
}
|
||||
|
||||
export function buildFireworksProvider(): ModelProviderConfig {
|
||||
|
||||
@@ -688,6 +688,100 @@ describe("resolveModel", () => {
|
||||
expect(discoverModels).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("resolves a deferred Fireworks manifest id from the bundled static catalog", async () => {
|
||||
resolveBundledStaticCatalogModelMock.mockReturnValueOnce({
|
||||
provider: "fireworks",
|
||||
id: "accounts/fireworks/models/kimi-k2p6",
|
||||
name: "Kimi K2.6",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.fireworks.ai/inference/v1",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.95, output: 4, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
});
|
||||
|
||||
const result = await resolveModelAsync(
|
||||
"fireworks",
|
||||
"accounts/fireworks/models/kimi-k2p6",
|
||||
"/tmp/agent",
|
||||
undefined,
|
||||
{
|
||||
allowBundledStaticCatalogFallback: true,
|
||||
runtimeHooks: createRuntimeHooks(),
|
||||
skipAgentDiscovery: true,
|
||||
},
|
||||
);
|
||||
|
||||
expectRecordFields(expectResolvedModel(result), {
|
||||
provider: "fireworks",
|
||||
id: "accounts/fireworks/models/kimi-k2p6",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.fireworks.ai/inference/v1",
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
});
|
||||
expect(resolveBundledStaticCatalogModelMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "fireworks",
|
||||
modelId: "accounts/fireworks/models/kimi-k2p6",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("prefers user openclaw.json config over the Fireworks manifest for the same id", () => {
|
||||
resolveBundledStaticCatalogModelMock.mockReturnValue({
|
||||
...makeModel("accounts/fireworks/models/kimi-k2p6"),
|
||||
provider: "fireworks",
|
||||
name: "Kimi K2.6",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.fireworks.ai/inference/v1",
|
||||
input: ["text", "image"],
|
||||
contextWindow: 262_144,
|
||||
maxTokens: 262_144,
|
||||
});
|
||||
const cfg = {
|
||||
models: {
|
||||
providers: {
|
||||
fireworks: {
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.fireworks.ai/inference/v1",
|
||||
models: [
|
||||
{
|
||||
...makeModel("accounts/fireworks/models/kimi-k2p6"),
|
||||
name: "Kimi K2.6 (user override)",
|
||||
contextWindow: 300_000,
|
||||
maxTokens: 300_000,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as OpenClawConfig;
|
||||
|
||||
const result = resolveModelForTest(
|
||||
"fireworks",
|
||||
"accounts/fireworks/models/kimi-k2p6",
|
||||
"/tmp/agent",
|
||||
cfg,
|
||||
);
|
||||
|
||||
expectRecordFields(expectResolvedModel(result), {
|
||||
provider: "fireworks",
|
||||
id: "accounts/fireworks/models/kimi-k2p6",
|
||||
contextWindow: 300_000,
|
||||
maxTokens: 300_000,
|
||||
});
|
||||
expect(resolveBundledStaticCatalogModelMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "fireworks",
|
||||
modelId: "accounts/fireworks/models/kimi-k2p6",
|
||||
cfg,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps provider dynamic metadata for runtime-preferred models", async () => {
|
||||
resolveBundledStaticCatalogModelMock.mockReturnValueOnce({
|
||||
provider: "openai",
|
||||
|
||||
Reference in New Issue
Block a user