mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-09 15:59:30 +00:00
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 <litianning@stepfun.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
parent
240ca9dbd7
commit
583ca34bf8
4 changed files with 248 additions and 10 deletions
|
|
@ -35,16 +35,18 @@ Auth env var: `STEPFUN_API_KEY`
|
|||
|
||||
Standard (`stepfun`):
|
||||
|
||||
| Model ref | Context | Max output | Notes |
|
||||
| ------------------------ | ------- | ---------- | ---------------------- |
|
||||
| `stepfun/step-3.5-flash` | 262,144 | 65,536 | Default standard model |
|
||||
| Model ref | Context | Max output | Notes |
|
||||
| ------------------------ | ------- | ---------- | ------------------------------ |
|
||||
| `stepfun/step-3.5-flash` | 262,144 | 65,536 | Default standard model |
|
||||
| `stepfun/step-3.7-flash` | 262,144 | 262,144 | Multimodal image input support |
|
||||
|
||||
Step Plan (`stepfun-plan`):
|
||||
|
||||
| Model ref | Context | Max output | Notes |
|
||||
| ---------------------------------- | ------- | ---------- | -------------------------- |
|
||||
| `stepfun-plan/step-3.5-flash` | 262,144 | 65,536 | Default Step Plan model |
|
||||
| `stepfun-plan/step-3.5-flash-2603` | 262,144 | 65,536 | Additional Step Plan model |
|
||||
| Model ref | Context | Max output | Notes |
|
||||
| ---------------------------------- | ------- | ---------- | ------------------------------ |
|
||||
| `stepfun-plan/step-3.5-flash` | 262,144 | 65,536 | Default Step Plan model |
|
||||
| `stepfun-plan/step-3.7-flash` | 262,144 | 262,144 | Multimodal image input support |
|
||||
| `stepfun-plan/step-3.5-flash-2603` | 262,144 | 65,536 | Additional Step Plan model |
|
||||
|
||||
## Getting started
|
||||
|
||||
|
|
@ -84,6 +86,7 @@ Step Plan (`stepfun-plan`):
|
|||
</Steps>
|
||||
|
||||
Default model: `stepfun/step-3.5-flash`
|
||||
Alternate model: `stepfun/step-3.7-flash`
|
||||
|
||||
</Tab>
|
||||
|
||||
|
|
@ -122,7 +125,7 @@ Step Plan (`stepfun-plan`):
|
|||
</Steps>
|
||||
|
||||
Default model: `stepfun-plan/step-3.5-flash`
|
||||
Alternate model: `stepfun-plan/step-3.5-flash-2603`
|
||||
Alternate models: `stepfun-plan/step-3.7-flash`, `stepfun-plan/step-3.5-flash-2603`
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
|
@ -145,6 +148,36 @@ A single auth flow writes region-matched profiles for both `stepfun` and `stepfu
|
|||
api: "openai-completions",
|
||||
apiKey: "${STEPFUN_API_KEY}",
|
||||
models: [
|
||||
{
|
||||
id: "step-3.7-flash",
|
||||
name: "Step 3.7 Flash",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
|
||||
cost: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
compat: {
|
||||
supportsStore: false,
|
||||
supportsDeveloperRole: false,
|
||||
supportsUsageInStreaming: false,
|
||||
supportsReasoningEffort: true,
|
||||
supportsStrictMode: false,
|
||||
supportedReasoningEfforts: ["low", "medium", "high"],
|
||||
maxTokensField: "max_tokens",
|
||||
reasoningEffortMap: {
|
||||
off: "low",
|
||||
none: "low",
|
||||
minimal: "low",
|
||||
low: "low",
|
||||
medium: "medium",
|
||||
high: "high",
|
||||
xhigh: "high",
|
||||
adaptive: "high",
|
||||
max: "high",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "step-3.5-flash",
|
||||
name: "Step 3.5 Flash",
|
||||
|
|
@ -175,6 +208,36 @@ A single auth flow writes region-matched profiles for both `stepfun` and `stepfu
|
|||
api: "openai-completions",
|
||||
apiKey: "${STEPFUN_API_KEY}",
|
||||
models: [
|
||||
{
|
||||
id: "step-3.7-flash",
|
||||
name: "Step 3.7 Flash",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
compat: {
|
||||
supportsStore: false,
|
||||
supportsDeveloperRole: false,
|
||||
supportsUsageInStreaming: false,
|
||||
supportsReasoningEffort: true,
|
||||
supportsStrictMode: false,
|
||||
supportedReasoningEfforts: ["low", "medium", "high"],
|
||||
maxTokensField: "max_tokens",
|
||||
reasoningEffortMap: {
|
||||
off: "low",
|
||||
none: "low",
|
||||
minimal: "low",
|
||||
low: "low",
|
||||
medium: "medium",
|
||||
high: "high",
|
||||
xhigh: "high",
|
||||
adaptive: "high",
|
||||
max: "high",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "step-3.5-flash",
|
||||
name: "Step 3.5 Flash",
|
||||
|
|
@ -202,6 +265,8 @@ A single auth flow writes region-matched profiles for both `stepfun` and `stepfu
|
|||
</Accordion>
|
||||
|
||||
<Accordion title="Notes">
|
||||
- `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.
|
||||
- Step 3.7 supports `low`, `medium`, and `high` reasoning effort. Because the model has no non-reasoning mode, `/think off` maps to `low`.
|
||||
- `step-3.5-flash-2603` is currently exposed only on `stepfun-plan`.
|
||||
- Use `openclaw models list` and `openclaw models set <provider/model>` to inspect or switch models.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
// Stepfun tests cover index plugin behavior.
|
||||
import { readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
import type { Context, Model } from "openclaw/plugin-sdk/llm";
|
||||
import {
|
||||
registerProviderPlugin,
|
||||
requireRegisteredProvider,
|
||||
} from "openclaw/plugin-sdk/plugin-test-runtime";
|
||||
import { buildOpenAICompletionsParams } from "openclaw/plugin-sdk/provider-transport-runtime";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import stepfunPlugin from "./index.js";
|
||||
import {
|
||||
STEPFUN_DEFAULT_MODEL_REF,
|
||||
STEPFUN_PLAN_DEFAULT_MODEL_REF,
|
||||
buildStepFunPlanProvider,
|
||||
buildStepFunProvider,
|
||||
} from "./provider-catalog.js";
|
||||
|
||||
type StepFunManifest = {
|
||||
setup?: {
|
||||
|
|
@ -28,6 +36,91 @@ function readManifest(): StepFunManifest {
|
|||
}
|
||||
|
||||
describe("stepfun provider registration", () => {
|
||||
it("adds Step 3.7 Flash without changing existing defaults", () => {
|
||||
const standard = buildStepFunProvider();
|
||||
const plan = buildStepFunPlanProvider();
|
||||
const standardModel = standard.models?.find((model) => model.id === "step-3.7-flash");
|
||||
const planModel = plan.models?.find((model) => model.id === "step-3.7-flash");
|
||||
if (!standardModel) {
|
||||
throw new Error("StepFun Standard catalog did not provide Step 3.7 Flash");
|
||||
}
|
||||
|
||||
expect(STEPFUN_DEFAULT_MODEL_REF).toBe("stepfun/step-3.5-flash");
|
||||
expect(STEPFUN_PLAN_DEFAULT_MODEL_REF).toBe("stepfun-plan/step-3.5-flash");
|
||||
expect(
|
||||
standard.models?.find((model) => model.id === "step-3.5-flash")?.compat
|
||||
?.supportsReasoningEffort,
|
||||
).not.toBe(true);
|
||||
expect(standardModel).toMatchObject({
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
cost: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 },
|
||||
compat: {
|
||||
supportsStore: false,
|
||||
supportsDeveloperRole: false,
|
||||
supportsUsageInStreaming: false,
|
||||
supportsReasoningEffort: true,
|
||||
supportsStrictMode: false,
|
||||
supportedReasoningEfforts: ["low", "medium", "high"],
|
||||
maxTokensField: "max_tokens",
|
||||
reasoningEffortMap: expect.objectContaining({ off: "low", medium: "medium", max: "high" }),
|
||||
},
|
||||
});
|
||||
expect(planModel).toMatchObject({
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
thinkingLevelMap: { off: "low", minimal: "low", xhigh: "high", max: "high" },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
compat: {
|
||||
supportsStore: false,
|
||||
supportsDeveloperRole: false,
|
||||
supportsUsageInStreaming: false,
|
||||
supportsReasoningEffort: true,
|
||||
supportsStrictMode: false,
|
||||
supportedReasoningEfforts: ["low", "medium", "high"],
|
||||
maxTokensField: "max_tokens",
|
||||
reasoningEffortMap: expect.objectContaining({ off: "low", medium: "medium", max: "high" }),
|
||||
},
|
||||
});
|
||||
|
||||
const transportModel = {
|
||||
...standardModel,
|
||||
provider: "stepfun",
|
||||
api: "openai-completions",
|
||||
baseUrl: standard.baseUrl,
|
||||
} as Model<"openai-completions">;
|
||||
const context = {
|
||||
systemPrompt: "system",
|
||||
messages: [{ role: "user", content: "hi", timestamp: 1 }],
|
||||
} as Context;
|
||||
const offReasoning = standardModel.thinkingLevelMap?.off;
|
||||
expect(offReasoning).toBe("low");
|
||||
const lowPayload = buildOpenAICompletionsParams(transportModel, context, {
|
||||
reasoning: offReasoning,
|
||||
maxTokens: 128,
|
||||
} as never);
|
||||
expect(lowPayload.reasoning_effort).toBe("low");
|
||||
expect(lowPayload.max_tokens).toBe(128);
|
||||
expect(lowPayload).not.toHaveProperty("max_completion_tokens");
|
||||
expect(lowPayload).not.toHaveProperty("store");
|
||||
expect(lowPayload).not.toHaveProperty("stream_options");
|
||||
expect(lowPayload.messages).toEqual(
|
||||
expect.arrayContaining([expect.objectContaining({ role: "system", content: "system" })]),
|
||||
);
|
||||
expect(lowPayload.messages).not.toEqual(
|
||||
expect.arrayContaining([expect.objectContaining({ role: "developer" })]),
|
||||
);
|
||||
expect(
|
||||
buildOpenAICompletionsParams(transportModel, context, { reasoning: "high" } as never)
|
||||
.reasoning_effort,
|
||||
).toBe("high");
|
||||
});
|
||||
|
||||
it("keeps manifest auth choices aligned with runtime provider methods", async () => {
|
||||
const { providers } = await registerProviderPlugin({
|
||||
plugin: stepfunPlugin,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,46 @@
|
|||
"baseUrl": "https://api.stepfun.ai/v1",
|
||||
"api": "openai-completions",
|
||||
"models": [
|
||||
{
|
||||
"id": "step-3.7-flash",
|
||||
"name": "Step 3.7 Flash",
|
||||
"reasoning": true,
|
||||
"input": ["text", "image"],
|
||||
"thinkingLevelMap": {
|
||||
"off": "low",
|
||||
"minimal": "low",
|
||||
"xhigh": "high",
|
||||
"max": "high"
|
||||
},
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 262144,
|
||||
"cost": {
|
||||
"input": 0.2,
|
||||
"output": 1.15,
|
||||
"cacheRead": 0.04,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"supportsStore": false,
|
||||
"supportsDeveloperRole": false,
|
||||
"supportsUsageInStreaming": false,
|
||||
"supportsReasoningEffort": true,
|
||||
"supportsStrictMode": false,
|
||||
"supportedReasoningEfforts": ["low", "medium", "high"],
|
||||
"maxTokensField": "max_tokens",
|
||||
"reasoningEffortMap": {
|
||||
"off": "low",
|
||||
"none": "low",
|
||||
"minimal": "low",
|
||||
"low": "low",
|
||||
"medium": "medium",
|
||||
"high": "high",
|
||||
"xhigh": "high",
|
||||
"adaptive": "high",
|
||||
"max": "high"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step-3.5-flash",
|
||||
"name": "Step 3.5 Flash",
|
||||
|
|
@ -45,6 +85,46 @@
|
|||
"baseUrl": "https://api.stepfun.ai/step_plan/v1",
|
||||
"api": "openai-completions",
|
||||
"models": [
|
||||
{
|
||||
"id": "step-3.7-flash",
|
||||
"name": "Step 3.7 Flash",
|
||||
"reasoning": true,
|
||||
"input": ["text", "image"],
|
||||
"thinkingLevelMap": {
|
||||
"off": "low",
|
||||
"minimal": "low",
|
||||
"xhigh": "high",
|
||||
"max": "high"
|
||||
},
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 262144,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"supportsStore": false,
|
||||
"supportsDeveloperRole": false,
|
||||
"supportsUsageInStreaming": false,
|
||||
"supportsReasoningEffort": true,
|
||||
"supportsStrictMode": false,
|
||||
"supportedReasoningEfforts": ["low", "medium", "high"],
|
||||
"maxTokensField": "max_tokens",
|
||||
"reasoningEffortMap": {
|
||||
"off": "low",
|
||||
"none": "low",
|
||||
"minimal": "low",
|
||||
"low": "low",
|
||||
"medium": "medium",
|
||||
"high": "high",
|
||||
"xhigh": "high",
|
||||
"adaptive": "high",
|
||||
"max": "high"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step-3.5-flash",
|
||||
"name": "Step 3.5 Flash",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import type { ModelDefinitionConfig, ModelProviderConfig } from "../config/types
|
|||
import { upsertAuthProfile } from "./auth-profiles.js";
|
||||
import { installModelsConfigTestHooks } from "./models-config.e2e-harness.js";
|
||||
|
||||
const EXPECTED_STANDARD_MODELS = ["step-3.5-flash"];
|
||||
const EXPECTED_PLAN_MODELS = ["step-3.5-flash", "step-3.5-flash-2603"];
|
||||
const EXPECTED_STANDARD_MODELS = ["step-3.7-flash", "step-3.5-flash"];
|
||||
const EXPECTED_PLAN_MODELS = ["step-3.7-flash", "step-3.5-flash", "step-3.5-flash-2603"];
|
||||
const STEPFUN_STANDARD_CN_BASE_URL = "https://api.stepfun.com/v1";
|
||||
const STEPFUN_STANDARD_INTL_BASE_URL = "https://api.stepfun.ai/v1";
|
||||
const STEPFUN_PLAN_CN_BASE_URL = "https://api.stepfun.com/step_plan/v1";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue