Skip to content

Commit 9d9389b

Browse files
authored
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 <[email protected]>
1 parent 6c88811 commit 9d9389b

5 files changed

Lines changed: 118 additions & 19 deletions

File tree

extensions/fireworks/index.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,19 @@ describe("fireworks provider plugin", () => {
144144
expect(resolved?.reasoning).toBe(false);
145145
});
146146

147-
it("disables reasoning metadata for Fireworks Kimi k2.6 dynamic models", async () => {
147+
it("defers manifest catalog models to core static-catalog resolution", async () => {
148148
const provider = await registerSingleProviderPlugin(fireworksPlugin);
149-
const resolved = provider.resolveDynamicModel?.(
150-
createProviderDynamicModelContext({
151-
provider: "fireworks",
152-
modelId: "accounts/fireworks/models/kimi-k2p6",
153-
models: [createFireworksDefaultRuntimeModel({ reasoning: false })],
154-
}),
155-
);
156-
157-
expect(resolved?.provider).toBe("fireworks");
158-
expect(resolved?.id).toBe("accounts/fireworks/models/kimi-k2p6");
159-
expect(resolved?.reasoning).toBe(false);
149+
for (const modelId of [FIREWORKS_K2_6_MODEL_ID, FIREWORKS_DEFAULT_MODEL_ID]) {
150+
const resolved = provider.resolveDynamicModel?.(
151+
createProviderDynamicModelContext({
152+
provider: "fireworks",
153+
modelId,
154+
models: [createFireworksDefaultRuntimeModel({ reasoning: false })],
155+
}),
156+
);
157+
158+
expect(resolved).toBeUndefined();
159+
}
160160
});
161161

162162
it("exposes off-only thinking policy for Fireworks Kimi models", async () => {

extensions/fireworks/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ import {
1515
FIREWORKS_DEFAULT_CONTEXT_WINDOW,
1616
FIREWORKS_DEFAULT_MAX_TOKENS,
1717
FIREWORKS_DEFAULT_MODEL_ID,
18+
isFireworksCatalogModelId,
1819
} from "./provider-catalog.js";
1920
import { wrapFireworksProviderStream } from "./stream.js";
2021
import { resolveFireworksThinkingProfile } from "./thinking-policy.js";
2122

2223
const PROVIDER_ID = "fireworks";
24+
2325
function isFireworksGlmModelId(modelId: string): boolean {
2426
const normalized = modelId.trim().toLowerCase();
2527
const lastSegment = normalized.split("/").pop() ?? normalized;
@@ -35,6 +37,11 @@ function resolveFireworksDynamicModel(ctx: ProviderResolveDynamicModelContext) {
3537
if (!modelId) {
3638
return undefined;
3739
}
40+
41+
if (isFireworksCatalogModelId(modelId)) {
42+
return undefined;
43+
}
44+
3845
const isKimiModel = isFireworksKimiModelId(modelId);
3946
const input = resolveFireworksDynamicInput(modelId);
4047

extensions/fireworks/openclaw.plugin.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
{
3838
"id": "accounts/fireworks/models/kimi-k2p6",
3939
"name": "Kimi K2.6",
40+
"reasoning": false,
4041
"input": ["text", "image"],
4142
"contextWindow": 262144,
4243
"maxTokens": 262144,
@@ -50,6 +51,7 @@
5051
{
5152
"id": "accounts/fireworks/routers/kimi-k2p5-turbo",
5253
"name": "Kimi K2.5 Turbo (Fire Pass)",
54+
"reasoning": false,
5355
"input": ["text", "image"],
5456
"contextWindow": 256000,
5557
"maxTokens": 256000,

extensions/fireworks/provider-catalog.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,12 @@ export const FIREWORKS_DEFAULT_MAX_TOKENS = FIREWORKS_DEFAULT_MODEL.maxTokens;
3131
export const FIREWORKS_K2_6_CONTEXT_WINDOW = FIREWORKS_K2_6_MODEL.contextWindow;
3232
export const FIREWORKS_K2_6_MAX_TOKENS = FIREWORKS_K2_6_MODEL.maxTokens;
3333

34-
function cloneFireworksCatalogModel(model: ModelDefinitionConfig): ModelDefinitionConfig {
35-
return {
36-
...model,
37-
input: [...model.input],
38-
cost: { ...model.cost },
39-
};
34+
export function isFireworksCatalogModelId(modelId: string): boolean {
35+
return FIREWORKS_MANIFEST_PROVIDER.models.some((model) => model.id === modelId);
4036
}
4137

4238
export function buildFireworksCatalogModels(): ModelDefinitionConfig[] {
43-
return FIREWORKS_MANIFEST_PROVIDER.models.map(cloneFireworksCatalogModel);
39+
return FIREWORKS_MANIFEST_PROVIDER.models.map((model) => structuredClone(model));
4440
}
4541

4642
export function buildFireworksProvider(): ModelProviderConfig {

src/agents/embedded-agent-runner/model.test.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,100 @@ describe("resolveModel", () => {
688688
expect(discoverModels).not.toHaveBeenCalled();
689689
});
690690

691+
it("resolves a deferred Fireworks manifest id from the bundled static catalog", async () => {
692+
resolveBundledStaticCatalogModelMock.mockReturnValueOnce({
693+
provider: "fireworks",
694+
id: "accounts/fireworks/models/kimi-k2p6",
695+
name: "Kimi K2.6",
696+
api: "openai-completions",
697+
baseUrl: "https://api.fireworks.ai/inference/v1",
698+
reasoning: false,
699+
input: ["text", "image"],
700+
cost: { input: 0.95, output: 4, cacheRead: 0, cacheWrite: 0 },
701+
contextWindow: 262144,
702+
maxTokens: 262144,
703+
});
704+
705+
const result = await resolveModelAsync(
706+
"fireworks",
707+
"accounts/fireworks/models/kimi-k2p6",
708+
"/tmp/agent",
709+
undefined,
710+
{
711+
allowBundledStaticCatalogFallback: true,
712+
runtimeHooks: createRuntimeHooks(),
713+
skipAgentDiscovery: true,
714+
},
715+
);
716+
717+
expectRecordFields(expectResolvedModel(result), {
718+
provider: "fireworks",
719+
id: "accounts/fireworks/models/kimi-k2p6",
720+
api: "openai-completions",
721+
baseUrl: "https://api.fireworks.ai/inference/v1",
722+
contextWindow: 262144,
723+
maxTokens: 262144,
724+
});
725+
expect(resolveBundledStaticCatalogModelMock).toHaveBeenCalledWith(
726+
expect.objectContaining({
727+
provider: "fireworks",
728+
modelId: "accounts/fireworks/models/kimi-k2p6",
729+
}),
730+
);
731+
});
732+
733+
it("prefers user openclaw.json config over the Fireworks manifest for the same id", () => {
734+
resolveBundledStaticCatalogModelMock.mockReturnValue({
735+
...makeModel("accounts/fireworks/models/kimi-k2p6"),
736+
provider: "fireworks",
737+
name: "Kimi K2.6",
738+
api: "openai-completions",
739+
baseUrl: "https://api.fireworks.ai/inference/v1",
740+
input: ["text", "image"],
741+
contextWindow: 262_144,
742+
maxTokens: 262_144,
743+
});
744+
const cfg = {
745+
models: {
746+
providers: {
747+
fireworks: {
748+
api: "openai-completions",
749+
baseUrl: "https://api.fireworks.ai/inference/v1",
750+
models: [
751+
{
752+
...makeModel("accounts/fireworks/models/kimi-k2p6"),
753+
name: "Kimi K2.6 (user override)",
754+
contextWindow: 300_000,
755+
maxTokens: 300_000,
756+
},
757+
],
758+
},
759+
},
760+
},
761+
} as unknown as OpenClawConfig;
762+
763+
const result = resolveModelForTest(
764+
"fireworks",
765+
"accounts/fireworks/models/kimi-k2p6",
766+
"/tmp/agent",
767+
cfg,
768+
);
769+
770+
expectRecordFields(expectResolvedModel(result), {
771+
provider: "fireworks",
772+
id: "accounts/fireworks/models/kimi-k2p6",
773+
contextWindow: 300_000,
774+
maxTokens: 300_000,
775+
});
776+
expect(resolveBundledStaticCatalogModelMock).toHaveBeenCalledWith(
777+
expect.objectContaining({
778+
provider: "fireworks",
779+
modelId: "accounts/fireworks/models/kimi-k2p6",
780+
cfg,
781+
}),
782+
);
783+
});
784+
691785
it("keeps provider dynamic metadata for runtime-preferred models", async () => {
692786
resolveBundledStaticCatalogModelMock.mockReturnValueOnce({
693787
provider: "openai",

0 commit comments

Comments
 (0)