Skip to content

fix: find config without HOME and match variant models in the fallback chain - #42

Merged
azumag merged 1 commit into
azumag:mainfrom
madsiberian:fix/windows-homedir-variant-fallback
Oct 24, 2026
Merged

azumag merged 1 commit into
azumag:mainfrom
madsiberian:fix/windows-homedir-variant-fallback

Conversation

@madsiberian

Copy link
Copy Markdown
Contributor

Problem

Two independent bugs kept the v2 fallback from working for Z.AI coding-plan users on Windows:

  1. Config never found on Windows. loadConfig used process.env.HOME || "". On Windows HOME is normally unset, so the home-based search paths resolved against the process cwd instead of the user profile. The plugin silently found no config, fallbackModels stayed empty, and setup registered nothing.

  2. Variant models never matched the chain. sameModel compared the reasoning-effort variant, so a session on glm-5.3#high (configured via reasoningEffort: "high") never matched a variant-less chain entry. The retry hook fired and detection passed (HTTP 429), but handles(model) returned false, so no fallback ever engaged.

Changes

  • src/utils/config.ts: fall back to os.homedir() when HOME is unset.
  • v2.ts: ignore the variant when matching (sameModel), and carry the failed model's variant onto same-model fallbacks (chainFor) so glm-5.3#high -> zai/glm-5.3#high preserves effort; different-model tiers (e.g. a flash model) keep their default effort.

Testing

  • Added a config test asserting loadConfig falls back to os.homedir() when HOME/XDG_CONFIG_HOME are unset.
  • Added two v2 tests: the variant is carried onto the same-model fallback, and not carried onto a different-model fallback.
  • vitest run: 734 passed (the 2 failures are pre-existing symlinkSync EPERM tests that need admin/Developer Mode on Windows — unrelated).
  • npm run typecheck and npm run build pass.
  • Version bumped 2.1.0 -> 2.1.1 per AGENTS.md.

Note

errorPatterns.custom is parsed by validateConfig but never wired into the v2 detection path (the v2 entrypoint matches against a fixed pattern list). That's a separate gap left untouched here; flagging it in case you want a follow-up.

…k chain

Two fixes that together make the v2 fallback work for Z.AI coding-plan
users on Windows.

- loadConfig used process.env.HOME || "", which on Windows (where HOME
  is usually unset) resolves the home-based config paths against the
  process cwd instead of the user profile, so the plugin silently finds
  no config and registers nothing. Fall back to os.homedir().

- sameModel compared the reasoning-effort variant, so a session on
  glm-5.3#high never matched a variant-less chain entry and the fallback
  never engaged. Ignore the variant when matching, and carry it onto
  same-model fallbacks (glm-5.3#high -> zai/glm-5.3#high) so effort is
  preserved across providers; different-model tiers (e.g. a flash model)
  keep their default effort.

@azumag azumag left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

差分を確認しました。Windows で HOME が無い場合の os.homedir() fallback と、reasoning-effort variant を同一モデルの provider fallback にだけ引き継ぐ変更は問題の境界に合っています。追加テストも HOME/XDG 未設定、同一モデルへの variant 継承、異モデルへ継承しないケースを直接カバーしています。CI の action_required は jobs=0 でコード/テスト failure ではなく、fork PR の Actions 実行承認待ちと判断します。必須修正なしです。

@azumag
azumag merged commit 51e7b48 into azumag:main Oct 24, 2026

azumag commented Oct 24, 2026

Copy link
Copy Markdown
Owner

追レビューで1点見つけました(PRは既にmerge済みなので follow-up 推奨です)。

sameModel() を providerID + id のみの比較へ変更した影響が、chain membership 以外にも波及しています。restoreModel() の「someone picked another model since this plugin switched it」判定と、decide() の mid-streak model-change 判定も同じ sameModel() を使っているため、ユーザーが同一 provider/model のまま variant(reasoning effort)だけ変更した場合、その変更を検知できません。

具体的には、fallback中にユーザーが foo#high -> foo#low のようにvariantだけ変えると、次のuser promptで restoreModel() が current と selected を同一視して original variantへ戻してしまう可能性があります。また retry 中も variant-only change を外部変更として streak reset できません。

今回必要なのは「設定された fallback chain と runtime model の照合では variant を無視する」ことなので、matcherを分けるのが安全だと思います。

  • sameModelKey: providerID + id(handles / chainFor の config-chain lookup 用)
  • sameModelExact: providerID + id + variant(restoreModel の current-vs-selected、decide の streak position / 外部変更検知用)

回帰テストとして「fallback後、get() が selected と同じ provider/id だが variant だけ別値を返す → 新規promptで switchModel しない」を追加するとこの境界を固定できます。

Windows の os.homedir() fallback と、同一modelの別providerへvariantをcarryする本体変更自体は妥当です。CI run #103 は conclusion=failure ですが jobs が0件なので、コード/テスト失敗を示すログはありません。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants