Compare commits

...
Author SHA1 Message Date
Saoud Rizwan fd1e1b8ca2 Add reasoning effort checkbox and fix plan mode toggling 2025-04-11 19:50:38 -07:00
celestial-vault 0e71950ad7 merge conflicts 2025-04-11 18:19:22 -07:00
celestial-vault 732043444c changeset 2025-04-11 18:17:58 -07:00
celestial-vault 17fb30fe34 toggle xai grok 3 mini reasoning 2025-04-11 18:17:30 -07:00
celestial-vault 580c6bf328 changeset 2025-04-11 12:30:53 -07:00
celestial-vault 596b639bc2 stream reasoning tokens 2025-04-11 12:30:19 -07:00
7 changed files with 93 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": minor
---
Add reasoning effort to grok 3 mini
+12 -1
View File
@@ -4,6 +4,7 @@ import { ApiHandler } from "../"
import { ApiHandlerOptions, XAIModelId, ModelInfo, xaiDefaultModelId, xaiModels } from "../../shared/api"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { ApiStream } from "../transform/stream"
import { ChatCompletionReasoningEffort } from "openai/resources/chat/completions.mjs"
export class XAIHandler implements ApiHandler {
private options: ApiHandlerOptions
@@ -18,12 +19,22 @@ export class XAIHandler implements ApiHandler {
}
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
const modelId = this.getModel().id
// ensure reasoning effort is either "low" or "high" for grok-3-mini
let reasoningEffort: ChatCompletionReasoningEffort | undefined
if (modelId.includes("3-mini")) {
let reasoningEffort = this.options.reasoningEffort
if (reasoningEffort && !["low", "high"].includes(reasoningEffort)) {
reasoningEffort = undefined
}
}
const stream = await this.client.chat.completions.create({
model: this.getModel().id,
model: modelId,
max_completion_tokens: this.getModel().info.maxTokens,
temperature: 0,
messages: [{ role: "system", content: systemPrompt }, ...convertToOpenAiMessages(messages)],
stream: true,
reasoning_effort: reasoningEffort,
})
for await (const chunk of stream) {
+12 -1
View File
@@ -943,6 +943,7 @@ export class Controller {
previousModeModelInfo: newModelInfo,
previousModeVsCodeLmModelSelector: newVsCodeLmModelSelector,
previousModeThinkingBudgetTokens: newThinkingBudgetTokens,
previousModeReasoningEffort: newReasoningEffort,
planActSeparateModelsSetting,
} = await getAllExtensionState(this.context)
@@ -952,6 +953,7 @@ export class Controller {
// Save the last model used in this mode
await updateGlobalState(this.context, "previousModeApiProvider", apiConfiguration.apiProvider)
await updateGlobalState(this.context, "previousModeThinkingBudgetTokens", apiConfiguration.thinkingBudgetTokens)
await updateGlobalState(this.context, "previousModeReasoningEffort", apiConfiguration.reasoningEffort)
switch (apiConfiguration.apiProvider) {
case "anthropic":
case "bedrock":
@@ -961,6 +963,7 @@ export class Controller {
case "openai-native":
case "qwen":
case "deepseek":
case "xai":
await updateGlobalState(this.context, "previousModeModelId", apiConfiguration.apiModelId)
break
case "openrouter":
@@ -996,9 +999,16 @@ export class Controller {
}
// Restore the model used in previous mode
if (newApiProvider || newModelId || newThinkingBudgetTokens !== undefined || newVsCodeLmModelSelector) {
if (
newApiProvider ||
newModelId ||
newThinkingBudgetTokens !== undefined ||
newReasoningEffort ||
newVsCodeLmModelSelector
) {
await updateGlobalState(this.context, "apiProvider", newApiProvider)
await updateGlobalState(this.context, "thinkingBudgetTokens", newThinkingBudgetTokens)
await updateGlobalState(this.context, "reasoningEffort", newReasoningEffort)
switch (newApiProvider) {
case "anthropic":
case "bedrock":
@@ -1008,6 +1018,7 @@ export class Controller {
case "openai-native":
case "qwen":
case "deepseek":
case "xai":
await updateGlobalState(this.context, "apiModelId", newModelId)
break
case "openrouter":
+2
View File
@@ -54,6 +54,7 @@ export type GlobalStateKey =
| "previousModeApiProvider"
| "previousModeModelId"
| "previousModeThinkingBudgetTokens"
| "previousModeReasoningEffort"
| "previousModeVsCodeLmModelSelector"
| "previousModeModelInfo"
| "liteLlmBaseUrl"
@@ -67,5 +68,6 @@ export type GlobalStateKey =
| "telemetrySetting"
| "asksageApiUrl"
| "thinkingBudgetTokens"
| "reasoningEffort"
| "planActSeparateModelsSetting"
| "favoritedModelIds"
+8
View File
@@ -109,6 +109,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
previousModeModelInfo,
previousModeVsCodeLmModelSelector,
previousModeThinkingBudgetTokens,
previousModeReasoningEffort,
qwenApiLine,
liteLlmApiKey,
telemetrySetting,
@@ -116,6 +117,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
asksageApiUrl,
xaiApiKey,
thinkingBudgetTokens,
reasoningEffort,
sambanovaApiKey,
planActSeparateModelsSettingRaw,
favoritedModelIds,
@@ -177,6 +179,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
getGlobalState(context, "previousModeModelInfo") as Promise<ModelInfo | undefined>,
getGlobalState(context, "previousModeVsCodeLmModelSelector") as Promise<vscode.LanguageModelChatSelector | undefined>,
getGlobalState(context, "previousModeThinkingBudgetTokens") as Promise<number | undefined>,
getGlobalState(context, "previousModeReasoningEffort") as Promise<string | undefined>,
getGlobalState(context, "qwenApiLine") as Promise<string | undefined>,
getSecret(context, "liteLlmApiKey") as Promise<string | undefined>,
getGlobalState(context, "telemetrySetting") as Promise<TelemetrySetting | undefined>,
@@ -184,6 +187,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
getGlobalState(context, "asksageApiUrl") as Promise<string | undefined>,
getSecret(context, "xaiApiKey") as Promise<string | undefined>,
getGlobalState(context, "thinkingBudgetTokens") as Promise<number | undefined>,
getGlobalState(context, "reasoningEffort") as Promise<string | undefined>,
getSecret(context, "sambanovaApiKey") as Promise<string | undefined>,
getGlobalState(context, "planActSeparateModelsSetting") as Promise<boolean | undefined>,
getGlobalState(context, "favoritedModelIds") as Promise<string[] | undefined>,
@@ -272,6 +276,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
vsCodeLmModelSelector,
o3MiniReasoningEffort,
thinkingBudgetTokens,
reasoningEffort,
liteLlmBaseUrl,
liteLlmModelId,
liteLlmApiKey,
@@ -294,6 +299,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
previousModeModelInfo,
previousModeVsCodeLmModelSelector,
previousModeThinkingBudgetTokens,
previousModeReasoningEffort,
mcpMarketplaceEnabled,
telemetrySetting: telemetrySetting || "unset",
planActSeparateModelsSetting,
@@ -352,6 +358,7 @@ export async function updateApiConfiguration(context: vscode.ExtensionContext, a
asksageApiUrl,
xaiApiKey,
thinkingBudgetTokens,
reasoningEffort,
clineApiKey,
sambanovaApiKey,
favoritedModelIds,
@@ -406,6 +413,7 @@ export async function updateApiConfiguration(context: vscode.ExtensionContext, a
await storeSecret(context, "asksageApiKey", asksageApiKey)
await updateGlobalState(context, "asksageApiUrl", asksageApiUrl)
await updateGlobalState(context, "thinkingBudgetTokens", thinkingBudgetTokens)
await updateGlobalState(context, "reasoningEffort", reasoningEffort)
await storeSecret(context, "clineApiKey", clineApiKey)
await storeSecret(context, "sambanovaApiKey", sambanovaApiKey)
await updateGlobalState(context, "favoritedModelIds", favoritedModelIds)
+1
View File
@@ -74,6 +74,7 @@ export interface ApiHandlerOptions {
asksageApiKey?: string
xaiApiKey?: string
thinkingBudgetTokens?: number
reasoningEffort?: string
sambanovaApiKey?: string
}
@@ -102,6 +102,7 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
const [modelConfigurationSelected, setModelConfigurationSelected] = useState(false)
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
const [providerSortingSelected, setProviderSortingSelected] = useState(!!apiConfiguration?.openRouterProviderSorting)
const [reasoningEffortSelected, setReasoningEffortSelected] = useState(!!apiConfiguration?.reasoningEffort)
const handleInputChange = (field: keyof ApiConfiguration) => (event: any) => {
const newValue = event.target.value
@@ -1534,6 +1535,58 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
<ThinkingBudgetSlider apiConfiguration={apiConfiguration} setApiConfiguration={setApiConfiguration} />
)}
{selectedProvider === "xai" && selectedModelId.includes("3-mini") && (
<>
<VSCodeCheckbox
style={{ marginTop: 0 }}
checked={reasoningEffortSelected}
onChange={(e: any) => {
const isChecked = e.target.checked === true
setReasoningEffortSelected(isChecked)
if (!isChecked) {
setApiConfiguration({
...apiConfiguration,
reasoningEffort: "",
})
}
}}>
Modify reasoning effort
</VSCodeCheckbox>
{reasoningEffortSelected && (
<div>
<label htmlFor="reasoning-effort-dropdown">
<span style={{}}>Reasoning Effort</span>
</label>
<DropdownContainer className="dropdown-container" zIndex={DROPDOWN_Z_INDEX - 100}>
<VSCodeDropdown
id="reasoning-effort-dropdown"
style={{ width: "100%", marginTop: 3 }}
value={apiConfiguration?.reasoningEffort || "high"}
onChange={(e: any) => {
setApiConfiguration({
...apiConfiguration,
reasoningEffort: e.target.value,
})
}}>
<VSCodeOption value="low">low</VSCodeOption>
<VSCodeOption value="high">high</VSCodeOption>
</VSCodeDropdown>
</DropdownContainer>
<p
style={{
fontSize: "12px",
marginTop: 3,
marginBottom: 0,
color: "var(--vscode-descriptionForeground)",
}}>
High effort may produce more thorough analysis but takes longer and uses more tokens.
</p>
</div>
)}
</>
)}
<ModelInfoView
selectedModelId={selectedModelId}
modelInfo={selectedModelInfo}
@@ -1831,12 +1884,6 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration):
selectedModelId: apiConfiguration?.lmStudioModelId || "",
selectedModelInfo: openAiModelInfoSaneDefaults,
}
case "requesty":
return {
selectedProvider: provider,
selectedModelId: apiConfiguration?.requestyModelId || "",
selectedModelInfo: openAiModelInfoSaneDefaults,
}
case "vscode-lm":
return {
selectedProvider: provider,