Skip to content

fix(model-system): import reasoning effort options from models.dev presets (PR-ready on fork) #196

Closed

Description

@hezhongtang

EN: A fix is ready on a fork branch (see links below), but this repository currently rejects pull request creation from my account (hezhongtang does not have the correct permissions to execute CreatePullRequest), so I am opening this tracking issue instead. A maintainer can either grant PR permission or push the branch and open the PR directly — the full bilingual PR description is included below.

中文: 修复已在 fork 分支上就绪(链接见下),但仓库当前拒绝我的账号创建 PR(hezhongtang does not have the correct permissions to execute CreatePullRequest),因此先开此跟踪 issue。维护者可以授予 PR 权限,或直接推送该分支并创建 PR——完整的双语 PR 描述附在下方。


fix(model-system): import reasoning effort options from models.dev presets

Summary / 概述

EN: The provider preset parser only reads the boolean reasoning flag from models.dev and drops the reasoning_options metadata. Models that declare configurable reasoning effort — e.g. Moonshot kimi-k3 (moonshotai / moonshotai-cn, reasoning_options: [{type: 'effort', values: ['low','high','max']}]) — are imported as reasoning: true only, so:

  • the TUI effort selector shows no levels for K3
  • mcode exec --effort high is rejected by local validation
  • the existing openai-completions → reasoning_effort wire mapping can never be reached through the normal user path

中文: 目前的 provider preset 解析器只读取 models.dev 的布尔字段 reasoning,丢弃了 reasoning_options 元数据。对于声明了可配置推理强度(reasoning effort)的模型——例如月之暗面 kimi-k3(moonshotai / moonshotai-cn,reasoning_options: [{type: 'effort', values: ['low','high','max']}])——导入时只保留了 reasoning: true,导致:

  • TUI 的 effort 选择器中 K3 没有任何可选档位
  • mcode exec --effort high 被本地校验拒绝
  • 已有的 openai-completions → reasoning_effort 请求映射无法通过正常用户路径触达

Fix / 修复方案

EN: Add a generic parseModelEffortOptions step to the preset parser that normalizes the {type: 'effort', values: [...]} entry of reasoning_options into UserModelInputView.effortOptions (trim, drop empty/non-string values, dedupe, preserve declared order; no output when empty).

  • No hard-coded K3 / provider special-casing — any models.dev model declaring effort values benefits automatically (both Moonshot providers included).
  • Toggle-only entries and bare reasoning: true still produce no effortOptions; reasoning is not generalized into effort support.
  • No changes to TUI, headless validation, model-ref, or transport: the existing persistence (thinking.effortOptions), roster exposure, --effort validation, and reasoning_effort request patch flow through unchanged. MiniMax M3 on/off logic untouched.

中文: 在 preset 解析器中新增通用的 parseModelEffortOptions 步骤,将 reasoning_options 中的 {type: 'effort', values: [...]} 条目规范化到 UserModelInputView.effortOptions(去除首尾空白、丢弃空值与非字符串、去重、保持声明顺序;结果为空则不输出)。

  • 不针对 K3 或特定 provider 做硬编码——任何在 models.dev 声明 effort 档位的模型都会自动受益(两个 Moonshot provider 均包含)。
  • 仅有 toggle 的条目和裸 reasoning: true 仍然不会产生 effortOptions;不会把"支持思考"泛化为"支持 effort 选择"。
  • 不改动 TUI、headless 校验、model-ref 和传输层:已有的持久化(thinking.effortOptions)、模型列表暴露、--effort 校验以及 reasoning_effort 请求补丁流程均原样复用。MiniMax M3 的开关逻辑不受影响。

Tests / 测试

