Skip to content

Commit c8a9375

Browse files
committed
More progress
1 parent 0ab2790 commit c8a9375

File tree

10 files changed

+158
-83
lines changed

10 files changed

+158
-83
lines changed

src/api/__tests__/index.test.ts

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@ describe("getModelParams", () => {
1212
}
1313

1414
const result = getModelParams({
15-
options: {},
15+
format: "openai",
16+
settings: {},
1617
model,
1718
defaultMaxTokens: 1000,
1819
defaultTemperature: 0.5,
1920
})
2021

2122
expect(result).toEqual({
23+
format: "openai",
2224
maxTokens: 1000,
23-
thinking: undefined,
2425
temperature: 0.5,
26+
reasoningEffort: undefined,
27+
reasoningBudget: undefined,
28+
reasoning: undefined,
2529
})
2630
})
2731

@@ -32,16 +36,20 @@ describe("getModelParams", () => {
3236
}
3337

3438
const result = getModelParams({
35-
options: { modelTemperature: 0.7 },
39+
format: "openai",
40+
settings: { modelTemperature: 0.7 },
3641
model,
3742
defaultMaxTokens: 1000,
3843
defaultTemperature: 0.5,
3944
})
4045

4146
expect(result).toEqual({
47+
format: "openai",
4248
maxTokens: 1000,
43-
thinking: undefined,
4449
temperature: 0.7,
50+
reasoningEffort: undefined,
51+
reasoningBudget: undefined,
52+
reasoning: undefined,
4553
})
4654
})
4755

