feat(core): one-shot modality probe for pattern-guessed models (/model action, phase 1) - #10335
Draft
jarvislee90s-dot wants to merge 7 commits into
Draft
feat(core): one-shot modality probe for pattern-guessed models (/model action, phase 1)#10335jarvislee90s-dot wants to merge 7 commits into
jarvislee90s-dot wants to merge 7 commits into
Conversation
jarvislee90s-dot
force-pushed
the
feat/modality-probe-phase1
branch
from
August 30, 2026 09:21
f443463 to
615b9d5
Compare
Contributor
|
Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. 中文请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Implements phase 1 of #10309: an explicit one-shot image modality probe for models whose input modalities were guessed by the name-pattern table.
packages/core/src/services/modalityProbe/): sends a single chat-completions request carrying a red 8×8 PNG to the model's own endpoint, deliberately bypassing the content pipeline (the converter's modality gate is exactly the belief under test). Three-state verdict:200→image; error text carrying modality semantics →text_only; auth / rate-limit / timeout / ambiguous errors →unknown(no conclusion, nothing persisted). The successful response's content is never inspected — reasoning models routinely return an emptycontentwith text inreasoning_content/thinkingeven when the image was accepted. The error-dialect dictionary covers the four vendor dialects observed in the Feature: probe actual modality support at model setup (one-shot capability probe instead of static pattern guessing) #10309 validation matrix (DeepSeek/Ollamadoes not support image…, Zhipu's content-type enum validation, OpenRouter's router-level 404), with hints deliberately phrased with an object (not support image,不支持图片) so region-availability errors abstain rather than misjudge.probeResultssettings key (authType|modelId|baseUrl→{ verdict, probedAt }).unknownis never persisted; the write side guards against hand-corrupted stores; probe results never touch a model entry'sgenerationConfig.modalities.explicit modalities (settings/modelProviders) > persisted probe result > name-pattern table, stamped asmodalitiesSource(explicit/probe/pattern) on the resolved config. A comment marks the insertion point reserved for the Use API-backed model metadata for limits and capabilities #8558 API-backed catalog layer (final chain: explicit > provider-native catalog > probe > regex > conservative defaults)./modeldialog shows a provenance badge next to the modality value (manual/probe-tested/auto-detected) and offers at— test image support action on pattern-sourced entries only (live settings read; hidden once a verdict concludes, retryable afterunknown; never offered for user-configured entries).Why it's needed
Fixes the recurring pattern-table race documented on #10309 (#4219, then #10270 → #10278 hours later): every newly shipped vision model needs a manual
MODALITY_PATTERNSentry, and until one lands, users' images are silently replaced by a text placeholder. This PR is the staged first step the #10309 triage recommended ("explicit test-image-support action on pattern-guessed entries in /model"), submitted as a Draft to anchor the design discussion — wizard-time auto-probing, invalidation/re-probe policy, and offline behavior are deliberately out of scope pending that discussion.Reviewer Test Plan
How to verify
Coverage highlights: three-state classification (all four vendor dialects, region-error abstention EN/zh, 5xx abstention, network failure), storage round-trip + corrupted-store guards, and the resolution chain in both directions — an explicit declaration written after a probe verdict still wins at the resolver and in the dialog display.
Optional end-to-end (any OpenAI-compatible provider): configure a pattern-guessed vision model (e.g.
deepseek-v4-flash-vision-expwithout amodalitiesoverride), open/model, presston the entry — the badge flips toprobe-testedand the verdict lands inprobeResults. The probe script from #10309 (gist) re-runs the four-endpoint validation with any subset of keys.Evidence (Before & After)
User-visible TUI change; screenshots to be attached once CI renders the draft. Unit-level before/after is expressed by the tests above (N/A — no visual capture in this environment yet).
Tested on
Environment (optional)
Local source build on Windows, Node ≥22. Scoped suites: probe 19, resolver 62, registry 82, modelsConfig 85, ModelDialog 73 — all green; typecheck / eslint / prettier clean on changed files;
settings.schema.jsonregenerated (CI drift gate). Repo-wide preflight on this Windows machine has known environment-only failures (EPERM symlink, git-path classes — same set on baseb90c2f0); none touch the changed files' suites.Risk & Scope
packages/cli/src/ui/hooks/use-image-support-probe.ts), so theModelDialogdiff is mostly rendering and keybinding. Before this draft is marked ready-for-review, the plan is to split it into two stacked PRs — core resolution chain (probe module + resolver + persistence + unit tests, ≈1,150 lines) and UI (hook + dialog + dialog tests, ≈970 lines) — each under the guideline.text_onlyverdict would be persisted with no phase-1 re-probe path — mitigated by the three-state protocol (uncertainty abstains), object-scoped dialect hints, verdict re-validation on read, and the explicit-declaration escape hatch that always overrides in both the runtime chain and the dialog.QWEN_OAUTHroutes are not probeable in phase 1; abaseUrlenv override can key-diverge from the resolver path (documented inprobe-store.ts).probeResultsmap becausesettings.setValuecannot address nested array items and composite keys containing URLs are unsafe as dotted paths; alternatives (per-entry field, standalone cache file) noted for the discussion.accepted-not-seenfourth state.probeResults, behavior is byte-identical to current main (covered by the untouched existing suites).Linked Issues
References #10309 (draft for the design discussion; not requesting merge yet). Complements #8558 — the catalog covers known provider+model pairs, the probe covers the catalog's blind spots (self-hosted, gateways, brand-new releases); the chain insertion point is marked in
modelConfigResolver.ts.中文说明
本 PR 的改动
实现 #10309 的一期:为模态来源是名称模式表猜测的模型提供显式一次性图片模态探测。
packages/core/src/services/modalityProbe/):向模型自身端点发送一条携带红色 8×8 PNG 的 chat-completions 请求,刻意绕过内容管线(转换器的模态闸门正是被检验的对象)。三态判定:200→image;报错文本含模态语义 →text_only;鉴权/限流/超时/含糊报错 →unknown(不下结论、不落盘)。绝不检查成功响应的内容——推理模型即使在图片被接受时也经常返回空content、正文落在reasoning_content/thinking。报错方言字典覆盖 Feature: probe actual modality support at model setup (one-shot capability probe instead of static pattern guessing) #10309 验证矩阵实测的四种厂商方言,且短语刻意带宾语(not support image、不支持图片),使区域可用性类报错弃权而非误判。probeResults(authType|modelId|baseUrl→{ verdict, probedAt })。unknown永不落盘;写侧对手改损坏的 store 设防;探测结论绝不触碰模型条目的generationConfig.modalities。modalities> 已持久化探测结果 > 名称模式表,来源以modalitiesSource(explicit/probe/pattern)标注在解析结果上。注释标出为 Use API-backed model metadata for limits and capabilities #8558 目录层预留的插入位(终态链:显式 > 目录 > 探测 > 正则 > 保守默认)。/model对话框模态值旁显示来源徽标(manual / probe-tested / auto-detected),仅对 pattern 来源条目提供t测试图片支持动作(活读 settings;得出结论后隐藏,unknown 后可重试;用户手写条目永不显示)。为什么需要此改动
修复 #10309 记录的反复出现的模式表竞速(#4219,随后 #10270 → #10278 数小时竞态):每个新发布的视觉模型都需要人工补
MODALITY_PATTERNS条目,补上之前用户的图片被静默替换为文本占位符。本 PR 是 #10309 triage 建议的分期第一步("先做 /model 中对 pattern 猜测条目的显式测试动作"),以 Draft 形式提交作为设计讨论的锚点——向导自动探测、失效/重测策略、离线行为均刻意留待讨论。审查者测试计划
验证方式
覆盖要点:三态分类(四种厂商方言、中英文区域报错弃权、5xx 弃权、网络失败)、存取往返与损坏 store 守卫、以及双向优先级链——探测结论落盘之后再手写显式声明,在解析器与对话框显示两层都仍然获胜。
可选端到端(任一 OpenAI 兼容 provider):配置一个 pattern 猜测的视觉模型(如不带
modalities覆盖的deepseek-v4-flash-vision-exp),打开/model,在条目上按t—— 徽标变为 probe-tested、判定落入probeResults。#10309 的探测脚本(gist)可用任意子集 key 复跑四端点验证。证据(修复前后)
用户可见的 TUI 变更;截图待 CI 渲染草稿后补。单测层面的前后对照由上述测试表达(本环境暂无视觉捕获,N/A)。
测试平台
环境(可选)
Windows 本地源码构建,Node ≥22。分范围套件:probe 19、resolver 62、registry 82、modelsConfig 85、ModelDialog 73——全绿;改动文件的 typecheck / eslint / prettier 干净;
settings.schema.json已重新生成(CI 漂移门禁)。本 Windows 机器的全仓 preflight 存在已知环境性失败(EPERM symlink、git 路径类——baseb90c2f0上同一集合);均不涉及改动文件的套件。风险与范围
packages/cli/src/ui/hooks/use-image-support-probe.ts),ModelDialog的 diff 以渲染与键位绑定为主。本草稿标记 ready-for-review 前,计划拆为两个堆叠 PR——核心解析链(探测模块 + resolver + 持久化 + 单测,约 1,150 行)与 UI(hook + 对话框 + 对话框测试,约 970 行)——各自低于指引线。text_only判定会被持久化且一期无重测出口——由三态协议(不确定即弃权)、带宾语的方言短语、读侧 verdict 复验、以及永远获胜的显式声明补救出口共同缓解。QWEN_OAUTH路由一期不可探测;baseUrl环境覆盖可能与解析路径键分歧(已记录于probe-store.ts)。probeResults映射——因 settings.setValue 无法寻址嵌套数组元素、含 URL 的组合键作 dotted path 不安全;备选(条目内字段、独立缓存文件)已列出供讨论。accepted-not-seen第四态。probeResults时行为与当前 main 逐字节一致(由未改动的既有套件覆盖)。关联 Issue
References #10309(设计讨论用草稿;暂不请求合并)。与 #8558 互补——目录覆盖已知 provider+model 对,探测覆盖目录盲区(自托管、网关、全新发布);链插入位已在
modelConfigResolver.ts标注。