Skip to content

Commit 583ca34

Browse files
lit26Tianning Listeipete
authored
feat(stepfun): add step-3.7-flash model (#88082)
* feat(stepfun): add step-3.7-flash model and make it default * fix(stepfun): set step-3.7-flash cacheRead cost to 0.04 * fix(stepfun): raise step-3.7-flash maxTokens to context limit Output was artificially capped at 65536; StepFun docs set max_tokens default to INF, bounded only by the 256K context window. Raise step-3.7-flash maxTokens to 262144 on both stepfun and stepfun-plan, matching contextWindow. Per models.dev anomalyco/models.dev#1903. step-3.5-flash entries unchanged. * fix(stepfun): zero step-plan step-3.7-flash cost for plan billing Step Plan endpoint bills per subscription plan, not per token, matching the sibling stepfun-plan/step-3.5-flash and step-3.5-flash-2603 entries which already carry zero cost. Standard stepfun/step-3.7-flash keeps its per-token rate. Per models.dev anomalyco/models.dev#1903, whose step-plan providers omit cost entirely. * docs(changelog): note StepFun 3.7 support * style(stepfun): format provider table * fix(stepfun): forward reasoning effort * fix(stepfun): scope reasoning compat to 3.7 * test(stepfun): keep 3.5 reasoning compat unchanged * fix(stepfun): carry off fallback through agent turns * fix(stepfun): use documented token limit field * fix(stepfun): match chat completions contract * chore(stepfun): keep changelog release-owned --------- Co-authored-by: Tianning Li <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
1 parent 240ca9d commit 583ca34

4 files changed

Lines changed: 248 additions & 10 deletions

File tree

docs/providers/stepfun.md

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,18 @@ Auth env var: `STEPFUN_API_KEY`
3535

3636
Standard (`stepfun`):
3737

38-
| Model ref | Context | Max output | Notes |
39-
| ------------------------ | ------- | ---------- | ---------------------- |
40-
| `stepfun/step-3.5-flash` | 262,144 | 65,536 | Default standard model |
38+
| Model ref | Context | Max output | Notes |
39+
| ------------------------ | ------- | ---------- | ------------------------------ |
40+
| `stepfun/step-3.5-flash` | 262,144 | 65,536 | Default standard model |
41+
| `stepfun/step-3.7-flash` | 262,144 | 262,144 | Multimodal image input support |
4142

4243
Step Plan (`stepfun-plan`):
4344

44-
| Model ref | Context | Max output | Notes |
45-
| ---------------------------------- | ------- | ---------- | -------------------------- |
46-
| `stepfun-plan/step-3.5-flash` | 262,144 | 65,536 | Default Step Plan model |
47-
| `stepfun-plan/step-3.5-flash-2603` | 262,144 | 65,536 | Additional Step Plan model |
45+
| Model ref | Context | Max output | Notes |
46+
| ---------------------------------- | ------- | ---------- | ------------------------------ |
47+
| `stepfun-plan/step-3.5-flash` | 262,144 | 65,536 | Default Step Plan model |
48+
| `stepfun-plan/step-3.7-flash` | 262,144 | 262,144 | Multimodal image input support |
49+
| `stepfun-plan/step-3.5-flash-2603` | 262,144 | 65,536 | Additional Step Plan model |
4850

4951
## Getting started
5052

@@ -84,6 +86,7 @@ Step Plan (`stepfun-plan`):
8486
</Steps>
8587

8688
Default model: `stepfun/step-3.5-flash`
89+
Alternate model: `stepfun/step-3.7-flash`
8790

8891
</Tab>
8992

@@ -122,7 +125,7 @@ Step Plan (`stepfun-plan`):
122125
</Steps>
123126

124127
Default model: `stepfun-plan/step-3.5-flash`
125-
Alternate model: `stepfun-plan/step-3.5-flash-2603`
128+
Alternate models: `stepfun-plan/step-3.7-flash`, `stepfun-plan/step-3.5-flash-2603`
126129

127130
</Tab>
128131
</Tabs>
@@ -145,6 +148,36 @@ A single auth flow writes region-matched profiles for both `stepfun` and `stepfu
145148
api: "openai-completions",
146149
apiKey: "${STEPFUN_API_KEY}",
147150
models: [
151+
{
152+
id: "step-3.7-flash",
153+
name: "Step 3.7 Flash",
154+
reasoning: true,
155+
input: ["text", "image"],
156+
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
157+
cost: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 },
158+
contextWindow: 262144,
159+
maxTokens: 262144,
160+
compat: {
161+
supportsStore: false,
162+
supportsDeveloperRole: false,
163+
supportsUsageInStreaming: false,
164+
supportsReasoningEffort: true,
165+
supportsStrictMode: false,
166+
supportedReasoningEfforts: ["low", "medium", "high"],
167+
maxTokensField: "max_tokens",
168+
reasoningEffortMap: {
169+
off: "low",
170+
none: "low",
171+
minimal: "low",
172+
low: "low",
173+
medium: "medium",
174+
high: "high",
175+
xhigh: "high",
176+
adaptive: "high",
177+
max: "high",
178+
},
179+
},
180+
},
148181
{
149182
id: "step-3.5-flash",
150183
name: "Step 3.5 Flash",
@@ -175,6 +208,36 @@ A single auth flow writes region-matched profiles for both `stepfun` and `stepfu
175208
api: "openai-completions",
176209
apiKey: "${STEPFUN_API_KEY}",
177210
models: [
211+
{
212+
id: "step-3.7-flash",
213+
name: "Step 3.7 Flash",
214+
reasoning: true,
215+
input: ["text", "image"],
216+
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
217+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
218+
contextWindow: 262144,
219+
maxTokens: 262144,
220+
compat: {
221+
supportsStore: false,
222+
supportsDeveloperRole: false,
223+
supportsUsageInStreaming: false,
224+
supportsReasoningEffort: true,
225+
supportsStrictMode: false,
226+
supportedReasoningEfforts: ["low", "medium", "high"],
227+
maxTokensField: "max_tokens",
228+
reasoningEffortMap: {
229+
off: "low",
230+
none: "low",
231+
minimal: "low",
232+
low: "low",
233+
medium: "medium",
234+
high: "high",
235+
xhigh: "high",
236+
adaptive: "high",
237+
max: "high",
238+
},
239+
},
240+
},
178241
{
179242
id: "step-3.5-flash",
180243
name: "Step 3.5 Flash",
@@ -202,6 +265,8 @@ A single auth flow writes region-matched profiles for both `stepfun` and `stepfu
202265
</Accordion>
203266

204267
<Accordion title="Notes">
268+
- `step-3.7-flash` accepts text and image input through OpenClaw. StepFun's API also supports video, which is not yet a model input modality in OpenClaw.
269+
- Step 3.7 supports `low`, `medium`, and `high` reasoning effort. Because the model has no non-reasoning mode, `/think off` maps to `low`.
205270
- `step-3.5-flash-2603` is currently exposed only on `stepfun-plan`.
206271
- Use `openclaw models list` and `openclaw models set <provider/model>` to inspect or switch models.
207272

extensions/stepfun/index.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
// Stepfun tests cover index plugin behavior.
22
import { readFileSync } from "node:fs";
33
import { resolve } from "node:path";
4+
import type { Context, Model } from "openclaw/plugin-sdk/llm";
45
import {
56
registerProviderPlugin,
67
requireRegisteredProvider,
78
} from "openclaw/plugin-sdk/plugin-test-runtime";
9+
import { buildOpenAICompletionsParams } from "openclaw/plugin-sdk/provider-transport-runtime";
810
import { describe, expect, it } from "vitest";
911
import stepfunPlugin from "./index.js";
12+
import {
13+
STEPFUN_DEFAULT_MODEL_REF,
14+
STEPFUN_PLAN_DEFAULT_MODEL_REF,
15+
buildStepFunPlanProvider,
16+
buildStepFunProvider,
17+
} from "./provider-catalog.js";
1018

1119
type StepFunManifest = {
1220
setup?: {
@@ -28,6 +36,91 @@ function readManifest(): StepFunManifest {
2836
}
2937

3038
describe("stepfun provider registration", () => {
39+
it("adds Step 3.7 Flash without changing existing defaults", () => {
40+
const standard = buildStepFunProvider();
41+
const plan = buildStepFunPlanProvider();
42+
const standardModel = standard.models?.find((model) => model.id === "step-3.7-flash");
43+
const planModel = plan.models?.find((model) => model.id === "step-3.7-flash");
44+
if (!standardModel) {
45+
throw new Error("StepFun Standard catalog did not provide Step 3.7 Flash");
46+
}
47+
48+
expect(STEPFUN_DEFAULT_MODEL_REF).toBe("stepfun/step-3.5-flash");
49+
expect(STEPFUN_PLAN_DEFAULT_MODEL_REF).toBe("stepfun-plan/step-3.5-flash");
50+
expect(
51+
standard.models?.find((model) => model.id === "step-3.5-flash")?.compat
52+
?.supportsReasoningEffort,
53+
).not.toBe(true);
54+
expect(standardModel).toMatchObject({
55+
reasoning: true,
56+
input: ["text", "image"],
57+
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
58+
contextWindow: 262144,
59+
maxTokens: 262144,
60+
cost: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 },
61+
compat: {
62+
supportsStore: false,
63+
supportsDeveloperRole: false,
64+
supportsUsageInStreaming: false,
65+
supportsReasoningEffort: true,
66+
supportsStrictMode: false,
67+
supportedReasoningEfforts: ["low", "medium", "high"],
68+
maxTokensField: "max_tokens",
69+
reasoningEffortMap: expect.objectContaining({ off: "low", medium: "medium", max: "high" }),
70+
},
71+
});
72+
expect(planModel).toMatchObject({
73+
reasoning: true,
74+
input: ["text", "image"],
75+
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
76+
contextWindow: 262144,
77+
maxTokens: 262144,
78+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
79+
compat: {
80+
supportsStore: false,
81+
supportsDeveloperRole: false,
82+
supportsUsageInStreaming: false,
83+
supportsReasoningEffort: true,
84+
supportsStrictMode: false,
85+
supportedReasoningEfforts: ["low", "medium", "high"],
86+
maxTokensField: "max_tokens",
87+
reasoningEffortMap: expect.objectContaining({ off: "low", medium: "medium", max: "high" }),
88+
},
89+
});
90+
91+
const transportModel = {
92+
...standardModel,
93+
provider: "stepfun",
94+
api: "openai-completions",
95+
baseUrl: standard.baseUrl,
96+
} as Model<"openai-completions">;
97+
const context = {
98+
systemPrompt: "system",
99+
messages: [{ role: "user", content: "hi", timestamp: 1 }],
100+
} as Context;
101+
const offReasoning = standardModel.thinkingLevelMap?.off;
102+
expect(offReasoning).toBe("low");
103+
const lowPayload = buildOpenAICompletionsParams(transportModel, context, {
104+
reasoning: offReasoning,
105+
maxTokens: 128,
106+
} as never);
107+
expect(lowPayload.reasoning_effort).toBe("low");
108+
expect(lowPayload.max_tokens).toBe(128);
109+
expect(lowPayload).not.toHaveProperty("max_completion_tokens");
110+
expect(lowPayload).not.toHaveProperty("store");
111+
expect(lowPayload).not.toHaveProperty("stream_options");
112+
expect(lowPayload.messages).toEqual(
113+
expect.arrayContaining([expect.objectContaining({ role: "system", content: "system" })]),
114+
);
115+
expect(lowPayload.messages).not.toEqual(
116+
expect.arrayContaining([expect.objectContaining({ role: "developer" })]),
117+
);
118+
expect(
119+
buildOpenAICompletionsParams(transportModel, context, { reasoning: "high" } as never)
120+
.reasoning_effort,
121+
).toBe("high");
122+
});
123+
31124
it("keeps manifest auth choices aligned with runtime provider methods", async () => {
32125
const { providers } = await registerProviderPlugin({
33126
plugin: stepfunPlugin,

extensions/stepfun/openclaw.plugin.json

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,46 @@
2525
"baseUrl": "https://api.stepfun.ai/v1",
2626
"api": "openai-completions",
2727
"models": [
28+
{
29+
"id": "step-3.7-flash",
30+
"name": "Step 3.7 Flash",
31+
"reasoning": true,
32+
"input": ["text", "image"],
33+
"thinkingLevelMap": {
34+
"off": "low",
35+
"minimal": "low",
36+
"xhigh": "high",
37+
"max": "high"
38+
},
39+
"contextWindow": 262144,
40+
"maxTokens": 262144,
41+
"cost": {
42+
"input": 0.2,
43+
"output": 1.15,
44+
"cacheRead": 0.04,
45+
"cacheWrite": 0
46+
},
47+
"compat": {
48+
"supportsStore": false,
49+
"supportsDeveloperRole": false,
50+
"supportsUsageInStreaming": false,
51+
"supportsReasoningEffort": true,
52+
"supportsStrictMode": false,
53+
"supportedReasoningEfforts": ["low", "medium", "high"],
54+
"maxTokensField": "max_tokens",
55+
"reasoningEffortMap": {
56+
"off": "low",
57+
"none": "low",
58+
"minimal": "low",
59+
"low": "low",
60+
"medium": "medium",
61+
"high": "high",
62+
"xhigh": "high",
63+
"adaptive": "high",
64+
"max": "high"
65+
}
66+
}
67+
},
2868
{
2969
"id": "step-3.5-flash",
3070
"name": "Step 3.5 Flash",
@@ -45,6 +85,46 @@
4585
"baseUrl": "https://api.stepfun.ai/step_plan/v1",
4686
"api": "openai-completions",
4787
"models": [
88+
{
89+
"id": "step-3.7-flash",
90+
"name": "Step 3.7 Flash",
91+
"reasoning": true,
92+
"input": ["text", "image"],
93+
"thinkingLevelMap": {
94+
"off": "low",
95+
"minimal": "low",
96+
"xhigh": "high",
97+
"max": "high"
98+
},
99+
"contextWindow": 262144,
100+
"maxTokens": 262144,
101+
"cost": {
102+
"input": 0,
103+
"output": 0,
104+
"cacheRead": 0,
105+
"cacheWrite": 0
106+
},
107+
"compat": {
108+
"supportsStore": false,
109+
"supportsDeveloperRole": false,
110+
"supportsUsageInStreaming": false,
111+
"supportsReasoningEffort": true,
112+
"supportsStrictMode": false,
113+
"supportedReasoningEfforts": ["low", "medium", "high"],
114+
"maxTokensField": "max_tokens",
115+
"reasoningEffortMap": {
116+
"off": "low",
117+
"none": "low",
118+
"minimal": "low",
119+
"low": "low",
120+
"medium": "medium",
121+
"high": "high",
122+
"xhigh": "high",
123+
"adaptive": "high",
124+
"max": "high"
125+
}
126+
}
127+
},
48128
{
49129
"id": "step-3.5-flash",
50130
"name": "Step 3.5 Flash",

src/agents/models-config.providers.stepfun.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import type { ModelDefinitionConfig, ModelProviderConfig } from "../config/types
77
import { upsertAuthProfile } from "./auth-profiles.js";
88
import { installModelsConfigTestHooks } from "./models-config.e2e-harness.js";
99

10-
const EXPECTED_STANDARD_MODELS = ["step-3.5-flash"];
11-
const EXPECTED_PLAN_MODELS = ["step-3.5-flash", "step-3.5-flash-2603"];
10+
const EXPECTED_STANDARD_MODELS = ["step-3.7-flash", "step-3.5-flash"];
11+
const EXPECTED_PLAN_MODELS = ["step-3.7-flash", "step-3.5-flash", "step-3.5-flash-2603"];
1212
const STEPFUN_STANDARD_CN_BASE_URL = "https://api.stepfun.com/v1";
1313
const STEPFUN_STANDARD_INTL_BASE_URL = "https://api.stepfun.ai/v1";
1414
const STEPFUN_PLAN_CN_BASE_URL = "https://api.stepfun.com/step_plan/v1";

0 commit comments

Comments
 (0)