@@ -52,10 +60,13 @@ describe("getModelParams", () => {
5260
supportsPromptCache: true,
5361
}
5462

55-
expect(getModelParams({ options: {}, model, defaultMaxTokens: 1000 })).toEqual({
63+
expect(getModelParams({ format: "openai", settings: {}, model, defaultMaxTokens: 1000 })).toEqual({
64+
format: "openai",
5665
maxTokens: 2000,
57-
thinking: undefined,
5866
temperature: 0,
67+
reasoningEffort: undefined,
68+
reasoningBudget: undefined,
69+
reasoning: undefined,
5970
})
6071
})
6172

@@ -67,10 +78,13 @@ describe("getModelParams", () => {
6778
supportsReasoningBudget: true,
6879
}
6980

70-
expect(getModelParams({ options: {}, model })).toEqual({
81+
expect(getModelParams({ format: "openai", settings: {}, model })).toEqual({
82+
format: "openai",
7183
maxTokens: 2000,
72-
reasoningBudget: 1600, // 80% of 2000,
7384
temperature: 1.0, // Thinking models require temperature 1.0.
85+
reasoningEffort: undefined,
86+
reasoningBudget: 1600, // 80% of 2000,
87+
reasoning: undefined,
7488
})
7589
})
7690

@@ -81,10 +95,15 @@ describe("getModelParams", () => {
8195
supportsReasoningBudget: true,
8296
}
8397

84-
expect(getModelParams({ options: { modelMaxTokens: 3000 }, model, defaultMaxTokens: 2000 })).toEqual({
98+
expect(
99+
getModelParams({ format: "openai", settings: { modelMaxTokens: 3000 }, model, defaultMaxTokens: 2000 }),
100+
).toEqual({
101+
format: "openai",
85102
maxTokens: 3000,
86-
reasoningBudget: 2400, // 80% of 3000,
87103
temperature: 1.0,
104+
reasoningEffort: undefined,
105+
reasoningBudget: 2400, // 80% of 3000,
106+
reasoning: undefined,
88107
})
89108
})
90109

@@ -96,10 +115,13 @@ describe("getModelParams", () => {
96115
supportsReasoningBudget: true,
97116
}
98117

99-
expect(getModelParams({ options: { modelMaxThinkingTokens: 1500 }, model })).toEqual({
118+
expect(getModelParams({ format: "openai", settings: { modelMaxThinkingTokens: 1500 }, model })).toEqual({
119+
format: "openai",
100120
maxTokens: 4000,
101-
reasoningBudget: 1500, // Using the custom value.
102121
temperature: 1.0,
122+
reasoningEffort: undefined,
123+
reasoningBudget: 1500, // Using the custom value.
124+
reasoning: undefined,
103125
})
104126
})
105127

@@ -110,11 +132,13 @@ describe("getModelParams", () => {
110132
supportsPromptCache: true,
111133
}
112134

113-
expect(getModelParams({ options: { modelMaxThinkingTokens: 1500 }, model })).toEqual({
135+
expect(getModelParams({ format: "openai", settings: { modelMaxThinkingTokens: 1500 }, model })).toEqual({
136+
format: "openai",
114137
maxTokens: 4000,
115-
reasoningBudget: undefined, // Should remain undefined despite customMaxThinkingTokens being set.
116-
reasoningEffort: undefined,
117138
temperature: 0, // Using default temperature.
139+
reasoningEffort: undefined,
140+
reasoningBudget: undefined, // Should remain undefined despite customMaxThinkingTokens being set.
141+
reasoning: undefined,
118142
})
119143
})
120144

@@ -126,10 +150,13 @@ describe("getModelParams", () => {
126150
supportsReasoningBudget: true,
127151
}
128152

129-
expect(getModelParams({ options: { modelMaxThinkingTokens: 500 }, model })).toEqual({
153+
expect(getModelParams({ format: "openai", settings: { modelMaxThinkingTokens: 500 }, model })).toEqual({
154+
format: "openai",
130155
maxTokens: 2000,
131-
reasoningBudget: 1024, // Minimum is 1024
132156
temperature: 1.0,
157+
reasoningEffort: undefined,
158+
reasoningBudget: 1024, // Minimum is 1024
159+
reasoning: undefined,
133160
})
134161
})
135162

@@ -141,10 +168,13 @@ describe("getModelParams", () => {
141168
supportsReasoningBudget: true,
142169
}
143170

144-
expect(getModelParams({ options: { modelMaxThinkingTokens: 5000 }, model })).toEqual({
171+
expect(getModelParams({ format: "openai", settings: { modelMaxThinkingTokens: 5000 }, model })).toEqual({
172+
format: "openai",
145173
maxTokens: 4000,
146-
reasoningBudget: 3200, // 80% of 4000
147174
temperature: 1.0,
175+
reasoningEffort: undefined,
176+
reasoningBudget: 3200, // 80% of 4000
177+
reasoning: undefined,
148178
})
149179
})
150180

@@ -155,10 +185,13 @@ describe("getModelParams", () => {
155185
supportsReasoningBudget: true,
156186
}
157187

158-
expect(getModelParams({ options: {}, model })).toEqual({
188+
expect(getModelParams({ format: "openai", settings: {}, model })).toEqual({
189+
format: "openai",
159190
maxTokens: undefined,
160191
temperature: 1.0,
192+
reasoningEffort: undefined,
161193
reasoningBudget: Math.floor(ANTHROPIC_DEFAULT_MAX_TOKENS * 0.8),
194+
reasoning: undefined,
162195
})
163196
})
164197
})

src/api/providers/anthropic-vertex.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { safeJsonParse } from "../../shared/safeJsonParse"
77

88
import { ApiStream } from "../transform/stream"
99
import { addCacheBreakpoints } from "../transform/caching/vertex"
10-
import { getAnthropicReasoning } from "../transform/reasoning"
1110
import { getModelParams } from "../transform/model-params"
1211

1312
import { ANTHROPIC_DEFAULT_MAX_TOKENS } from "./constants"
@@ -57,7 +56,7 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple
5756
info: { supportsPromptCache },
5857
temperature,
5958
maxTokens,
60-
thinking,
59+
reasoning: thinking,
6160
} = this.getModel()
6261

6362
/**
@@ -158,18 +157,17 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple
158157
const info: ModelInfo = vertexModels[id]
159158

160159
const params = getModelParams({
161-
options: this.options,
160+
format: "anthropic",
161+
settings: this.options,
162162
model: info,
163163
defaultMaxTokens: ANTHROPIC_DEFAULT_MAX_TOKENS,
164164
})
165165

166-
const thinking = getAnthropicReasoning({ model: info, params, settings: this.options })
167-
168166
// The `:thinking` suffix indicates that the model is a "Hybrid"
169167
// reasoning model and that reasoning is required to be enabled.
170168
// The actual model ID honored by Anthropic's API does not have this
171169
// suffix.
172-
return { id: id.endsWith(":thinking") ? id.replace(":thinking", "") : id, info, ...params, thinking }
170+
return { id: id.endsWith(":thinking") ? id.replace(":thinking", "") : id, info, ...params }
173171
}
174172

175173
async completePrompt(prompt: string) {
@@ -179,7 +177,7 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple
179177
info: { supportsPromptCache },
180178
temperature,
181179
maxTokens = ANTHROPIC_DEFAULT_MAX_TOKENS,
182-
thinking,
180+
reasoning: thinking,
183181
} = this.getModel()
184182

185183
const params: Anthropic.Messages.MessageCreateParamsNonStreaming = {

src/api/providers/anthropic.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
} from "../../shared/api"
1212

1313
import { ApiStream } from "../transform/stream"
14-
import { getAnthropicReasoning } from "../transform/reasoning"
1514
import { getModelParams } from "../transform/model-params"
1615

1716
import { ANTHROPIC_DEFAULT_MAX_TOKENS } from "./constants"
@@ -38,7 +37,7 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
3837
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
3938
let stream: AnthropicStream<Anthropic.Messages.RawMessageStreamEvent>
4039
const cacheControl: CacheControlEphemeral = { type: "ephemeral" }
41-
let { id: modelId, betas = [], maxTokens, temperature, thinking } = this.getModel()
40+
let { id: modelId, betas = [], maxTokens, temperature, reasoning: thinking } = this.getModel()
4241

4342
switch (modelId) {
4443
case "claude-sonnet-4-20250514":
@@ -202,13 +201,12 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
202201
const info: ModelInfo = anthropicModels[id]
203202

204203
const params = getModelParams({
205-
options: this.options,
204+
format: "anthropic",
205+
settings: this.options,
206206
model: info,
207207
defaultMaxTokens: ANTHROPIC_DEFAULT_MAX_TOKENS,
208208
})
209209

210-
const thinking = getAnthropicReasoning({ model: info, params, settings: this.options })
211-
212210
// The `:thinking` suffix indicates that the model is a "Hybrid"
213211
// reasoning model and that reasoning is required to be enabled.
214212
// The actual model ID honored by Anthropic's API does not have this
@@ -218,7 +216,6 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
218216
info,
219217
betas: id === "claude-3-7-sonnet-20250219:thinking" ? ["output-128k-2025-02-19"] : undefined,
220218
...params,
221-
thinking,
222219
}
223220
}
224221

src/api/providers/deepseek.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type { ApiHandlerOptions } from "../../shared/api"
33

44
import type { ApiStreamUsageChunk } from "../transform/stream"
55
import { getModelParams } from "../transform/model-params"
6-
import { getOpenAiReasoning } from "../transform/reasoning"
76

87
import { OpenAiHandler } from "./openai"
98

@@ -22,9 +21,8 @@ export class DeepSeekHandler extends OpenAiHandler {
2221
override getModel() {
2322
const modelId = this.options.apiModelId ?? deepSeekDefaultModelId
2423
const info = deepSeekModels[modelId as keyof typeof deepSeekModels] || deepSeekModels[deepSeekDefaultModelId]
25-
const params = getModelParams({ options: this.options, model: info })
26-
const reasoning = getOpenAiReasoning({ model: info, params, settings: this.options })
27-
return { id: modelId, info, ...params, reasoning }
24+
const params = getModelParams({ format: "openai", settings: this.options, model: info })
25+
return { id: modelId, info, ...params }
2826
}
2927

3028
// Override to handle DeepSeek's usage metrics, including caching.

src/api/providers/openai-native.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { calculateApiCostOpenAI } from "../../utils/cost"
1414
import { convertToOpenAiMessages } from "../transform/openai-format"
1515
import { ApiStream } from "../transform/stream"
1616
import { getModelParams } from "../transform/model-params"
17-
import { getOpenAiReasoning } from "../transform/reasoning"
1817

1918
import type { SingleCompletionHandler } from "../index"
2019
import { BaseProvider } from "./base-provider"
@@ -166,23 +165,21 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
166165

167166
const info: ModelInfo = openAiNativeModels[id]
168167

169-
const params = getModelParams({
170-
options: this.options,
168+
const { temperature, ...params } = getModelParams({
169+
format: "openai",
170+
settings: this.options,
171171
model: info,
172172
defaultTemperature: OPENAI_NATIVE_DEFAULT_TEMPERATURE,
173173
})
174174

175-
const reasoning = getOpenAiReasoning({ model: info, params, settings: this.options })
176-
177175
// The o3 models are named like "o3-mini-[reasoning-effort]", which are
178176
// not valid model ids, so we need to strip the suffix.
179177
// Also note that temperature is not supported for o1 and o3-mini.
180178
return {
181179
id: id.startsWith("o3-mini") ? "o3-mini" : id,
182180
info,
183181
...params,
184-
temperature: id.startsWith("o1") || id.startsWith("o3-mini") ? undefined : params.temperature,
185-
reasoning,
182+
temperature: id.startsWith("o1") || id.startsWith("o3-mini") ? undefined : temperature,
186183
}
187184
}
188185

src/api/providers/openai.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { convertToOpenAiMessages } from "../transform/openai-format"
1515
import { convertToR1Format } from "../transform/r1-format"
1616
import { convertToSimpleMessages } from "../transform/simple-format"
1717
import { ApiStream, ApiStreamUsageChunk } from "../transform/stream"
18-
import { getOpenAiReasoning } from "../transform/reasoning"
1918
import { getModelParams } from "../transform/model-params"
2019

2120
import { DEFAULT_HEADERS, DEEP_SEEK_DEFAULT_TEMPERATURE } from "./constants"
@@ -241,9 +240,8 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
241240
override getModel() {
242241
const id = this.options.openAiModelId ?? ""
243242
const info = this.options.openAiCustomModelInfo ?? openAiModelInfoSaneDefaults
244-
const params = getModelParams({ options: this.options, model: info })
245-
const reasoning = getOpenAiReasoning({ model: info, params, settings: this.options })
246-
return { id, info, ...params, reasoning }
243+
const params = getModelParams({ format: "openai", settings: this.options, model: info })
244+
return { id, info, ...params }
247245
}
248246

249247
async completePrompt(prompt: string): Promise<string> {

src/api/providers/openrouter.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { ApiStreamChunk } from "../transform/stream"
1414
import { convertToR1Format } from "../transform/r1-format"
1515
import { addCacheBreakpoints as addAnthropicCacheBreakpoints } from "../transform/caching/anthropic"
1616
import { addCacheBreakpoints as addGeminiCacheBreakpoints } from "../transform/caching/gemini"
17-
import { type OpenRouterReasoningParams, getOpenRouterReasoning } from "../transform/reasoning"
17+
import type { OpenRouterReasoningParams } from "../transform/reasoning"
1818
import { getModelParams } from "../transform/model-params"
1919

2020
import { getModels } from "./fetchers/modelCache"
@@ -189,9 +189,8 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
189189

190190
const isDeepSeekR1 = id.startsWith("deepseek/deepseek-r1") || id === "perplexity/sonar-reasoning"
191191
const defaultTemperature = isDeepSeekR1 ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0
192-
const params = getModelParams({ options: this.options, model: info, defaultTemperature })
193-
const reasoning = getOpenRouterReasoning({ model: info, params, settings: this.options })
194-
return { id, info, topP: isDeepSeekR1 ? 0.95 : undefined, ...params, reasoning }
192+
const params = getModelParams({ format: "openrouter", settings: this.options, model: info, defaultTemperature })
193+
return { id, info, topP: isDeepSeekR1 ? 0.95 : undefined, ...params }
195194
}
196195

197196
async completePrompt(prompt: string) {

src/api/providers/xai.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { ApiHandlerOptions, XAIModelId, xaiDefaultModelId, xaiModels } from "../
55

66
import { ApiStream } from "../transform/stream"
77
import { convertToOpenAiMessages } from "../transform/openai-format"
8-
import { getOpenAiReasoning } from "../transform/reasoning"
98
import { getModelParams } from "../transform/model-params"
109

1110
import { DEFAULT_HEADERS } from "./constants"
@@ -35,9 +34,8 @@ export class XAIHandler extends BaseProvider implements SingleCompletionHandler
3534
: xaiDefaultModelId
3635

3736
const info = xaiModels[id]
38-
const params = getModelParams({ options: this.options, model: info })
39-
const reasoning = getOpenAiReasoning({ model: info, params, settings: this.options })
40-
return { id, info, ...params, reasoning }
37+
const params = getModelParams({ format: "openai", settings: this.options, model: info })
38+
return { id, info, ...params }
4139
}
4240

4341
override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {

0 commit comments

Comments
 (0)