Skip to content

Commit 4124352

Browse files
committed
refactor(providers): centralize provider model policy
1 parent e07d8fd commit 4124352

24 files changed

Lines changed: 254 additions & 288 deletions

extensions/anthropic/index.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@ import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-
33
import anthropicPlugin from "./index.js";
44

55
describe("anthropic provider replay hooks", () => {
6+
it("owns native reasoning output mode for Claude transports", () => {
7+
const provider = registerSingleProviderPlugin(anthropicPlugin);
8+
9+
expect(
10+
provider.resolveReasoningOutputMode?.({
11+
provider: "anthropic",
12+
modelApi: "anthropic-messages",
13+
modelId: "claude-sonnet-4-6",
14+
} as never),
15+
).toBe("native");
16+
});
17+
618
it("owns replay policy for Claude transports", () => {
719
const provider = registerSingleProviderPlugin(anthropicPlugin);
820

extensions/anthropic/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ export default definePluginEntry({
450450
resolveDynamicModel: (ctx) => resolveAnthropicForwardCompatModel(ctx),
451451
buildReplayPolicy: (ctx) => buildAnthropicReplayPolicy(ctx),
452452
isModernModelRef: ({ modelId }) => matchesAnthropicModernModel(modelId),
453+
resolveReasoningOutputMode: () => "native",
453454
wrapStreamFn: (ctx) => {
454455
const anthropicBetas = resolveAnthropicBetas(ctx.extraParams, ctx.modelId);
455456
const serviceTier = resolveAnthropicServiceTier(ctx.extraParams);

extensions/deepgram/openclaw.plugin.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{
22
"id": "deepgram",
33
"enabledByDefault": true,
4+
"providerAuthEnvVars": {
5+
"deepgram": ["DEEPGRAM_API_KEY"]
6+
},
47
"contracts": {
58
"mediaUnderstandingProviders": ["deepgram"]
69
},

extensions/groq/openclaw.plugin.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{
22
"id": "groq",
33
"enabledByDefault": true,
4+
"providerAuthEnvVars": {
5+
"groq": ["GROQ_API_KEY"]
6+
},
47
"contracts": {
58
"mediaUnderstandingProviders": ["groq"]
69
},

extensions/ollama/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export default definePluginEntry({
153153
});
154154
},
155155
buildReplayPolicy: (ctx) => buildOpenAICompatibleReplayPolicy(ctx.modelApi),
156+
resolveReasoningOutputMode: () => "native",
156157
wrapStreamFn: (ctx) => {
157158
return createConfiguredOllamaCompatStreamWrapper(ctx);
158159
},

extensions/openai/openai-codex-provider.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ describe("openai codex provider", () => {
8787
);
8888
});
8989

90+
it("owns native reasoning output mode for Codex responses", () => {
91+
const provider = buildOpenAICodexProviderPlugin();
92+
93+
expect(
94+
provider.resolveReasoningOutputMode?.({
95+
provider: "openai-codex",
96+
modelApi: "openai-codex-responses",
97+
modelId: "gpt-5.4",
98+
} as never),
99+
).toBe("native");
100+
});
101+
90102
it("resolves gpt-5.4 with native contextWindow plus default contextTokens cap", () => {
91103
const provider = buildOpenAICodexProviderPlugin();
92104

extensions/openai/openai-codex-provider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ export function buildOpenAICodexProviderPlugin(): ProviderPlugin {
319319
wrapStreamFn: (ctx) => wrapOpenAICodexProviderStream(ctx),
320320
resolveTransportTurnState: (ctx) => resolveOpenAITransportTurnState(ctx),
321321
resolveWebSocketSessionPolicy: (ctx) => resolveOpenAIWebSocketSessionPolicy(ctx),
322+
resolveReasoningOutputMode: () => "native",
322323
normalizeResolvedModel: (ctx) => {
323324
if (normalizeProviderId(ctx.provider) !== PROVIDER_ID) {
324325
return undefined;

extensions/openai/openai-provider.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,25 @@ describe("buildOpenAIProvider", () => {
163163
);
164164
});
165165

166+
it("owns native reasoning output mode for OpenAI and Azure OpenAI responses", () => {
167+
const provider = buildOpenAIProvider();
168+
169+
expect(
170+
provider.resolveReasoningOutputMode?.({
171+
provider: "openai",
172+
modelApi: "openai-responses",
173+
modelId: "gpt-5.4",
174+
} as never),
175+
).toBe("native");
176+
expect(
177+
provider.resolveReasoningOutputMode?.({
178+
provider: "azure-openai-responses",
179+
modelApi: "azure-openai-responses",
180+
modelId: "gpt-5.4",
181+
} as never),
182+
).toBe("native");
183+
});
184+
166185
it("keeps GPT-5.4 family metadata aligned with native OpenAI docs", () => {
167186
const provider = buildOpenAIProvider();
168187
const codexProvider = buildOpenAICodexProviderPlugin();

extensions/openai/openai-provider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ export function buildOpenAIProvider(): ProviderPlugin {
261261
: wrapAzureOpenAIProviderStream(ctx),
262262
resolveTransportTurnState: (ctx) => resolveOpenAITransportTurnState(ctx),
263263
resolveWebSocketSessionPolicy: (ctx) => resolveOpenAIWebSocketSessionPolicy(ctx),
264+
resolveReasoningOutputMode: () => "native",
264265
supportsXHighThinking: ({ modelId }) => matchesExactOrPrefix(modelId, OPENAI_XHIGH_MODEL_IDS),
265266
isModernModelRef: ({ modelId }) => matchesExactOrPrefix(modelId, OPENAI_MODERN_MODEL_IDS),
266267
buildMissingAuthMessage: (ctx) => {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { describe, expect, it } from "vitest";
2+
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
3+
import openrouterPlugin from "./index.js";
4+
5+
describe("openrouter provider hooks", () => {
6+
it("owns native reasoning output mode", () => {
7+
const provider = registerSingleProviderPlugin(openrouterPlugin);
8+
9+
expect(
10+
provider.resolveReasoningOutputMode?.({
11+
provider: "openrouter",
12+
modelApi: "openai-completions",
13+
modelId: "openai/gpt-5.4",
14+
} as never),
15+
).toBe("native");
16+
});
17+
});

0 commit comments

Comments
 (0)