EN:

  • Preset parser: K3 fixtures for both moonshotai and moonshotai-cn parse ['low','high','max']; toggle-only / empty-options models do not gain effortOptions; normalization keeps unknown values, dedupes, drops empties.
  • Persistence: K3 input saves { reasoning: true, thinking: { effortOptions: [...] } }.
  • Roster: list-models exposes effortOptions for K3.
  • Headless: --effort low|high|max accepted; --effort medium rejected with Available levels: low, high, max.
  • End-to-end: config metadata → modelRef → thinking protocol → requestPatch { reasoning_effort } for all three levels.
  • CLI e2e against a mock OpenAI-compatible transport: --effort low/high/max produce wire reasoning_effort of low/high/max; medium is rejected locally before any request is sent.

中文:

  • Preset 解析器:moonshotai 与 moonshotai-cn 的 K3 fixture 均能解析出 ['low','high','max'];仅 toggle / 空 options 的模型不会获得 effortOptions;规范化保留未知档位、去重、丢弃空值。
  • 持久化:K3 输入保存为 { reasoning: true, thinking: { effortOptions: [...] } }。
  • 模型列表:list-models 为 K3 暴露 effortOptions。
  • Headless:--effort low|high|max 均被接受;--effort medium 被拒绝并提示 Available levels: low, high, max.
  • 端到端:配置元数据 → modelRef → thinking protocol → 三个档位的 requestPatch { reasoning_effort }。
  • CLI 端到端(模拟 OpenAI 兼容传输):--effort low/high/max 产生线上的 reasoning_effort 为 low/high/max;medium 在发送任何请求前即被本地拒绝。

Verification / 验证

EN:

  • Targeted vitest files: 154/154 passing
  • pnpm typecheck, pnpm check:source, pnpm build, node --test test/byok.test.mjs (11/11) passing
  • 12 failures in tui-app.test.ts / update-application.test.ts are pre-existing on the base commit (reproduced identically on base commit 81b666a; locale-dependent assertions) and unrelated to this change
  • The reasoning_options fixtures match the live models.dev catalog (moonshotai/moonshotai-cn kimi-k3)

中文:

  • 相关 vitest 文件:154/154 通过
  • pnpm typecheck、pnpm check:source、pnpm build、node --test test/byok.test.mjs(11/11)均通过
  • tui-app.test.ts / update-application.test.ts 中的 12 个失败为基线提交上已存在的问题(已在基线提交 81b666a 上以完全相同的方式复现;为依赖语言环境的断言),与本改动无关
  • reasoning_options 测试 fixture 与线上 models.dev 目录一致(moonshotai/moonshotai-cn 的 kimi-k3)

Activity

  1. hetaoBackend commented on Sep 19, 2026

    @hetaoBackend
    Collaborator

    Thanks @hezhongtang — I independently reproduced the dropped metadata and opened maintainer PR #201: #201.

    I reviewed your fork commit 098fcf98, adopted its narrowly scoped parser fix and regression tests, and preserved your co-author attribution. The live models.dev catalog confirms low/high/max for K3 on both moonshotai and moonshotai-cn. The two parser regressions fail before the production fix and pass afterward.

    Additional validation covers parsed preset → stored model shape → roster, TUI effort selection, and the built CLI against a local synthetic OpenAI-compatible server: low/high/max reach the conversation request as reasoning_effort, while medium is rejected before any request. Full pnpm verify passes all 14 gates on clean commit c1b6a83 (macOS arm64, Node 26.4.0), including 3,605 capability tests and 11/11 BYOK tests. I did not reproduce the locale-dependent failures in this environment. Live Moonshot inference, manual terminal interaction and other platforms remain unverified.

    One scope detail: existing saved models are not automatically migrated. Reusing a saved connection deliberately preserves existing model fields, so it will not repair already-imported K3 metadata. For such a model, add the following under its existing entry in custom_provider.<your-provider>.models.kimi-k3 in your config, preserving the rest of that entry:

    thinking:
      effortOptions: [low, high, max]

    The PR is open for review; this is not yet a merged or released fix. No collaborator access change is needed for this maintainer-submitted PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions