diff --git a/mateclaw-server/src/main/java/vip/mate/llm/model/ModelInfoDTO.java b/mateclaw-server/src/main/java/vip/mate/llm/model/ModelInfoDTO.java index e840068c..18013199 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/model/ModelInfoDTO.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/model/ModelInfoDTO.java @@ -23,21 +23,42 @@ public class ModelInfoDTO { private String probeError; /** - * RFC-049 PR-1-UI: whether this model's {@code ModelFamily} accepts the - * {@code reasoning_effort} parameter. Derived from the model name on the - * server side so the frontend can gray out the "thinking depth" selector - * for chat-type models that don't support thinking — a product contract, - * not a runtime toggle. - * - *
{@code true} only for the OpenAI reasoning family (gpt-5*, o1*, o3*, o4*). + * RFC-049 PR-1-UI (narrow): whether this model's {@code ModelFamily} accepts the + * OpenAI {@code reasoning_effort} parameter specifically. True only for + * the OpenAI reasoning family (gpt-5, o1, o3, o4 variants). Retained for callers + * that need to know parameter-level compatibility; the UI "deep thinking" toggle + * should use {@link #supportsThinking} instead. */ private boolean supportsReasoningEffort; + /** + * RFC-049 PR-1-UI (broad): whether this model supports any form of + * deep thinking — either OpenAI-style via {@code reasoning_effort}, provider- + * native (Kimi K2.x, DeepSeek-Reasoner, qwen-thinking), or Anthropic extended + * thinking (Claude family). This is what the UI "deep thinking" toggle reads. + * + *
Derived from the model name so every construction site stays consistent.
+ */
+ private boolean supportsThinking;
+
public ModelInfoDTO(String id, String name) {
this.id = id;
this.name = name;
- // RFC-049 PR-1-UI: derived from id (the model name) so every construction
- // site populates the capability consistently.
this.supportsReasoningEffort = ModelFamily.detect(id).supportsReasoningEffort();
+ this.supportsThinking = computeSupportsThinking(id);
+ }
+
+ /**
+ * Thinking capability at the product level (what the UI toggle should reflect):
+ * any model family that has a thinking mode, regardless of how it is triggered
+ * (parameter vs. model-native vs. Anthropic extended thinking).
+ */
+ private static boolean computeSupportsThinking(String modelName) {
+ if (modelName == null || modelName.isBlank()) return false;
+ ModelFamily family = ModelFamily.detect(modelName);
+ if (family.isThinking()) return true; // OPENAI_REASONING / KIMI_THINKING / DEEPSEEK_REASONER / GENERIC_THINKING
+ // Anthropic Claude supports extended thinking via AnthropicChatOptions.thinking;
+ // ModelFamily doesn't model non-OpenAI-compatible providers so match by name.
+ return modelName.toLowerCase().contains("claude");
}
}
diff --git a/mateclaw-ui/src/types/index.ts b/mateclaw-ui/src/types/index.ts
index 6b1e0607..0e0896b7 100644
--- a/mateclaw-ui/src/types/index.ts
+++ b/mateclaw-ui/src/types/index.ts
@@ -587,13 +587,17 @@ export interface ProviderModelInfo {
/** Short error message when probeOk=false */
probeError?: string
/**
- * RFC-049 PR-1-UI: whether the model's `ModelFamily` accepts the
- * `reasoning_effort` parameter. Derived server-side from the model name;
- * true only for the OpenAI reasoning family (gpt-5, o1, o3, o4 variants).
- * Used by the thinking-depth selector to gray itself out on non-reasoning
- * models.
+ * RFC-049 PR-1-UI (narrow): whether the model accepts the OpenAI
+ * `reasoning_effort` parameter. True only for OpenAI reasoning family.
*/
supportsReasoningEffort?: boolean
+ /**
+ * RFC-049 PR-1-UI (broad): whether the model supports any form of deep
+ * thinking (OpenAI reasoning_effort, Kimi/DeepSeek native thinking,
+ * Anthropic extended thinking). This is the field the UI "thinking depth"
+ * toggle should gate on.
+ */
+ supportsThinking?: boolean
}
export interface ProviderInfo {
diff --git a/mateclaw-ui/src/views/ChatConsole.vue b/mateclaw-ui/src/views/ChatConsole.vue
index 548b7494..7120e658 100644
--- a/mateclaw-ui/src/views/ChatConsole.vue
+++ b/mateclaw-ui/src/views/ChatConsole.vue
@@ -252,7 +252,7 @@
@deny="handleDeny"
:enable-talk-mode="!!selectedAgentId"
:thinking-enabled="thinkingEnabled"
- :thinking-supported="currentModelSupportsReasoningEffort"
+ :thinking-supported="currentModelSupportsThinking"
@toggle-thinking="thinkingEnabled = !thinkingEnabled"
@talk="showTalkMode = true"
/>
@@ -637,15 +637,17 @@ const currentRuntimeModel = computed(() => {
})
/**
- * RFC-049 PR-1-UI: whether the active runtime model supports `reasoning_effort`.
- * Drives the enable/disable state of the thinking-depth toggle in ChatInput:
- * chat-type models that don't support thinking must not honor the "deep thinking"
- * selection (product contract — UI reflects the backend gate).
+ * RFC-049 PR-1-UI: whether the active runtime model supports any form
+ * of deep thinking (OpenAI reasoning_effort / Kimi native / DeepSeek-Reasoner
+ * native / Anthropic extended thinking). Drives the enable/disable state of
+ * the thinking-depth toggle in ChatInput.
*
- * Source of truth: ProviderModelInfo.supportsReasoningEffort (set by backend via
- * ModelFamily.detect(modelName) in ModelInfoDTO).
+ * Reads the broad capability (`supportsThinking`) from ProviderModelInfo,
+ * populated server-side in ModelInfoDTO. The narrow `supportsReasoningEffort`
+ * only covers OpenAI gpt-5/o1/o3/o4 and would wrongly gray out Kimi K2.x,
+ * DeepSeek-Reasoner, and Claude — all of which legitimately support thinking.
*/
-const currentModelSupportsReasoningEffort = computed